diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 0000000000000000000000000000000000000000..72652ad2f11c848a7b1dd184899acc04caa604f9 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,3 @@ +[target.x86_64-pc-windows-msvc] +# Link the C runtime statically ; https://github.com/paritytech/parity/issues/6643 +rustflags = ["-Ctarget-feature=+crt-static"] diff --git a/.editorconfig b/.editorconfig index 28b11218608140435d9349f36da97bcbcde1235a..e47fd12f0cd0fa589ab851721520156fbaf5976f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ trim_trailing_whitespace=true max_line_length=120 insert_final_newline=true -[.travis.yml] +[*.{yml,sh}] indent_style=space indent_size=2 tab_width=8 diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000000000000000000000000000000000..a737b1a880f109c11fd555643c0955632605044f --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -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 people’s 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 someone’s 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 venues–online and in-person–as 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/) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..e3438f10a23b548453645c4a5d5b65d58fbabc3c --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -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. diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index f4b5311d59e848c65698b314f6bc9e9da3e732c5..15dc3fa1a2331c2d16e10061bf9b59a35babf8a2 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,11 +2,12 @@ _Before filing a new issue, please **provide the following information**._ > I'm running: > -> - **Parity version**: 0.0.0 -> - **Operating system**: Windows / MacOS / Linux -> - **And installed**: via installer / homebrew / binaries / from source +> - **Which Parity version?**: 0.0.0 +> - **Which operating system?**: Windows / MacOS / Linux +> - **How installed?**: via installer / homebrew / binaries / from source +> - **Are you fully synchronized?**: no / yes +> - **Which network are you connected to?**: ethereum / ropsten / kovan / ... +> - **Did you try to restart the node?**: no / yes _Your issue description goes here below. Try to include **actual** vs. **expected behavior** and **steps to reproduce** the issue._ ---- - diff --git a/.gitignore b/.gitignore index 994559bb157102bcbfdbdf98cebe9aa784635885..0675bc41ebf2703740d770a58ac3fd6a4544b952 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ # vim stuff *.swp +*.swo # mac stuff .DS_Store @@ -23,6 +24,9 @@ npm-debug.log node_modules +# js build artifacts +.git-release.log + # gdb files .gdb_history diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ed3a3675a12f6f21fde2d43cf73062ff62701277..f3a8a3f0c1e49fb1819e781f294fe97e88e92736 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,17 +1,17 @@ stages: - test - - js-build - push-release - build variables: - GIT_DEPTH: "3" - SIMPLECOV: "true" RUST_BACKTRACE: "1" RUSTFLAGS: "" CARGOFLAGS: "" CI_SERVER_NAME: "GitLab CI" + LIBSSL: "libssl1.0.0 (>=1.0.0)" cache: - key: "$CI_BUILD_STAGE/$CI_BUILD_REF_NAME" + key: "$CI_BUILD_STAGE-$CI_BUILD_REF_NAME" + paths: + - target/ untracked: true linux-stable: stage: build @@ -23,77 +23,14 @@ linux-stable: - triggers script: - rustup default stable - - cargo build -j $(nproc) --release --features final $CARGOFLAGS - - cargo build -j $(nproc) --release -p evmbin - - cargo build -j $(nproc) --release -p ethstore-cli - - cargo build -j $(nproc) --release -p ethkey-cli - - strip target/release/parity - - strip target/release/parity-evm - - strip target/release/ethstore - - strip target/release/ethkey - - export SHA3=$(target/release/parity tools hash target/release/parity) - - md5sum target/release/parity > parity.md5 - - sh scripts/deb-build.sh amd64 - - cp target/release/parity deb/usr/bin/parity - - cp target/release/parity-evm deb/usr/bin/parity-evm - - cp target/release/ethstore deb/usr/bin/ethstore - - cp target/release/ethkey deb/usr/bin/ethkey - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - dpkg-deb -b deb "parity_"$VER"_amd64.deb" - - md5sum "parity_"$VER"_amd64.deb" > "parity_"$VER"_amd64.deb.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity --body target/release/parity - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/parity.md5 --body parity.md5 - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu + # ARGUMENTS: 1. BUILD_PLATFORM (target for binaries) 2. PLATFORM (target for cargo) 3. ARC (architecture) 4. & 5. CC & CXX flags 6. binary identifier + - scripts/gitlab-build.sh x86_64-unknown-linux-gnu x86_64-unknown-linux-gnu amd64 gcc g++ ubuntu tags: - - rust - rust-stable artifacts: paths: - - target/release/parity - - target/release/parity-evm - - target/release/ethstore - - target/release/ethkey + - parity.zip name: "stable-x86_64-unknown-linux-gnu_parity" -linux-snap: - stage: build - image: parity/snapcraft:gitlab-ci - only: - - snap - - beta - - tags - - triggers - script: - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - cd snap - - rm -rf *snap - - sed -i 's/master/'"$VER"'/g' snapcraft.yaml - - echo "Version:"$VER - - snapcraft - - ls - - cp "parity_"$CI_BUILD"_REF_NAME_amd64.snap" "parity_"$VER"_amd64.snap" - - md5sum "parity_"$VER"_amd64.snap" > "parity_"$VER"_amd64.snap.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.snap" --body "parity_"$VER"_amd64.snap" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu/"parity_"$VER"_amd64.snap.md5" --body "parity_"$VER"_amd64.snap.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-linux-gnu - tags: - - rust - - rust-stable - artifacts: - paths: - - scripts/parity_*_amd64.snap - name: "stable-x86_64-unknown-snap-gnu_parity" - allow_failure: true linux-stable-debian: stage: build image: parity/rust-debian:gitlab-ci @@ -103,81 +40,14 @@ linux-stable-debian: - stable - triggers script: - - cargo build -j $(nproc) --release --features final $CARGOFLAGS - - cargo build -j $(nproc) --release -p evmbin - - cargo build -j $(nproc) --release -p ethstore-cli - - cargo build -j $(nproc) --release -p ethkey-cli - - strip target/release/parity - - strip target/release/parity-evm - - strip target/release/ethstore - - strip target/release/ethkey - - export SHA3=$(target/release/parity tools hash target/release/parity) - - md5sum target/release/parity > parity.md5 - - sh scripts/deb-build.sh amd64 - - cp target/release/parity deb/usr/bin/parity - - cp target/release/parity-evm deb/usr/bin/parity-evm - - cp target/release/ethstore deb/usr/bin/ethstore - - cp target/release/ethkey deb/usr/bin/ethkey - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - dpkg-deb -b deb "parity_"$VER"_amd64.deb" - - md5sum "parity_"$VER"_amd64.deb" > "parity_"$VER"_amd64.deb.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu/parity --body target/release/parity - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu/parity.md5 --body parity.md5 - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu/"parity_"$VER"_amd64.deb" --body "parity_"$VER"_amd64.deb" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu/"parity_"$VER"_amd64.deb.md5" --body "parity_"$VER"_amd64.deb.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/x86_64-unknown-debian-gnu + - export LIBSSL="libssl1.1 (>=1.1.0)" + - scripts/gitlab-build.sh x86_64-unknown-debian-gnu x86_64-unknown-linux-gnu amd64 gcc g++ debian tags: - - rust - rust-debian artifacts: paths: - - target/release/parity + - parity.zip name: "stable-x86_64-unknown-debian-gnu_parity" -linux-beta: - stage: build - image: parity/rust:gitlab-ci - only: - - beta - - tags - - stable - - triggers - script: - - rustup default beta - - cargo build -j $(nproc) --release $CARGOFLAGS - - strip target/release/parity - tags: - - rust - - rust-beta - artifacts: - paths: - - target/release/parity - name: "beta-x86_64-unknown-linux-gnu_parity" - allow_failure: true -linux-nightly: - stage: build - image: parity/rust:gitlab-ci - only: - - beta - - tags - - stable - - triggers - script: - - rustup default nightly - - cargo build -j $(nproc) --release $CARGOFLAGS - - strip target/release/parity - tags: - - rust - - rust-nightly - artifacts: - paths: - - target/release/parity - name: "nigthly-x86_64-unknown-linux-gnu_parity" - allow_failure: true linux-centos: stage: build image: parity/rust-centos:gitlab-ci @@ -187,42 +57,12 @@ linux-centos: - stable - triggers script: - - export CXX="g++" - - export CC="gcc" - - export PLATFORM=x86_64-unknown-centos-gnu - - cargo build -j $(nproc) --release --features final $CARGOFLAGS - - cargo build -j $(nproc) --release -p evmbin - - cargo build -j $(nproc) --release -p ethstore-cli - - cargo build -j $(nproc) --release -p ethkey-cli - - strip target/release/parity - - strip target/release/parity-evm - - strip target/release/ethstore - - strip target/release/ethkey - - md5sum target/release/parity > parity.md5 - - md5sum target/release/parity-evm > parity-evm.md5 - - md5sum target/release/ethstore > ethstore.md5 - - md5sum target/release/ethkey > ethkey.md5 - - export SHA3=$(target/release/parity tools hash target/release/parity) - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity --body target/release/parity - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity.md5 --body parity.md5 - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity-evm --body target/release/parity-evm - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/parity-evm.md5 --body parity-evm.md5 - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/ethstore --body target/release/ethstore - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/ethstore.md5 --body ethstore.md5 - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/ethkey --body target/release/ethkey - - aws s3api put-object --bucket builds-parity --key $CI_BUILD_REF_NAME/x86_64-unknown-centos-gnu/ethkey.md5 --body ethkey.md5 - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM + - scripts/gitlab-build.sh x86_64-unknown-centos-gnu x86_64-unknown-linux-gnu x86_64 gcc g++ centos tags: - - rust - rust-centos artifacts: paths: - - target/release/parity + - parity.zip name: "x86_64-unknown-centos-gnu_parity" linux-i686: stage: build @@ -233,47 +73,13 @@ linux-i686: - stable - triggers script: - - export HOST_CC=gcc - - export HOST_CXX=g++ - - export COMMIT=$(git rev-parse HEAD) - - export PLATFORM=i686-unknown-linux-gnu - - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - - cargo build -j $(nproc) --target $PLATFORM --release -p evmbin - - cargo build -j $(nproc) --target $PLATFORM --release -p ethstore-cli - - cargo build -j $(nproc) --target $PLATFORM --release -p ethkey-cli - - strip target/$PLATFORM/release/parity - - strip target/$PLATFORM/release/parity-evm - - strip target/$PLATFORM/release/ethstore - - strip target/$PLATFORM/release/ethkey - - strip target/$PLATFORM/release/parity - - md5sum target/$PLATFORM/release/parity > parity.md5 - - export SHA3=$(target/$PLATFORM/release/parity tools hash target/$PLATFORM/release/parity) - - sh scripts/deb-build.sh i386 - - cp target/$PLATFORM/release/parity deb/usr/bin/parity - - cp target/$PLATFORM/release/parity-evm deb/usr/bin/parity-evm - - cp target/$PLATFORM/release/ethstore deb/usr/bin/ethstore - - cp target/$PLATFORM/release/ethkey deb/usr/bin/ethkey - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - dpkg-deb -b deb "parity_"$VER"_i386.deb" - - md5sum "parity_"$VER"_i386.deb" > "parity_"$VER"_i386.deb.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity --body target/$PLATFORM/release/parity - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_i386.deb" --body "parity_"$VER"_i386.deb" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_i386.deb.md5" --body "parity_"$VER"_i386.deb.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM + - scripts/gitlab-build.sh i686-unknown-linux-gnu i686-unknown-linux-gnu i386 gcc g++ ubuntu tags: - - rust - rust-i686 artifacts: paths: - - target/i686-unknown-linux-gnu/release/parity + - parity.zip name: "i686-unknown-linux-gnu" - allow_failure: true linux-armv7: stage: build image: parity/rust-armv7:gitlab-ci @@ -283,55 +89,13 @@ linux-armv7: - stable - triggers script: - - export CC=arm-linux-gnueabihf-gcc - - export CXX=arm-linux-gnueabihf-g++ - - export HOST_CC=gcc - - export HOST_CXX=g++ - - export PLATFORM=armv7-unknown-linux-gnueabihf - - rm -rf .cargo - - mkdir -p .cargo - - echo "[target.$PLATFORM]" >> .cargo/config - - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - - cat .cargo/config - - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - - cargo build -j $(nproc) --target $PLATFORM --release -p evmbin - - cargo build -j $(nproc) --target $PLATFORM --release -p ethstore-cli - - cargo build -j $(nproc) --target $PLATFORM --release -p ethkey-cli - - md5sum target/$PLATFORM/release/parity > parity.md5 - - export SHA3=$(target/$PLATFORM/release/parity tools hash target/$PLATFORM/release/parity) - - sh scripts/deb-build.sh i386 - - arm-linux-gnueabihf-strip target/$PLATFORM/release/parity - - arm-linux-gnueabihf-strip target/$PLATFORM/release/parity-evm - - arm-linux-gnueabihf-strip target/$PLATFORM/release/ethstore - - arm-linux-gnueabihf-strip target/$PLATFORM/release/ethkey - - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - - md5sum target/$PLATFORM/release/parity > parity.md5 - - sh scripts/deb-build.sh armhf - - cp target/$PLATFORM/release/parity deb/usr/bin/parity - - cp target/$PLATFORM/release/parity-evm deb/usr/bin/parity-evm - - cp target/$PLATFORM/release/ethstore deb/usr/bin/ethstore - - cp target/$PLATFORM/release/ethkey deb/usr/bin/ethkey - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - dpkg-deb -b deb "parity_"$VER"_armhf.deb" - - md5sum "parity_"$VER"_armhf.deb" > "parity_"$VER"_armhf.deb.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity --body target/$PLATFORM/release/parity - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM + - scripts/gitlab-build.sh armv7-unknown-linux-gnueabihf armv7-unknown-linux-gnueabihf armhf arm-linux-gnueabihf-gcc arm-linux-gnueabihf-g++ ubuntu tags: - - rust - rust-arm artifacts: paths: - - target/armv7-unknown-linux-gnueabihf/release/parity + - parity.zip name: "armv7_unknown_linux_gnueabihf_parity" - allow_failure: true linux-arm: stage: build image: parity/rust-arm:gitlab-ci @@ -341,52 +105,13 @@ linux-arm: - stable - triggers script: - - export CC=arm-linux-gnueabihf-gcc - - export CXX=arm-linux-gnueabihf-g++ - - export HOST_CC=gcc - - export HOST_CXX=g++ - - export PLATFORM=arm-unknown-linux-gnueabihf - - rm -rf .cargo - - mkdir -p .cargo - - echo "[target.$PLATFORM]" >> .cargo/config - - echo "linker= \"arm-linux-gnueabihf-gcc\"" >> .cargo/config - - cat .cargo/config - - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - - cargo build -j $(nproc) --target $PLATFORM --release -p evmbin - - cargo build -j $(nproc) --target $PLATFORM --release -p ethstore-cli - - cargo build -j $(nproc) --target $PLATFORM --release -p ethkey-cli - - arm-linux-gnueabihf-strip target/$PLATFORM/release/parity - - arm-linux-gnueabihf-strip target/$PLATFORM/release/parity-evm - - arm-linux-gnueabihf-strip target/$PLATFORM/release/ethstore - - arm-linux-gnueabihf-strip target/$PLATFORM/release/ethkey - - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - - md5sum target/$PLATFORM/release/parity > parity.md5 - - sh scripts/deb-build.sh armhf - - cp target/$PLATFORM/release/parity deb/usr/bin/parity - - cp target/$PLATFORM/release/parity-evm deb/usr/bin/parity-evm - - cp target/$PLATFORM/release/ethstore deb/usr/bin/ethstore - - cp target/$PLATFORM/release/ethkey deb/usr/bin/ethkey - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - dpkg-deb -b deb "parity_"$VER"_armhf.deb" - - md5sum "parity_"$VER"_armhf.deb" > "parity_"$VER"_armhf.deb.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity --body target/$PLATFORM/release/parity - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb" --body "parity_"$VER"_armhf.deb" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_armhf.deb.md5" --body "parity_"$VER"_armhf.deb.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM + - scripts/gitlab-build.sh arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabihf armhf arm-linux-gnueabihf-gcc arm-linux-gnueabihf-g++ ubuntu tags: - - rust - rust-arm artifacts: paths: - - target/arm-unknown-linux-gnueabihf/release/parity + - parity.zip name: "arm-unknown-linux-gnueabihf_parity" - allow_failure: true linux-aarch64: stage: build image: parity/rust-arm64:gitlab-ci @@ -396,51 +121,29 @@ linux-aarch64: - stable - triggers script: - - export CC=aarch64-linux-gnu-gcc - - export CXX=aarch64-linux-gnu-g++ - - export HOST_CC=gcc - - export HOST_CXX=g++ - - export PLATFORM=aarch64-unknown-linux-gnu - - rm -rf .cargo - - mkdir -p .cargo - - echo "[target.$PLATFORM]" >> .cargo/config - - echo "linker= \"aarch64-linux-gnu-gcc\"" >> .cargo/config - - cat .cargo/config - - cargo build -j $(nproc) --target $PLATFORM --features final --release $CARGOFLAGS - - cargo build -j $(nproc) --target $PLATFORM --release -p evmbin - - cargo build -j $(nproc) --target $PLATFORM --release -p ethstore-cli - - cargo build -j $(nproc) --target $PLATFORM --release -p ethkey-cli - - aarch64-linux-gnu-strip target/$PLATFORM/release/parity - - aarch64-linux-gnu-strip target/$PLATFORM/release/parity-evm - - aarch64-linux-gnu-strip target/$PLATFORM/release/ethstore - - aarch64-linux-gnu-strip target/$PLATFORM/release/ethkey - - export SHA3=$(rhash --sha3-256 target/$PLATFORM/release/parity -p %h) - - md5sum target/$PLATFORM/release/parity > parity.md5 - - sh scripts/deb-build.sh arm64 - - cp target/$PLATFORM/release/parity deb/usr/bin/parity - - cp target/$PLATFORM/release/parity-evm deb/usr/bin/parity-evm - - cp target/$PLATFORM/release/ethstore deb/usr/bin/ethstore - - cp target/$PLATFORM/release/ethkey deb/usr/bin/ethkey - - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - - dpkg-deb -b deb "parity_"$VER"_arm64.deb" - - md5sum "parity_"$VER"_arm64.deb" > "parity_"$VER"_arm64.deb.md5" - - aws configure set aws_access_key_id $s3_key - - aws configure set aws_secret_access_key $s3_secret - - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_arm64.deb" --body "parity_"$VER"_arm64.deb" - - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity_"$VER"_arm64.deb.md5" --body "parity_"$VER"_arm64.deb.md5" - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM - - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM + - scripts/gitlab-build.sh aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu arm64 aarch64-linux-gnu-gcc aarch64-linux-gnu-g++ ubuntu tags: - - rust - rust-arm artifacts: paths: - - target/aarch64-unknown-linux-gnu/release/parity + - parity.zip name: "aarch64-unknown-linux-gnu_parity" - allow_failure: true +linux-snap: + stage: build + image: parity/snapcraft:gitlab-ci + only: + - stable + - beta + - tags + - triggers + script: + - scripts/gitlab-build.sh x86_64-unknown-snap-gnu x86_64-unknown-linux-gnu amd64 gcc g++ snap + tags: + - rust-stable + artifacts: + paths: + - parity.zip + name: "stable-x86_64-unknown-snap-gnu_parity" darwin: stage: build only: @@ -448,45 +151,17 @@ darwin: - tags - stable - triggers - script: | - export COMMIT=$(git rev-parse HEAD) - export PLATFORM=x86_64-apple-darwin - rustup default stable - cargo clean - cargo build -j 8 --features final --release #$CARGOFLAGS - cargo build -j 8 --release -p ethstore-cli #$CARGOFLAGS - cargo build -j 8 --release -p ethkey-cli #$CARGOFLAGS - cargo build -j 8 --release -p evmbin #$CARGOFLAGS - rm -rf parity.md5 - md5sum target/release/parity > parity.md5 - export SHA3=$(target/release/parity tools hash target/release/parity) - cd mac - xcodebuild -configuration Release - cd .. - packagesbuild -v mac/Parity.pkgproj - productsign --sign 'Developer ID Installer: PARITY TECHNOLOGIES LIMITED (P2PX3JU8FT)' target/release/Parity\ Ethereum.pkg target/release/Parity\ Ethereum-signed.pkg - export VER=$(grep -m 1 version Cargo.toml | awk '{print $3}' | tr -d '"' | tr -d "\n") - mv target/release/Parity\ Ethereum-signed.pkg "parity-"$VER"-macos-installer.pkg" - md5sum "parity-"$VER"-macos-installer.pkg" >> "parity-"$VER"-macos-installer.pkg.md5" - aws configure set aws_access_key_id $s3_key - aws configure set aws_secret_access_key $s3_secret - if [[ $CI_BUILD_REF_NAME =~ ^(master|beta|stable|nightly)$ ]]; then export S3_BUCKET=builds-parity-published; else export S3_BUCKET=builds-parity; fi - aws s3 rm --recursive s3://$S3_BUCKET/$CI_BUILD_REF_NAME/$PLATFORM - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity --body target/release/parity - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/parity.md5 --body parity.md5 - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity-"$VER"-macos-installer.pkg" --body "parity-"$VER"-macos-installer.pkg" - aws s3api put-object --bucket $S3_BUCKET --key $CI_BUILD_REF_NAME/$PLATFORM/"parity-"$VER"-macos-installer.pkg.md5" --body "parity-"$VER"-macos-installer.pkg.md5" - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1337/push-build/$CI_BUILD_REF_NAME/$PLATFORM - curl --data "commit=$CI_BUILD_REF&sha3=$SHA3&filename=parity&secret=$RELEASES_SECRET" http://update.parity.io:1338/push-build/$CI_BUILD_REF_NAME/$PLATFORM + script: + - scripts/gitlab-build.sh x86_64-apple-darwin x86_64-apple-darwin macos gcc g++ macos tags: - osx artifacts: paths: - - target/release/parity + - parity.zip name: "x86_64-apple-darwin_parity" windows: cache: - key: "%CI_BUILD_STAGE%/%CI_BUILD_REF_NAME%" + key: "%CI_BUILD_STAGE%-%CI_BUILD_REF_NAME%" untracked: true stage: build only: @@ -495,62 +170,12 @@ windows: - stable - triggers script: - - set PLATFORM=x86_64-pc-windows-msvc - - set INCLUDE=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include;C:\vs2015\VC\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.10240.0\ucrt - - set LIB=C:\vs2015\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64 - - set RUST_BACKTRACE=1 - - set RUSTFLAGS=%RUSTFLAGS% - - rustup default stable-x86_64-pc-windows-msvc - - cargo clean - - cargo build --features final --release #%CARGOFLAGS% - - cargo build --release -p ethstore-cli #%CARGOFLAGS% - - cargo build --release -p ethkey-cli #%CARGOFLAGS% - - cargo build --release -p evmbin #%CARGOFLAGS% - - signtool sign /f %keyfile% /p %certpass% target\release\parity.exe - - target\release\parity.exe tools hash target\release\parity.exe > parity.sha3 - - set /P SHA3= InstallParity.exe.md5 - - zip win-installer.zip InstallParity.exe InstallParity.exe.md5 - - md5sums win-installer.zip > win-installer.zip.md5 - - cd ..\target\release\ - - md5sums parity.exe > parity.exe.md5 - - zip parity.zip parity.exe parity.md5 - - md5sums parity.zip > parity.zip.md5 - - cd ..\.. - - aws configure set aws_access_key_id %s3_key% - - aws configure set aws_secret_access_key %s3_secret% - - echo %CI_BUILD_REF_NAME% - - echo %CI_BUILD_REF_NAME% | findstr /R "master" >nul 2>&1 && set S3_BUCKET=builds-parity-published|| set S3_BUCKET=builds-parity - - echo %CI_BUILD_REF_NAME% | findstr /R "beta" >nul 2>&1 && set S3_BUCKET=builds-parity-published|| set S3_BUCKET=builds-parity - - echo %CI_BUILD_REF_NAME% | findstr /R "stable" >nul 2>&1 && set S3_BUCKET=builds-parity-published|| set S3_BUCKET=builds-parity - - echo %CI_BUILD_REF_NAME% | findstr /R "nightly" >nul 2>&1 && set S3_BUCKET=builds-parity-published|| set S3_BUCKET=builds-parity - - echo %S3_BUCKET% - - aws s3 rm --recursive s3://%S3_BUCKET%/%CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.exe --body target\release\parity.exe - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.exe.md5 --body target\release\parity.exe.md5 - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.zip --body target\release\parity.zip - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/parity.zip.md5 --body target\release\parity.zip.md5 - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe --body nsis\InstallParity.exe - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/InstallParity.exe.md5 --body nsis\InstallParity.exe.md5 - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip --body nsis\win-installer.zip - - aws s3api put-object --bucket %S3_BUCKET% --key %CI_BUILD_REF_NAME%/x86_64-pc-windows-msvc/win-installer.zip.md5 --body nsis\win-installer.zip.md5 - - curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://update.parity.io:1337/push-build/%CI_BUILD_REF_NAME%/%PLATFORM% - - curl --data "commit=%CI_BUILD_REF%&sha3=%SHA3%&filename=parity.exe&secret=%RELEASES_SECRET%" http://update.parity.io:1338/push-build/%CI_BUILD_REF_NAME%/%PLATFORM% + - sh scripts/gitlab-build.sh x86_64-pc-windows-msvc x86_64-pc-windows-msvc installer "" "" windows tags: - rust-windows artifacts: paths: - - target/release/parity.exe - - target/release/parity.pdb - - nsis/InstallParity.exe + - parity.zip name: "x86_64-pc-windows-msvc_parity" docker-build: stage: build @@ -563,7 +188,7 @@ docker-build: - if [ "$CI_BUILD_REF_NAME" == "beta-release" ]; then DOCKER_TAG="latest"; else DOCKER_TAG=$CI_BUILD_REF_NAME; fi - echo "Tag:" $DOCKER_TAG - docker login -u $Docker_Hub_User_Parity -p $Docker_Hub_Pass_Parity - - sh scripts/docker-build.sh $DOCKER_TAG + - scripts/docker-build.sh $DOCKER_TAG - docker logout tags: - docker @@ -572,65 +197,16 @@ test-coverage: only: - master script: - - git submodule update --init --recursive - - rm -rf target/* - - rm -rf js/.coverage - - scripts/cov.sh - # - COVERAGE=$(grep -Po 'covered":.*?[^\\]"' target/cov/index.json | grep "[0-9]*\.[0-9]" -o) - # - echo "Coverage:" $COVERAGE + - scripts/gitlab-test.sh test-coverage tags: - kcov allow_failure: true -test-darwin: - stage: test - only: - - triggers - before_script: - - git submodule update --init --recursive - - export RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e "^js/" -e ^\\. -e ^LICENSE -e ^README.md -e ^appveyor.yml -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l) - script: - - export RUST_BACKTRACE=1 - - if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi - tags: - - osx - allow_failure: true -test-windows: - stage: test - only: - - triggers - before_script: - - git submodule update --init --recursive - script: - - set RUST_BACKTRACE=1 - - echo cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p parity-dapps -p parity-rpc -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity-rpc-client -p parity %CARGOFLAGS% --verbose --release - tags: - - rust-windows - allow_failure: true test-rust-stable: stage: test image: parity/rust:gitlab-ci - before_script: - - git submodule update --init --recursive - - export RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e ^js -e ^\\. -e ^LICENSE -e ^README.md -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l) script: - - rustup show - - export RUST_BACKTRACE=1 - - if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi - - if [ "$CI_BUILD_REF_NAME" == "nightly" ]; then sh scripts/aura-test.sh; fi + - scripts/gitlab-test.sh stable tags: - - rust - - rust-stable -js-test: - stage: test - image: parity/rust:gitlab-ci - before_script: - - git submodule update --init --recursive - - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep ^js/ | wc -l) - - if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS deps install since no JS files modified."; else ./js/scripts/install-deps.sh;fi - script: - - if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS lint since no JS files modified."; else ./js/scripts/lint.sh && ./js/scripts/test.sh && ./js/scripts/build.sh; fi - tags: - - rust - rust-stable test-rust-beta: stage: test @@ -638,15 +214,9 @@ test-rust-beta: - triggers - master image: parity/rust:gitlab-ci - before_script: - - git submodule update --init --recursive - - export RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e ^js -e ^\\. -e ^LICENSE -e ^README.md -e ^appveyor.yml -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l) script: - - rustup default beta - - export RUST_BACKTRACE=1 - - if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi + - scripts/gitlab-test.sh beta tags: - - rust - rust-beta allow_failure: true test-rust-nightly: @@ -655,36 +225,12 @@ test-rust-nightly: - triggers - master image: parity/rust:gitlab-ci - before_script: - - git submodule update --init --recursive - - export RUST_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep -v -e ^js -e ^\\. -e ^LICENSE -e ^README.md -e ^appveyor.yml -e ^test.sh -e ^windows/ -e ^scripts/ -e^mac/ -e ^nsis/ | wc -l) script: - - rustup default nightly - - export RUST_BACKTRACE=1 - - if [ $RUST_FILES_MODIFIED -eq 0 ]; then echo "Skipping Rust tests since no Rust files modified."; else ./test.sh $CARGOFLAGS; fi + - scripts/gitlab-test.sh nightly tags: - rust - rust-nightly allow_failure: true -js-release: - stage: js-build - only: - - master - - beta - - stable - - tags - - triggers - image: parity/rust:gitlab-ci - before_script: - - export JS_FILES_MODIFIED=$(git --no-pager diff --name-only $CI_BUILD_REF^ $CI_BUILD_REF | grep ^js/ | wc -l) - - echo $JS_FILES_MODIFIED - - if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS deps install since no JS files modified."; else ./js/scripts/install-deps.sh;fi - script: - - rustup default stable - - echo $JS_FILES_MODIFIED - - if [ $JS_FILES_MODIFIED -eq 0 ]; then echo "Skipping JS rebuild since no JS files modified."; else ./js/scripts/build.sh && ./js/scripts/release.sh; fi - tags: - - javascript push-release: stage: push-release only: @@ -692,8 +238,6 @@ push-release: - triggers image: parity/rust:gitlab-ci script: - - rustup default stable - - curl --data "secret=$RELEASES_SECRET" http://update.parity.io:1337/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF - - curl --data "secret=$RELEASES_SECRET" http://update.parity.io:1338/push-release/$CI_BUILD_REF_NAME/$CI_BUILD_REF + - scripts/gitlab-push-release.sh tags: - curl diff --git a/CHANGELOG.md b/CHANGELOG.md index 78bf895ee48026b07ad761ca32fd909f18710c75..c0f438696b66e7611bee7bfee252ccfcdb0193d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4394 +1,213 @@ -## Parity [v1.7.0](https://github.com/paritytech/parity/releases/tag/v1.7.0) (2017-07-28) +## Parity [v1.10.0](https://github.com/paritytech/parity/releases/tag/v1.10.0) (2018-03-22) -Parity 1.7.0 is a major release introducing several important features: +This is the Parity 1.10.0-beta release! Cool! -- **Experimental [Light client](https://github.com/paritytech/parity/wiki/The-Parity-Light-Protocol-(PIP)) support**. Start Parity with `--light` to enable light mode. Please, note: The wallet UI integration for the light client is not included, yet. -- **Experimental web wallet**. A hosted version of Parity that keeps the keys and signs transactions using your browser storage. Try it at https://wallet.parity.io or run your own with `--public-node`. -- **WASM contract support**. Private networks can run contracts compiled into WASM bytecode. _More information and documentation to follow_. -- **DApps and RPC server merge**. DApp and RPC are now available through a single API endpoint. DApp server related settings are deprecated. -- **Export accounts from the wallet**. Backing up your keys can now simply be managed through the wallet interface. -- **PoA/Kovan validator set contract**. The PoA network validator-set management via smart contract is now supported by warp and, in the near future, light sync. -- **PubSub API**. https://github.com/paritytech/parity/wiki/JSONRPC-Parity-Pub-Sub-module -- **Signer apps for IOS and Android**. +### Disabling the Parity Wallet -Full list of included changes: +The **Parity Wallet (a.k.a. "UI") is now disabled by default**. We are preparing to split the wallet from the core client. -- Backports [#6163](https://github.com/paritytech/parity/pull/6163) - - Light client improvements ([#6156](https://github.com/paritytech/parity/pull/6156)) - - No seal checking - - Import command and --no-seal-check for light client - - Fix eth_call - - Tweak registry dapps lookup - - Ignore failed requests to non-server peers - - Fix connecting to wildcard addresses. ([#6167](https://github.com/paritytech/parity/pull/6167)) - - Don't display an overlay in case the time sync check fails. ([#6164](https://github.com/paritytech/parity/pull/6164)) - - Small improvements to time estimation. - - Temporarily disable NTP time check by default. -- Light client fixes ([#6148](https://github.com/paritytech/parity/pull/6148)) [#6151](https://github.com/paritytech/parity/pull/6151) - - Light client fixes - - Fix memory-lru-cache - - Clear pending reqs on disconnect -- Filter tokens logs from current block, not genesis ([#6128](https://github.com/paritytech/parity/pull/6128)) [#6141](https://github.com/paritytech/parity/pull/6141) -- Fix QR scanner returning null on confirm [#6122](https://github.com/paritytech/parity/pull/6122) -- Check QR before lowercase ([#6119](https://github.com/paritytech/parity/pull/6119)) [#6120](https://github.com/paritytech/parity/pull/6120) -- Remove chunk to restore from pending set only upon successful import [#6117](https://github.com/paritytech/parity/pull/6117) -- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094) -- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095) -- Update wallet library binaries [#6108](https://github.com/paritytech/parity/pull/6108) -- Backported wallet fix [#6105](https://github.com/paritytech/parity/pull/6105) - - Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102)) - - Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103)) -- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095) -- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094) -- Bump snap version and tweak importing detection logic ([#6079](https://github.com/paritytech/parity/pull/6079)) [#6081](https://github.com/paritytech/parity/pull/6081) - - bump last tick just before printing info and restore sync detection - - bump kovan snapshot version - - Fixed sync tests - - Fixed rpc tests -- Acquire client report under lock in informant [#6071](https://github.com/paritytech/parity/pull/6071) -- Show busy indicator on Address forget [#6069](https://github.com/paritytech/parity/pull/6069) -- Add CSP for worker-src ([#6059](https://github.com/paritytech/parity/pull/6059)) [#6064](https://github.com/paritytech/parity/pull/6064) - - Specify worker-src seperately, add blob - - Upgrade react-qr-scan to latest version -- Set release channel to beta -- Limit transaction queue memory & limit future queue [#6038](https://github.com/paritytech/parity/pull/6038) -- Fix CI build issue [#6050](https://github.com/paritytech/parity/pull/6050) -- New contract PoA sync fixes [#5991](https://github.com/paritytech/parity/pull/5991) -- Fixed link to Multisig Contract Wallet on master [#5984](https://github.com/paritytech/parity/pull/5984) -- Ethcore crate split part 1 [#6041](https://github.com/paritytech/parity/pull/6041) -- Fix status icon [#6039](https://github.com/paritytech/parity/pull/6039) -- Errors & warnings for inappropriate RPCs [#6029](https://github.com/paritytech/parity/pull/6029) -- Add missing CSP for web3.site [#5992](https://github.com/paritytech/parity/pull/5992) -- Remove cargo install --git from README.md [#6037](https://github.com/paritytech/parity/pull/6037) -- Node Health warnings [#5951](https://github.com/paritytech/parity/pull/5951) -- RPC cpu pool [#6023](https://github.com/paritytech/parity/pull/6023) -- Use crates.io dependencies for parity-wasm [#6036](https://github.com/paritytech/parity/pull/6036) -- Add test for loading the chain specs [#6028](https://github.com/paritytech/parity/pull/6028) -- Whitelist APIs for generic Pub-Sub [#5840](https://github.com/paritytech/parity/pull/5840) -- WASM contracts MVP [#5679](https://github.com/paritytech/parity/pull/5679) -- Fix valid QR scan not advancing [#6033](https://github.com/paritytech/parity/pull/6033) -- --reseal-on-uncle [#5940](https://github.com/paritytech/parity/pull/5940) -- Support comments in reserved peers file ([#6004](https://github.com/paritytech/parity/pull/6004)) [#6012](https://github.com/paritytech/parity/pull/6012) -- Add new md tnc [#5937](https://github.com/paritytech/parity/pull/5937) -- Fix output of parity-evm in case of bad instruction [#5955](https://github.com/paritytech/parity/pull/5955) -- Don't send notifications to unsubscribed clients of PubSub [#5960](https://github.com/paritytech/parity/pull/5960) -- Proper light client informant and more verification of imported headers [#5897](https://github.com/paritytech/parity/pull/5897) -- New Kovan bootnodes [#6017](https://github.com/paritytech/parity/pull/6017) -- Use standard paths for Ethash cache [#5881](https://github.com/paritytech/parity/pull/5881) -- Defer code hash calculation. [#5959](https://github.com/paritytech/parity/pull/5959) -- Fix first run wizard. [#6000](https://github.com/paritytech/parity/pull/6000) -- migration to serde 1.0 [#5996](https://github.com/paritytech/parity/pull/5996) -- SecretStore: generating signatures [#5764](https://github.com/paritytech/parity/pull/5764) -- bigint upgraded to version 3.0 [#5986](https://github.com/paritytech/parity/pull/5986) -- config: don't allow dev chain with force sealing option [#5965](https://github.com/paritytech/parity/pull/5965) -- Update lockfile for miniz-sys and gcc [#5969](https://github.com/paritytech/parity/pull/5969) -- Clean up function naming in RPC error module [#5995](https://github.com/paritytech/parity/pull/5995) -- Fix underflow in gas calculation [#5975](https://github.com/paritytech/parity/pull/5975) -- PubSub for parity-js [#5830](https://github.com/paritytech/parity/pull/5830) -- Report whether a peer was kept from `Handler::on_connect` [#5958](https://github.com/paritytech/parity/pull/5958) -- Implement skeleton for transaction index and epoch transition proof PIP messages [#5908](https://github.com/paritytech/parity/pull/5908) -- TransactionQueue improvements [#5917](https://github.com/paritytech/parity/pull/5917) -- constant time HMAC comparison and clarify docs in ethkey [#5952](https://github.com/paritytech/parity/pull/5952) -- Avoid pre-computing jump destinations [#5954](https://github.com/paritytech/parity/pull/5954) -- Upgrade elastic array [#5949](https://github.com/paritytech/parity/pull/5949) -- PoA: Wait for transition finality before applying [#5774](https://github.com/paritytech/parity/pull/5774) -- Logs Pub-Sub [#5705](https://github.com/paritytech/parity/pull/5705) -- Add the command to install the parity snap [#5945](https://github.com/paritytech/parity/pull/5945) -- Reduce unnecessary allocations [#5944](https://github.com/paritytech/parity/pull/5944) -- Clarify confusing messages. [#5935](https://github.com/paritytech/parity/pull/5935) -- Content Security Policy [#5790](https://github.com/paritytech/parity/pull/5790) -- CLI: Export error message and less verbose peer counter. [#5870](https://github.com/paritytech/parity/pull/5870) -- network: make it more explicit about StreamToken and TimerToken [#5939](https://github.com/paritytech/parity/pull/5939) -- sync: make it more idiomatic rust [#5938](https://github.com/paritytech/parity/pull/5938) -- Prioritize accounts over address book [#5909](https://github.com/paritytech/parity/pull/5909) -- Fixing failing compilation of RPC test on master. [#5916](https://github.com/paritytech/parity/pull/5916) -- Empty local middleware, until explicitly requested [#5912](https://github.com/paritytech/parity/pull/5912) -- Cancel propagated TX [#5899](https://github.com/paritytech/parity/pull/5899) -- fix minor race condition in aura seal generation [#5910](https://github.com/paritytech/parity/pull/5910) -- Docs for Pub-Sub, optional parameter for parity_subscribe [#5833](https://github.com/paritytech/parity/pull/5833) -- Fix gas editor doubling-up on gas [#5820](https://github.com/paritytech/parity/pull/5820) -- Information about used paths added to general output block [#5904](https://github.com/paritytech/parity/pull/5904) -- Domain-locked web tokens. [#5894](https://github.com/paritytech/parity/pull/5894) -- Removed panic handlers [#5895](https://github.com/paritytech/parity/pull/5895) -- Latest changes from Rust RocksDB binding merged [#5905](https://github.com/paritytech/parity/pull/5905) -- Adjust keyethereum/secp256 aliasses [#5903](https://github.com/paritytech/parity/pull/5903) -- Keyethereum fs dependency [#5902](https://github.com/paritytech/parity/pull/5902) -- Ethereum Classic Monetary Policy [#5741](https://github.com/paritytech/parity/pull/5741) -- Initial token should allow full access. [#5873](https://github.com/paritytech/parity/pull/5873) -- Fixed account selection for Dapps on public node [#5856](https://github.com/paritytech/parity/pull/5856) -- blacklist bad snapshot manifest hashes upon failure [#5874](https://github.com/paritytech/parity/pull/5874) -- Fix wrongly called timeouts [#5838](https://github.com/paritytech/parity/pull/5838) -- ArchiveDB and other small fixes [#5867](https://github.com/paritytech/parity/pull/5867) -- convert try!() to ? [#5866](https://github.com/paritytech/parity/pull/5866) -- Make config file optional in systemd [#5847](https://github.com/paritytech/parity/pull/5847) -- EIP-116 (214), [#4833](https://github.com/paritytech/parity/issues/4833) [#4851](https://github.com/paritytech/parity/pull/4851) -- all executables are workspace members [#5865](https://github.com/paritytech/parity/pull/5865) -- minor optimizations of the modexp builtin [#5860](https://github.com/paritytech/parity/pull/5860) -- three small commits for HashDB and MemoryDB [#5766](https://github.com/paritytech/parity/pull/5766) -- use rust 1.18's retain to boost the purge performance [#5801](https://github.com/paritytech/parity/pull/5801) -- Allow IPFS server to accept POST requests [#5858](https://github.com/paritytech/parity/pull/5858) -- Dutch i18n from [#5802](https://github.com/paritytech/parity/issues/5802) for master [#5836](https://github.com/paritytech/parity/pull/5836) -- Typos in token deploy dapp ui [#5851](https://github.com/paritytech/parity/pull/5851) -- A CLI flag to allow fast transaction signing when account is unlocked. [#5778](https://github.com/paritytech/parity/pull/5778) -- Removing `additional` field from EVM instructions [#5821](https://github.com/paritytech/parity/pull/5821) -- Don't fail on wrong log decoding [#5813](https://github.com/paritytech/parity/pull/5813) -- Use randomized subscription ids for PubSub [#5756](https://github.com/paritytech/parity/pull/5756) -- Fixed mem write for empty slice [#5827](https://github.com/paritytech/parity/pull/5827) -- Fix party technologies [#5810](https://github.com/paritytech/parity/pull/5810) -- Revert "Fixed mem write for empty slice" [#5826](https://github.com/paritytech/parity/pull/5826) -- Fixed mem write for empty slice [#5825](https://github.com/paritytech/parity/pull/5825) -- Fix JS tests [#5822](https://github.com/paritytech/parity/pull/5822) -- Bump native-tls and openssl crates. [#5817](https://github.com/paritytech/parity/pull/5817) -- Public node using WASM [#5734](https://github.com/paritytech/parity/pull/5734) -- enforce block signer == author field in PoA [#5808](https://github.com/paritytech/parity/pull/5808) -- Fix stack display in evmbin. [#5733](https://github.com/paritytech/parity/pull/5733) -- Disable UI if it's not compiled in. [#5773](https://github.com/paritytech/parity/pull/5773) -- Require phrase confirmation. [#5731](https://github.com/paritytech/parity/pull/5731) -- Duration limit made optional for EthashParams [#5777](https://github.com/paritytech/parity/pull/5777) -- Update Changelog for 1.6.8 [#5798](https://github.com/paritytech/parity/pull/5798) -- Replace Ethcore comany name in T&C and some other places [#5796](https://github.com/paritytech/parity/pull/5796) -- PubSub for IPC. [#5800](https://github.com/paritytech/parity/pull/5800) -- Fix terminology distributed -> decentralized applications [#5797](https://github.com/paritytech/parity/pull/5797) -- Disable compression for RLP strings [#5786](https://github.com/paritytech/parity/pull/5786) -- update the source for the snapcraft package [#5781](https://github.com/paritytech/parity/pull/5781) -- Fixed default UI port for mac installer [#5782](https://github.com/paritytech/parity/pull/5782) -- Block invalid account name creation [#5784](https://github.com/paritytech/parity/pull/5784) -- Update Cid/multihash/ring/tinykeccak [#5785](https://github.com/paritytech/parity/pull/5785) -- use NULL_RLP, remove NULL_RLP_STATIC [#5742](https://github.com/paritytech/parity/pull/5742) -- Blacklist empty phrase account. [#5730](https://github.com/paritytech/parity/pull/5730) -- EIP-211 RETURNDATACOPY and RETURNDATASIZE [#5678](https://github.com/paritytech/parity/pull/5678) -- Bump mio [#5763](https://github.com/paritytech/parity/pull/5763) -- Fixing UI issues after UI server refactor [#5710](https://github.com/paritytech/parity/pull/5710) -- Fix WS server expose issue. [#5728](https://github.com/paritytech/parity/pull/5728) -- Fix local transactions without condition. [#5716](https://github.com/paritytech/parity/pull/5716) -- Bump parity-wordlist. [#5748](https://github.com/paritytech/parity/pull/5748) -- two small changes in evm [#5700](https://github.com/paritytech/parity/pull/5700) -- Evmbin: JSON format printing pre-state. [#5712](https://github.com/paritytech/parity/pull/5712) -- Recover from empty phrase in dev mode [#5698](https://github.com/paritytech/parity/pull/5698) -- EIP-210 BLOCKHASH changes [#5505](https://github.com/paritytech/parity/pull/5505) -- fixes typo [#5708](https://github.com/paritytech/parity/pull/5708) -- Bump rocksdb [#5707](https://github.com/paritytech/parity/pull/5707) -- Fixed --datadir option [#5697](https://github.com/paritytech/parity/pull/5697) -- rpc -> weak to arc [#5688](https://github.com/paritytech/parity/pull/5688) -- typo fix [#5699](https://github.com/paritytech/parity/pull/5699) -- Revamping parity-evmbin [#5696](https://github.com/paritytech/parity/pull/5696) -- Update dependencies and bigint api [#5685](https://github.com/paritytech/parity/pull/5685) -- UI server refactoring [#5580](https://github.com/paritytech/parity/pull/5580) -- Fix from/into electrum in ethkey [#5686](https://github.com/paritytech/parity/pull/5686) -- Add unit tests [#5668](https://github.com/paritytech/parity/pull/5668) -- Guanqun add unit tests [#5671](https://github.com/paritytech/parity/pull/5671) -- Parity-PubSub as a separate API. [#5676](https://github.com/paritytech/parity/pull/5676) -- EIP-140 REVERT opcode [#5477](https://github.com/paritytech/parity/pull/5477) -- Update CHANGELOG for 1.6.7 [#5683](https://github.com/paritytech/parity/pull/5683) -- Updated docs slightly. [#5674](https://github.com/paritytech/parity/pull/5674) -- Fix build [#5684](https://github.com/paritytech/parity/pull/5684) -- Back-references for the on-demand service [#5573](https://github.com/paritytech/parity/pull/5573) -- Dynamically adjust PIP request costs based on gathered data [#5603](https://github.com/paritytech/parity/pull/5603) -- use cargo workspace [#5601](https://github.com/paritytech/parity/pull/5601) -- Latest headers Pub-Sub [#5655](https://github.com/paritytech/parity/pull/5655) -- improved dockerfile builds [#5659](https://github.com/paritytech/parity/pull/5659) -- Adding CLI options: port shift and unsafe expose. [#5677](https://github.com/paritytech/parity/pull/5677) -- Report missing author in Aura [#5583](https://github.com/paritytech/parity/pull/5583) -- typo fix [#5669](https://github.com/paritytech/parity/pull/5669) -- Remove public middleware (temporary) [#5665](https://github.com/paritytech/parity/pull/5665) -- Remove additional polyfill [#5663](https://github.com/paritytech/parity/pull/5663) -- Importing accounts from files. [#5644](https://github.com/paritytech/parity/pull/5644) -- remove the deprecated options in rustfmt.toml [#5616](https://github.com/paritytech/parity/pull/5616) -- Update the Console dapp [#5602](https://github.com/paritytech/parity/pull/5602) -- Create an account for chain=dev [#5612](https://github.com/paritytech/parity/pull/5612) -- Use babel-runtime as opposed to babel-polyfill [#5662](https://github.com/paritytech/parity/pull/5662) -- Connection dialog timestamp info [#5554](https://github.com/paritytech/parity/pull/5554) -- use copy_from_slice instead of for loop [#5647](https://github.com/paritytech/parity/pull/5647) -- Light friendly dapps [#5634](https://github.com/paritytech/parity/pull/5634) -- Add Recover button to Accounts and warnings [#5645](https://github.com/paritytech/parity/pull/5645) -- Update eth_sign docs. [#5631](https://github.com/paritytech/parity/pull/5631) -- Proper signer Pub-Sub for pending requests. [#5594](https://github.com/paritytech/parity/pull/5594) -- Bump bigint to 1.0.5 [#5641](https://github.com/paritytech/parity/pull/5641) -- PoA warp implementation [#5488](https://github.com/paritytech/parity/pull/5488) -- Improve on-demand dispatch and add support for batch requests [#5419](https://github.com/paritytech/parity/pull/5419) -- Use default account for sending transactions [#5588](https://github.com/paritytech/parity/pull/5588) -- Add peer management to the Status tab [#5566](https://github.com/paritytech/parity/pull/5566) -- Add monotonic step transition [#5587](https://github.com/paritytech/parity/pull/5587) -- Decrypting for external accounts. [#5581](https://github.com/paritytech/parity/pull/5581) -- only enable warp sync when engine supports it [#5595](https://github.com/paritytech/parity/pull/5595) -- fix the doc of installing rust [#5586](https://github.com/paritytech/parity/pull/5586) -- Small fixes [#5584](https://github.com/paritytech/parity/pull/5584) -- SecretStore: remove session on master node [#5545](https://github.com/paritytech/parity/pull/5545) -- run-clean [#5607](https://github.com/paritytech/parity/pull/5607) -- relicense RLP to MIT/Apache2 [#5591](https://github.com/paritytech/parity/pull/5591) -- Fix eth_sign signature encoding. [#5597](https://github.com/paritytech/parity/pull/5597) -- Check pending request on Node local transactions [#5564](https://github.com/paritytech/parity/pull/5564) -- Add tooltips on ActionBar [#5562](https://github.com/paritytech/parity/pull/5562) -- Can't deploy without compiling Contract [#5593](https://github.com/paritytech/parity/pull/5593) -- Add a warning when node is syncing [#5565](https://github.com/paritytech/parity/pull/5565) -- Update registry middleware [#5585](https://github.com/paritytech/parity/pull/5585) -- Set block condition to BigNumber in MethodDecoding [#5592](https://github.com/paritytech/parity/pull/5592) -- Load the sources immediately in Contract Dev [#5575](https://github.com/paritytech/parity/pull/5575) -- Remove formal verification messages in Dev Contract [#5574](https://github.com/paritytech/parity/pull/5574) -- Fix event params decoding when no names for parameters [#5567](https://github.com/paritytech/parity/pull/5567) -- Do not convert to Dates twice [#5563](https://github.com/paritytech/parity/pull/5563) -- Fix Multisig wallet settings [#5560](https://github.com/paritytech/parity/pull/5560) -- Typo [#5547](https://github.com/paritytech/parity/pull/5547) -- Generic PubSub implementation [#5456](https://github.com/paritytech/parity/pull/5456) -- Fix CI paths. [#5570](https://github.com/paritytech/parity/pull/5570) -- reorg into blocks before minimum history [#5558](https://github.com/paritytech/parity/pull/5558) -- EIP-86 update [#5506](https://github.com/paritytech/parity/pull/5506) -- Secretstore RPCs + integration [#5439](https://github.com/paritytech/parity/pull/5439) -- Fixes Parity Bar position [#5557](https://github.com/paritytech/parity/pull/5557) -- Fixes invalid log in BadgeReg events [#5556](https://github.com/paritytech/parity/pull/5556) -- Fix issues in Contract Development view [#5555](https://github.com/paritytech/parity/pull/5555) -- Added missing methods [#5542](https://github.com/paritytech/parity/pull/5542) -- option to disable persistent txqueue [#5544](https://github.com/paritytech/parity/pull/5544) -- Bump jsonrpc [#5552](https://github.com/paritytech/parity/pull/5552) -- Retrieve block headers only for header-only info [#5480](https://github.com/paritytech/parity/pull/5480) -- add snap to CI [#5519](https://github.com/paritytech/parity/pull/5519) -- Pass additional data when reporting [#5527](https://github.com/paritytech/parity/pull/5527) -- Calculate post-constructors state root in spec at load time [#5523](https://github.com/paritytech/parity/pull/5523) -- Fix utf8 decoding [#5533](https://github.com/paritytech/parity/pull/5533) -- Add CHANGELOG.md [#5513](https://github.com/paritytech/parity/pull/5513) -- Change all occurrences of ethcore.io into parity.io [#5528](https://github.com/paritytech/parity/pull/5528) -- Memory usage optimization [#5526](https://github.com/paritytech/parity/pull/5526) -- Compose transaction RPC. [#5524](https://github.com/paritytech/parity/pull/5524) -- Support external eth_sign [#5481](https://github.com/paritytech/parity/pull/5481) -- Treat block numbers as strings, not BigNums. [#5449](https://github.com/paritytech/parity/pull/5449) -- npm cleanups [#5512](https://github.com/paritytech/parity/pull/5512) -- Export acc js [#4973](https://github.com/paritytech/parity/pull/4973) -- YARN [#5395](https://github.com/paritytech/parity/pull/5395) -- Fix linting issues [#5511](https://github.com/paritytech/parity/pull/5511) -- Chinese Translation [#5460](https://github.com/paritytech/parity/pull/5460) -- Fixing secretstore TODOs - part 2 [#5416](https://github.com/paritytech/parity/pull/5416) -- fix json format of state snapshot [#5504](https://github.com/paritytech/parity/pull/5504) -- Bump jsonrpc version [#5489](https://github.com/paritytech/parity/pull/5489) -- Groundwork for generalized warp sync [#5454](https://github.com/paritytech/parity/pull/5454) -- Add the packaging metadata to build the parity snap [#5496](https://github.com/paritytech/parity/pull/5496) -- Cancel tx JS [#4958](https://github.com/paritytech/parity/pull/4958) -- EIP-212 (bn128 curve pairing) [#5307](https://github.com/paritytech/parity/pull/5307) -- fix panickers in tree-route [#5479](https://github.com/paritytech/parity/pull/5479) -- Update links to etherscan.io [#5455](https://github.com/paritytech/parity/pull/5455) -- Refresh UI on nodeKind changes, e.g. personal -> public [#5312](https://github.com/paritytech/parity/pull/5312) -- Correct contract address for EIP-86 [#5473](https://github.com/paritytech/parity/pull/5473) -- Force two decimals for USD conversion rate [#5471](https://github.com/paritytech/parity/pull/5471) -- Refactoring of Tokens & Balances [#5372](https://github.com/paritytech/parity/pull/5372) -- Background-repeat round [#5475](https://github.com/paritytech/parity/pull/5475) -- nl i18n updated [#5461](https://github.com/paritytech/parity/pull/5461) -- Show ETH value (even 0) if ETH transfer in transaction list [#5406](https://github.com/paritytech/parity/pull/5406) -- Store the pending requests per network version [#5405](https://github.com/paritytech/parity/pull/5405) -- Use in-memory database for tests [#5451](https://github.com/paritytech/parity/pull/5451) -- WebSockets RPC server [#5425](https://github.com/paritytech/parity/pull/5425) -- Added missing docs [#5452](https://github.com/paritytech/parity/pull/5452) -- Tests and tweaks for public node middleware [#5417](https://github.com/paritytech/parity/pull/5417) -- Fix removal of hash-mismatched files. [#5440](https://github.com/paritytech/parity/pull/5440) -- parity_getBlockHeaderByNumber and LightFetch utility [#5383](https://github.com/paritytech/parity/pull/5383) -- New state tests [#5418](https://github.com/paritytech/parity/pull/5418) -- Fix buffer length for QR code gen. [#5447](https://github.com/paritytech/parity/pull/5447) -- Add raw hash signing [#5423](https://github.com/paritytech/parity/pull/5423) -- Filters and block RPCs for the light client [#5320](https://github.com/paritytech/parity/pull/5320) -- Work around mismatch for QR checksum [#5374](https://github.com/paritytech/parity/pull/5374) -- easy to use conversion from and to string for ethstore::Crypto [#5437](https://github.com/paritytech/parity/pull/5437) -- Tendermint fixes [#5415](https://github.com/paritytech/parity/pull/5415) -- Adrianbrink lightclientcache branch. [#5428](https://github.com/paritytech/parity/pull/5428) -- Add caching to HeaderChain struct [#5403](https://github.com/paritytech/parity/pull/5403) -- Add decryption to the UI (in the Signer) [#5422](https://github.com/paritytech/parity/pull/5422) -- Add CIDv0 RPC [#5414](https://github.com/paritytech/parity/pull/5414) -- Updating documentation for RPCs [#5392](https://github.com/paritytech/parity/pull/5392) -- Fixing secretstore TODOs - part 1 [#5386](https://github.com/paritytech/parity/pull/5386) -- Fixing disappearing content. [#5399](https://github.com/paritytech/parity/pull/5399) -- Snapshot chunks packed by size [#5318](https://github.com/paritytech/parity/pull/5318) -- APIs wildcards and simple arithmetic. [#5402](https://github.com/paritytech/parity/pull/5402) -- Fixing compilation without dapps. [#5410](https://github.com/paritytech/parity/pull/5410) -- Don't use port 8080 anymore [#5397](https://github.com/paritytech/parity/pull/5397) -- Quick'n'dirty CLI for the light client [#5002](https://github.com/paritytech/parity/pull/5002) -- set gas limit before proving transactions [#5401](https://github.com/paritytech/parity/pull/5401) -- Public node: perf and fixes [#5390](https://github.com/paritytech/parity/pull/5390) -- Straight download path in the readme [#5393](https://github.com/paritytech/parity/pull/5393) -- On-chain ACL checker for secretstore [#5015](https://github.com/paritytech/parity/pull/5015) -- Allow empty-encoded values from QR encoding [#5385](https://github.com/paritytech/parity/pull/5385) -- Update npm build for new inclusions [#5381](https://github.com/paritytech/parity/pull/5381) -- Fix for Ubuntu Dockerfile [#5356](https://github.com/paritytech/parity/pull/5356) -- Secretstore over network [#4974](https://github.com/paritytech/parity/pull/4974) -- Dapps and RPC server merge [#5365](https://github.com/paritytech/parity/pull/5365) -- trigger js build release [#5379](https://github.com/paritytech/parity/pull/5379) -- Update expanse json with fork at block 600000 [#5351](https://github.com/paritytech/parity/pull/5351) -- Futures-based native wrappers for contract ABIs [#5341](https://github.com/paritytech/parity/pull/5341) -- Kovan warp sync fixed [#5337](https://github.com/paritytech/parity/pull/5337) -- Aura eip155 validation transition [#5362](https://github.com/paritytech/parity/pull/5362) -- Shared wordlist for brain wallets [#5331](https://github.com/paritytech/parity/pull/5331) -- Allow signing via Qr [#4881](https://github.com/paritytech/parity/pull/4881) -- Allow entry of url or hash for DappReg meta [#5360](https://github.com/paritytech/parity/pull/5360) -- Adjust tx overlay colours [#5353](https://github.com/paritytech/parity/pull/5353) -- Add ability to disallow API subscriptions [#5366](https://github.com/paritytech/parity/pull/5366) -- EIP-213 (bn128 curve operations) [#4999](https://github.com/paritytech/parity/pull/4999) -- Fix analize output file name [#5357](https://github.com/paritytech/parity/pull/5357) -- Add default eip155 validation [#5346](https://github.com/paritytech/parity/pull/5346) -- Add new seed nodes for Classic chain [#5345](https://github.com/paritytech/parity/pull/5345) -- Shared wordlist for frontend [#5336](https://github.com/paritytech/parity/pull/5336) -- fix rpc tests [#5338](https://github.com/paritytech/parity/pull/5338) -- Public node with accounts and signing in Frontend [#5304](https://github.com/paritytech/parity/pull/5304) -- Rename Status/Status -> Status/NodeStatus [#5332](https://github.com/paritytech/parity/pull/5332) -- Updating paths to repos. [#5330](https://github.com/paritytech/parity/pull/5330) -- Separate status for canceled local transactions. [#5319](https://github.com/paritytech/parity/pull/5319) -- Cleanup the Status View [#5317](https://github.com/paritytech/parity/pull/5317) -- Update UI minimised requests [#5324](https://github.com/paritytech/parity/pull/5324) -- Order signer transactions FIFO [#5321](https://github.com/paritytech/parity/pull/5321) -- updating dependencies [#5028](https://github.com/paritytech/parity/pull/5028) -- Minimise transactions progress [#4942](https://github.com/paritytech/parity/pull/4942) -- Fix eth_sign showing as wallet account [#5309](https://github.com/paritytech/parity/pull/5309) -- Ropsten revival [#5302](https://github.com/paritytech/parity/pull/5302) -- Strict validation transitions [#4988](https://github.com/paritytech/parity/pull/4988) -- Fix default list sorting [#5303](https://github.com/paritytech/parity/pull/5303) -- Use unique owners for multisig wallets [#5298](https://github.com/paritytech/parity/pull/5298) -- Copy all existing i18n strings into zh (as-is translation aid) [#5305](https://github.com/paritytech/parity/pull/5305) -- Fix booleans in Typedinput [#5295](https://github.com/paritytech/parity/pull/5295) -- node kind RPC [#5025](https://github.com/paritytech/parity/pull/5025) -- Fix the use of MobX in playground [#5294](https://github.com/paritytech/parity/pull/5294) -- Fine grained snapshot chunking [#5019](https://github.com/paritytech/parity/pull/5019) -- Add lint:i18n to find missing & extra keys [#5290](https://github.com/paritytech/parity/pull/5290) -- Scaffolding for zh translations, including first-round by @btceth [#5289](https://github.com/paritytech/parity/pull/5289) -- JS package bumps [#5287](https://github.com/paritytech/parity/pull/5287) -- Auto-extract new i18n strings (update) [#5288](https://github.com/paritytech/parity/pull/5288) -- eip100b [#5027](https://github.com/paritytech/parity/pull/5027) -- Set earliest era in snapshot restoration [#5021](https://github.com/paritytech/parity/pull/5021) -- Avoid clogging up tmp when updater dir has bad permissions. [#5024](https://github.com/paritytech/parity/pull/5024) -- Resilient warp sync [#5018](https://github.com/paritytech/parity/pull/5018) -- Create webpack analysis files (size) [#5009](https://github.com/paritytech/parity/pull/5009) -- Dispatch an open event on drag of Parity Bar [#4987](https://github.com/paritytech/parity/pull/4987) -- Various installer and tray apps fixes [#4970](https://github.com/paritytech/parity/pull/4970) -- Export account RPC [#4967](https://github.com/paritytech/parity/pull/4967) -- Switching ValidatorSet [#4961](https://github.com/paritytech/parity/pull/4961) -- Implement PIP messages, request builder, and handlers [#4945](https://github.com/paritytech/parity/pull/4945) -- auto lint [#5003](https://github.com/paritytech/parity/pull/5003) -- Fix FireFox overflows [#5000](https://github.com/paritytech/parity/pull/5000) -- Show busy indicator, focus first field in password change [#4997](https://github.com/paritytech/parity/pull/4997) -- Consistent store naming in the Signer components [#4996](https://github.com/paritytech/parity/pull/4996) -- second (and last) part of rlp refactor [#4901](https://github.com/paritytech/parity/pull/4901) -- Double click to select account creation type [#4986](https://github.com/paritytech/parity/pull/4986) -- Fixes to the Registry dapp [#4984](https://github.com/paritytech/parity/pull/4984) -- Extend api.util [#4979](https://github.com/paritytech/parity/pull/4979) -- Updating JSON-RPC crates [#4934](https://github.com/paritytech/parity/pull/4934) -- splitting part of util into smaller crates [#4956](https://github.com/paritytech/parity/pull/4956) -- Updating syntex et al [#4983](https://github.com/paritytech/parity/pull/4983) -- EIP198 and built-in activation [#4926](https://github.com/paritytech/parity/pull/4926) -- Fix MethodDecoding for Arrays [#4977](https://github.com/paritytech/parity/pull/4977) -- Try to fix WS race condition connection [#4976](https://github.com/paritytech/parity/pull/4976) -- eth_sign where account === undefined [#4964](https://github.com/paritytech/parity/pull/4964) -- Fix references to api outside of `parity.js` [#4981](https://github.com/paritytech/parity/pull/4981) -- Fix Password Dialog form overflow [#4968](https://github.com/paritytech/parity/pull/4968) -- Changing Mutex into RwLock for transaction queue [#4951](https://github.com/paritytech/parity/pull/4951) -- Disable max seal period for external sealing [#4927](https://github.com/paritytech/parity/pull/4927) -- Attach hardware wallets already in addressbook [#4912](https://github.com/paritytech/parity/pull/4912) -- rlp serialization refactor [#4873](https://github.com/paritytech/parity/pull/4873) -- Bump nanomsg [#4965](https://github.com/paritytech/parity/pull/4965) -- Fixed multi-chunk ledger transactions on windows [#4960](https://github.com/paritytech/parity/pull/4960) -- Fix outputs in Contract Constant Queries [#4953](https://github.com/paritytech/parity/pull/4953) -- systemd: Start parity after network.target [#4952](https://github.com/paritytech/parity/pull/4952) -- Remove transaction RPC [#4949](https://github.com/paritytech/parity/pull/4949) -- Swap out ethcore.io url for parity.io [#4947](https://github.com/paritytech/parity/pull/4947) -- Don't remove confirmed requests to early. [#4933](https://github.com/paritytech/parity/pull/4933) -- Ensure sealing work enabled in miner once subscribers added [#4930](https://github.com/paritytech/parity/pull/4930) -- Add z-index to small modals as well [#4923](https://github.com/paritytech/parity/pull/4923) -- Bump nanomsg [#4946](https://github.com/paritytech/parity/pull/4946) -- Bumping multihash and libc [#4943](https://github.com/paritytech/parity/pull/4943) -- Edit ETH value, gas and gas price in Contract Deployment [#4919](https://github.com/paritytech/parity/pull/4919) -- Add ability to configure Secure API [#4922](https://github.com/paritytech/parity/pull/4922) -- Add Token image from URL [#4916](https://github.com/paritytech/parity/pull/4916) -- Use the registry fee in Token Deployment dapp [#4915](https://github.com/paritytech/parity/pull/4915) -- Add reseal max period [#4903](https://github.com/paritytech/parity/pull/4903) -- Detect rust compiler version in Parity build script, closes 4742 [#4907](https://github.com/paritytech/parity/pull/4907) -- Add Vaults logic to First Run [#4914](https://github.com/paritytech/parity/pull/4914) -- Updated gcc and rayon crates to remove outdated num_cpus dependency [#4909](https://github.com/paritytech/parity/pull/4909) -- Renaming evm binary to avoid conflicts. [#4899](https://github.com/paritytech/parity/pull/4899) -- Better error handling for traces RPC [#4849](https://github.com/paritytech/parity/pull/4849) -- Safari SectionList fix [#4895](https://github.com/paritytech/parity/pull/4895) -- Safari Dialog scrolling fix [#4893](https://github.com/paritytech/parity/pull/4893) -- Spelling :) [#4900](https://github.com/paritytech/parity/pull/4900) -- Additional kovan params [#4892](https://github.com/paritytech/parity/pull/4892) -- trigger js-precompiled build [#4898](https://github.com/paritytech/parity/pull/4898) -- Recalculate receipt roots in close_and_lock [#4884](https://github.com/paritytech/parity/pull/4884) -- Reload UI on network switch [#4864](https://github.com/paritytech/parity/pull/4864) -- Update parity-ui-precompiled with branch [#4850](https://github.com/paritytech/parity/pull/4850) -- OSX Installer is no longer experimental [#4882](https://github.com/paritytech/parity/pull/4882) -- Chain-selection from UI [#4859](https://github.com/paritytech/parity/pull/4859) -- removed redundant (and unused) FromJson trait [#4871](https://github.com/paritytech/parity/pull/4871) -- fix typos and grammar [#4880](https://github.com/paritytech/parity/pull/4880) -- Remove old experimental remote-db code [#4872](https://github.com/paritytech/parity/pull/4872) -- removed redundant FixedHash trait, fixes [#4029](https://github.com/paritytech/parity/issues/4029) [#4866](https://github.com/paritytech/parity/pull/4866) -- Reference JSON-RPC more changes-friendly [#4870](https://github.com/paritytech/parity/pull/4870) -- Better handling of Solidity compliation [#4860](https://github.com/paritytech/parity/pull/4860) -- Go through contract links in Transaction List display [#4863](https://github.com/paritytech/parity/pull/4863) -- Fix Gas Price Selector Tooltips [#4865](https://github.com/paritytech/parity/pull/4865) -- Fix auto-updater [#4867](https://github.com/paritytech/parity/pull/4867) -- Make the UI work offline [#4861](https://github.com/paritytech/parity/pull/4861) -- Subscribe to accounts info in Signer / ParityBar [#4856](https://github.com/paritytech/parity/pull/4856) -- Don't link libsnappy explicitly [#4841](https://github.com/paritytech/parity/pull/4841) -- Fix paste in Inputs [#4854](https://github.com/paritytech/parity/pull/4854) -- Extract i18n from shared UI components [#4834](https://github.com/paritytech/parity/pull/4834) -- Fix paste in Inputs [#4844](https://github.com/paritytech/parity/pull/4844) -- Pull contract deployment title from available steps [#4848](https://github.com/paritytech/parity/pull/4848) -- Supress USB error message [#4839](https://github.com/paritytech/parity/pull/4839) -- Fix getTransactionCount in --geth mode [#4837](https://github.com/paritytech/parity/pull/4837) -- CI: test coverage (for core and js) [#4832](https://github.com/paritytech/parity/pull/4832) -- Lowering threshold for transactions above gas limit [#4831](https://github.com/paritytech/parity/pull/4831) -- Fix TxViewer when no `to` (contract deployment) [#4847](https://github.com/paritytech/parity/pull/4847) -- Fix method decoding [#4845](https://github.com/paritytech/parity/pull/4845) -- Add React Hot Reload to dapps + TokenDeploy fix [#4846](https://github.com/paritytech/parity/pull/4846) -- Dapps show multiple times in some cases [#4843](https://github.com/paritytech/parity/pull/4843) -- Fixes to the Registry dapp [#4838](https://github.com/paritytech/parity/pull/4838) -- Show token icons on list summary pages [#4826](https://github.com/paritytech/parity/pull/4826) -- Calibrate step before rejection [#4800](https://github.com/paritytech/parity/pull/4800) -- Add replay protection [#4808](https://github.com/paritytech/parity/pull/4808) -- Better icon on windows [#4804](https://github.com/paritytech/parity/pull/4804) -- Better logic for contract deployments detection [#4821](https://github.com/paritytech/parity/pull/4821) -- Fix wrong default values for contract queries inputs [#4819](https://github.com/paritytech/parity/pull/4819) -- Adjust selection colours/display [#4811](https://github.com/paritytech/parity/pull/4811) -- Update the Wallet Library Registry key [#4817](https://github.com/paritytech/parity/pull/4817) -- Update Wallet to new Wallet Code [#4805](https://github.com/paritytech/parity/pull/4805) +To reactivate the parity wallet, you have to run Parity either with `parity --force-ui` (not recommended) or `parity ui` (deprecated) from the command line. Or, if you feel super fancy and want to test our pre-releases of the stand-alone electron wallet, head over to the [Parity-JS repositories and check the releases](https://github.com/Parity-JS/shell/releases). -## Parity [v1.6.10](https://github.com/paritytech/parity/releases/tag/v1.6.10) (2017-07-25) +Further reading: -This is a hotfix release for the stable channel addressing the recent [multi-signature wallet vulnerability](https://blog.parity.io/security-alert-high-2/). Note, upgrading is not mandatory, and all future multi-sig wallets created by any version of Parity are secure. +- [Docs: Parity Wallet](https://wiki.parity.io/Parity-Wallet) +- [Docs: How to customize Parity UI?](https://wiki.parity.io/FAQ-Customize-Parity-UI.html) +- [Github: Parity-JS](https://github.com/parity-js) -All Changes: +### Introducing the Wasm VM -- Backports for stable [#6116](https://github.com/paritytech/parity/pull/6116) - - Remove chunk to restore from pending set only upon successful import [#6112](https://github.com/paritytech/parity/pull/6112) - - Blacklist bad snapshot manifest hashes upon failure [#5874](https://github.com/paritytech/parity/pull/5874) - - Bump snap version and tweak importing detection logic [#6079](https://github.com/paritytech/parity/pull/6079) (modified to work) -- Fix docker build for stable [#6118](https://github.com/paritytech/parity/pull/6118) -- Update wallet library binaries [#6108](https://github.com/paritytech/parity/pull/6108) -- Backported wallet fix [#6104](https://github.com/paritytech/parity/pull/6104) - - Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102)) - - Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103)) -- Bump to v1.6.10 +We are excited to announce support for **Wasm Smart Contracts on Kovan network**. The hard-fork to activate the Wasm-VM will take place on block `6_600_000`. -## Parity [v1.6.9](https://github.com/paritytech/parity/releases/tag/v1.6.9) (2017-07-16) +To enable Wasm contracts on your custom network, just schedule a `wasmActivationTransition` at your favorite block number (e.g., `42`, `666`, or `0xbada55`). To hack your first Wasm smart contracts in Rust, have a look at the [Parity Wasm Tutorials](https://github.com/paritytech/pwasm-tutorial). -This is a first stable release of 1.6 series. It contains a number of minor fixes and introduces the `--reseal-on-uncles` option for miners. +Further reading: -Full list of changes: +- [Docs: WebAssembly (wasm)](https://wiki.parity.io/WebAssembly-Home) +- [Docs: Wasm VM Design](https://wiki.parity.io/WebAssembly-Design) +- [Docs: Wasm tutorials and examples](https://wiki.parity.io/WebAssembly-Links) -- Backports [#6061](https://github.com/paritytech/parity/pull/6061) - - Ethereum Classic Monetary Policy [#5741](https://github.com/paritytech/parity/pull/5741) - - Update rewards for uncle miners for ECIP1017 - - Fix an off-by-one error in ECIP1017 era calculation - - `ecip1017_era_rounds` missing from EthashParams when run in build bot - - strip out ecip1017_eras_block_reward function and add unit test - - JS precompiled set to stable -- Backports [#6060](https://github.com/paritytech/parity/pull/6060) - - --reseal-on-uncle [#5940](https://github.com/paritytech/parity/pull/5940) - - Optimized uncle check - - Additional uncle check - - Updated comment - - Bump to v1.6.9 - - CLI: Export error message and less verbose peer counter. [#5870](https://github.com/paritytech/parity/pull/5870) - - Removed numbed of active connections from informant - - Print error message when fatdb is required - - Remove peers from UI +### Empty step messages in PoA -## Parity [v1.6.8](https://github.com/paritytech/parity/releases/tag/v1.6.8) (2017-06-08) +To **reduce blockchain bloat, proof-of-authority networks can now enable _empty step messages_ which replace empty blocks**. Each step message will be signed and broadcasted by the issuing authorities, and included and rewarded in the next non-empty block. -This release addresses: +To enable empty step messages, set the `emptyStepsTransition` to your favorite block number. You can also specify a maximum number of empty steps with `maximumEmptySteps` in your chain spec. -- a rare condition where quickly creating a new account was generating an account not matching the recovery phrase. -- compressed RLP strings caused wrong/empty transaction receipts on Classic network. -- blacklisting the _empty phrase_ account from UI and RPC on non-development chains. See also [this blog post](https://blog.parity.io/restoring-blank-seed-phrase/). -- canceling transactions that didn't have a condition. -- the updated Expanse fork block and chain ID. +### Other noteworthy changes -Full changelog: +We removed the old database migrations from 2016. In case you upgrade Parity from a really, really old version, you will have to reset your database manually first with `parity db kill`. -- Backporting to beta [#5791](https://github.com/paritytech/parity/pull/5791) - - Bump to v1.6.8 - - Update expanse json with fork at block 600000 [#5351](https://github.com/paritytech/parity/pull/5351) - - Update expanse json with fork at block 600000 - - Update exp chainID to 2 - - Bumped mio [#5763](https://github.com/paritytech/parity/pull/5763) - - Fixed default UI port for mac installer [#5782](https://github.com/paritytech/parity/pull/5782) - - Blacklist empty phrase account. [#5730](https://github.com/paritytech/parity/pull/5730) - - Update Cid/multihash/ring/tinykeccak [#5785](https://github.com/paritytech/parity/pull/5785) - - Updating ring,multihash,tiny-keccak - - Updating CID in ipfs. - - Disable compression for RLP strings [#5786](https://github.com/paritytech/parity/pull/5786) -- Beta Backports [#5789](https://github.com/paritytech/parity/pull/5789) - - Fix local transactions without condition. [#5716](https://github.com/paritytech/parity/pull/5716) - - Block invalid account name creation [#5784](https://github.com/paritytech/parity/pull/5784) - - Additional non-empty phrase check (fromNew) - - Explicit canCreate check in create (not only on UI) - - BN instance check (fixes Geth imports) - - Fixup tests after better checks - - Recover from empty phrase in dev mode [#5698](https://github.com/paritytech/parity/pull/5698) - - Add dev chain to isTest - - Fix signer - - Fix no condition transactions - - Fix case: old parity - - Fix propTypes. +We fixed DELEGATECALL `from` and `to` fields, see [#7166](https://github.com/paritytech/parity/issues/7166). -## Parity [v1.6.7](https://github.com/paritytech/parity/releases/tag/v1.6.7) (2017-05-18) +We reduced the default USD per transaction value to 0.0001. Thanks, @MysticRyuujin! -This release addresses: +The Musicoin chain is now enabled with Byzantium features starting at block `2_222_222`. -- potential usability issues with [import and recovery of existing accounts](https://blog.parity.io/restoring-blank-seed-phrase/). -- canceling scheduled transactions via RPC or UI. -- warp sync issues with the Kovan network. +### Overview of all changes included -Full changelog: +The full list of included changes: -- Backporting to beta [#5657](https://github.com/paritytech/parity/pull/5657) - - Add CHANGELOG.md [#5513](https://github.com/paritytech/parity/pull/5513) - - Reorg into blocks before minimum history [#5558](https://github.com/paritytech/parity/pull/5558) - - Bump to v1.6.7 -- Cancel Transaction [#5656](https://github.com/paritytech/parity/pull/5656) - - option to disable persistent txqueue [#5544](https://github.com/paritytech/parity/pull/5544) - - Remove transaction RPC [#4949](https://github.com/paritytech/parity/pull/4949) - - Cancel tx JS [#4958](https://github.com/paritytech/parity/pull/4958) - - Updating documentation for RPCs [#5392](https://github.com/paritytech/parity/pull/5392) -- Backport Recover button [#5654](https://github.com/paritytech/parity/pull/5654) - - Backport [#5645](https://github.com/paritytech/parity/pull/5645) -- Add monotonic step to Kovan [#5630](https://github.com/paritytech/parity/pull/5630) - - Add monotonic transition to kovan [#5587](https://github.com/paritytech/parity/pull/5587) -- Fix ethsign [#5600](https://github.com/paritytech/parity/pull/5600) -- Registry backports [#5445](https://github.com/paritytech/parity/pull/5445) - - Fixes to the Registry dapp [#4984](https://github.com/paritytech/parity/pull/4984) - - Fix references to api outside of `parity.js` [#4981](https://github.com/paritytech/parity/pull/4981) - -## Parity [v1.6.6](https://github.com/paritytech/parity/releases/tag/v1.6.6) (2017-04-11) - -This release brings warp sync support for kovan network. - -- Beta Backports [#5434](https://github.com/paritytech/parity/pull/5434) - - Bump to v1.6.6 - - Strict validation transitions [#4988](https://github.com/paritytech/parity/pull/4988) - - Ability to make validation stricter - - Fix consensus - - Remove logger - - Fix eth_sign showing as wallet account [#5309](https://github.com/paritytech/parity/pull/5309) - - DefaultProps for account - - Pass signing account - - Update tests for Connect(...) - - Add new seed nodes [#5345](https://github.com/paritytech/parity/pull/5345) - - Kovan warp sync fixed -- Aura eip155 validation transition [#5363](https://github.com/paritytech/parity/pull/5363) - - Add eip155 validation - - Add transition block -- Default eip155 validation [#5350](https://github.com/paritytech/parity/pull/5350) -- Backport syntax libs update [#5316](https://github.com/paritytech/parity/pull/5316) - -## Parity [v1.6.5](https://github.com/paritytech/parity/releases/tag/v1.6.5) (2017-03-28) - -This release contains the following changes: - -- Warp sync snapshot format improvements. -- Fix for Firefox UI issues. -- Fix for restoring from a file snapshot. -- Fix for auto-updater error handling. -- Updated configuration for [Ropsten revival](https://github.com/ethereum/ropsten/blob/master/revival.md). Make sure to delete old Ropsten blockchain first with `parity db kill --chain ropsten`. After that you can sync normally with `parity --chain ropsten`. - -Full changes: - -- Beta Backports [#5299](https://github.com/paritytech/parity/pull/5299) - - Fix FireFox overflows [#5000](https://github.com/paritytech/parity/pull/5000) - - Max width for container - - Set min-width - - Switching ValidatorSet [#4961](https://github.com/paritytech/parity/pull/4961) - - Add multi validator set - - Nicer comment - - Validate in constructor - - Reporting - - Avoid clogging up tmp when updater dir has bad permissions. [#5024](https://github.com/paritytech/parity/pull/5024) - - Force earliest era set in snapshot restore [#5021](https://github.com/paritytech/parity/pull/5021) - - Bumb to v1.6.5 - - Fine grained snapshot chunking - - Ropsten revival -- Fix validator contract syncing [#4789](https://github.com/paritytech/parity/pull/4789) [#5011](https://github.com/paritytech/parity/pull/5011) - - Make validator set aware of various states - - Fix updater build - - Clean up contract call - - Failing sync test - - Adjust tests - - Nicer indent - - Revert bound divisor - -## Parity [v1.5.12](https://github.com/paritytech/parity/releases/tag/v1.5.12) (2017-03-27) - -Stable release that adds support for a new warp sync snapshot format. - -- Stable Backports [#5297](https://github.com/paritytech/parity/pull/5297) - - Bump to v1.5.12 - - Fine grained snapshot chunking - -## Parity [v1.6.4](https://github.com/paritytech/parity/releases/tag/v1.6.4) (2017-03-22) - -A number of issues fixed in this release: - -- Ledger device connectivity issues for some users on Windows. -- Improved vault usability. -- Stratum mining no longer requires `--force-sealing`. -- `evm` binary has been renamed to `parity-evm` to avoid conflict with cpp-ethereum package. - -Full Changes: - -- Backporting to beta [#4995](https://github.com/paritytech/parity/pull/4995) - - Bump to v1.6.4 - - Ensure sealing work enabled if notifier registed - - Fix condition check - - Always send full chunks [#4960](https://github.com/paritytech/parity/pull/4960) - - Bump nanomsg [#4965](https://github.com/paritytech/parity/pull/4965) - - Renaming evm binary to avoid conflicts. [#4899](https://github.com/paritytech/parity/pull/4899) -- Beta UI backports [#4993](https://github.com/paritytech/parity/pull/4993) - - Update js-precompiled 20170314-121823 - - Attach hardware wallets already in addressbook [#4912](https://github.com/paritytech/parity/pull/4912) - - Attach hardware wallets already in addressbook - - Only set values changed - - Add Vaults logic to First Run [#4894](https://github.com/paritytech/parity/issues/4894) [#4914](https://github.com/paritytech/parity/pull/4914) - - Add ability to configure Secure API (for [#4885](https://github.com/paritytech/parity/issues/4885)) [#4922](https://github.com/paritytech/parity/pull/4922) - - Add z-index to small modals as well [#4923](https://github.com/paritytech/parity/pull/4923) - - Eth_sign where account === undefined [#4964](https://github.com/paritytech/parity/pull/4964) - - Update for case where account === undefined - - Update tests to not mask account === undefined - - Default account = {} where undefined (thanks [@tomusdrw](https://github.com/tomusdrw)) - - Fix Password Dialog forms style issue [#4968](https://github.com/paritytech/parity/pull/4968) - - -## Parity [v1.6.3](https://github.com/paritytech/parity/releases/tag/v1.6.3) (2017-03-14) - -This release fixes issue compatibility with Safari on MacOS. - -- Safari fixes [#4902](https://github.com/paritytech/parity/pull/4902) - - Add intitial max-width to sections - - Move background z-index to -1 - -## Parity [v1.5.11](https://github.com/paritytech/parity/releases/tag/v1.5.11) (2017-03-14) - -Parity 1.5.11 Includes a patch for a more comprehensive block verification. - -- Bump to v1.5.11 -- Additional kovan params -- Recalculate receipt roots in close_and_lock -- Bump to v1.5.10 - -## Parity [v1.6.2](https://github.com/paritytech/parity/releases/tag/v1.6.2) (2017-03-13) - -A major release introducing a few new features: - -- Revamped UI. -- Account Vaults. -- Support for Ledger hardware wallet devices. -- Stratum protocol for PoW mining. -- A new MacOS installer. Parity for MacOS now includes a Menu Bar icon that allows controlling Parity service. -- Disk backed transaction store. Pending transactions are now saved to disk and won't get lost when Parity is restarted. -- Improved memory management. - -See the [blog post](https://blog.parity.io/announcing-parity-1-6/) for more details. - -Full Changes: - -- Fix auto-updater beta [#4868](https://github.com/paritytech/parity/pull/4868) -- Beta UI backports [#4855](https://github.com/paritytech/parity/pull/4855) - - Added React Hot Reload to dapps + TokenDeplpoy fix ([#4846](https://github.com/paritytech/parity/pull/4846)) - - Fix method decoding ([#4845](https://github.com/paritytech/parity/pull/4845)) - - Fix contract deployment method decoding in Signer - - Linting - - Fix TxViewer when no `to` (contract deployment) ([#4847](https://github.com/paritytech/parity/pull/4847)) - - Added React Hot Reload to dapps + TokenDeplpoy fix - - Fixes to the LocalTx dapp - - Don't send the nonce for mined transactions - - Don't encode empty to values for options - - Pull steps from actual available steps ([#4848](https://github.com/paritytech/parity/pull/4848)) - - Wait for the value to have changed in the input ([#4844](https://github.com/paritytech/parity/pull/4844)) - - Backport Regsirty changes from [#4589](https://github.com/paritytech/parity/pull/4589) - - Test fixes for [#4589](https://github.com/paritytech/parity/pull/4589) -- Beta Simple score [#4852](https://github.com/paritytech/parity/pull/4852) - - Simple score - - Ignore part of a test -- Backporting to beta [#4840](https://github.com/paritytech/parity/pull/4840) - - Fixes to the Registry dapp ([#4838](https://github.com/paritytech/parity/pull/4838)) - - Fix wrong ABI methods - - Fix comparison - - Bump to v1.6.1 -- Show token icons on list summary pages ([#4826](https://github.com/paritytech/parity/pull/4826)) [#4827](https://github.com/paritytech/parity/pull/4827) - - Adjust balance overlay margins (no jumps) - - Img only balances, small verifications - - Invalid tests removed - - Always wrap display (Thanks [@ngotchac](https://github.com/ngotchac)) - - Update tests to reflect reality -- Beta Engine backports [#4806](https://github.com/paritytech/parity/pull/4806) - - Calibrate before rejection - - Change flag name - - Add eip155 - - Make network_id default -- Beta UI backports [#4823](https://github.com/paritytech/parity/pull/4823) - - Better logic for contract deployments ([#4821](https://github.com/paritytech/parity/pull/4821)) -- Beta UI backports [#4818](https://github.com/paritytech/parity/pull/4818) - - Update the key ([#4817](https://github.com/paritytech/parity/pull/4817)) - - Adjust selection colours/display ([#4811](https://github.com/paritytech/parity/pull/4811)) - - Adjust selection colours to match with mui - - allow -> disable (simplify selections) - - Only use top-border - - Overlay selection line - - Slightly more muted unselected - - Restore address icon - - Fix default values for contract queries -- Beta UI backports [#4809](https://github.com/paritytech/parity/pull/4809) - - Update Wallet to new Wallet Code ([#4805](https://github.com/paritytech/parity/pull/4805)) - - Update Wallet Version - - Update Wallet Library - - Update Wallets Bytecodes - - Typo - - Separate Deploy in Contract API - - Use the new Wallet ABI // Update wallet code - - WIP .// Deploy from Wallet - - Update Wallet contract - - Contract Deployment for Wallet - - Working deployments for Single Owned Wallet contracts - - Linting - - Create a Wallet from a Wallet - - Linting - - Fix Signer transactions // Add Gas Used for transactions - - Deploy wallet contract fix - - Fix too high gas estimate for Wallet Contract Deploys - - Final piece ; deploying from Wallet owned by wallet - - Update Wallet Code - - Updated the Wallet Codes - - Fixing Wallet Deployments - - Add Support for older wallets - - Linting - - SMS Faucet ([#4774](https://github.com/paritytech/parity/pull/4774)) - - Faucet - - Remove flakey button-index testing - - Only display faucet when sms verified (mainnet) - - Simplify availability checks - - WIP - - Resuest from verified -> verified - - Update endpoint, display response text - - Error icon on errors - - Parse hash text response - - Use /api/:address endpoint - - Hash -> data - - Adjust sms-certified message - - Fix SectionList hovering issue ([#4749](https://github.com/paritytech/parity/pull/4749)) - - Fix SectionList Items hover when <3 items - - Even easier... - - Lint (new) -- Update ETC bootnodes [#4794](https://github.com/paritytech/parity/pull/4794) -- Update comments and reg ABI [#4787](https://github.com/paritytech/parity/pull/4787) -- Optimize signature for fallback function. [#4780](https://github.com/paritytech/parity/pull/4780) -- Rephrasing token generation screen. [#4777](https://github.com/paritytech/parity/pull/4777) -- Etherscan links based on netVersion identifier [#4772](https://github.com/paritytech/parity/pull/4772) -- Update README.md [#4762](https://github.com/paritytech/parity/pull/4762) -- Fix invalid props to verification code [#4766](https://github.com/paritytech/parity/pull/4766) -- Extend authority round consensus test [#4756](https://github.com/paritytech/parity/pull/4756) -- Revert last hyper "fix" [#4752](https://github.com/paritytech/parity/pull/4752) -- Vault Management UI (round 3) [#4652](https://github.com/paritytech/parity/pull/4652) -- Update SelectionList indicators [#4736](https://github.com/paritytech/parity/pull/4736) -- Update testnet detection [#4746](https://github.com/paritytech/parity/pull/4746) -- Fix Portal in Portal ESC issue [#4745](https://github.com/paritytech/parity/pull/4745) -- Update wiki [#4743](https://github.com/paritytech/parity/pull/4743) -- Account selector close operations [#4728](https://github.com/paritytech/parity/pull/4728) -- Fix Account Selection in Signer [#4744](https://github.com/paritytech/parity/pull/4744) -- Support both V1 & V2 DataChanged events in registry [#4734](https://github.com/paritytech/parity/pull/4734) -- Add info on forks. [#4733](https://github.com/paritytech/parity/pull/4733) -- Add registry addr [#4732](https://github.com/paritytech/parity/pull/4732) -- UI support for hardware wallets [#4539](https://github.com/paritytech/parity/pull/4539) -- S/delete/forget/ for wallets [#4729](https://github.com/paritytech/parity/pull/4729) -- New chains [#4720](https://github.com/paritytech/parity/pull/4720) -- Enable --warp by default [#4719](https://github.com/paritytech/parity/pull/4719) -- Update Uglify (fix to 2.8.2) to fix binary builds [#4723](https://github.com/paritytech/parity/pull/4723) -- Extract i18n strings in modals/* [#4706](https://github.com/paritytech/parity/pull/4706) -- Provide uncle size where available in RPC [#4713](https://github.com/paritytech/parity/pull/4713) -- EC math functions [#4696](https://github.com/paritytech/parity/pull/4696) -- Add registrar fields [#4716](https://github.com/paritytech/parity/pull/4716) -- Extract i18n strings in views/* [#4695](https://github.com/paritytech/parity/pull/4695) -- Removing network=disable from config files [#4715](https://github.com/paritytech/parity/pull/4715) -- Fast in-place migration for adding and removing column families [#4687](https://github.com/paritytech/parity/pull/4687) -- Display badges on summary view [#4689](https://github.com/paritytech/parity/pull/4689) -- Consistent file uploads [#4699](https://github.com/paritytech/parity/pull/4699) -- Rename https://mkr.market -> https://oasisdex.com [#4701](https://github.com/paritytech/parity/pull/4701) -- Stop copy & clickthrough from list summaries [#4700](https://github.com/paritytech/parity/pull/4700) -- Display ... for address summary overflows [#4691](https://github.com/paritytech/parity/pull/4691) -- Less agressive grayscale/opacity in SelectionList [#4688](https://github.com/paritytech/parity/pull/4688) -- Propagate trie errors upwards from State [#4655](https://github.com/paritytech/parity/pull/4655) -- Generic state backend [#4632](https://github.com/paritytech/parity/pull/4632) -- Enhance dialog layouts (round 1) [#4637](https://github.com/paritytech/parity/pull/4637) -- Vault Management UI (round 2) [#4631](https://github.com/paritytech/parity/pull/4631) -- Fix Portal broad event stopper [#4674](https://github.com/paritytech/parity/pull/4674) -- Custom dev chain presets [#4671](https://github.com/paritytech/parity/pull/4671) -- Max gas limit and min gas price [#4661](https://github.com/paritytech/parity/pull/4661) -- Align list displays with SectionList (UI consistency) [#4621](https://github.com/paritytech/parity/pull/4621) -- Add SelectionList component to DRY up [#4639](https://github.com/paritytech/parity/pull/4639) -- I18n NL linting updates [#4662](https://github.com/paritytech/parity/pull/4662) -- Misc. small UI fixes [#4657](https://github.com/paritytech/parity/pull/4657) -- More CLI settings for IPFS API [#4608](https://github.com/paritytech/parity/pull/4608) -- Fix Tendermint deadlock [#4654](https://github.com/paritytech/parity/pull/4654) -- Nl translations [#4649](https://github.com/paritytech/parity/pull/4649) -- Update transaction condition documentation [#4659](https://github.com/paritytech/parity/pull/4659) -- Bump hyper versions [#4645](https://github.com/paritytech/parity/pull/4645) -- Sane updater [#4658](https://github.com/paritytech/parity/pull/4658) -- Remainder of RPC APIs implemented for the light client [#4594](https://github.com/paritytech/parity/pull/4594) -- Preserve vault meta when changing pwd [#4650](https://github.com/paritytech/parity/pull/4650) -- Fix Geth account import [#4641](https://github.com/paritytech/parity/pull/4641) -- Tweak some checks. [#4633](https://github.com/paritytech/parity/pull/4633) -- Attempt to fix subscribeToEvents test [#4638](https://github.com/paritytech/parity/pull/4638) -- Fix selection value from RadioButtons [#4636](https://github.com/paritytech/parity/pull/4636) -- Convert all remaining Modals to use Portal (UI consistency) [#4625](https://github.com/paritytech/parity/pull/4625) -- Default account selection update [#4609](https://github.com/paritytech/parity/pull/4609) -- Display ETH balance in overlay account selector [#4588](https://github.com/paritytech/parity/pull/4588) -- Fixed minor grammar mistake in readme [#4627](https://github.com/paritytech/parity/pull/4627) -- Extract newly available i18n strings [#4623](https://github.com/paritytech/parity/pull/4623) -- Save pending local transactions in the database [#4566](https://github.com/paritytech/parity/pull/4566) -- Bump CID version to allow compilation on all platforms [#4614](https://github.com/paritytech/parity/pull/4614) -- Vault Management UI (first round) [#4446](https://github.com/paritytech/parity/pull/4446) -- Let Engine decide if it seals internally [#4613](https://github.com/paritytech/parity/pull/4613) -- Show only known accounts/wallets/addresses on Home [#4612](https://github.com/paritytech/parity/pull/4612) -- Proper default accounts RPCs [#4580](https://github.com/paritytech/parity/pull/4580) -- Hash-fetch errors in case upstream returns non-200 [#4599](https://github.com/paritytech/parity/pull/4599) -- Added pending transaction info to eth_getTransactionByHash [#4570](https://github.com/paritytech/parity/pull/4570) -- Secret store - initial version [#4567](https://github.com/paritytech/parity/pull/4567) -- Handle invalid ABI retrieved from address_book gracefully [#4606](https://github.com/paritytech/parity/pull/4606) -- Optimize key directory reloads [#4583](https://github.com/paritytech/parity/pull/4583) -- Revert Double Click on Accounts to close in Signer Bar [#4590](https://github.com/paritytech/parity/pull/4590) -- IPFS MVP [#4545](https://github.com/paritytech/parity/pull/4545) -- Networking fixes [#4563](https://github.com/paritytech/parity/pull/4563) -- Remove eth_compile* RPCs [#4577](https://github.com/paritytech/parity/pull/4577) -- Ledger wallet signing fixed [#4578](https://github.com/paritytech/parity/pull/4578) -- Remove vertx from Webpack config [#4576](https://github.com/paritytech/parity/pull/4576) -- Better display of tags [#4564](https://github.com/paritytech/parity/pull/4564) -- Added vaults support to `ethstore-cli` [#4532](https://github.com/paritytech/parity/pull/4532) -- Fixed font URLs [#4579](https://github.com/paritytech/parity/pull/4579) -- Explicitly set seconds to 0 from selector [#4559](https://github.com/paritytech/parity/pull/4559) -- Fixes evmbin compilation and adding to standard build. [#4561](https://github.com/paritytech/parity/pull/4561) -- Alias for personal_sendTransaction [#4554](https://github.com/paritytech/parity/pull/4554) -- Key derivation in ethstore & rpc [#4515](https://github.com/paritytech/parity/pull/4515) -- Skip OOG check for simple transfers [#4558](https://github.com/paritytech/parity/pull/4558) -- Light Client transaction queue, initial LightDispatcher [#4501](https://github.com/paritytech/parity/pull/4501) -- Fixes BadgeReg Middleware [#4556](https://github.com/paritytech/parity/pull/4556) -- Fix pasting of value in Input fields [#4555](https://github.com/paritytech/parity/pull/4555) -- Tooltips with react-intl [#4549](https://github.com/paritytech/parity/pull/4549) -- Close on double-click for Signer Account selection [#4540](https://github.com/paritytech/parity/pull/4540) -- Signer provenance [#4477](https://github.com/paritytech/parity/pull/4477) -- Fix console dapp [#4544](https://github.com/paritytech/parity/pull/4544) -- Extract i18n string into i18n/_defaults (base of translations) [#4514](https://github.com/paritytech/parity/pull/4514) -- Fix contract queries bug [#4534](https://github.com/paritytech/parity/pull/4534) -- Fixing namespace of couple methods in console. [#4538](https://github.com/paritytech/parity/pull/4538) -- Home landing page [#4178](https://github.com/paritytech/parity/pull/4178) -- Bump JSON RPC crates versions [#4530](https://github.com/paritytech/parity/pull/4530) -- Update rust version in README [#4531](https://github.com/paritytech/parity/pull/4531) -- Lower default pruning history and memory [#4528](https://github.com/paritytech/parity/pull/4528) -- Serde 0.9 [#4508](https://github.com/paritytech/parity/pull/4508) -- Fixes to Token Deploy dapp [#4513](https://github.com/paritytech/parity/pull/4513) -- Fixed receipt decoding [#4521](https://github.com/paritytech/parity/pull/4521) -- Several fixes to the Wallet in general [#4504](https://github.com/paritytech/parity/pull/4504) -- Use the current contract name for Solidity compilation [#4510](https://github.com/paritytech/parity/pull/4510) -- Preparation for Light client RPC [#4485](https://github.com/paritytech/parity/pull/4485) -- Fix Dutch translation [#4509](https://github.com/paritytech/parity/pull/4509) -- Fixed a warning and bumped libusb-sys [#4507](https://github.com/paritytech/parity/pull/4507) -- Fix TnC overflows on small screens [#4505](https://github.com/paritytech/parity/pull/4505) -- Fix no data sent in TxQueue dapp [#4502](https://github.com/paritytech/parity/pull/4502) -- Ledger wallet support [#4486](https://github.com/paritytech/parity/pull/4486) -- Add new Componennt for Token Images [#4498](https://github.com/paritytech/parity/pull/4498) -- Fix address and accounts links [#4491](https://github.com/paritytech/parity/pull/4491) -- Fix Token Reg Dapp issues in Firefox [#4489](https://github.com/paritytech/parity/pull/4489) -- Parity.js interfaces for vaults [#4497](https://github.com/paritytech/parity/pull/4497) -- Initial Dutch translations [#4484](https://github.com/paritytech/parity/pull/4484) -- Fix key.meta.vault for root dir keys && read vault.meta without vault key [#4482](https://github.com/paritytech/parity/pull/4482) -- Arbitrary labels for extended keys (u32, H256 built-in) [#4438](https://github.com/paritytech/parity/pull/4438) -- Fix ethstore build [#4492](https://github.com/paritytech/parity/pull/4492) -- Fixed compilation of ethstore-cli [#4493](https://github.com/paritytech/parity/pull/4493) -- Build embedded Parity JS properly and separatly [#4426](https://github.com/paritytech/parity/pull/4426) -- Static link for snappy [#4487](https://github.com/paritytech/parity/pull/4487) -- Work with string numbers in contract (Fixes #4472) [#4478](https://github.com/paritytech/parity/pull/4478) -- Metadata support for vaults [#4475](https://github.com/paritytech/parity/pull/4475) -- Sort gas price corpus when hitting genesis [#4470](https://github.com/paritytech/parity/pull/4470) -- Fixing CORS headers for parity.web3.site [#4461](https://github.com/paritytech/parity/pull/4461) -- Make signing compatible with geth. [#4468](https://github.com/paritytech/parity/pull/4468) -- Handle registry not found errors [#4465](https://github.com/paritytech/parity/pull/4465) -- Fix Portal scrolling getting stuck [#4455](https://github.com/paritytech/parity/pull/4455) -- Fix AccountCard stretch to 100% [#4450](https://github.com/paritytech/parity/pull/4450) -- Include total difficulty in CHTs and hide implementation details from consumers [#4428](https://github.com/paritytech/parity/pull/4428) -- Fix RLP encoding for types recursively calling `RlpStream::append` [#4362](https://github.com/paritytech/parity/pull/4362) -- Open popup without attempting inline [#4440](https://github.com/paritytech/parity/pull/4440) -- Fixing histogram again ([#4464](https://github.com/paritytech/parity/issues/4464)) port from beta [#4467](https://github.com/paritytech/parity/pull/4467) -- Vaults RPCs [#4366](https://github.com/paritytech/parity/pull/4366) -- Ethkey - extended keys [#4377](https://github.com/paritytech/parity/pull/4377) -- Use secure websocket from HTTPS clients [#4436](https://github.com/paritytech/parity/pull/4436) -- RPC middleware: Informant & Client.keep_alive [#4384](https://github.com/paritytech/parity/pull/4384) -- Fix eth_sign/parity_postSign [#4432](https://github.com/paritytech/parity/pull/4432) -- Web view with web3.site support [#4313](https://github.com/paritytech/parity/pull/4313) -- Extend Portal component with title, buttons & steps (as per Modal) [#4392](https://github.com/paritytech/parity/pull/4392) -- Extension installation overlay [#4423](https://github.com/paritytech/parity/pull/4423) -- Add block & timestamp conditions to Signer [#4411](https://github.com/paritytech/parity/pull/4411) -- Transaction timestamp condition [#4419](https://github.com/paritytech/parity/pull/4419) -- Poll for defaultAccount to update dapp & overlay subscriptions [#4417](https://github.com/paritytech/parity/pull/4417) -- Validate dapps accounts with address book [#4407](https://github.com/paritytech/parity/pull/4407) -- Dapps use defaultAccount instead of own selectors [#4386](https://github.com/paritytech/parity/pull/4386) -- Fix lock and rename tracing [#4403](https://github.com/paritytech/parity/pull/4403) -- Restarting fetch client every now and then [#4399](https://github.com/paritytech/parity/pull/4399) -- Perform a sync between Rust and JS when generating markdown instead of in spec tests [#4408](https://github.com/paritytech/parity/pull/4408) -- Registry dapp: make lookup use lower case [#4409](https://github.com/paritytech/parity/pull/4409) -- Available Dapp selection alignment with Permissions (Portal) [#4374](https://github.com/paritytech/parity/pull/4374) -- More permissive verification process [#4317](https://github.com/paritytech/parity/pull/4317) -- Fix ParityBar account selection overflows [#4405](https://github.com/paritytech/parity/pull/4405) -- Mac binaries signing [#4397](https://github.com/paritytech/parity/pull/4397) -- Revert "remove [ci skip]" [#4398](https://github.com/paritytech/parity/pull/4398) -- Registry, s/a the owner/the owner/ [#4391](https://github.com/paritytech/parity/pull/4391) -- Fixing invalid address in docs [#4388](https://github.com/paritytech/parity/pull/4388) -- Remove [ci skip] [#4381](https://github.com/paritytech/parity/pull/4381) -- Fixing estimate gas in case histogram is not available [#4387](https://github.com/paritytech/parity/pull/4387) -- Default Account selector in Signer overlay [#4375](https://github.com/paritytech/parity/pull/4375) -- Fixing web3 in console [#4382](https://github.com/paritytech/parity/pull/4382) -- Add parity_defaultAccount RPC (with subscription) [#4383](https://github.com/paritytech/parity/pull/4383) -- Full JSON-RPC docs + sync tests. [#4335](https://github.com/paritytech/parity/pull/4335) -- Expose util as Api.util [#4372](https://github.com/paritytech/parity/pull/4372) -- Dapp Account Selection & Defaults [#4355](https://github.com/paritytech/parity/pull/4355) -- Publish @parity/jsonrpc [#4365](https://github.com/paritytech/parity/pull/4365) -- Fix signing [#4363](https://github.com/paritytech/parity/pull/4363) -- Fixing embedded bar not closing in chrome extension [#4367](https://github.com/paritytech/parity/pull/4367) -- Update AccountCard for re-use [#4350](https://github.com/paritytech/parity/pull/4350) -- Add proper event listener to Portal [#4359](https://github.com/paritytech/parity/pull/4359) -- Optional from field in Transaction Requests [#4332](https://github.com/paritytech/parity/pull/4332) -- Rust 1.14 in README [ci-skip] [#4361](https://github.com/paritytech/parity/pull/4361) -- Fix JournalDB::earliest_era on empty database [#4316](https://github.com/paritytech/parity/pull/4316) -- Fixed race condition deadlock on fetching enode URL [#4354](https://github.com/paritytech/parity/pull/4354) -- Allow Portal to be used as top-level modal [#4338](https://github.com/paritytech/parity/pull/4338) -- Fix postsign [#4347](https://github.com/paritytech/parity/pull/4347) -- Renaming signAndSendTransaction to sendTransaction [#4351](https://github.com/paritytech/parity/pull/4351) -- Add api.util.encodeMethodCall to parity.js [#4330](https://github.com/paritytech/parity/pull/4330) -- Initial commit for vaults [#4312](https://github.com/paritytech/parity/pull/4312) -- Returning default account as coinbase + allow altering sender in signer [#4323](https://github.com/paritytech/parity/pull/4323) -- Persistent tracking of dapps [#4302](https://github.com/paritytech/parity/pull/4302) -- Exposing all RPCs over dapps port as CLI option [#4346](https://github.com/paritytech/parity/pull/4346) -- New macOS App [#4345](https://github.com/paritytech/parity/pull/4345) -- Display QrCode for accounts, addresses & contracts [#4329](https://github.com/paritytech/parity/pull/4329) -- Add QrCode & Copy to ShapeShift [#4322](https://github.com/paritytech/parity/pull/4322) -- Parity.js api.parity.chainStatus should handle { blockGap: null } [#4327](https://github.com/paritytech/parity/pull/4327) -- DeleteAccount & LoadContract modal updates [#4320](https://github.com/paritytech/parity/pull/4320) -- Split Tab from TabBar [#4318](https://github.com/paritytech/parity/pull/4318) -- Contracts interface expansion [#4307](https://github.com/paritytech/parity/pull/4307) -- HistoryStore for tracking relevant routes [#4305](https://github.com/paritytech/parity/pull/4305) -- Split Dapp icon into ui/DappIcon (re-use) [#4308](https://github.com/paritytech/parity/pull/4308) -- Add a Playground for the UI Components [#4301](https://github.com/paritytech/parity/pull/4301) -- Update CreateWallet with FormattedMessage [#4298](https://github.com/paritytech/parity/pull/4298) -- Update dates for new PRs missed [#4306](https://github.com/paritytech/parity/pull/4306) -- EIP-98: Optional transaction state root [#4296](https://github.com/paritytech/parity/pull/4296) -- Fix whitespace [#4299](https://github.com/paritytech/parity/pull/4299) -- Attempt to fix console. [#4294](https://github.com/paritytech/parity/pull/4294) -- Ui/SectionList component [#4292](https://github.com/paritytech/parity/pull/4292) -- Stratum up [#4233](https://github.com/paritytech/parity/pull/4233) -- Logging transaction duration [#4297](https://github.com/paritytech/parity/pull/4297) -- Generic engine utilities [#4258](https://github.com/paritytech/parity/pull/4258) -- JSON-RPC interfaces with documentation [#4276](https://github.com/paritytech/parity/pull/4276) -- Dont decode seal fields [#4263](https://github.com/paritytech/parity/pull/4263) -- Skip misbehaving test until properly fixed [#4283](https://github.com/paritytech/parity/pull/4283) -- Additional logs for own transactions [#4278](https://github.com/paritytech/parity/pull/4278) -- Ensure write lock isn't held when calling handlers [#4285](https://github.com/paritytech/parity/pull/4285) -- Feature selector [#4074](https://github.com/paritytech/parity/pull/4074) -- AccountCreate updates [#3988](https://github.com/paritytech/parity/pull/3988) -- Extended JS interface -> Markdown generator [#4275](https://github.com/paritytech/parity/pull/4275) -- Added 3 warpnodes for ropsten [#4289](https://github.com/paritytech/parity/pull/4289) -- Ledger Communication JS toolkit [#4268](https://github.com/paritytech/parity/pull/4268) -- ValidatorSet reporting [#4208](https://github.com/paritytech/parity/pull/4208) -- Add support for api.subscribe('parity_accountsInfo') [#4273](https://github.com/paritytech/parity/pull/4273) -- Display AccountCard name via IdentityName [#4235](https://github.com/paritytech/parity/pull/4235) -- Dapp visibility save/load tests [#4150](https://github.com/paritytech/parity/pull/4150) -- Fix wrong output format of peers [#4270](https://github.com/paritytech/parity/pull/4270) -- Chain scoring [#4218](https://github.com/paritytech/parity/pull/4218) -- Rust 1.14 for windows builds [#4269](https://github.com/paritytech/parity/pull/4269) -- Eslint formatting updates [#4234](https://github.com/paritytech/parity/pull/4234) -- Embeddable ParityBar [#4222](https://github.com/paritytech/parity/pull/4222) -- Update deb-build.sh to fix libssl dependency [#4260](https://github.com/paritytech/parity/pull/4260) -- Integration with zgp whitelist contract [#4215](https://github.com/paritytech/parity/pull/4215) -- Adjust the location of the signer snippet [#4155](https://github.com/paritytech/parity/pull/4155) -- Fix wrong token handling [#4254](https://github.com/paritytech/parity/pull/4254) -- Additional building-block UI components [#4239](https://github.com/paritytech/parity/pull/4239) -- Bump package.json to 0.3.0 (1.6 track) [#4244](https://github.com/paritytech/parity/pull/4244) -- Disable incoming ETH notifications [#4243](https://github.com/paritytech/parity/pull/4243) -- Memory-based pruning history size [#4114](https://github.com/paritytech/parity/pull/4114) -- Common EngineSigner [#4189](https://github.com/paritytech/parity/pull/4189) -- Verification: don't request a code twice [#4221](https://github.com/paritytech/parity/pull/4221) -- S/Delete Contract/Forget Contract/ [#4237](https://github.com/paritytech/parity/pull/4237) -- Light protocol syncing improvements [#4212](https://github.com/paritytech/parity/pull/4212) -- LES Peer Info [#4195](https://github.com/paritytech/parity/pull/4195) -- Don't panic on uknown git commit hash [#4231](https://github.com/paritytech/parity/pull/4231) -- Cache registry reverses in local storage [#4182](https://github.com/paritytech/parity/pull/4182) -- Update version numbers in README [#4223](https://github.com/paritytech/parity/pull/4223) -- CHT calculations for full nodes [#4181](https://github.com/paritytech/parity/pull/4181) -- Use single source of info for dapp meta (build & display) [#4217](https://github.com/paritytech/parity/pull/4217) -- Non-secure API for DappReg [#4216](https://github.com/paritytech/parity/pull/4216) -- Console now has admin [#4220](https://github.com/paritytech/parity/pull/4220) -- Verification: add mainnet BadgeReg ids [#4190](https://github.com/paritytech/parity/pull/4190) -- Fixing minimal transaction queue price [#4204](https://github.com/paritytech/parity/pull/4204) -- Remove unnecessary Engine method [#4184](https://github.com/paritytech/parity/pull/4184) -- Fixed --base-path on windows [#4193](https://github.com/paritytech/parity/pull/4193) -- Fixing etherscan price parsing [#4202](https://github.com/paritytech/parity/pull/4202) -- LES: Better timeouts + Track failed requests [#4093](https://github.com/paritytech/parity/pull/4093) -- ESLint additional rules [#4186](https://github.com/paritytech/parity/pull/4186) -- JsonRPC bump for IPC fix [#4200](https://github.com/paritytech/parity/pull/4200) -- Poll for upgrades as part of global status (long) [#4197](https://github.com/paritytech/parity/pull/4197) -- Updater fixes [#4196](https://github.com/paritytech/parity/pull/4196) -- Prevent duplicate incoming connections [#4180](https://github.com/paritytech/parity/pull/4180) -- Minor typo to ensure it updates only when synced. [#4188](https://github.com/paritytech/parity/pull/4188) -- Minor refactor for clarity [#4174](https://github.com/paritytech/parity/pull/4174) -- Secret - from hash function, also validate data [#4159](https://github.com/paritytech/parity/pull/4159) -- Gas_limit for blocks, mined by Parity will be divisible by 37 [#4154](https://github.com/paritytech/parity/pull/4154) -- Support HTML5-routed dapps [#4173](https://github.com/paritytech/parity/pull/4173) -- Fix subscribeToEvents test [#4166](https://github.com/paritytech/parity/pull/4166) -- Fix dapps not loading [#4170](https://github.com/paritytech/parity/pull/4170) -- Fix broken token images [#4169](https://github.com/paritytech/parity/pull/4169) -- Bumping hyper [#4167](https://github.com/paritytech/parity/pull/4167) -- Icarus -> update, increase web timeout. [#4165](https://github.com/paritytech/parity/pull/4165) -- Add a password strength component [#4153](https://github.com/paritytech/parity/pull/4153) -- Stop flickering + added loader in AddressSelector [#4149](https://github.com/paritytech/parity/pull/4149) -- On demand LES request [#4036](https://github.com/paritytech/parity/pull/4036) -- Ropsten fork detection [#4163](https://github.com/paritytech/parity/pull/4163) -- Pull in console dapp as builtin [#4145](https://github.com/paritytech/parity/pull/4145) -- Optimized hash lookups [#4144](https://github.com/paritytech/parity/pull/4144) -- UnverifiedTransaction type [#4134](https://github.com/paritytech/parity/pull/4134) -- Verification: check if server is running [#4140](https://github.com/paritytech/parity/pull/4140) -- Remove onSubmit of current (no auto-change on password edit) [#4151](https://github.com/paritytech/parity/pull/4151) -- Trim spaces from InputAddress [#4126](https://github.com/paritytech/parity/pull/4126) -- Don't pop-up notifications after network switch [#4076](https://github.com/paritytech/parity/pull/4076) -- Use estimateGas error (as per updated implementation) [#4131](https://github.com/paritytech/parity/pull/4131) -- Improvements and optimisations to estimate_gas [#4142](https://github.com/paritytech/parity/pull/4142) -- New jsonrpc-core with futures and metadata support [#3859](https://github.com/paritytech/parity/pull/3859) -- Reenable mainnet update server. [#4137](https://github.com/paritytech/parity/pull/4137) -- Temporarily skip failing test [#4138](https://github.com/paritytech/parity/pull/4138) -- Refactor VoteCollector [#4101](https://github.com/paritytech/parity/pull/4101) -- Another minor estimation fix [#4133](https://github.com/paritytech/parity/pull/4133) -- Add proper label to method decoding inputs [#4136](https://github.com/paritytech/parity/pull/4136) -- Remove bindActionCreators({}, dispatch) (empty, unneeded) [#4135](https://github.com/paritytech/parity/pull/4135) -- Better contract error log reporting & handling [#4128](https://github.com/paritytech/parity/pull/4128) -- Fix broken Transfer : total account balance [#4127](https://github.com/paritytech/parity/pull/4127) -- Test harness for lightsync [#4109](https://github.com/paritytech/parity/pull/4109) -- Fix call/estimate_gas [#4121](https://github.com/paritytech/parity/pull/4121) -- Fixing decoding ABI with signatures in names [#4125](https://github.com/paritytech/parity/pull/4125) -- Get rid of unsafe code in ethkey, propagate incorrect Secret errors. [#4119](https://github.com/paritytech/parity/pull/4119) -- Basic tests for subscribeToEvents [#4115](https://github.com/paritytech/parity/pull/4115) -- Auto-detect hex encoded bytes in sha3 [#4108](https://github.com/paritytech/parity/pull/4108) -- Use binary chop to estimate gas accurately [#4100](https://github.com/paritytech/parity/pull/4100) -- V1.6 in master [#4113](https://github.com/paritytech/parity/pull/4113) -- Ignore get_price_info test by default. [#4112](https://github.com/paritytech/parity/pull/4112) -- Fix wrong information logging [#4106](https://github.com/paritytech/parity/pull/4106) -- Avoid comms with not-yet-active release update server. [#4111](https://github.com/paritytech/parity/pull/4111) -- Update Transfer logic + Better logging [#4098](https://github.com/paritytech/parity/pull/4098) -- Fix Signer : wrong account on reload [#4104](https://github.com/paritytech/parity/pull/4104) -- Cache registry reverses, completion in address selector [#4066](https://github.com/paritytech/parity/pull/4066) -- Validator/authority contract [#3937](https://github.com/paritytech/parity/pull/3937) -- No reorg limit for ancient blocks [#4099](https://github.com/paritytech/parity/pull/4099) -- Update registration after every write [#4102](https://github.com/paritytech/parity/pull/4102) -- Default to no auto-update. [#4092](https://github.com/paritytech/parity/pull/4092) -- Don't remove out of date local transactions [#4094](https://github.com/paritytech/parity/pull/4094) - -## Parity [v1.5.9](https://github.com/paritytech/parity/releases/tag/v1.5.9) (2017-03-11) - -First stable release of 1.5.x series. This release enables EIP-161 transaction replay protection for PoA networks. - -- Bump to v1.5.9 -- Fix auto-updater stable [#4869](https://github.com/paritytech/parity/pull/4869) -- Fixing windows build script -- Bump js-precompiled 20170308-152339 -- Force js update -- Stable Engine backports [#4807](https://github.com/paritytech/parity/pull/4807) - - Calibrate before rejection - - Change flag name - - Add eip155 - - Fix build - - Make network_id default -- Switch js branch to stable -- Bump to v1.5.8 - -## Parity [v1.5.7](https://github.com/paritytech/parity/releases/tag/v1.5.7) (2017-03-07) - -This release resolves a single issue with failing auto-updates. - -- Update ETC bootnodes [#4794](https://github.com/paritytech/parity/pull/4794) -- Bump to v1.5.7 -- Sane updater [#4658](https://github.com/paritytech/parity/pull/4658) - - Disable if files can't be moved. - - Make updater avoid downloading earlier versions. - -## Parity [v1.5.6](https://github.com/paritytech/parity/releases/tag/v1.5.6) (2017-03-06) - -This release among various stability fixes adds support for a new [Kovan](https://github.com/kovan-testnet/proposal) testnet. - -See [full list of changes.](https://github.com/paritytech/parity/compare/v1.5.4...v1.5.6): - -- Beta Update comments and reg ABI [#4788](https://github.com/paritytech/parity/pull/4788) - - Update comments. - - Fix up new ABI. -- Bump to v1.5.6 in beta [#4786](https://github.com/paritytech/parity/pull/4786) -- Beta Optimize signature for fallback function. ([#4780](https://github.com/paritytech/parity/pull/4780)) [#4784](https://github.com/paritytech/parity/pull/4784) -- Beta Add registrar fields ([#4716](https://github.com/paritytech/parity/pull/4716)) [#4781](https://github.com/paritytech/parity/pull/4781) -- Beta Etherscan links ([#4772](https://github.com/paritytech/parity/pull/4772)) [#4778](https://github.com/paritytech/parity/pull/4778) - - Etherscan links [#4772](https://github.com/paritytech/parity/pull/4772) - - Use netVersion to determine external links - - Update additional isTest references - - Port tests - - Update address links - - Signer accountlink isTest -- Beta Fix invalid props [#4767](https://github.com/paritytech/parity/pull/4767) -- Backporting to beta [#4741](https://github.com/paritytech/parity/pull/4741) - - New chains [#4720](https://github.com/paritytech/parity/pull/4720) - - Add Kovan chain. - - Fix up --testnet. - - Fix tests. - - Fix to UglifyJS 2.8.2 to fix app build issues [#4723](https://github.com/paritytech/parity/pull/4723) - - Update classic bootnodes, ref #4717 [#4735](https://github.com/paritytech/parity/pull/4735) - - Allow failure docker beta - - Adjust pruning history default to 64 [#4709](https://github.com/paritytech/parity/pull/4709) - - Backporting from master - - Update docker-build.sh - - Update gitlab.ci - - Fix docker hub build - - Update gitlab - - Docker beta-release->latest - - Add registry. - - Add info on forks. - - Fixed spec file - - Support both V1 & V2 DataChanged events in registry [#4734](https://github.com/paritytech/parity/pull/4734) - - Add info on forks. - - Add new registry ABI - - Import registry2 & fix exports - - Select ABI based on code hash - - Render new event types (owner not available) - - New registry. - - Rename old chain. - - Fix test. - - Another fix. - - Finish rename. - - Fixed fonts URLs [#4579](https://github.com/paritytech/parity/pull/4579) - - Fix Token Reg Dapp issues in Firefox [#4489](https://github.com/paritytech/parity/pull/4489) - - Fix overflow issues in Firefox [#4348](https://github.com/paritytech/parity/issues/4348) - - Fix wrong Promise inferance - - Revert "Add new Componennt for Token Images [#4496](https://github.com/paritytech/parity/issues/4496)" - - Add new Componennt for Token Images [#4496](https://github.com/paritytech/parity/issues/4496) - - Add StackEventListener [#4745](https://github.com/paritytech/parity/pull/4745) - - Update testnet detection [#4746](https://github.com/paritytech/parity/pull/4746) - - Fix Account Selection in Signer [#4744](https://github.com/paritytech/parity/pull/4744) - - Can pass FormattedMessage to Input (eg. Status // RPC Enabled) - - Simple fixed-width fix for Accoutn Selection in Parity Signer -- Beta backports [#4763](https://github.com/paritytech/parity/pull/4763) - - Https://mkr-market -> https://oasisdex.com [#4701](https://github.com/paritytech/parity/pull/4701) - - Wallet s/delete/forget/ [#4741](https://github.com/paritytech/parity/pull/4741) -- Update classic bootnodes [#4735](https://github.com/paritytech/parity/pull/4735) -- Engine backports [#4718](https://github.com/paritytech/parity/pull/4718) - - Custom dev presets - - Add registrar field - - Use constructor for dev registrar - - Fix test -- Beta Adjust pruning history default to 64 [#4709](https://github.com/paritytech/parity/pull/4709) -- Bump to v1.5.5 - -## Parity [v1.5.4](https://github.com/paritytech/parity/releases/tag/v1.5.4) (2017-02-23) - -A couple of issue fixed in this release: - -- Parity now allows uncles headers to have timestamp set to arbitrary future value. -- Importing keys from geth is now working again. - -Changes: - -- Beta Fix Geth account import [#4643](https://github.com/paritytech/parity/pull/4643) - - Fix Geth import - actually pass addresses through - - Fix geth accounts not displayed - - Port saving of returned addresses (master MobX, beta state) - - Log result -> importGethAccounts -- Beta Backporting ([#4633](https://github.com/paritytech/parity/pull/4633)) [#4640](https://github.com/paritytech/parity/pull/4640) - - Tweak some checks. - - Fixed build and added a difficulty test - - Bump to v1.5.4 - -## Parity [v1.4.12](https://github.com/paritytech/parity/releases/tag/v1.4.12) (2017-02-22) - -This stable release fixes an issue with block uncle validation. Parity now allows uncle headers to have timestamp set to arbitrary future value. - -- Stable Backporting ([#4633](https://github.com/paritytech/parity/pull/4633)) [#4642](https://github.com/paritytech/parity/pull/4642) - - Tweak some checks. - - Fixed build and added a difficulty test - - Bump to v1.4.12 -- Add missing maxCodeSize [#4585](https://github.com/paritytech/parity/pull/4585) - -## Parity [v1.5.3](https://github.com/paritytech/parity/releases/tag/v1.5.3) (2017-02-20) - -This is a maintenance release that fixes a number of stability issues. Notably this resolves an issue where Parity would allow a pre EIP-155 transaction into the sealed block. - -See [full list of changes](https://github.com/paritytech/parity/compare/v1.5.2...v1.5.3): - -- Bump to v1.5.3 [#4611](https://github.com/paritytech/parity/pull/4611) -- Handle invalid ABI retrieved from address_book gracefully ([#4606](https://github.com/paritytech/parity/pull/4606)) [#4610](https://github.com/paritytech/parity/pull/4610) - - Handle invalid ABI gracefully - - Also include failed abi in log -- Backporting to beta [#4602](https://github.com/paritytech/parity/pull/4602) - - Static link for snappy - - added 3 warpnodes for ropsten ([#4289](https://github.com/paritytech/parity/pull/4289)) - - Fixed indentation -- Validate transaction before adding to the queue [#4600](https://github.com/paritytech/parity/pull/4600) -- Beta backports [#4569](https://github.com/paritytech/parity/pull/4569) - - Fixing evmbin compilation and added standard build. ([#4561](https://github.com/paritytech/parity/pull/4561)) - - Alias for personal_sendTransaction ([#4554](https://github.com/paritytech/parity/pull/4554)) - - Fix console dapp ([#4544](https://github.com/paritytech/parity/pull/4544)) - - Fixing linting issues. Better support for console as secure app - - Fixing linting issues - - Fix no data sent in TxQueue dapp ([#4502](https://github.com/paritytech/parity/pull/4502)) - - Fix wrong PropType req for Embedded Signer - - Fix wrong data for tx #4499 -- Explicitly set seconds to 0 from selector ([#4559](https://github.com/paritytech/parity/pull/4559)) [#4571](https://github.com/paritytech/parity/pull/4571) - - Explicitly set seconds/milli to 0 - - Use condition time & block setters consistently - - Fix failing test - - test for 0 ms & sec - - It cannot hurt, clone date before setting - - Prettier date test constants (OCD) -- Remove invalid expectation [#4542](https://github.com/paritytech/parity/pull/4542) -- Skip OOG check for simple transfers [#4558](https://github.com/paritytech/parity/pull/4558) [#4560](https://github.com/paritytech/parity/pull/4560) - - Skip OOG check for simple transfers [#4558](https://github.com/paritytech/parity/pull/4558) - - Fix failing test - -## Parity [v1.4.11](https://github.com/paritytech/parity/releases/tag/v1.4.11) (2017-02-17) - -This release corrects the Ropsten chain specification file. - -- Bump to v1.4.11 [#4587](https://github.com/paritytech/parity/pull/4587) -- Fixing etherscan price parsing ([#4202](https://github.com/paritytech/parity/pull/4202)) [#4209](https://github.com/paritytech/parity/pull/4209) - - Fixing etherscan price parsing - - Handling all errors -- Removed pdbs -- Add missing maxCodeSize [#4585](https://github.com/paritytech/parity/pull/4585) - -## Parity [v1.5.2](https://github.com/paritytech/parity/releases/tag/v1.5.2) (2017-02-08) - -This release brings a few stability fixes along with a feature that allows queuing transactions that are activated and send out on selected date or block number. -- Debian packages have been updated to require `libssl1.0.0` for better compatibility. -- eth_sign (and parity_postSign) used to return concatenated r ++ s ++ v with v being 0 or 1. it now agrees with geth as v ++ r ++ s with v being 27 or 28. - -Parity Wallet -- Accounts & ShapeShift integration now displays QR code for scanning from mobile wallets -- Dapp integration now allows for the selection of available accounts and the setting of the default account -- Transaction creation now allows for the selection of future blocks or timestamps after which the transaction is released - -Parity Extension -- First release of the Parity Extension, allowing for Parity integration from web-based dapps - -See [full list of changes](https://github.com/paritytech/parity/compare/v1.5.0...v1.5.2): -- Work with string numbers in contract (Fixes #4472) ([#4478](https://github.com/paritytech/parity/pull/4478)) [#4480](https://github.com/paritytech/parity/pull/4480) -- Eth_sign improvements backport [#4473](https://github.com/paritytech/parity/pull/4473) - - Fix postsign ([#4347](https://github.com/paritytech/parity/pull/4347)) - - Fix whitespace. - - Fix post sign. +- Re-enable signer, even with no UI. ([#8167](https://github.com/paritytech/parity/pull/8167)) ([#8168](https://github.com/paritytech/parity/pull/8168)) + - Re-enable signer, even with no UI. - Fix message. - - Fix tests. - - Rest of the problems. - - All hail the linter and its omniscience. - - ...and its divine omniscience. - - Grumbles and wording. - - Make signing compatible with geth. ([#4468](https://github.com/paritytech/parity/pull/4468)) -- Sort gas price corpus when hitting genesis [#4471](https://github.com/paritytech/parity/pull/4471) -- Wallet dev chain fix [#4466](https://github.com/paritytech/parity/pull/4466) -- Fixing histogram again [#4464](https://github.com/paritytech/parity/pull/4464) -- Beta backports [#4462](https://github.com/paritytech/parity/pull/4462) - - Support HTML5-routed dapps ([#4173](https://github.com/paritytech/parity/pull/4173)) - - Fix compilation on latest nightly - - Updating precompiled -- Fix Portal scrolling getting stuck [#4456](https://github.com/paritytech/parity/pull/4456) - - Fix Portal scrolling getting stuck - - DappCard container flex - - Container height to 100% -- Fix AccountCard stretch to 100% [#4451](https://github.com/paritytech/parity/pull/4451) -- Fix wrong output format of peers ([#4270](https://github.com/paritytech/parity/pull/4270)) [#4442](https://github.com/paritytech/parity/pull/4442) - - Fix wrong output format of peers - - Add outPeer tests -- Opening extension page without inline installation [#4441](https://github.com/paritytech/parity/pull/4441) - - Open popup without attempting inline - - Cater for all .web3.site addresses -- Fix svg extension image webpack inlining [#4437](https://github.com/paritytech/parity/pull/4437) -- Backporting to beta [#4434](https://github.com/paritytech/parity/pull/4434) - - Bump to v1.5.2 - - Fix eth_sign/parity_postSign ([#4432](https://github.com/paritytech/parity/pull/4432)) - - Fix dispatch for signing. - - Remove console log - - Fix signing & tests. -- Returning default account as coinbase [#4431](https://github.com/paritytech/parity/pull/4431) - - Returning first address as coinbase - - Allowing sender alteration in signer - - Adding default account RPC -- UI updates for 1.5.1 [#4429](https://github.com/paritytech/parity/pull/4429) - - S/Delete Contract/Forget Contract/ ([#4237](https://github.com/paritytech/parity/pull/4237)) - - Adjust the location of the signer snippet ([#4155](https://github.com/paritytech/parity/pull/4155)) - - Additional building-block UI components ([#4239](https://github.com/paritytech/parity/pull/4239)) - - Currency WIP - - Expand tests - - Pass className - - Add QrCode - - Export new components in ~/ui - - S/this.props.netSymbol/netSymbol/ - - Fix import case - - Ui/SectionList component ([#4292](https://github.com/paritytech/parity/pull/4292)) - - Array chunking utility - - Add SectionList component - - Add TODOs to indicate possible future work - - Add missing overlay style (as used in dapps at present) - - Add a Playground for the UI Components ([#4301](https://github.com/paritytech/parity/pull/4301)) - - Playground // WIP - - Linting - - Add Examples with code - - CSS Linting - - Linting - - Add Connected Currency Symbol - - 2015-2017 - - Added `renderSymbol` tests - - PR grumbles - - Add Eth and Btc QRCode examples - - 2015-2017 - - Add tests for playground - - Fixing tests - - Split Dapp icon into ui/DappIcon ([#4308](https://github.com/paritytech/parity/pull/4308)) - - Add QrCode & Copy to ShapeShift ([#4322](https://github.com/paritytech/parity/pull/4322)) - - Extract CopyIcon to ~/ui/Icons - - Add copy & QrCode address - - Default size 4 - - Add bitcoin: link - - Use protocol links applicable to coin exchanged - - Remove .only - - Display QrCode for accounts, addresses & contracts ([#4329](https://github.com/paritytech/parity/pull/4329)) - - Allow Portal to be used as top-level modal ([#4338](https://github.com/paritytech/parity/pull/4338)) - - Portal - - Allow Portal to be used in as both top-level and popover - - Modal/popover variable naming - - Export Portal in ~/ui - - Properly handle optional onKeyDown - - Add simple Playground Example - - Add proper event listener to Portal ([#4359](https://github.com/paritytech/parity/pull/4359)) - - Display AccountCard name via IdentityName ([#4235](https://github.com/paritytech/parity/pull/4235)) - - Fix signing ([#4363](https://github.com/paritytech/parity/pull/4363)) - - Dapp Account Selection & Defaults ([#4355](https://github.com/paritytech/parity/pull/4355)) - - Add parity_defaultAccount RPC (with subscription) ([#4383](https://github.com/paritytech/parity/pull/4383)) - - Default Account selector in Signer overlay ([#4375](https://github.com/paritytech/parity/pull/4375)) - - Typo, fixes #4271 ([#4391](https://github.com/paritytech/parity/pull/4391)) - - Fix ParityBar account selection overflows ([#4405](https://github.com/paritytech/parity/pull/4405)) - - Available Dapp selection alignment with Permissions (Portal) ([#4374](https://github.com/paritytech/parity/pull/4374)) - - Registry dapp: make lookup use lower case ([#4409](https://github.com/paritytech/parity/pull/4409)) - - Dapps use defaultAccount instead of own selectors ([#4386](https://github.com/paritytech/parity/pull/4386)) - - Poll for defaultAccount to update dapp & overlay subscriptions ([#4417](https://github.com/paritytech/parity/pull/4417)) - - Poll for defaultAccount (Fixes #4413) - - Fix nextTimeout on catch - - Store timers - - Re-enable default updates on change detection - - Add block & timestamp conditions to Signer ([#4411](https://github.com/paritytech/parity/pull/4411)) - - Extension installation overlay ([#4423](https://github.com/paritytech/parity/pull/4423)) - - Extension installation overlay - - Pr gumbles - - Spelling - - Update Chrome URL - - Fix for non-included jsonrpc - - Extend Portal component (as per Modal) [#4392](https://github.com/paritytech/parity/pull/4392) -- Transaction timestamp condition [#4427](https://github.com/paritytech/parity/pull/4427) -- Fixing embedded bar not closing in chrome extension [#4421](https://github.com/paritytech/parity/pull/4421) -- Backporting to beta [#4418](https://github.com/paritytech/parity/pull/4418) - - Bump to 1.5.1 - - Disable notifications ([#4243](https://github.com/paritytech/parity/pull/4243)) - - Fix wrong token handling ([#4254](https://github.com/paritytech/parity/pull/4254)) - - Fixing wrong token displayed - - Linting - - Revert filtering out - - Revert the revert - - Don't panic on uknown git commit hash ([#4231](https://github.com/paritytech/parity/pull/4231)) - - Additional logs for own transactions ([#4278](https://github.com/paritytech/parity/pull/4278)) - - Integration with zgp whitelist contract ([#4215](https://github.com/paritytech/parity/pull/4215)) - - Zgp-transactions checker - - Polishing - - Rename + refactor - - Refuse-service-transactions cl option - - Fixed tests compilation - - Renaming signAndSendTransaction to sendTransaction ([#4351](https://github.com/paritytech/parity/pull/4351)) - - Fixed deadlock in external_url ([#4354](https://github.com/paritytech/parity/pull/4354)) - - Fixing web3 in console ([#4382](https://github.com/paritytech/parity/pull/4382)) - - Fixing estimate gas in case histogram is not available ([#4387](https://github.com/paritytech/parity/pull/4387)) - - Restarting fetch client every now and then ([#4399](https://github.com/paritytech/parity/pull/4399)) -- Embeddable ParityBar ([#4222](https://github.com/paritytech/parity/pull/4222)) [#4287](https://github.com/paritytech/parity/pull/4287) - - Embeddable ParityBar - - Replacing storage with store - - Fixing references. - - Addressing style issues - - Supporting parity background - -## Parity [v1.5.0: "Nativity"](https://github.com/paritytech/parity/releases/tag/v1.5.0) (2017-01-19) - -Major feature release including _Tendermint_ consensus engine, _Multisig wallet_ support, _badge/certification_ UI integration and _automatic updates_. - -Directories: - -- New XDG-informed Parity data directory structure. Base dir (`--base-path` or `-d`) that defaulted to `$HOME/.parity` is changed to: - - `/Users/You/AppData/Roaming/Parity/Ethereum` on Windows - - `/Users/you/Library/Application Support/io.parity.ethereum` on MacOS - - `/home/you/.local/share/parity` on Linux/Unix -- Keys are now stored in chain-specific directories . On first run of 1.5, all keys will be moved into the key's directory of the chain you run. You'll need to move the wallet files between directories manually if you wish to split them between testnet/mainnet. -- `--db-path` option now controls the path just for the databases, not for keys (`--keys-path`) or dapps (`--dapps-path`). - -Basics: - -- Version tracking, consensus-protection, hypervised auto-updating: - - Parity will ensure syncing is paused if its version cannot support an upcoming hard-fork (disable with `--no-consensus`). - - Parity will automatically download the latest version and may be updated through Parity Wallet (disable with `--no-download`) - - Parity can automatically update and seamlessly restart to later versions in the same release track (enable with `--auto-update=all` or `--auto-update=critical`). - - Parity hypervisor will automatically run the latest version (disable with `--force-direct`). -- Fat database; to enable, sync the chain with the option `--fat-db`. - - Accounts and storage entries can be enumerated. - - Chain state can be exported to JSON for analysis with `parity export state`. -- CLI and config options renamed: all variants of `--signer` are renamed to `--ui`. -- Log files are appended by default rather than truncated (useful for daemon deployments). - -Parity Wallet: - -- Multisig wallet support: "New Wallet" button in the "Accounts" section allows you to create a new multisig wallet or import an existing one. -- Solidity compiler: "Develop Contract" button in the "Contracts" section allows you to write, edit, compile and deploy contracts. -- SMS & e-mail verification: Accounts can now be certified as verified using Parity's SMS and e-Mail verification/registration oracle. -- Badge/certification integration: The `BadgeReg` contract can be used to deploy additional certifications. -- Local transaction propagation tracking: "TxQueue Viewer" in the "Applications" section allows you to track and resubmit previously sent transactions. -- Contract executions can now have gas and gas-price configured. -- Signer can now alter the gas and gas-price of transactions at password-entry. -- The deprecated Chrome "Signer" extension is now incompatible. - -[Proof of Authority](https://github.com/paritytech/parity/wiki/Proof-of-Authority-Chains): - -- Authority Round consensus engine: `engine: authorityRound {...}`; this is a high-performance Proof-of-Authority consensus engine. It is not BFT under normal circumstances (however the `--force-sealing` flag can be used to ensure consensus even with Byzantine nodes). -- Tendermint Engine: `engine: tendermint {...}`; this is an experimental Proof-of-Authority consensus engine. BFT up to one third of the authorities and falling back to delayed finalization chain ordering (50% fault tolerant). -- Generic seal JSON spec includes engine-specific types (`seal: { generic: { rlp: "0x..." } }` becomes `seal: { authority_round { step: 0, signature: "0x..." } }`. -- To set a node as authority either `--engine-signer ADDRESS` should be used with `--password` or `parity_setEngineSigner(address, password)` RPC should be called. Unlocking the account permanently or using `--author` is now unnecessary. -- Set of authorities can now be specified using a [list or a contract](https://github.com/paritytech/parity/wiki/Consensus-Engines#validator-engines). - -Chains: - -- Dev chain: `--chain=dev`; instant seal engine (no mining needed). Great for development work. -- Ropsten chain (`--chain=ropsten` or `--chain=testnet`) configures for Ropsten, the new test net. -- Morden chain (`--chain=morden`) changed to "Classic" rules and stays as the Ethereum Classic test net. - -RPCs/APIs: - -- All JSON-RPC interfaces have strict JSON deserialization - no extra fields are allowed. -- `eth_sign` RPC now hashes given data instead of getting the hash. -- `signer_confirmRequestWithToken`: additional RPC for signing transactions with a rotating token, alleviating the need for keeping an account password in memory. -- `eth_signTransaction` now conforms to the specification, `eth_submitTransaction` is introduced. - -Full changes: - -- Backporting to beta [#4211](https://github.com/paritytech/parity/pull/4211) - - JsonRPC bump for IPC fix - - Fixing etherscan price parsing ([#4202](https://github.com/paritytech/parity/pull/4202)) - - Handling all errors - - Fixed --base-path on windows ([#4193](https://github.com/paritytech/parity/pull/4193)) - - Add support for optional args with default text - - Fixing minimal transaction queue price ([#4204](https://github.com/paritytech/parity/pull/4204)) - - Fixing tests - - verification: add mainnet BadgeReg ids ([#4190](https://github.com/paritytech/parity/pull/4190)) - - verification: fetch contracts by name - - verification: better wording - - typo - - reregistered badges - - Console now has admin ([#4220](https://github.com/paritytech/parity/pull/4220)) - - Fixes [#4210](https://github.com/paritytech/parity/pull/4210) - - Non-secure for DappReg ([#4216](https://github.com/paritytech/parity/pull/4216)) -- Backporting to beta [#4203](https://github.com/paritytech/parity/pull/4203) - - Minor typo to ensure it updates only when synced. ([#4188](https://github.com/paritytech/parity/pull/4188)) - - Updater fixes ([#4196](https://github.com/paritytech/parity/pull/4196)) - - Minor typo to ensure it updates only when synced. - - Fix deadlock. - - Skip unneeded arg in making list. - - Allow auto-restart even when not running an update. - - Fix trace. - - Update update info on each loop. - - Fix build. - - Shutdown all sockets - - Remove superfluous use. - - Poll for upgrades as part of global status (long) ([#4197](https://github.com/paritytech/parity/pull/4197)) - - Fix path - - Prevent duplicate incoming connections ([#4180](https://github.com/paritytech/parity/pull/4180)) -- Gas_limit for blocks, mined by Parity will be divisible by 37 ([#4154](https://github.com/paritytech/parity/pull/4154)) [#4176](https://github.com/paritytech/parity/pull/4176) - - gas_limit for new blocks will divide evenly by 13 - - increased PARITY_GAS_LIMIT_DETERMINANT to 37 - - separate method for marking mined block - - debug_asserts(gas_limit within protocol range) - - round_block_gas_limit method is now static - - made round_block_gas_limit free-function - - multiplier->multiple -- Backporting to beta [#4175](https://github.com/paritytech/parity/pull/4175) - - verification: check if server is running ([#4140](https://github.com/paritytech/parity/pull/4140)) - - verification: check if server is running - - See also ethcore/email-verification#67c6466 and ethcore/sms-verification#a585e42. - - verification: show in the UI if server is running - - verification: code style ✨, more i18n - - fix i18n key - - Optimized hash lookups ([#4144](https://github.com/paritytech/parity/pull/4144)) - - Optimize hash comparison - - Use libc - - Ropsten fork detection ([#4163](https://github.com/paritytech/parity/pull/4163)) - - Stop flickering + added loader in AddressSelector ([#4149](https://github.com/paritytech/parity/pull/4149)) - - Stop UI flickering + added loader to AddressSelector [#4103](https://github.com/paritytech/parity/pull/4103) - - PR Grumbles - - Add a password strength component ([#4153](https://github.com/paritytech/parity/pull/4153)) - - Added new PasswordStrength Component - - Added tests - - PR Grumbles - - icarus -> update, increase web timeout. ([#4165](https://github.com/paritytech/parity/pull/4165)) - - Fix estimate gas - - Fix token images // Error in Contract Queries ([#4169](https://github.com/paritytech/parity/pull/4169)) - - Fix dapps not loading ([#4170](https://github.com/paritytech/parity/pull/4170)) - - Add secure to dappsreg - - Remove trailing slash // fix dapps -- Bumping hyper [#4168](https://github.com/paritytech/parity/pull/4168) - - Bumping hyper - - Bumping again -- Backporting to beta [#4158](https://github.com/paritytech/parity/pull/4158) - - Remove onSubmit of current (no auto-change on password edit) ([#4151](https://github.com/paritytech/parity/pull/4151)) - - Remove onSubmit from current password - - Remove onSubmit from hint - - Pull in console dapp as builtin ([#4145](https://github.com/paritytech/parity/pull/4145)) - - Copy static dapps from static (no build) - - Console sources - - Add console to builtins - - Remove console assets - - Disable eslint on console.js - - Enable eslint after disable - - Webpack copy -- Backporting to beta [#4152](https://github.com/paritytech/parity/pull/4152) - - Fix broken transfer total balance ([#4127](https://github.com/paritytech/parity/pull/4127)) - - Add proper label to method decoding inputs ([#4136](https://github.com/paritytech/parity/pull/4136)) - - Another minor estimation fix ([#4133](https://github.com/paritytech/parity/pull/4133)) - - Return 0 instead of error with out of gas on estimate_gas - - Fix stuff up. - - Another estimate gas fix. - - Alter balance to maximum possible rather than GP=0. - - Only increase to amount strictly necessary. - - Get rid of unsafe code in ethkey, propagate incorrect Secret errors. ([#4119](https://github.com/paritytech/parity/pull/4119)) - - Implementing secret - - Fixing tests - - Refactor VoteCollector ([#4101](https://github.com/paritytech/parity/pull/4101)) - - dir - - simple validator list - - stub validator contract - - make the engine hold Weak instead of IoChannel - - validator set factory - - register weak client with ValidatorContract - - check chain security - - add address array to generator - - register provider contract - - update validator set on notify - - add validator contract spec - - simple list test - - split update and contract test - - contract change - - use client in tendermint - - fix deadlock - - step duration in params - - adapt tendermint tests - - add storage fields to test spec - - constructor spec - - execute under wrong address - - create under correct address - - revert - - validator contract constructor - - move genesis block lookup - - add removal ability to contract - - validator contract adding validators - - fix basic authority - - validator changing test - - more docs - - update sync tests - - remove env_logger - - another env_logger - - cameltoe - - hold EngineClient instead of Client - - return error on misbehaviour - - nicer return - - sprinkle docs - - Reenable mainnet update server. ([#4137](https://github.com/paritytech/parity/pull/4137)) - - basic tests for subscribeToEvents ([#4115](https://github.com/paritytech/parity/pull/4115)) - - subscribeToEvent fixtures ✅ - - subscribeToEvent tests ✅ - - temporarily skip failing test ([#4138](https://github.com/paritytech/parity/pull/4138)) - - Improvements and optimisations to estimate_gas ([#4142](https://github.com/paritytech/parity/pull/4142)) - - Return 0 instead of error with out of gas on estimate_gas - - Fix stuff up. - - Another estimate gas fix. - - Alter balance to maximum possible rather than GP=0. - - Only increase to amount strictly necessary. - - Improvements and optimisations to estimate_gas. - - Introduce proper error type - - Avoid building costly traces - - Fix tests. - - Actually fix testsActually fix tests - - Use estimateGas error (as per updated implementation) ([#4131](https://github.com/paritytech/parity/pull/4131)) - - EXCEPTION_ERROR as per #4142 - - Better error log reporting & handling ([#4128](https://github.com/paritytech/parity/pull/4128)) - - Don't pop-up notifications after network switch ([#4076](https://github.com/paritytech/parity/pull/4076)) - - Better notifications - - Don't pollute with notifs if switched networks - - Better connection close/open events / No more notifs on change network - - PR Grumbles - - Add close and open events to HTTP // Add tests - - Fix tests - - WIP Signer Fix - - Fix Signer // Better reconnection handling - - PR Grumbles - - PR Grumbles - - Fixes wrong fetching of balances + Notifications - - Secure API WIP - - Updated Secure API Connection + Status - - Linting - - Updated Secure API Logic - - Proper handling of token updates // Fixing poping notifications - - PR Grumbles - - Fixing tests - - Trim spaces from InputAddress ([#4126](https://github.com/paritytech/parity/pull/4126)) - - Trim spaces for addresses - - onSubmit has only value, not event - - onSubmit (again) - - Length check on trimmed value - - Remove bindActionCreators({}, dispatch) (empty) ([#4135](https://github.com/paritytech/parity/pull/4135)) -- Backporting to beta [#4118](https://github.com/paritytech/parity/pull/4118) - - Ignore get_price_info test by default. ([#4112](https://github.com/paritytech/parity/pull/4112)) - - Auto-detect hex encoded bytes in sha3 ([#4108](https://github.com/paritytech/parity/pull/4108)) - - Using types/isHex - - Removing unused imports - - Use binary chop to estimate gas accurately ([#4100](https://github.com/paritytech/parity/pull/4100)) - - Initial sketch. - - Building. - - Fix a few things. - - Fix issue, add tracing. - - Address grumbles - - Raise upper limit if needed - - Fix test. - - Fixing decoding API with signatures in names ([#4125](https://github.com/paritytech/parity/pull/4125)) - - Fix call/estimate_gas ([#4121](https://github.com/paritytech/parity/pull/4121)) - - Return 0 instead of error with out of gas on estimate_gas - - Fix stuff up. -- Current release: 1.3 -> 1.4 [#4183](https://github.com/paritytech/parity/pull/4183) -- Fix rebroadcast panic [#4084](https://github.com/paritytech/parity/pull/4084) -- Use shallow-only rendering in all tests [#4087](https://github.com/paritytech/parity/pull/4087) -- Sending transactions in chunks [#4089](https://github.com/paritytech/parity/pull/4089) -- Move to new auto-update server. [#4091](https://github.com/paritytech/parity/pull/4091) -- Fixing compilation without dapps. [#4088](https://github.com/paritytech/parity/pull/4088) -- Fix balances update [#4077](https://github.com/paritytech/parity/pull/4077) -- Key derivation in Worker [#4071](https://github.com/paritytech/parity/pull/4071) -- Display contract block creation [#4069](https://github.com/paritytech/parity/pull/4069) -- Improving logs for transactions sync and disable re-broadcasting while syncing [#4065](https://github.com/paritytech/parity/pull/4065) -- Passwords are valid by default [#4075](https://github.com/paritytech/parity/pull/4075) -- Show Origin label to events table [#4073](https://github.com/paritytech/parity/pull/4073) -- Fix tags not working [#4070](https://github.com/paritytech/parity/pull/4070) -- Zero-alloc trie lookups [#3998](https://github.com/paritytech/parity/pull/3998) -- Opening local dapp [#4041](https://github.com/paritytech/parity/pull/4041) -- Bringing back `js-sha3` to fix in-browser signing [#4063](https://github.com/paritytech/parity/pull/4063) -- Fix wrong transaction input for contract deployments [#4052](https://github.com/paritytech/parity/pull/4052) -- Re-broadcast transactions to few random peers on each new block. [#4054](https://github.com/paritytech/parity/pull/4054) -- Removing old transactions from the queue [#4046](https://github.com/paritytech/parity/pull/4046) -- Add block rewards to more Engines [#4055](https://github.com/paritytech/parity/pull/4055) -- Return old trie values on insert and remove [#4053](https://github.com/paritytech/parity/pull/4053) -- Let users open urls from dapps view [#4042](https://github.com/paritytech/parity/pull/4042) -- Util/validation update [#4051](https://github.com/paritytech/parity/pull/4051) -- Convert ShapeShift modal to store [#4035](https://github.com/paritytech/parity/pull/4035) -- Using local path on Windows [#4017](https://github.com/paritytech/parity/pull/4017) -- Fixing minGasLimit > ceil limit mining issue [#4018](https://github.com/paritytech/parity/pull/4018) -- Naive light client synchronization [#3892](https://github.com/paritytech/parity/pull/3892) -- Starting on homestead shows reload snackbar [#4043](https://github.com/paritytech/parity/pull/4043) -- Show contract parameters in MethodDecoding [#4024](https://github.com/paritytech/parity/pull/4024) -- UI component updates [#4010](https://github.com/paritytech/parity/pull/4010) -- Account view updates [#4008](https://github.com/paritytech/parity/pull/4008) -- Better error messages for PoA chains [#4034](https://github.com/paritytech/parity/pull/4034) -- Make some spec fields optional [#4019](https://github.com/paritytech/parity/pull/4019) -- Basic account type [#4021](https://github.com/paritytech/parity/pull/4021) -- Fix wallet in main net [#4038](https://github.com/paritytech/parity/pull/4038) -- Removing orphaned Cargo.toml [#4032](https://github.com/paritytech/parity/pull/4032) -- Address selector: support reverse lookup [#4033](https://github.com/paritytech/parity/pull/4033) -- Only fetch App when necessary [#4023](https://github.com/paritytech/parity/pull/4023) -- Connection UI cleanups & tests for prior PR [#4020](https://github.com/paritytech/parity/pull/4020) -- Unsubscribe error on ShapeShift modal close [#4005](https://github.com/paritytech/parity/pull/4005) -- Add ownership checks the Registry dApp [#4001](https://github.com/paritytech/parity/pull/4001) -- Refresh balances of contacts & contracts when syncing [#4022](https://github.com/paritytech/parity/pull/4022) -- Show message on new chain [#4016](https://github.com/paritytech/parity/pull/4016) -- Use TypedInputs in Contracts view [#4015](https://github.com/paritytech/parity/pull/4015) -- Fix focus on Modal [#4014](https://github.com/paritytech/parity/pull/4014) -- Fix newError noops when not bound to dispacher [#4013](https://github.com/paritytech/parity/pull/4013) -- Parse testnet chain as ropsten [#4004](https://github.com/paritytech/parity/pull/4004) -- Work on Portal Style [#4003](https://github.com/paritytech/parity/pull/4003) -- Make Wallet first-class citizens [#3990](https://github.com/paritytech/parity/pull/3990) -- Don't slice non-existent tags [#4000](https://github.com/paritytech/parity/pull/4000) -- Update dev dependencies and make Webpack less verbose [#3997](https://github.com/paritytech/parity/pull/3997) -- Correct log index in transaction receipt [#3995](https://github.com/paritytech/parity/pull/3995) -- Add Email and Registry lookups to Address Selector [#3992](https://github.com/paritytech/parity/pull/3992) -- Remove node journal: dead code [#3994](https://github.com/paritytech/parity/pull/3994) -- Cleanup AddContract with store [#3981](https://github.com/paritytech/parity/pull/3981) -- Store for EditPassword Modal [#3979](https://github.com/paritytech/parity/pull/3979) -- Additional fetch tests [#3983](https://github.com/paritytech/parity/pull/3983) -- Owning views of blockchain data [#3982](https://github.com/paritytech/parity/pull/3982) -- Make test network generic over peer type [#3974](https://github.com/paritytech/parity/pull/3974) -- Fetch tests (first batch) [#3977](https://github.com/paritytech/parity/pull/3977) -- Fetch certifiers only when needed [#3978](https://github.com/paritytech/parity/pull/3978) -- Visible accounts for dapps (default whitelist) [#3898](https://github.com/paritytech/parity/pull/3898) -- Remove some old (unused/duplicate) files [#3975](https://github.com/paritytech/parity/pull/3975) -- Port `try` macro to new `?` operator. [#3962](https://github.com/paritytech/parity/pull/3962) -- Small UI fixes [#3966](https://github.com/paritytech/parity/pull/3966) -- Fix wrong use of Icons [#3973](https://github.com/paritytech/parity/pull/3973) -- Updating dependencies [#3968](https://github.com/paritytech/parity/pull/3968) -- Web Based Dapps [#3956](https://github.com/paritytech/parity/pull/3956) -- Contract query: render false as false [#3971](https://github.com/paritytech/parity/pull/3971) -- Email verification: add Terms of Service [#3970](https://github.com/paritytech/parity/pull/3970) -- Fix method decoding [#3967](https://github.com/paritytech/parity/pull/3967) -- Store for EditMeta modal [#3959](https://github.com/paritytech/parity/pull/3959) -- Registry dapp: cleanup, support reverse entries [#3933](https://github.com/paritytech/parity/pull/3933) -- New Address Selector Component [#3829](https://github.com/paritytech/parity/pull/3829) -- Limiting accounts returned by parity_accountInfo [#3931](https://github.com/paritytech/parity/pull/3931) -- Unknown block error for RPC [#3965](https://github.com/paritytech/parity/pull/3965) -- Remove unused fields in informant [#3963](https://github.com/paritytech/parity/pull/3963) -- Allow contract constructors in chain spec [#3932](https://github.com/paritytech/parity/pull/3932) -- Sync reorg up to history size [#3874](https://github.com/paritytech/parity/pull/3874) -- Rising the limit for fetch [#3964](https://github.com/paritytech/parity/pull/3964) -- Bring integer arithmetic up to crates.io [#3943](https://github.com/paritytech/parity/pull/3943) -- Eslint rule for block curlies [#3955](https://github.com/paritytech/parity/pull/3955) -- Gas exception warnings on deployment [#3938](https://github.com/paritytech/parity/pull/3938) -- Move verification store into modal [#3951](https://github.com/paritytech/parity/pull/3951) -- Allow setting of minBlock on sending [#3921](https://github.com/paritytech/parity/pull/3921) -- Allow empty address [#3961](https://github.com/paritytech/parity/pull/3961) -- Fix default import [#3960](https://github.com/paritytech/parity/pull/3960) -- Display 0x00..00 as null [#3950](https://github.com/paritytech/parity/pull/3950) -- Global Fetch Service [#3915](https://github.com/paritytech/parity/pull/3915) -- Update babel-loader for WebPack 2.2-rc [#3953](https://github.com/paritytech/parity/pull/3953) -- Fix Webpack build [#3946](https://github.com/paritytech/parity/pull/3946) -- Fix manual input token [#3945](https://github.com/paritytech/parity/pull/3945) -- Update Webpack [#3952](https://github.com/paritytech/parity/pull/3952) -- Add missing Ethcore -> Parity headers [#3948](https://github.com/paritytech/parity/pull/3948) -- Code example: do start before register_protocol [#3947](https://github.com/paritytech/parity/pull/3947) -- Set CHAIN_ID for Classic [#3934](https://github.com/paritytech/parity/pull/3934) -- Fixed compile error. [#3940](https://github.com/paritytech/parity/pull/3940) -- Fix dapps not loading [#3935](https://github.com/paritytech/parity/pull/3935) -- Fix Secure API hangs [#3927](https://github.com/paritytech/parity/pull/3927) -- Parity_chainStatus RPC for block gap info [#3899](https://github.com/paritytech/parity/pull/3899) -- Custom attribute for binary serialization [#3922](https://github.com/paritytech/parity/pull/3922) -- Split intermediate stage into two. [#3926](https://github.com/paritytech/parity/pull/3926) -- Move release-registering to intermediate stage. [#3920](https://github.com/paritytech/parity/pull/3920) -- Blocktime format rounding [#3894](https://github.com/paritytech/parity/pull/3894) -- Ignore dapps_policy.json [#3919](https://github.com/paritytech/parity/pull/3919) -- Fixing Contract Development [#3912](https://github.com/paritytech/parity/pull/3912) -- Use rhash for non-native CI platforms and submit build. [#3911](https://github.com/paritytech/parity/pull/3911) -- Remove -Zorbit=off from rustflags on windows [#3907](https://github.com/paritytech/parity/pull/3907) -- Fixed upgrading keys on the first run [#3904](https://github.com/paritytech/parity/pull/3904) -- Fix deadlock in queue drop [#3903](https://github.com/paritytech/parity/pull/3903) -- Require only simpler methods on Provider [#3897](https://github.com/paritytech/parity/pull/3897) -- Fix grammar ("you try" -> "you tried" + article) [#3902](https://github.com/paritytech/parity/pull/3902) -- Remove light server capability temporarily [#3872](https://github.com/paritytech/parity/pull/3872) -- Allow retry for future blocks [#3896](https://github.com/paritytech/parity/pull/3896) -- Consistent engine and seal names [#3895](https://github.com/paritytech/parity/pull/3895) -- Update email certification ABI [#3893](https://github.com/paritytech/parity/pull/3893) -- Remove existence & length checks on passwords & phrases [#3854](https://github.com/paritytech/parity/pull/3854) -- Refresh certifications automatically [#3878](https://github.com/paritytech/parity/pull/3878) -- Fix Wallet Settings Modal [#3856](https://github.com/paritytech/parity/pull/3856) -- Fix difficulty adjustment. [#3884](https://github.com/paritytech/parity/pull/3884) -- Final fixups for updater [#3883](https://github.com/paritytech/parity/pull/3883) -- Attempt to fix windows CI. [#3882](https://github.com/paritytech/parity/pull/3882) -- Fixing racy test [#3881](https://github.com/paritytech/parity/pull/3881) -- Fix updater permissions [#3880](https://github.com/paritytech/parity/pull/3880) -- Delayed transactions [#3865](https://github.com/paritytech/parity/pull/3865) -- Don't log auth token [#3853](https://github.com/paritytech/parity/pull/3853) -- Loading default config from default path [#3875](https://github.com/paritytech/parity/pull/3875) -- New paths [#3877](https://github.com/paritytech/parity/pull/3877) -- Update tests, gitlabci [#3876](https://github.com/paritytech/parity/pull/3876) -- Base directory option [#3868](https://github.com/paritytech/parity/pull/3868) -- Auto-updating [#3505](https://github.com/paritytech/parity/pull/3505) -- Fix naming collision [#3873](https://github.com/paritytech/parity/pull/3873) -- Get rid of unecessary redirection while fetching content [#3858](https://github.com/paritytech/parity/pull/3858) -- Fix verification stores [#3864](https://github.com/paritytech/parity/pull/3864) -- Store subscriptionId, align with main subscription model [#3863](https://github.com/paritytech/parity/pull/3863) -- Additional RPCs for dapps accounts management [#3792](https://github.com/paritytech/parity/pull/3792) -- Add Ws Json rpc client and command line utils (take 2) [#3830](https://github.com/paritytech/parity/pull/3830) -- Fix typo in method call (broken contract interface) [#3862](https://github.com/paritytech/parity/pull/3862) -- Fix flaky test [#3860](https://github.com/paritytech/parity/pull/3860) -- Converting traces API to AutoArgs [#3844](https://github.com/paritytech/parity/pull/3844) -- Get certifications from BadgeReg, show them in accounts overview [#3768](https://github.com/paritytech/parity/pull/3768) -- New directory structure [#3828](https://github.com/paritytech/parity/pull/3828) -- First run: skip account creation if they already have accounts [#3827](https://github.com/paritytech/parity/pull/3827) -- Tendermint seal [#3857](https://github.com/paritytech/parity/pull/3857) -- Tendermint Engine [#3759](https://github.com/paritytech/parity/pull/3759) -- Expand lint to catch css issues [#3852](https://github.com/paritytech/parity/pull/3852) -- Inject exports both partiy & web3 [#3851](https://github.com/paritytech/parity/pull/3851) -- Let Webpack talk again [#3848](https://github.com/paritytech/parity/pull/3848) -- AuthorityRound seal and simplify Generic seal Spec [#3843](https://github.com/paritytech/parity/pull/3843) -- Signing transactions with rotating token [#3691](https://github.com/paritytech/parity/pull/3691) -- Bump dev chain [#3835](https://github.com/paritytech/parity/pull/3835) -- Spelling [#3839](https://github.com/paritytech/parity/pull/3839) -- Email verification [#3766](https://github.com/paritytech/parity/pull/3766) -- Network configuration for Ethereum Classic [#3812](https://github.com/paritytech/parity/pull/3812) -- Using jsonrpc-macros [#3831](https://github.com/paritytech/parity/pull/3831) -- Fixed bool dropdown in contract execution [#3823](https://github.com/paritytech/parity/pull/3823) -- Avoid broadcasting transactions to peers that send them [#3796](https://github.com/paritytech/parity/pull/3796) -- Eth_sign RPC now hashes given data instead of getting the hash [#3800](https://github.com/paritytech/parity/pull/3800) -- Add store for MethodDecoding [#3821](https://github.com/paritytech/parity/pull/3821) -- Add store for AddAddress [#3819](https://github.com/paritytech/parity/pull/3819) -- Fix React-Router in i18n locale change [#3815](https://github.com/paritytech/parity/pull/3815) -- Cache fetched Dapps [#3804](https://github.com/paritytech/parity/pull/3804) -- Authors & homepage => Parity [#3818](https://github.com/paritytech/parity/pull/3818) -- Rename Ethcore -> Parity Technologies [#3817](https://github.com/paritytech/parity/pull/3817) -- Allow editing of gasPrice & gas in Signer [#3777](https://github.com/paritytech/parity/pull/3777) -- I18n string dictionaries [#3532](https://github.com/paritytech/parity/pull/3532) -- Fix padding in App [#3813](https://github.com/paritytech/parity/pull/3813) -- Light server improvements and protocol adjustments [#3801](https://github.com/paritytech/parity/pull/3801) -- Tolerate errors in user_defaults [#3810](https://github.com/paritytech/parity/pull/3810) -- Block: enforce gas limit falls within engine bounds [#3809](https://github.com/paritytech/parity/pull/3809) -- Target Babel to latest Chrome Versions in dev [#3806](https://github.com/paritytech/parity/pull/3806) -- Lowercase npm packages [#3807](https://github.com/paritytech/parity/pull/3807) -- Extended publishing of libraries to npm [#3786](https://github.com/paritytech/parity/pull/3786) -- Several Fixes to the UI [#3799](https://github.com/paritytech/parity/pull/3799) -- Remove "s [#3805](https://github.com/paritytech/parity/pull/3805) -- Extract CSS to file in production builds [#3783](https://github.com/paritytech/parity/pull/3783) -- Notify user on transaction received [#3782](https://github.com/paritytech/parity/pull/3782) -- Removing all old entries from transaction queue [#3772](https://github.com/paritytech/parity/pull/3772) -- Status page updates [#3774](https://github.com/paritytech/parity/pull/3774) -- Allow modifications of gas when confirming in signer [#3798](https://github.com/paritytech/parity/pull/3798) -- Network connectivity fixes [#3794](https://github.com/paritytech/parity/pull/3794) -- Make *ID names consistent with std Rust (Id) [#3781](https://github.com/paritytech/parity/pull/3781) -- Update CI builds [#3780](https://github.com/paritytech/parity/pull/3780) -- Update AuthorityRound tests to new spec [#3790](https://github.com/paritytech/parity/pull/3790) -- Fixes to the Wallet UI [#3787](https://github.com/paritytech/parity/pull/3787) -- Add support for wallets without getOwner() interface [#3779](https://github.com/paritytech/parity/pull/3779) -- Update Material-UI [#3785](https://github.com/paritytech/parity/pull/3785) -- Fixes error in Transfer modal [#3788](https://github.com/paritytech/parity/pull/3788) -- LES Part 3: Event handlers and handling responses [#3755](https://github.com/paritytech/parity/pull/3755) -- Basic UI rendering tests [#3743](https://github.com/paritytech/parity/pull/3743) -- Network: process packets only after connection handler finishes [#3776](https://github.com/paritytech/parity/pull/3776) -- AuthorityRound network simulation test [#3778](https://github.com/paritytech/parity/pull/3778) -- GasPrice selection for contract execution [#3770](https://github.com/paritytech/parity/pull/3770) -- Reject existing transactions [#3762](https://github.com/paritytech/parity/pull/3762) -- Allow autoRemove from api.subscribe based on callback return values [#3752](https://github.com/paritytech/parity/pull/3752) -- Replace misplaced & with && in gitlab-ci.yml [#3753](https://github.com/paritytech/parity/pull/3753) -- Lower gas usage for creating a Multisig Wallet [#3773](https://github.com/paritytech/parity/pull/3773) -- Added IO service explicit stop [#3761](https://github.com/paritytech/parity/pull/3761) -- Be lenient around invalid owners map [#3764](https://github.com/paritytech/parity/pull/3764) -- GasEditor component [#3750](https://github.com/paritytech/parity/pull/3750) -- Cleanups [#3742](https://github.com/paritytech/parity/pull/3742) -- Update babel, fix CI build due to breaking changes [#3754](https://github.com/paritytech/parity/pull/3754) -- Small fixes to contract [#3751](https://github.com/paritytech/parity/pull/3751) -- Make engine hold AccountProvider [#3725](https://github.com/paritytech/parity/pull/3725) -- Properly delete addresses/contracts in addressbook [#3739](https://github.com/paritytech/parity/pull/3739) -- Display Wallet Owners Icons in Accounts list [#3741](https://github.com/paritytech/parity/pull/3741) -- Edit Multisig Wallet settings [#3740](https://github.com/paritytech/parity/pull/3740) -- Replace build directory completely [#3748](https://github.com/paritytech/parity/pull/3748) -- Add existing release files before merge [#3747](https://github.com/paritytech/parity/pull/3747) -- Release script back to using fetch/merge [#3746](https://github.com/paritytech/parity/pull/3746) -- Update with -X only for merge [#3745](https://github.com/paritytech/parity/pull/3745) -- Give accounts precedence over address_book entries [#3732](https://github.com/paritytech/parity/pull/3732) -- Enable Panic=abort [#3423](https://github.com/paritytech/parity/pull/3423) -- Cleanups on js-precompiled [#3738](https://github.com/paritytech/parity/pull/3738) -- Add parity_removeAddress RPC [#3735](https://github.com/paritytech/parity/pull/3735) -- Fix up the transaction JSON serialisation for RPC. [#3633](https://github.com/paritytech/parity/pull/3633) -- Queue: CLI for auto-scaling and num verifiers [#3709](https://github.com/paritytech/parity/pull/3709) -- Add functionalities to multi-sig wallet [#3729](https://github.com/paritytech/parity/pull/3729) -- PropTypes as function call [#3731](https://github.com/paritytech/parity/pull/3731) -- Unify proptypes in util/proptypes.js [#3728](https://github.com/paritytech/parity/pull/3728) -- Bump jsonrpc-ipc-server to fix windows build [#3730](https://github.com/paritytech/parity/pull/3730) -- LES Part 2 [#3527](https://github.com/paritytech/parity/pull/3527) -- First draft of the MultiSig Wallet [#3700](https://github.com/paritytech/parity/pull/3700) -- Engine block ordering [#3719](https://github.com/paritytech/parity/pull/3719) -- Use fdlimit utility crate from crates.io [#3716](https://github.com/paritytech/parity/pull/3716) -- Move decoding for contract deployment logic earlier [#3714](https://github.com/paritytech/parity/pull/3714) -- Possible fix for queue drop deadlock [#3702](https://github.com/paritytech/parity/pull/3702) -- Encode networkid as a u64. [#3713](https://github.com/paritytech/parity/pull/3713) -- Use valid RLP in generic genesis seal spec [#3717](https://github.com/paritytech/parity/pull/3717) -- Update JS dependencies [#3710](https://github.com/paritytech/parity/pull/3710) -- Use Webpack Aliases [#3711](https://github.com/paritytech/parity/pull/3711) -- Dapps-specific accounts [#3627](https://github.com/paritytech/parity/pull/3627) -- Signer method parameter decoding & destination info [#3671](https://github.com/paritytech/parity/pull/3671) -- Remove invalid slice test [#3712](https://github.com/paritytech/parity/pull/3712) -- React library update [#3704](https://github.com/paritytech/parity/pull/3704) -- New Loading Component for the UI [#3707](https://github.com/paritytech/parity/pull/3707) -- Refactoring Transfer Modal [#3705](https://github.com/paritytech/parity/pull/3705) -- Fix extra scrollbars in dapps [#3706](https://github.com/paritytech/parity/pull/3706) -- Indent state tests [#3431](https://github.com/paritytech/parity/pull/3431) -- Filter null transactions for display (not available on node) [#3698](https://github.com/paritytech/parity/pull/3698) -- Move recovery phrase print button [#3697](https://github.com/paritytech/parity/pull/3697) -- Fix padding bottom needed after fixed status [#3701](https://github.com/paritytech/parity/pull/3701) -- Don't share the snapshot while downloading old blocks [#3695](https://github.com/paritytech/parity/pull/3695) -- Button to print recovery phrase [#3694](https://github.com/paritytech/parity/pull/3694) -- Fix status bar to bottom of the screen [#3692](https://github.com/paritytech/parity/pull/3692) -- Splitting serialization of signTransaction and sendTransaction confirmation requests [#3642](https://github.com/paritytech/parity/pull/3642) -- Implement basic badges/certifications/flair [#3665](https://github.com/paritytech/parity/pull/3665) -- Simplify Container title rendering [#3680](https://github.com/paritytech/parity/pull/3680) -- Update loading splash to fit in with l&f [#3685](https://github.com/paritytech/parity/pull/3685) -- Safari UI fixes [#3678](https://github.com/paritytech/parity/pull/3678) -- Remove strict mode for DappReg (work-around for package upgrade) [#3681](https://github.com/paritytech/parity/pull/3681) -- Bumping clippy [#3654](https://github.com/paritytech/parity/pull/3654) -- Return of the Fat DB [#3636](https://github.com/paritytech/parity/pull/3636) -- Invalidate blocks from future [#3652](https://github.com/paritytech/parity/pull/3652) -- Make Modal always scrollable [#3667](https://github.com/paritytech/parity/pull/3667) -- Display local/completed transactions [#3630](https://github.com/paritytech/parity/pull/3630) -- Added build-essential dep to dockerfiles [#3666](https://github.com/paritytech/parity/pull/3666) -- Strict config parsing (uknown keys are rejected) [#3663](https://github.com/paritytech/parity/pull/3663) -- Strict deserialization [#3662](https://github.com/paritytech/parity/pull/3662) -- Disable peer if no common block found [#3655](https://github.com/paritytech/parity/pull/3655) -- Show snackbar on password change [#3661](https://github.com/paritytech/parity/pull/3661) -- Bring back PV62 support [#3660](https://github.com/paritytech/parity/pull/3660) -- Unlock expecting quantity [#3659](https://github.com/paritytech/parity/pull/3659) -- Update Webpack => v2 [#3643](https://github.com/paritytech/parity/pull/3643) -- Update SMS verification [#3579](https://github.com/paritytech/parity/pull/3579) -- Simplify tx confirmations display [#3559](https://github.com/paritytech/parity/pull/3559) -- Fixes overflow in Signer tx data [#3657](https://github.com/paritytech/parity/pull/3657) -- Fixed tab bar not updating [#3653](https://github.com/paritytech/parity/pull/3653) -- Set default min tx price to $0.0025 [#3617](https://github.com/paritytech/parity/pull/3617) -- Use accountsInfo instead of eth_accounts for first check [#3618](https://github.com/paritytech/parity/pull/3618) -- Fix Copy to Clipboard Snackbar [#3619](https://github.com/paritytech/parity/pull/3619) -- Manually add \r to Windows phrases pre 1.4.5 [#3615](https://github.com/paritytech/parity/pull/3615) -- Signer layouts to flexbox [#3600](https://github.com/paritytech/parity/pull/3600) -- Fixing wrong tokens type in Redux store [#3621](https://github.com/paritytech/parity/pull/3621) -- Add dappreg link to apps list [#3568](https://github.com/paritytech/parity/pull/3568) -- Smarter balance fetching [#3605](https://github.com/paritytech/parity/pull/3605) -- Dapp iframe allow forms, allow target=_blank [#3597](https://github.com/paritytech/parity/pull/3597) -- Align copy button to input field [#3604](https://github.com/paritytech/parity/pull/3604) -- Appending logs by default [#3609](https://github.com/paritytech/parity/pull/3609) -- Update test, fix number. [#3612](https://github.com/paritytech/parity/pull/3612) -- Fixing phrases generated on windows [#3614](https://github.com/paritytech/parity/pull/3614) -- Check for network ID for live/test matching [#3602](https://github.com/paritytech/parity/pull/3602) -- Always insert traces for genesis. [#3603](https://github.com/paritytech/parity/pull/3603) -- Real deleting accounts [#3540](https://github.com/paritytech/parity/pull/3540) -- Trim whitespace from input recovery phrase [#3599](https://github.com/paritytech/parity/pull/3599) -- Fix local tx requests [#3589](https://github.com/paritytech/parity/pull/3589) -- Fix CPU usage when idle [#3592](https://github.com/paritytech/parity/pull/3592) -- Don't fetch balances on every new block if syncing [#3591](https://github.com/paritytech/parity/pull/3591) -- Work around WS in UI [#3587](https://github.com/paritytech/parity/pull/3587) -- CLI option to disable ancient block downloading [#3573](https://github.com/paritytech/parity/pull/3573) -- Move Signer balance queries to store for component-wide re-use [#3531](https://github.com/paritytech/parity/pull/3531) -- Fix wrong method name in `contract.js` [#3580](https://github.com/paritytech/parity/pull/3580) -- Smarter Tokens fetching [#3546](https://github.com/paritytech/parity/pull/3546) -- Fix panic on importing own invalid transaction [#3550](https://github.com/paritytech/parity/pull/3550) -- Use an adaptive number of threads in the verification queue [#2445](https://github.com/paritytech/parity/pull/2445) -- Faster UI - React Tweaks [#3555](https://github.com/paritytech/parity/pull/3555) -- Send value & contract execute gas limit warnings [#3512](https://github.com/paritytech/parity/pull/3512) -- Add TxQueue visibility specifier (not added between merges) [#3566](https://github.com/paritytech/parity/pull/3566) -- DappRegistry [#3405](https://github.com/paritytech/parity/pull/3405) -- Import account message [#3552](https://github.com/paritytech/parity/pull/3552) -- --testnet set to ropsten [#3551](https://github.com/paritytech/parity/pull/3551) -- Fix flaky test [#3547](https://github.com/paritytech/parity/pull/3547) -- Sms verification code style [#3564](https://github.com/paritytech/parity/pull/3564) -- [Registry] Clear input and working buttons [#3563](https://github.com/paritytech/parity/pull/3563) -- Fix peers not displaying [#3561](https://github.com/paritytech/parity/pull/3561) -- New registry contract address for ropsten [#3549](https://github.com/paritytech/parity/pull/3549) -- Use contract Registry fee, not a hard-coded value [#3554](https://github.com/paritytech/parity/pull/3554) -- Don't query chain in Signer, use Redux isTest [#3524](https://github.com/paritytech/parity/pull/3524) -- Moving fetching of hash-addressed dapps/content to separate crate. [#3543](https://github.com/paritytech/parity/pull/3543) -- Ropsten network [#3539](https://github.com/paritytech/parity/pull/3539) -- Add simple one-line installer to README.md [#3534](https://github.com/paritytech/parity/pull/3534) -- Propagations & local transactions tracking [#3491](https://github.com/paritytech/parity/pull/3491) -- Correct format of eth_signTransaction [#3503](https://github.com/paritytech/parity/pull/3503) -- ABI can be empty and auto-fill contract name [#3518](https://github.com/paritytech/parity/pull/3518) -- Fix versions for NPM [#3516](https://github.com/paritytech/parity/pull/3516) -- Better GHH event display & tracking [#3498](https://github.com/paritytech/parity/pull/3498) -- Dapp section & visibility changes [#3438](https://github.com/paritytech/parity/pull/3438) -- Fix parity.js badly built [#3526](https://github.com/paritytech/parity/pull/3526) -- Updated the european warp bootnode addresses [#3528](https://github.com/paritytech/parity/pull/3528) -- Limit sync reorg to 20 blocks [#3519](https://github.com/paritytech/parity/pull/3519) -- Revert "Limit sync reorganization to 20 blocks" [#3517](https://github.com/paritytech/parity/pull/3517) -- Check transaction signature when adding to the queue [#3508](https://github.com/paritytech/parity/pull/3508) -- Limit sync reorganization to 20 blocks [#3509](https://github.com/paritytech/parity/pull/3509) -- Keep track of block gasLimit [#3506](https://github.com/paritytech/parity/pull/3506) -- Smarter Status Polling [#3504](https://github.com/paritytech/parity/pull/3504) -- Handle solc combined output [#3496](https://github.com/paritytech/parity/pull/3496) -- Wallet names shouldn't use UUID [#3481](https://github.com/paritytech/parity/pull/3481) -- Make parity.js usable by Node and Browser [#3475](https://github.com/paritytech/parity/pull/3475) -- Sms verification modal [#3336](https://github.com/paritytech/parity/pull/3336) -- Sudo -c is not supported on Mac [#3488](https://github.com/paritytech/parity/pull/3488) -- Add trace_{call, rawTransaction, replayTransaction} [#3492](https://github.com/paritytech/parity/pull/3492) -- Check for possible panics in scrypt key derivation [#3490](https://github.com/paritytech/parity/pull/3490) -- Sync traffic optimization [#3477](https://github.com/paritytech/parity/pull/3477) -- Wallet files shouldn't give away the address [#3378](https://github.com/paritytech/parity/pull/3378) -- Fixing tests, fixing refreshing precompiled [#3483](https://github.com/paritytech/parity/pull/3483) -- Better Errors Snackbar in UI [#3478](https://github.com/paritytech/parity/pull/3478) -- Handle Signer Rejection [#3476](https://github.com/paritytech/parity/pull/3476) -- Enhanced MethodDecoding in Transactions list [#3454](https://github.com/paritytech/parity/pull/3454) -- Signer new-token generates a link and opens browser [#3379](https://github.com/paritytech/parity/pull/3379) -- Make tokenreg dapp fast again [#3474](https://github.com/paritytech/parity/pull/3474) -- Build fix [#3470](https://github.com/paritytech/parity/pull/3470) -- Display deployed Basic token addresses [#3447](https://github.com/paritytech/parity/pull/3447) -- Export accounts as JSON or CSV [#2866](https://github.com/paritytech/parity/pull/2866) -- Set HF2 block number [#3466](https://github.com/paritytech/parity/pull/3466) -- Better word list for secret phrase generation [#3461](https://github.com/paritytech/parity/pull/3461) -- Drop spec when no longer useful [#3460](https://github.com/paritytech/parity/pull/3460) -- Add fallback check in ABI validation [#3459](https://github.com/paritytech/parity/pull/3459) -- Save sort order in LocalStorage [#3457](https://github.com/paritytech/parity/pull/3457) -- Adds onPaste event to Inputs [#3456](https://github.com/paritytech/parity/pull/3456) -- Update signer to take care of text overflows [#3450](https://github.com/paritytech/parity/pull/3450) -- Authority round consensus engine [#3426](https://github.com/paritytech/parity/pull/3426) -- Fix transfer token decimal calculation [#3445](https://github.com/paritytech/parity/pull/3445) -- Restrict max code size for EIP-150 and after. [#3363](https://github.com/paritytech/parity/pull/3363) -- Contract queries should display IdentityIcons [#3453](https://github.com/paritytech/parity/pull/3453) -- Use Babel in vendor when needed [#3451](https://github.com/paritytech/parity/pull/3451) -- Use signature of functions instead of names [#3448](https://github.com/paritytech/parity/pull/3448) -- Handle contract constructor inputs [#3430](https://github.com/paritytech/parity/pull/3430) -- Use Contract owner for unregistering Token [#3446](https://github.com/paritytech/parity/pull/3446) -- Create directories only if feature is enabled [#3442](https://github.com/paritytech/parity/pull/3442) -- Import AddresBook from exported JSON [#3433](https://github.com/paritytech/parity/pull/3433) -- Scrollable accounts in autocomplete [#3427](https://github.com/paritytech/parity/pull/3427) -- Bump ws-rs [#3428](https://github.com/paritytech/parity/pull/3428) -- Swap TokenReg dapp from base to decimals [#3425](https://github.com/paritytech/parity/pull/3425) -- Change beta builds to stable on Travis [#3421](https://github.com/paritytech/parity/pull/3421) -- Refactor copy to clipboard functionality [#3420](https://github.com/paritytech/parity/pull/3420) -- Dev chain [#3385](https://github.com/paritytech/parity/pull/3385) -- Fetch known code from the database during restoration [#3377](https://github.com/paritytech/parity/pull/3377) -- Fixing benches [#3422](https://github.com/paritytech/parity/pull/3422) -- Fix chainspec storage field. [#3406](https://github.com/paritytech/parity/pull/3406) -- Abort snapshot restoration faster [#3356](https://github.com/paritytech/parity/pull/3356) -- Remove addresses, display non-refundable warning on registries [#3403](https://github.com/paritytech/parity/pull/3403) -- Don't auto-unsubscribe when subscriber callback throws [#3401](https://github.com/paritytech/parity/pull/3401) -- Fix dapp account selection [#3399](https://github.com/paritytech/parity/pull/3399) -- Fix travis build: remove unused import [#3381](https://github.com/paritytech/parity/pull/3381) -- Optimize memory footprint [#3376](https://github.com/paritytech/parity/pull/3376) -- Fixing parsing passwords from file [#3367](https://github.com/paritytech/parity/pull/3367) -- Remove some unwraps from parity/helpers [#3364](https://github.com/paritytech/parity/pull/3364) -- Load external, builtin & local apps in parallel [#3340](https://github.com/paritytech/parity/pull/3340) -- Solidity Compiler in UI [#3279](https://github.com/paritytech/parity/pull/3279) -- Determine real-time HTTP connected status [#3335](https://github.com/paritytech/parity/pull/3335) -- Clarify error message about disabled Signer [#3359](https://github.com/paritytech/parity/pull/3359) -- Cater for home.parity hostname in dappsUrl [#3341](https://github.com/paritytech/parity/pull/3341) -- Make sure Token is ECR20 [#3347](https://github.com/paritytech/parity/pull/3347) -- [TokenReg dApp] Fixed Unregister for Contract Owner only [#3346](https://github.com/paritytech/parity/pull/3346) -- LES Part 1 [#3322](https://github.com/paritytech/parity/pull/3322) -- Make transactions load [#3348](https://github.com/paritytech/parity/pull/3348) -- Manual bump package.json [#3345](https://github.com/paritytech/parity/pull/3345) -- Windows app and installer fixes [#3338](https://github.com/paritytech/parity/pull/3338) -- Fix JS API test [#3342](https://github.com/paritytech/parity/pull/3342) -- Git pre-push checks for UI [#3072](https://github.com/paritytech/parity/pull/3072) -- Disarm the HF and add more bootnodes [#3323](https://github.com/paritytech/parity/pull/3323) -- Default contract type on UI [#3310](https://github.com/paritytech/parity/pull/3310) -- In-browser signing support [#3231](https://github.com/paritytech/parity/pull/3231) -- Handle redirects from /api/content on manifest.json gracefully [#3315](https://github.com/paritytech/parity/pull/3315) -- Dapps interface RPC [#3311](https://github.com/paritytech/parity/pull/3311) -- Additional snapshot sync checks [#3318](https://github.com/paritytech/parity/pull/3318) -- Fix spurious signer tests failures [#3312](https://github.com/paritytech/parity/pull/3312) -- Fix signer token updates [#3302](https://github.com/paritytech/parity/pull/3302) -- Update account recovery phrase hint [#3316](https://github.com/paritytech/parity/pull/3316) -- New transaction tests [#3313](https://github.com/paritytech/parity/pull/3313) -- Remove 127.0.0.1 references [#3303](https://github.com/paritytech/parity/pull/3303) -- Fix for opening UI after installation on mac [#3300](https://github.com/paritytech/parity/pull/3300) -- Fixed uncle query [#3299](https://github.com/paritytech/parity/pull/3299) -- Updated blance display with max decimals [#3266](https://github.com/paritytech/parity/pull/3266) -- Refactoring Signer to auto_args + eth_signTransaction [#3261](https://github.com/paritytech/parity/pull/3261) -- Fix typo [#3298](https://github.com/paritytech/parity/pull/3298) -- Change to more common focused spelling [#3264](https://github.com/paritytech/parity/pull/3264) -- Manual bump of package.json (recovery) [#3295](https://github.com/paritytech/parity/pull/3295) -- Fix initial token generation [#3289](https://github.com/paritytech/parity/pull/3289) -- Fixed IO service shutdown [#3286](https://github.com/paritytech/parity/pull/3286) -- Autostart setting for windows tray app [#3269](https://github.com/paritytech/parity/pull/3269) -- Fixes for 1.4 [#3260](https://github.com/paritytech/parity/pull/3260) -- Build tray app for x64 [#3255](https://github.com/paritytech/parity/pull/3255) -- Add secure flag back [#3244](https://github.com/paritytech/parity/pull/3244) -- Verify chunk hashes in cli restore [#3241](https://github.com/paritytech/parity/pull/3241) -- Load network apps manifests as contentHash (no coding) [#3235](https://github.com/paritytech/parity/pull/3235) -- Fixed some typos [#3236](https://github.com/paritytech/parity/pull/3236) -- Rename cli and config options signer->ui [#3232](https://github.com/paritytech/parity/pull/3232) -- Add store for dapps state [#3211](https://github.com/paritytech/parity/pull/3211) -- Fix first-time tagging of contracts [#3222](https://github.com/paritytech/parity/pull/3222) -- Fix /parity-utils/{web3,parity}.js webpack errors [#3221](https://github.com/paritytech/parity/pull/3221) -- Improve 'invalid raw key' error msg [#3219](https://github.com/paritytech/parity/pull/3219) -- Cleaning up polluted namespaces [#3143](https://github.com/paritytech/parity/pull/3143) -- Set passive mode for first run only [#3214](https://github.com/paritytech/parity/pull/3214) -- Parity configuration settings, i.e. mode [#3212](https://github.com/paritytech/parity/pull/3212) -- Ethash unsafety cleanup [#3210](https://github.com/paritytech/parity/pull/3210) -- Mode improvements for UI [#3109](https://github.com/paritytech/parity/pull/3109) -- Delay bomb for Classic (ECIP-1010) [#3179](https://github.com/paritytech/parity/pull/3179) -- Use ethcore_dappsPort when constructing URLs [#3139](https://github.com/paritytech/parity/pull/3139) -- Add copy address button to Contract deploy [#3199](https://github.com/paritytech/parity/pull/3199) -- Expose Parity api as window.secureApi [#3207](https://github.com/paritytech/parity/pull/3207) -- Add error for sendRawTransaction and estimateGas [#3194](https://github.com/paritytech/parity/pull/3194) -- Exposing engine extra info in block RPC [#3169](https://github.com/paritytech/parity/pull/3169) -- V1.5 [#3195](https://github.com/paritytech/parity/pull/3195) -- Remove dapp logos (GHH points to dapp-assets) [#3192](https://github.com/paritytech/parity/pull/3192) -- Fixing possible race in ethcore_hashContent [#3191](https://github.com/paritytech/parity/pull/3191) -- Bump package.json version (1.5 is master) [#3193](https://github.com/paritytech/parity/pull/3193) - -## Parity [v1.4.10](https://github.com/paritytech/parity/releases/tag/v1.4.10) (2017-01-18) - -Parity 1.4.10 is a first stable release of 1.4.x series. It includes a few minor networking fixes. - -- Gas_limit for blocks, mined by Parity will be divisible by 37 (#4154) [#4179](https://github.com/paritytech/parity/pull/4179) - - gas_limit for new blocks will divide evenly by 13 - - increased PARITY_GAS_LIMIT_DETERMINANT to 37 - - separate method for marking mined block - - debug_asserts(gas_limit within protocol range) - - round_block_gas_limit method is now static - - made round_block_gas_limit free-function - - multiplier->multiple -- Backporing to 1.4.10-stable [#4110](https://github.com/paritytech/parity/pull/4110) - - Bump to v1.4.10 - - No reorg limit for ancient blocks - - Update registration after every write - -## Parity [v1.4.9](https://github.com/paritytech/parity/releases/tag/v1.4.9) (2017-01-09) - -This fixes an issue introduced in 1.4.8 that causes Parity to panic on propagating transactions in some cases. - -- v1.4.9 in beta [#4097](https://github.com/paritytech/parity/pull/4097) - - Bump to v1.4.9 - - Disable armv6 build -- beta Fix queue deadlock [#4095](https://github.com/paritytech/parity/pull/4095) -- Fix rebroadcast panic beta [#4085](https://github.com/paritytech/parity/pull/4085) - - fix compile - - fix backport - - clean up old method - - remove unnecessary reference - - simplify - - Fixing 'simplify' - -## Parity [v1.4.8](https://github.com/paritytech/parity/releases/tag/v1.4.8) (2017-01-06) - -Ethereum Classic Hard Fork ready release containing various bugfixes: - -- Fix for excessive transactions propagation -- Fix for inconsistent `logIndex` in transaction receipts - -See [full list of changes](https://github.com/paritytech/parity/compare/v1.4.7...v1.4.8): - -- Beta backports [#4067](https://github.com/paritytech/parity/pull/4067) -- Re-broadcast transactions to few random peers on each new block. (#4054) [#4061](https://github.com/paritytech/parity/pull/4061) -- Tolerate errors in user_defaults [#4060](https://github.com/paritytech/parity/pull/4060) -- ETC Config change backport [#4056](https://github.com/paritytech/parity/pull/4056) -- [beta] Avoid re-broadcasting transactions on each block [#4047](https://github.com/paritytech/parity/pull/4047) -- Beta Backports [#4012](https://github.com/paritytech/parity/pull/4012) - -## Parity [v1.4.7](https://github.com/paritytech/parity/releases/tag/v1.4.7) (2016-12-27) - -This maintenance release fixes an issue with sync falling behind occasionally. - -- Backporting to beta [#3980](https://github.com/paritytech/parity/pull/3980) -- [beta] enforce gas limit falls within engine bounds [#3816](https://github.com/paritytech/parity/pull/3816) - - -## Parity [v1.3.15](https://github.com/paritytech/parity/releases/tag/v1.3.15) (2016-12-10) - -This patch release fixes an issue with syncing on the Ropsten test network. - -- Backporting to stable [#3793](https://github.com/paritytech/parity/pull/3793) - -## Parity [v1.4.6](https://github.com/paritytech/parity/releases/tag/v1.4.6) (2016-12-05) - -This patch release fixes an issue with syncing on the Ropsten test network. - -- Backporting to beta [#3718](https://github.com/paritytech/parity/pull/3718) -- [beta] scrollable contract deploy & execute modals [#3656](https://github.com/paritytech/parity/pull/3656) - -## Parity [v1.4.5](https://github.com/paritytech/parity/releases/tag/v1.4.5) (2016-11-26) - -1.4.5 release fixes a number of issues, notably: -- High CPU usage when idle. -- Key recovery phrases generated on windows now can be imported. - -#### Configuration changes -- `--usd-per-tx` is now set to 0.0025 by default. - -#### New features -- Support for Ropsten test network is introduced with `--chain=ropsten` or `--testnet`. Morden network is still available via `--chain=morden` - -#### Full changes -- [beta] Pin package versions for React [#3628](https://github.com/paritytech/parity/pull/3628) -- Backporting to beta [#3623](https://github.com/paritytech/parity/pull/3623) -- [beta] Ropsten chain for UI [#3622](https://github.com/paritytech/parity/pull/3622) - -## Parity [v1.3.14](https://github.com/paritytech/parity/releases/tag/v1.3.14) (2016-11-25) - -Parity 1.3.14 fixes a few stability issues and adds support for the Ropsten testnet. - -- Backporting to stable [#3616](https://github.com/paritytech/parity/pull/3616) - -## Parity [v1.4.4](https://github.com/paritytech/parity/releases/tag/v1.4.4) (2016-11-18) - -This is a maintenance release that fixes an issue with EIP-155 transactions being added to the transaction pool. It also improves syncing stability and resolved a number of UI issues. -Full changelog is available [here.](https://github.com/paritytech/parity/commit/3e0d033eaf789cfdf517f4a97effc500f1f9263b) - -- [beta] apps typo fix [#3533](https://github.com/paritytech/parity/pull/3533) -- Backporting to beta [#3525](https://github.com/paritytech/parity/pull/3525) - -## Parity [v1.3.13](https://github.com/paritytech/parity/releases/tag/v1.3.13) (2016-11-18) - -This release fixes an issue with EIP-155 transactions being allowed into the transaction pool. - -- [stable] Check tx signatures before adding to the queue. [#3521](https://github.com/paritytech/parity/pull/3521) -- Fix Stable Docker Build [#3479](https://github.com/paritytech/parity/pull/3479) - -## Parity [v1.4.3](https://github.com/paritytech/parity/releases/tag/v1.4.3) (2016-11-16) - -This release includes memory footprint optimization as well as a few fixes in the UI. -EIP-155/160/161/170 hardfork is enabled at block 2675000 (1885000 for test network). -Full changelog is available [here.](https://github.com/paritytech/parity/compare/v1.4.2...v1.4.3) - -- [beta] EIP-170 [#3464](https://github.com/paritytech/parity/pull/3464) -- Backports to beta [#3465](https://github.com/paritytech/parity/pull/3465) -- Backport: additional fields on transaction and receipt [#3463](https://github.com/paritytech/parity/pull/3463) -- v1.4.3 in beta [#3424](https://github.com/paritytech/parity/pull/3424) - - -## Parity [v1.3.12](https://github.com/paritytech/parity/releases/tag/v1.3.12) (2016-11-16) - -This stable release enables EIP-155/160/161/170 hardfork at block 2675000 (1885000 for test network). - -- [stable] EIP-170 [#3462](https://github.com/paritytech/parity/pull/3462) -- #3035 Backport to stable [#3441](https://github.com/paritytech/parity/pull/3441) - -## Parity [v1.3.11](https://github.com/paritytech/parity/releases/tag/v1.3.11) (2016-11-11) - -This is a maintenance release for the stable series to delay the EIP-155/160/161 hard fork transition. **Update from 1.3.10 is mandatory**. It also deprecates and disables the old Parity UI. - -- [stable] Disable HF and UI [#3372](https://github.com/paritytech/parity/pull/3372) -- [stable] EIP-155 update with Vitalik's new test vectors (#3166) [#3190](https://github.com/paritytech/parity/pull/3190) -- Backport EIP-150 to stable [#2672](https://github.com/paritytech/parity/pull/2672) -- Create gitlab-ci.yml for stable [#2517](https://github.com/paritytech/parity/pull/2517) - -## Parity [v1.4.2](https://github.com/paritytech/parity/releases/tag/v1.4.2) (2016-11-10) - -This release fixes a few additional issues: -- Parity now correctly handles external `--dapps-interface` and `--ui-interface` in the UI. -- Crash in `eth_getUncle*` has been fixed. -- macOS installer now includes an uninstall script. -- Security token input UI has been fixed. -- Correct display for tokens with minimum decimals. - -And some additional minor changes. Full changelog is [available](https://github.com/paritytech/parity/compare/v1.4.1...v1.4.2) -- Backporting to beta [#3344](https://github.com/paritytech/parity/pull/3344) -- Backporting to beta [#3324](https://github.com/paritytech/parity/pull/3324) - -## Parity [v1.4.1](https://github.com/paritytech/parity/releases/tag/v1.4.1) (2016-11-09) - -This is a hotfix release to address a couple of issues with 1.4.0: - -- UI token is requested instead of being supplied automatically. -- Running with `--geth` results in an error. - -- Backporting to beta [#3293](https://github.com/paritytech/parity/pull/3293) - -## Parity [v1.4.0](https://github.com/paritytech/parity/releases/tag/v1.4.0) (2016-11-07) - -First beta release of the 1.4 series. - -This includes the new Parity Wallet and Warp-Sync synchronisation as well as several optimisations and fixes. - -- Add secure flag back [#3246](https://github.com/paritytech/parity/pull/3246) -- [BETA] verify chunk hashes in cli restore [#3242](https://github.com/paritytech/parity/pull/3242) -- Backporting to beta [#3239](https://github.com/paritytech/parity/pull/3239) -- UI fixes backporting [#3234](https://github.com/paritytech/parity/pull/3234) -- Backporting to beta [#3229](https://github.com/paritytech/parity/pull/3229) -- Beta branch cleanup [#3226](https://github.com/paritytech/parity/pull/3226) -- [beta] Set passive mode for first run only (#3214) [#3216](https://github.com/paritytech/parity/pull/3216) -- Mode configuration backported to beta [#3213](https://github.com/paritytech/parity/pull/3213) -- Backporting [#3198](https://github.com/paritytech/parity/pull/3198) -- [beta] EIP-155 update with Vitalik's new test vectors (#3166) [#3189](https://github.com/paritytech/parity/pull/3189) -- Backporting to beta [#3176](https://github.com/paritytech/parity/pull/3176) -- parity-ui-precompiled pinned to beta [#3168](https://github.com/paritytech/parity/pull/3168) -- EIP-155 update with Vitalik's new test vectors [#3166](https://github.com/paritytech/parity/pull/3166) -- Push precompiled for beta/stable, npm only master [#3163](https://github.com/paritytech/parity/pull/3163) -- Back to real root after npm publish [#3178](https://github.com/paritytech/parity/pull/3178) -- Remove extra cd js [#3177](https://github.com/paritytech/parity/pull/3177) -- Fixes Gas price selection bug [#3175](https://github.com/paritytech/parity/pull/3175) -- Exposing state root and logsBloom in RPC receipts [#3174](https://github.com/paritytech/parity/pull/3174) -- Exposing v,r,s from transaction signature in RPC [#3172](https://github.com/paritytech/parity/pull/3172) -- Enabling personal RPC over IPC by default [#3165](https://github.com/paritytech/parity/pull/3165) -- Gitlab CI badge [#3164](https://github.com/paritytech/parity/pull/3164) -- Dependencies in README [#3162](https://github.com/paritytech/parity/pull/3162) -- Make the footer a bit less ugly. [#3160](https://github.com/paritytech/parity/pull/3160) -- Linux build case sensitivity fix [#3161](https://github.com/paritytech/parity/pull/3161) -- abbreviated enode, `CopyToClipboard` component [#3131](https://github.com/paritytech/parity/pull/3131) -- EIPs 155, 160, 161 [#2976](https://github.com/paritytech/parity/pull/2976) -- beta reset to 1.4.0 [#3157](https://github.com/paritytech/parity/pull/3157) -- Fix histogram [#3150](https://github.com/paritytech/parity/pull/3150) -- Remove network label from TabBar [#3142](https://github.com/paritytech/parity/pull/3142) -- Speed up unresponsive Contract events & Account transactions [#3145](https://github.com/paritytech/parity/pull/3145) -- Better windows shortcut [#3147](https://github.com/paritytech/parity/pull/3147) -- Redirect content to the same address as requested [#3133](https://github.com/paritytech/parity/pull/3133) -- Fixed peer ping timeout [#3137](https://github.com/paritytech/parity/pull/3137) -- Fix for windows build [#3125](https://github.com/paritytech/parity/pull/3125) -- Fix AddessInput icon position [#3132](https://github.com/paritytech/parity/pull/3132) -- Fixed not scrollable accounts in tokenreg dapp [#3128](https://github.com/paritytech/parity/pull/3128) -- Returning cache headers for network content [#3123](https://github.com/paritytech/parity/pull/3123) -- Optimise contract events display [#3120](https://github.com/paritytech/parity/pull/3120) -- Add basic validation for contract execute values [#3118](https://github.com/paritytech/parity/pull/3118) -- Dapps errors embeddable on signer [#3115](https://github.com/paritytech/parity/pull/3115) -- Use enode RPC in UI [#3108](https://github.com/paritytech/parity/pull/3108) -- Windows tray app [#3103](https://github.com/paritytech/parity/pull/3103) -- Displaying CLI errors on stderr [#3116](https://github.com/paritytech/parity/pull/3116) -- new InputAddressSelect component [#3071](https://github.com/paritytech/parity/pull/3071) -- Bump mio [#3117](https://github.com/paritytech/parity/pull/3117) -- Minor typo fixed. [#3110](https://github.com/paritytech/parity/pull/3110) -- Sort by ETH balance and contract by date [#3107](https://github.com/paritytech/parity/pull/3107) -- Add RPC enode lookup [#3096](https://github.com/paritytech/parity/pull/3096) -- Initializing logger for each command [#3090](https://github.com/paritytech/parity/pull/3090) -- Allow registration of content bundles in GitHubHint [#3094](https://github.com/paritytech/parity/pull/3094) -- Add read-only inputs to UI plus Copy to Clipboard buttons [#3095](https://github.com/paritytech/parity/pull/3095) -- Allow boolean dropdowns for contract deploy [#3077](https://github.com/paritytech/parity/pull/3077) -- Add mac installer files [#2995](https://github.com/paritytech/parity/pull/2995) -- Fixing dapps sorting [#3086](https://github.com/paritytech/parity/pull/3086) -- Add a Gitter chat badge to README.md [#3092](https://github.com/paritytech/parity/pull/3092) -- Fixes webpack HTML loader [#3089](https://github.com/paritytech/parity/pull/3089) -- Redirecting /home to new UI [#3084](https://github.com/paritytech/parity/pull/3084) -- Allow GitHubHint content owner to update url [#3083](https://github.com/paritytech/parity/pull/3083) -- Remove token assets (moved to ethcore/dapps-assets) [#3082](https://github.com/paritytech/parity/pull/3082) -- Goodbye Gavcoin, Hello Gavcoin [#3080](https://github.com/paritytech/parity/pull/3080) -- Load network dapps [#3078](https://github.com/paritytech/parity/pull/3078) -- Swap account phrase input to normal (non-multiline) [#3060](https://github.com/paritytech/parity/pull/3060) -- Fix minor typo in informant [#3056](https://github.com/paritytech/parity/pull/3056) -- Warp sync status display [#3045](https://github.com/paritytech/parity/pull/3045) -- Enhance address input [#3065](https://github.com/paritytech/parity/pull/3065) -- Go to Accounts Page if Tooltips are displayed [#3063](https://github.com/paritytech/parity/pull/3063) -- Change contract Execute bool values & query bool value display [#3024](https://github.com/paritytech/parity/pull/3024) -- Update Parity logo [#3036](https://github.com/paritytech/parity/pull/3036) -- settings: replace background patterns (inline) [#3047](https://github.com/paritytech/parity/pull/3047) -- Multiple line description for dapps [#3058](https://github.com/paritytech/parity/pull/3058) -- Fix status log order [#3062](https://github.com/paritytech/parity/pull/3062) -- Graphical gas price selection [#2898](https://github.com/paritytech/parity/pull/2898) -- [Registry dApp] Actions not available before selecting accounts [#3032](https://github.com/paritytech/parity/pull/3032) -- apply post-consolidation migrations after consolidating [#3020](https://github.com/paritytech/parity/pull/3020) -- fix chain badge padding [#3046](https://github.com/paritytech/parity/pull/3046) -- Don't delete Tags input on blur (eg. tab) [#3044](https://github.com/paritytech/parity/pull/3044) -- Fixing last hashes for ethcall [#3043](https://github.com/paritytech/parity/pull/3043) -- Remove signer icons [#3039](https://github.com/paritytech/parity/pull/3039) -- execute periodic snapshot in new thread [#3029](https://github.com/paritytech/parity/pull/3029) -- fix background of embedded signer [#3026](https://github.com/paritytech/parity/pull/3026) -- registry dapp: fix reducer [#3028](https://github.com/paritytech/parity/pull/3028) -- Replace Execute by Query in contract button [#3031](https://github.com/paritytech/parity/pull/3031) -- Fixing GavCoin dApp overflow issues [#3030](https://github.com/paritytech/parity/pull/3030) -- execute contract function: validate address [#3013](https://github.com/paritytech/parity/pull/3013) -- Align tag inputs with other input boxes [#2965](https://github.com/paritytech/parity/pull/2965) -- Sweep panickers from IO and network [#3018](https://github.com/paritytech/parity/pull/3018) -- Terms & Conditions [#3019](https://github.com/paritytech/parity/pull/3019) -- open column families after reparing db corruption [#3017](https://github.com/paritytech/parity/pull/3017) -- Snapshot sync and block gap info in `eth_syncing` [#2948](https://github.com/paritytech/parity/pull/2948) -- personal_ RPCs to AutoArgs [#3000](https://github.com/paritytech/parity/pull/3000) -- RPCs for mode change [#3002](https://github.com/paritytech/parity/pull/3002) -- Fix a test sensitive to slow execution. [#3014](https://github.com/paritytech/parity/pull/3014) -- Fixes search filtering issues [#3011](https://github.com/paritytech/parity/pull/3011) -- Restart sync if no more peers with snapshots [#3007](https://github.com/paritytech/parity/pull/3007) -- Allow empty/non-existant input arrays for ABIs in contract view [#3001](https://github.com/paritytech/parity/pull/3001) -- Allow operation when no registry is available [#2980](https://github.com/paritytech/parity/pull/2980) -- Make JS lint & test run on Travis [#2894](https://github.com/paritytech/parity/pull/2894) -- Update account dropdowns [#2959](https://github.com/paritytech/parity/pull/2959) -- Modify gas price statistics [#2947](https://github.com/paritytech/parity/pull/2947) -- Fixes pending/mined transactions in registry dApp [#3004](https://github.com/paritytech/parity/pull/3004) -- Prevent connecting to self [#2997](https://github.com/paritytech/parity/pull/2997) -- Disable verbose in gitlab CI [#2999](https://github.com/paritytech/parity/pull/2999) -- Allow warnings in gitlab [#2998](https://github.com/paritytech/parity/pull/2998) -- Fix the brainwallet functionality. [#2994](https://github.com/paritytech/parity/pull/2994) -- Provided gas description update [#2993](https://github.com/paritytech/parity/pull/2993) -- Print messages to stderr [#2991](https://github.com/paritytech/parity/pull/2991) -- Networking and syncing tweaks [#2990](https://github.com/paritytech/parity/pull/2990) -- Allow build warnings [#2985](https://github.com/paritytech/parity/pull/2985) -- Display network status for finished Signer requests [#2983](https://github.com/paritytech/parity/pull/2983) -- Fixed rejecting transactions [#2984](https://github.com/paritytech/parity/pull/2984) -- mio version bump [#2982](https://github.com/paritytech/parity/pull/2982) -- Publish parity.js to npmjs registry [#2978](https://github.com/paritytech/parity/pull/2978) -- Import raw private key [#2945](https://github.com/paritytech/parity/pull/2945) -- refactor etherscan.io links [#2896](https://github.com/paritytech/parity/pull/2896) -- Use separate lock for code cache [#2977](https://github.com/paritytech/parity/pull/2977) -- Add favicon [#2974](https://github.com/paritytech/parity/pull/2974) -- Align password change dialog with create dialog ordering [#2970](https://github.com/paritytech/parity/pull/2970) -- WS bump [#2973](https://github.com/paritytech/parity/pull/2973) -- Discovery performance optimization [#2972](https://github.com/paritytech/parity/pull/2972) -- Pass gas & gasPrice to token transfers [#2964](https://github.com/paritytech/parity/pull/2964) -- Updating ws-rs [#2962](https://github.com/paritytech/parity/pull/2962) -- Run cargo with verbose flag when testing [#2943](https://github.com/paritytech/parity/pull/2943) -- Fixing clippy warnings take two [#2961](https://github.com/paritytech/parity/pull/2961) -- Snapshot sync improvements [#2960](https://github.com/paritytech/parity/pull/2960) -- Gavcoin event display updates [#2956](https://github.com/paritytech/parity/pull/2956) -- Eslint fixes [#2957](https://github.com/paritytech/parity/pull/2957) -- Add import of raw private key RPCs [#2942](https://github.com/paritytech/parity/pull/2942) -- Bring in styling queues from original Gavcoin [#2936](https://github.com/paritytech/parity/pull/2936) -- Validating minimal required gas for a transaction [#2937](https://github.com/paritytech/parity/pull/2937) -- Even more snapshot validity checks [#2935](https://github.com/paritytech/parity/pull/2935) -- Shared code cache [#2921](https://github.com/paritytech/parity/pull/2921) -- Updating bootnodes for ETC [#2938](https://github.com/paritytech/parity/pull/2938) -- More bootnodes [#2926](https://github.com/paritytech/parity/pull/2926) -- Revert hash updates until testable [#2925](https://github.com/paritytech/parity/pull/2925) -- Release.sh verbose output [#2924](https://github.com/paritytech/parity/pull/2924) -- additional release.sh debugging info [#2922](https://github.com/paritytech/parity/pull/2922) -- Pass the js-precompiled commit hash to cargo update [#2920](https://github.com/paritytech/parity/pull/2920) -- Next nonce RPC [#2917](https://github.com/paritytech/parity/pull/2917) -- Get rid of duplicated code in EVM [#2915](https://github.com/paritytech/parity/pull/2915) -- Transaction Queue banning [#2524](https://github.com/paritytech/parity/pull/2524) -- Revert to gas price ordering [#2919](https://github.com/paritytech/parity/pull/2919) -- Personal split [#2879](https://github.com/paritytech/parity/pull/2879) -- Fixing config values for pruning_history [#2918](https://github.com/paritytech/parity/pull/2918) -- Apply pending block details on commit [#2254](https://github.com/paritytech/parity/pull/2254) -- Fixed GetNodeData output [#2892](https://github.com/paritytech/parity/pull/2892) -- New sync protocol ID [#2912](https://github.com/paritytech/parity/pull/2912) -- Clippy bump [#2877](https://github.com/paritytech/parity/pull/2877) -- iconomi token images [#2906](https://github.com/paritytech/parity/pull/2906) -- Fixes too long description and Token balance value in Dapps/Accounts [#2902](https://github.com/paritytech/parity/pull/2902) -- Add missing images for local dapps [#2890](https://github.com/paritytech/parity/pull/2890) -- Fix Webpack, again [#2895](https://github.com/paritytech/parity/pull/2895) -- Enable suicide json test [#2893](https://github.com/paritytech/parity/pull/2893) -- More snapshot fixes and optimizations [#2883](https://github.com/paritytech/parity/pull/2883) -- Fixes CI JS precompiled build [#2886](https://github.com/paritytech/parity/pull/2886) -- Fix empty tags modification [#2884](https://github.com/paritytech/parity/pull/2884) -- Fix up informant. [#2865](https://github.com/paritytech/parity/pull/2865) -- Get rid of MemoryDB denote [#2881](https://github.com/paritytech/parity/pull/2881) -- Add inject to "bundle everything" list [#2871](https://github.com/paritytech/parity/pull/2871) -- Fixes signer and MUI errors throwing [#2876](https://github.com/paritytech/parity/pull/2876) -- Fix failing tests after log parsing updates [#2878](https://github.com/paritytech/parity/pull/2878) -- Sweep some more panics [#2848](https://github.com/paritytech/parity/pull/2848) -- Make GitLab js-precompiled really update Cargo.toml in main repo [#2869](https://github.com/paritytech/parity/pull/2869) -- IPC version bump [#2870](https://github.com/paritytech/parity/pull/2870) -- Snapshot sync fixes and optimizations [#2863](https://github.com/paritytech/parity/pull/2863) -- Add Check and Change Password for an Account [#2861](https://github.com/paritytech/parity/pull/2861) -- Output git fetch/push to log files [#2862](https://github.com/paritytech/parity/pull/2862) -- Align contract event log l&f with transactions [#2812](https://github.com/paritytech/parity/pull/2812) -- Nicer port in use errors [#2859](https://github.com/paritytech/parity/pull/2859) -- Remove personal_* calls from dapps [#2860](https://github.com/paritytech/parity/pull/2860) -- Token sorting, zero-ETH transfer & token decimals [#2805](https://github.com/paritytech/parity/pull/2805) -- Don't fail badly when no transactions in last 100 blocks. [#2856](https://github.com/paritytech/parity/pull/2856) -- Fixing home.parity address for new signer [#2851](https://github.com/paritytech/parity/pull/2851) -- Enabling UI build back [#2853](https://github.com/paritytech/parity/pull/2853) -- Remove eventName in unsubscribe API arguments [#2844](https://github.com/paritytech/parity/pull/2844) -- Don't return empty names as clickable titles [#2809](https://github.com/paritytech/parity/pull/2809) -- Auto-bump js-precompiled on release [#2828](https://github.com/paritytech/parity/pull/2828) -- Remove ethcore::common re-export module [#2792](https://github.com/paritytech/parity/pull/2792) -- Prevent database corruption on OOM [#2832](https://github.com/paritytech/parity/pull/2832) -- Download/Export Addressbook [#2847](https://github.com/paritytech/parity/pull/2847) -- Snapshot and blockchain stability improvements [#2843](https://github.com/paritytech/parity/pull/2843) -- Extended network options [#2845](https://github.com/paritytech/parity/pull/2845) -- fix failing master test build [#2846](https://github.com/paritytech/parity/pull/2846) -- Local dapps embeddable on signer port [#2815](https://github.com/paritytech/parity/pull/2815) -- Trigger accounts/contracts search on search input change [#2838](https://github.com/paritytech/parity/pull/2838) -- Move snapshot sync to a subprotocol [#2820](https://github.com/paritytech/parity/pull/2820) -- fix node log being reversed [#2839](https://github.com/paritytech/parity/pull/2839) -- Fixes currency symbol font size in Shapeshift modal [#2840](https://github.com/paritytech/parity/pull/2840) -- Disable personal APIs by default for security reasons [#2834](https://github.com/paritytech/parity/pull/2834) -- Clear cached content [#2833](https://github.com/paritytech/parity/pull/2833) -- Add ethcore_[dapps|signer]Port APIs [#2821](https://github.com/paritytech/parity/pull/2821) -- CLI option to skip seal check when importing [#2842](https://github.com/paritytech/parity/pull/2842) -- Fix case error in Dapps import [#2837](https://github.com/paritytech/parity/pull/2837) -- Double click on address in account detail view should select it [#2841](https://github.com/paritytech/parity/pull/2841) -- Bump js-precompiled to 20161022-223915 UTC [#2826](https://github.com/paritytech/parity/pull/2826) -- Adjust paths to handle CORS changes [#2816](https://github.com/paritytech/parity/pull/2816) -- RPC for dapps port and signer port [#2819](https://github.com/paritytech/parity/pull/2819) -- Update build to working version on pre-compiled repo [#2825](https://github.com/paritytech/parity/pull/2825) -- Adjust network name badge colours (darker) [#2823](https://github.com/paritytech/parity/pull/2823) -- Removing submodule in favour of rust crate [#2756](https://github.com/paritytech/parity/pull/2756) -- Return old-ish content even when syncing [#2757](https://github.com/paritytech/parity/pull/2757) -- fix Signer UI [#2750](https://github.com/paritytech/parity/pull/2750) -- USG, GBP, Euro & Yuan updates [#2818](https://github.com/paritytech/parity/pull/2818) -- Make locally installed apps available again (Fixes #2771) [#2808](https://github.com/paritytech/parity/pull/2808) -- Additional RPCs for password management [#2779](https://github.com/paritytech/parity/pull/2779) -- flush DB changes on drop [#2795](https://github.com/paritytech/parity/pull/2795) -- rename State::snapshot to checkpoint to avoid confusion [#2796](https://github.com/paritytech/parity/pull/2796) -- Missing changes required to make new UI work [#2793](https://github.com/paritytech/parity/pull/2793) -- Cleanup method decoding (Fixes #2811) [#2810](https://github.com/paritytech/parity/pull/2810) -- Use trace API for decentralized transaction list [#2784](https://github.com/paritytech/parity/pull/2784) -- Automatic compaction selection on Linux [#2785](https://github.com/paritytech/parity/pull/2785) -- Update token images [#2804](https://github.com/paritytech/parity/pull/2804) -- Hackergold token images [#2801](https://github.com/paritytech/parity/pull/2801) -- Additional token images [#2800](https://github.com/paritytech/parity/pull/2800) -- Additional token images [#2798](https://github.com/paritytech/parity/pull/2798) -- Resolve morden fork [#2773](https://github.com/paritytech/parity/pull/2773) -- Using SipHashes from crates.io [#2778](https://github.com/paritytech/parity/pull/2778) -- Fixed issues on Searchable Addresses [#2790](https://github.com/paritytech/parity/pull/2790) -- Currency icons [#2788](https://github.com/paritytech/parity/pull/2788) -- Update token images [#2783](https://github.com/paritytech/parity/pull/2783) -- Fix warning in master [#2775](https://github.com/paritytech/parity/pull/2775) -- Add empty account existence test from beta. [#2769](https://github.com/paritytech/parity/pull/2769) -- Update name of basiccoin manager [#2768](https://github.com/paritytech/parity/pull/2768) -- sweep most unwraps from ethcore crate, dapps crate [#2762](https://github.com/paritytech/parity/pull/2762) -- Check queue to determine major importing [#2763](https://github.com/paritytech/parity/pull/2763) -- Trace filtering fix [#2760](https://github.com/paritytech/parity/pull/2760) -- Update js precompiled to 20161020-141636 [#2761](https://github.com/paritytech/parity/pull/2761) -- Incrementally calculate verification queue heap size [#2749](https://github.com/paritytech/parity/pull/2749) -- Don't add empty accounts to bloom [#2753](https://github.com/paritytech/parity/pull/2753) -- fix contract deployments not showing up [#2759](https://github.com/paritytech/parity/pull/2759) -- Fixes a positioning issue in Address Selection component [#2754](https://github.com/paritytech/parity/pull/2754) -- fix linting issues [#2758](https://github.com/paritytech/parity/pull/2758) -- Making Trie.iter non-recursive [#2733](https://github.com/paritytech/parity/pull/2733) -- Block import optimization [#2748](https://github.com/paritytech/parity/pull/2748) -- Update js-precompiled to 20161020-110858 [#2752](https://github.com/paritytech/parity/pull/2752) -- Fixing small files fetching [#2742](https://github.com/paritytech/parity/pull/2742) -- Fixing stalled sync [#2747](https://github.com/paritytech/parity/pull/2747) -- refactor signer components [#2691](https://github.com/paritytech/parity/pull/2691) -- Png images with backgrounds (original svg) [#2740](https://github.com/paritytech/parity/pull/2740) -- Make address selection searchable [#2739](https://github.com/paritytech/parity/pull/2739) -- very basic dapp add/remove interface [#2721](https://github.com/paritytech/parity/pull/2721) -- Frontport commits from beta to master [#2743](https://github.com/paritytech/parity/pull/2743) -- Implements Trace API Formatter [#2732](https://github.com/paritytech/parity/pull/2732) -- bump parking_lot to 0.3.x series [#2702](https://github.com/paritytech/parity/pull/2702) -- Unify major syncing detection [#2699](https://github.com/paritytech/parity/pull/2699) -- Fixes gas/gasPrice change not reflected in transaction modal [#2735](https://github.com/paritytech/parity/pull/2735) -- Fixing build UI stuff along with Rust [#2726](https://github.com/paritytech/parity/pull/2726) -- Fixed Snackbar not showing and/or behind transactions (#2730) [#2731](https://github.com/paritytech/parity/pull/2731) -- Updating json tests to latest develop commit [#2728](https://github.com/paritytech/parity/pull/2728) -- dapps: show errors [#2727](https://github.com/paritytech/parity/pull/2727) -- node logs: break lines [#2722](https://github.com/paritytech/parity/pull/2722) -- Bumping JSON-RPC http server [#2714](https://github.com/paritytech/parity/pull/2714) -- Add ability to copy address to the clipboard [#2716](https://github.com/paritytech/parity/pull/2716) -- Sort tags when displaying ; use AND for search results [#2720](https://github.com/paritytech/parity/pull/2720) -- allow-same-origin for iframe [#2711](https://github.com/paritytech/parity/pull/2711) -- Update Registry address (mainnet) [#2713](https://github.com/paritytech/parity/pull/2713) -- Allow tags for Accounts, Addresses and Contracts [#2712](https://github.com/paritytech/parity/pull/2712) -- Correct parameters for eth_sign [#2703](https://github.com/paritytech/parity/pull/2703) -- Bump js-precompiled to 20161018-161705 [#2698](https://github.com/paritytech/parity/pull/2698) -- Add inject.js (for web3 exposed) [#2692](https://github.com/paritytech/parity/pull/2692) -- Remove obsolete dapps and update security headers [#2694](https://github.com/paritytech/parity/pull/2694) -- Snapshot sync part 2 [#2098](https://github.com/paritytech/parity/pull/2098) -- Fix issues with no ethereum test dir present (2382) [#2659](https://github.com/paritytech/parity/pull/2659) -- Apply UI PRs after master merge [#2690](https://github.com/paritytech/parity/pull/2690) -- Fix importing traces for non-canon blocks [#2683](https://github.com/paritytech/parity/pull/2683) -- Fixing random test failures [#2577](https://github.com/paritytech/parity/pull/2577) -- Disable IPC in default build for 1.4 [#2657](https://github.com/paritytech/parity/pull/2657) -- use pruning history in CLI snapshots [#2658](https://github.com/paritytech/parity/pull/2658) -- Fixing --no-default-features again and evmbin [#2670](https://github.com/paritytech/parity/pull/2670) -- Settings > Proxy for proxy.pac setup instructions [#2678](https://github.com/paritytech/parity/pull/2678) -- Re-instate transaitions to allow updating busy indicator [#2682](https://github.com/paritytech/parity/pull/2682) -- signer: remove reject counter [#2685](https://github.com/paritytech/parity/pull/2685) -- Initial new UI source code import [#2607](https://github.com/paritytech/parity/pull/2607) -- Additional dapp logo images [#2677](https://github.com/paritytech/parity/pull/2677) -- Redirect from :8080 to :8180 [#2676](https://github.com/paritytech/parity/pull/2676) -- script to update js-precompiled [#2673](https://github.com/paritytech/parity/pull/2673) -- Styling in FF is not 100% [#2669](https://github.com/paritytech/parity/pull/2669) -- Don't allow gavcoin transfer with no balances [#2667](https://github.com/paritytech/parity/pull/2667) -- fix signer rejections [#2666](https://github.com/paritytech/parity/pull/2666) -- better text on unique background pattern [#2664](https://github.com/paritytech/parity/pull/2664) -- Adjust z-index for error overlay [#2662](https://github.com/paritytech/parity/pull/2662) -- Fix address selection for contract deployment [#2660](https://github.com/paritytech/parity/pull/2660) -- Add additional contract images [#2655](https://github.com/paritytech/parity/pull/2655) -- Update /api/* to point to :8080/api/* (first generation interface) [#2612](https://github.com/paritytech/parity/pull/2612) -- Initial import of new UI (compiled JS code) [#2220](https://github.com/paritytech/parity/pull/2220) -- Fixing evmbin compilation [#2652](https://github.com/paritytech/parity/pull/2652) -- Fix up ETC EIP-150 transition to 2,500,000. [#2636](https://github.com/paritytech/parity/pull/2636) -- Fixing compilation without default features [#2638](https://github.com/paritytech/parity/pull/2638) -- [frontport] CLI to specify queue ordering strategy (#2494) [#2623](https://github.com/paritytech/parity/pull/2623) -- Support for decryption in Signer [#2421](https://github.com/paritytech/parity/pull/2421) -- EIP150.1c [#2591](https://github.com/paritytech/parity/pull/2591) -- Release merge with origin with ours strategy [#2631](https://github.com/paritytech/parity/pull/2631) -- Adjust build output directories [#2630](https://github.com/paritytech/parity/pull/2630) -- cater for txhash returning null/empty object [#2629](https://github.com/paritytech/parity/pull/2629) -- snapshot: single byte for empty accounts [#2625](https://github.com/paritytech/parity/pull/2625) -- Configurable history size in master [#2606](https://github.com/paritytech/parity/pull/2606) -- Database performance tweaks [#2619](https://github.com/paritytech/parity/pull/2619) -- Enable suicide json test [#2626](https://github.com/paritytech/parity/pull/2626) -- Split journaldb commit into two functions: journal_under and mark_canonical [#2329](https://github.com/paritytech/parity/pull/2329) -- Fixed tx queue limit for local transactions [#2616](https://github.com/paritytech/parity/pull/2616) -- Additional logs when transactions is removed from queue [#2617](https://github.com/paritytech/parity/pull/2617) -- mitigate refcell conflict in state diffing [#2601](https://github.com/paritytech/parity/pull/2601) -- Fix tests [#2611](https://github.com/paritytech/parity/pull/2611) -- small styling updates [#2610](https://github.com/paritytech/parity/pull/2610) -- Remove web3 from Signer, bring in parity.js API [#2604](https://github.com/paritytech/parity/pull/2604) -- Mostly configurable canonical cache size [#2516](https://github.com/paritytech/parity/pull/2516) -- Added peers details to ethcore_netPeers RPC [#2580](https://github.com/paritytech/parity/pull/2580) -- Display account password hint when available [#2596](https://github.com/paritytech/parity/pull/2596) -- Fix gas estimation on transfer when data supplied [#2593](https://github.com/paritytech/parity/pull/2593) -- remove unused npm packages [#2590](https://github.com/paritytech/parity/pull/2590) -- Bundle fonts as part of the build process [#2588](https://github.com/paritytech/parity/pull/2588) -- Contract constructor params [#2586](https://github.com/paritytech/parity/pull/2586) -- Update json test suite [#2574](https://github.com/paritytech/parity/pull/2574) -- Filter apps that has been replaced for the local list [#2583](https://github.com/paritytech/parity/pull/2583) -- Display local apps listed by Parity [#2581](https://github.com/paritytech/parity/pull/2581) -- Network-specific nodes file [#2569](https://github.com/paritytech/parity/pull/2569) -- Dont close when block is known to be invalid [#2572](https://github.com/paritytech/parity/pull/2572) -- deny compiler warnings in CI [#2570](https://github.com/paritytech/parity/pull/2570) -- adjust alignment of queries [#2573](https://github.com/paritytech/parity/pull/2573) -- update ethcore-bigint crate to 0.1.1 [#2562](https://github.com/paritytech/parity/pull/2562) -- Registry dapp uses setAddress to actually set addresses now [#2568](https://github.com/paritytech/parity/pull/2568) -- Add the new EIP150 test. [#2563](https://github.com/paritytech/parity/pull/2563) -- fix failing tests [#2567](https://github.com/paritytech/parity/pull/2567) -- ΞTH -> ETH [#2566](https://github.com/paritytech/parity/pull/2566) -- Ensure polling is only done when connected [#2565](https://github.com/paritytech/parity/pull/2565) -- Fixed race condition in trace import [#2555](https://github.com/paritytech/parity/pull/2555) -- Disable misbehaving peers while seeking for best block [#2537](https://github.com/paritytech/parity/pull/2537) -- TX queue gas limit config and allow local transactions over the gas limit [#2553](https://github.com/paritytech/parity/pull/2553) -- standard component for address -> name mappings (consistent use everywhere) [#2557](https://github.com/paritytech/parity/pull/2557) -- Remove unwrap from client module [#2554](https://github.com/paritytech/parity/pull/2554) -- Removing panickers from sync module [#2551](https://github.com/paritytech/parity/pull/2551) -- Address images (tokens, dapps) as registered via contentHash (when available) [#2526](https://github.com/paritytech/parity/pull/2526) -- TokenReg set & get images working [#2540](https://github.com/paritytech/parity/pull/2540) -- adjust app_id where /api/content/ is called, fixes #2541 [#2543](https://github.com/paritytech/parity/pull/2543) -- connection dialog now shows up in dapps as well, closes #2538 [#2550](https://github.com/paritytech/parity/pull/2550) -- display account uuid (where available), closes #2546 [#2549](https://github.com/paritytech/parity/pull/2549) -- create accounts via recovery phrase [#2545](https://github.com/paritytech/parity/pull/2545) -- Build ethcore/js-precompiled on GitLab [#2522](https://github.com/paritytech/parity/pull/2522) -- Return errors from eth_call RPC [#2498](https://github.com/paritytech/parity/pull/2498) -- registry dapp: manage records [#2323](https://github.com/paritytech/parity/pull/2323) -- Print backtrace on panic [#2535](https://github.com/paritytech/parity/pull/2535) -- GitHubHint dapp [#2531](https://github.com/paritytech/parity/pull/2531) -- Backports to master [#2530](https://github.com/paritytech/parity/pull/2530) -- Handle reorganizations in the state cache [#2490](https://github.com/paritytech/parity/pull/2490) -- Hypervisor: terminate hanging modules [#2513](https://github.com/paritytech/parity/pull/2513) -- signer & node connection prompts/indicators [#2504](https://github.com/paritytech/parity/pull/2504) -- Using pending block only if is not old [#2514](https://github.com/paritytech/parity/pull/2514) -- More caching optimizations [#2505](https://github.com/paritytech/parity/pull/2505) -- Fixed possible panic in the networking [#2495](https://github.com/paritytech/parity/pull/2495) -- Trim password from file [#2503](https://github.com/paritytech/parity/pull/2503) -- Fixing RPC Filter conversion to EthFilter [#2500](https://github.com/paritytech/parity/pull/2500) -- Fixing error message for transactions [#2496](https://github.com/paritytech/parity/pull/2496) -- Adjustable stack size for EVM [#2483](https://github.com/paritytech/parity/pull/2483) -- [master] Fixing penalization in future [#2499](https://github.com/paritytech/parity/pull/2499) -- Preserve cache on reverting the snapshot [#2488](https://github.com/paritytech/parity/pull/2488) -- RocksDB version bump [#2492](https://github.com/paritytech/parity/pull/2492) -- Increase default size of transaction queue [#2489](https://github.com/paritytech/parity/pull/2489) -- basiccoin v1 available [#2491](https://github.com/paritytech/parity/pull/2491) -- Small EVM optimization [#2487](https://github.com/paritytech/parity/pull/2487) -- Track dirty accounts in the state [#2461](https://github.com/paritytech/parity/pull/2461) -- fix signature lookup address [#2480](https://github.com/paritytech/parity/pull/2480) -- update registrar test with generic non-empty test [#2476](https://github.com/paritytech/parity/pull/2476) -- Derive IPC interface only when ipc feature is on [#2463](https://github.com/paritytech/parity/pull/2463) -- Fix ethstore opening all key files in the directory at once [#2471](https://github.com/paritytech/parity/pull/2471) -- contract api event log fixes [#2469](https://github.com/paritytech/parity/pull/2469) -- basiccoin base functionality in-place [#2468](https://github.com/paritytech/parity/pull/2468) -- Merge IPC codegen attributes into one [#2460](https://github.com/paritytech/parity/pull/2460) -- Close after importing keys from geth [#2464](https://github.com/paritytech/parity/pull/2464) -- Port a couple more RPC APIs to the new auto args [#2325](https://github.com/paritytech/parity/pull/2325) -- update rustc for appveyor to 1.12.0 [#2423](https://github.com/paritytech/parity/pull/2423) -- dapp basiccoin send operations [#2456](https://github.com/paritytech/parity/pull/2456) -- Better EVM informant & Slow transactions warning [#2436](https://github.com/paritytech/parity/pull/2436) -- Fixing Signer token RPC API [#2437](https://github.com/paritytech/parity/pull/2437) -- Fixed FatDB check [#2443](https://github.com/paritytech/parity/pull/2443) -- dapp basiccoin structure [#2444](https://github.com/paritytech/parity/pull/2444) -- Accounts bloom in master [#2426](https://github.com/paritytech/parity/pull/2426) -- Polishing Actually enable fat db pr (#1974) [#2048](https://github.com/paritytech/parity/pull/2048) -- Jumptable cache [#2427](https://github.com/paritytech/parity/pull/2427) -- signaturereg registered, remove hardcoding [#2431](https://github.com/paritytech/parity/pull/2431) -- tokenreg dapp fixes for non-null returns [#2430](https://github.com/paritytech/parity/pull/2430) -- update ABI json to latest deployed versions [#2428](https://github.com/paritytech/parity/pull/2428) -- update Morden registry address [#2417](https://github.com/paritytech/parity/pull/2417) -- Make migration api more friendly [#2420](https://github.com/paritytech/parity/pull/2420) -- Journaling bloom filter crate in util [#2395](https://github.com/paritytech/parity/pull/2395) -- move abis from js/json to contracts/abi [#2418](https://github.com/paritytech/parity/pull/2418) -- Fixing logs-receipt matching [#2403](https://github.com/paritytech/parity/pull/2403) -- fix broken beta compilation [#2405](https://github.com/paritytech/parity/pull/2405) -- registry dapp: transfer names [#2335](https://github.com/paritytech/parity/pull/2335) -- manage firstRun better [#2398](https://github.com/paritytech/parity/pull/2398) -- render contract deployment address [#2397](https://github.com/paritytech/parity/pull/2397) -- Transaction Queue fix [#2392](https://github.com/paritytech/parity/pull/2392) -- contracts abi types & execute value [#2394](https://github.com/paritytech/parity/pull/2394) -- update styling with ParityBar overlay [#2390](https://github.com/paritytech/parity/pull/2390) -- application Signer popup window [#2388](https://github.com/paritytech/parity/pull/2388) -- Fixing Delegate Call in JIT [#2378](https://github.com/paritytech/parity/pull/2378) -- Prioritizing re-imported transactions [#2372](https://github.com/paritytech/parity/pull/2372) -- Revert #2172, pretty much. [#2387](https://github.com/paritytech/parity/pull/2387) -- correct sync memory usage calculation [#2385](https://github.com/paritytech/parity/pull/2385) -- fix migration system for post-consolidation migrations, better errors [#2334](https://github.com/paritytech/parity/pull/2334) -- Fix the traceAddress field in transaction traces. [#2373](https://github.com/paritytech/parity/pull/2373) -- Gavcoin utilises the popup box [#2381](https://github.com/paritytech/parity/pull/2381) -- registry dapp: support dropping names [#2328](https://github.com/paritytech/parity/pull/2328) -- settings view, set background & store views [#2380](https://github.com/paritytech/parity/pull/2380) -- Removing extras data from retracted blocks. [#2375](https://github.com/paritytech/parity/pull/2375) -- fixed #2263, geth keys with ciphertext shorter than 32 bytes [#2318](https://github.com/paritytech/parity/pull/2318) -- Expanse compatibility [#2369](https://github.com/paritytech/parity/pull/2369) -- Allow queries of constant functions on contracts [#2360](https://github.com/paritytech/parity/pull/2360) -- Auto Open/Close the Signer window on new transaction request [#2362](https://github.com/paritytech/parity/pull/2362) -- Specify column cache sizes explicitly; default fallback of 2MB [#2358](https://github.com/paritytech/parity/pull/2358) -- Canonical state cache (master) [#2311](https://github.com/paritytech/parity/pull/2311) -- method signature lookups, parameter decoding & management [#2313](https://github.com/paritytech/parity/pull/2313) -- make block queue into a more generic verification queue and fix block heap size calculation [#2095](https://github.com/paritytech/parity/pull/2095) -- Hash Content RPC method [#2355](https://github.com/paritytech/parity/pull/2355) -- registry dapp: show reserved events by default [#2359](https://github.com/paritytech/parity/pull/2359) -- Display timestamp in Signer requests details [#2324](https://github.com/paritytech/parity/pull/2324) -- Reorder transaction_by_hash to favour canon search [#2332](https://github.com/paritytech/parity/pull/2332) -- Optimize DIV for some common divisors [#2327](https://github.com/paritytech/parity/pull/2327) -- Return error when deserializing invalid hex [#2339](https://github.com/paritytech/parity/pull/2339) -- Changed http:// to https:// on some links [#2349](https://github.com/paritytech/parity/pull/2349) -- user defaults [#2014](https://github.com/paritytech/parity/pull/2014) -- Fixing jit feature compilation [#2310](https://github.com/paritytech/parity/pull/2310) -- Tx Queue improvements [#2292](https://github.com/paritytech/parity/pull/2292) -- Removing PropTypes on build [#2322](https://github.com/paritytech/parity/pull/2322) -- Lenient bytes deserialization [#2036](https://github.com/paritytech/parity/pull/2036) -- reverse call data decoding given transaction data & method [#2312](https://github.com/paritytech/parity/pull/2312) -- add missing gpl headers to gavcoin dapp [#2317](https://github.com/paritytech/parity/pull/2317) -- contract Events, Functions & Queries sub-components as well as Event log visual updates [#2306](https://github.com/paritytech/parity/pull/2306) -- webpack config updates (really include babel-polyfill, rename npm steps) [#2305](https://github.com/paritytech/parity/pull/2305) -- remove unneeded Form from Account header [#2302](https://github.com/paritytech/parity/pull/2302) -- edit of metadata across accounts, addresses & contracts [#2300](https://github.com/paritytech/parity/pull/2300) -- Adjust all modals for consistency & css DRY-ness [#2301](https://github.com/paritytech/parity/pull/2301) -- update container spacing [#2296](https://github.com/paritytech/parity/pull/2296) -- local cache of generated background (no allocation on each re-render) [#2298](https://github.com/paritytech/parity/pull/2298) -- fix failing tests [#2290](https://github.com/paritytech/parity/pull/2290) -- Respecting standards for tokenreg dapp [#2287](https://github.com/paritytech/parity/pull/2287) -- Separate RPC serialization from implementation [#2072](https://github.com/paritytech/parity/pull/2072) -- Webpack optimisations - Using DLL [#2264](https://github.com/paritytech/parity/pull/2264) -- header background, theme adjustments (not that harsh) [#2273](https://github.com/paritytech/parity/pull/2273) -- contract view (developer-centric) [#2259](https://github.com/paritytech/parity/pull/2259) -- Add hash as CLI function [#1995](https://github.com/paritytech/parity/pull/1995) -- registry: fix mined events showing as pending [#2267](https://github.com/paritytech/parity/pull/2267) -- Dapp - Tokereg ; Query Tokens from TLA or Address [#2266](https://github.com/paritytech/parity/pull/2266) -- Fixes to the Token Registration dApp [#2250](https://github.com/paritytech/parity/pull/2250) -- remove abi *.json duplication, provide a single version of the truth [#2253](https://github.com/paritytech/parity/pull/2253) -- Separate path for ext code size [#2251](https://github.com/paritytech/parity/pull/2251) -- Snapshot format changes [#2234](https://github.com/paritytech/parity/pull/2234) -- Serving content at /api/content/ [#2248](https://github.com/paritytech/parity/pull/2248) -- Fails when deserializing non-hex uints [#2247](https://github.com/paritytech/parity/pull/2247) -- registry dapp: add GPL headers [#2252](https://github.com/paritytech/parity/pull/2252) -- registry dapp: user-friendly lookup [#2229](https://github.com/paritytech/parity/pull/2229) -- registry dapp: show DataChanged events [#2242](https://github.com/paritytech/parity/pull/2242) -- fixups for deploys [#2249](https://github.com/paritytech/parity/pull/2249) -- Fixing output of eth_call and Bytes deserialization [#2230](https://github.com/paritytech/parity/pull/2230) -- Encryption, decryption and public key RPCs. [#1946](https://github.com/paritytech/parity/pull/1946) -- limit number of event logs returned [#2231](https://github.com/paritytech/parity/pull/2231) -- babel-polyfill [#2239](https://github.com/paritytech/parity/pull/2239) -- procedurally generate background based on signer key [#2233](https://github.com/paritytech/parity/pull/2233) -- UI fixes [#2238](https://github.com/paritytech/parity/pull/2238) -- expose isConnected() from transport [#2225](https://github.com/paritytech/parity/pull/2225) -- registry dapp: rename event log [#2227](https://github.com/paritytech/parity/pull/2227) -- registry dapp: show pending events [#2223](https://github.com/paritytech/parity/pull/2223) -- Handle RLP to string UTF-8 decoding errors [#2217](https://github.com/paritytech/parity/pull/2217) -- Use WebSocket transport for all built-in calls [#2216](https://github.com/paritytech/parity/pull/2216) -- Remove panickers from trie iterators [#2209](https://github.com/paritytech/parity/pull/2209) -- Limit for logs filter. [#2180](https://github.com/paritytech/parity/pull/2180) -- Various state copy optimizations [#2172](https://github.com/paritytech/parity/pull/2172) -- New signer token RPC & Initial signer connection without token. [#2096](https://github.com/paritytech/parity/pull/2096) -- signer ui fixes [#2219](https://github.com/paritytech/parity/pull/2219) -- contract deploy ui [#2212](https://github.com/paritytech/parity/pull/2212) -- registry dapp: fix propTypes [#2218](https://github.com/paritytech/parity/pull/2218) -- registry: fix IdentityIcon in events log [#2206](https://github.com/paritytech/parity/pull/2206) -- Fixing evm-debug [#2161](https://github.com/paritytech/parity/pull/2161) -- Fix syncing with pv63 peers [#2204](https://github.com/paritytech/parity/pull/2204) -- registry: show shortened hashes [#2205](https://github.com/paritytech/parity/pull/2205) -- registry dapp: remove owner [#2203](https://github.com/paritytech/parity/pull/2203) -- webpack proxy updates for /api* [#2175](https://github.com/paritytech/parity/pull/2175) -- simplify personal event publishing, fix delete refresh issues [#2183](https://github.com/paritytech/parity/pull/2183) -- fix global & initial states [#2160](https://github.com/paritytech/parity/pull/2160) -- Allow selection & saving of available views [#2131](https://github.com/paritytech/parity/pull/2131) -- global/contract events with promisy subscribe/unsubscribe [#2136](https://github.com/paritytech/parity/pull/2136) -- Token Registry dApp [#2178](https://github.com/paritytech/parity/pull/2178) -- re-usable bytesToHex exposed in api.util [#2174](https://github.com/paritytech/parity/pull/2174) -- Webpack optimisations [#2179](https://github.com/paritytech/parity/pull/2179) -- cleanup on contract event subscriptions [#2104](https://github.com/paritytech/parity/pull/2104) -- move utility functions to api.util [#2105](https://github.com/paritytech/parity/pull/2105) -- registry dapp [#2077](https://github.com/paritytech/parity/pull/2077) -- mui/FlatButton to ui/Button [#2129](https://github.com/paritytech/parity/pull/2129) -- address delete functionality [#2128](https://github.com/paritytech/parity/pull/2128) -- contract deployment updates [#2106](https://github.com/paritytech/parity/pull/2106) -- contract events, indexed string fix [#2108](https://github.com/paritytech/parity/pull/2108) -- Bumping jsonrpc-core & jsonrpc-http-server [#2162](https://github.com/paritytech/parity/pull/2162) -- gitlab testing & build processes [#2090](https://github.com/paritytech/parity/pull/2090) -- Misc small UI fixes (recently broken) [#2101](https://github.com/paritytech/parity/pull/2101) -- Bump clippy & Fix warnings [#2109](https://github.com/paritytech/parity/pull/2109) -- Import command summary [#2102](https://github.com/paritytech/parity/pull/2102) -- check for existence of deprecated ethash file before attempting delete [#2103](https://github.com/paritytech/parity/pull/2103) -- shapeshift Promise API library [#2088](https://github.com/paritytech/parity/pull/2088) -- fund account via ShapeShift [#2099](https://github.com/paritytech/parity/pull/2099) -- Get bigint on crates.io [#2078](https://github.com/paritytech/parity/pull/2078) -- Enable sealing if Engine provides internal sealing given author [#2084](https://github.com/paritytech/parity/pull/2084) -- Config files [#2070](https://github.com/paritytech/parity/pull/2070) -- re-add lodash plugin to babel config [#2092](https://github.com/paritytech/parity/pull/2092) -- Remove old cache data [#2081](https://github.com/paritytech/parity/pull/2081) -- Logs limit & log_index bug [#2073](https://github.com/paritytech/parity/pull/2073) -- flatten store, muiTheme & api providers [#2087](https://github.com/paritytech/parity/pull/2087) -- add babel es2016 & es2017 presets [#2083](https://github.com/paritytech/parity/pull/2083) -- remove all '/index' imports in API [#2089](https://github.com/paritytech/parity/pull/2089) -- add missing GPL headers to all files [#2086](https://github.com/paritytech/parity/pull/2086) -- readme cleanups [#2085](https://github.com/paritytech/parity/pull/2085) -- gavcoin global import of parity api [#2082](https://github.com/paritytech/parity/pull/2082) -- Fixing removal from gas price when moving future->current [#2076](https://github.com/paritytech/parity/pull/2076) -- Split internal sealing from work preparation [#2071](https://github.com/paritytech/parity/pull/2071) -- ensure the target folder doesn't exist before renaming [#2074](https://github.com/paritytech/parity/pull/2074) -- Get rid of 'Dapp is being downloaded' page [#2055](https://github.com/paritytech/parity/pull/2055) -- fix failing master build: update tests to new init_restore signature. [#2069](https://github.com/paritytech/parity/pull/2069) -- Local snapshot restore [#2058](https://github.com/paritytech/parity/pull/2058) -- import: keep informant going until finished [#2065](https://github.com/paritytech/parity/pull/2065) -- Add a few tests for the snapshot service [#2059](https://github.com/paritytech/parity/pull/2059) -- IPC tweaks [#2046](https://github.com/paritytech/parity/pull/2046) -- Update arm* Docker [#2064](https://github.com/paritytech/parity/pull/2064) -- Fetching any content-addressed content [#2050](https://github.com/paritytech/parity/pull/2050) -- Use proper database configuration in snapshots. [#2052](https://github.com/paritytech/parity/pull/2052) -- periodic snapshot tweaks [#2054](https://github.com/paritytech/parity/pull/2054) -- ethkey-cli [#2057](https://github.com/paritytech/parity/pull/2057) -- Forward ethstore-cli feature [#2056](https://github.com/paritytech/parity/pull/2056) -- handling invalid spec jsons properly, additional tests, closes #1840 [#2049](https://github.com/paritytech/parity/pull/2049) -- Periodic snapshots [#2044](https://github.com/paritytech/parity/pull/2044) -- Snapshot sync [#2047](https://github.com/paritytech/parity/pull/2047) -- Nice error pages for Dapps & Signer [#2033](https://github.com/paritytech/parity/pull/2033) -- Add a few small snapshot tests [#2038](https://github.com/paritytech/parity/pull/2038) -- facelift for traces, added errors [#2042](https://github.com/paritytech/parity/pull/2042) -- Fetching content from HTTPS using `rustls` [#2024](https://github.com/paritytech/parity/pull/2024) -- Skipping log when there are no transactions were sent [#2045](https://github.com/paritytech/parity/pull/2045) -- rlp as separate crate [#2034](https://github.com/paritytech/parity/pull/2034) -- Fixing uint serialization [#2037](https://github.com/paritytech/parity/pull/2037) -- Fixing new transactions propagation [#2039](https://github.com/paritytech/parity/pull/2039) -- Propagating transactions to peers on timer. [#2035](https://github.com/paritytech/parity/pull/2035) -- Remove Populatable and BytesConvertable traits [#2019](https://github.com/paritytech/parity/pull/2019) -- fixed #1933 [#1979](https://github.com/paritytech/parity/pull/1979) -- Synchronization tweaks for IPC services [#2028](https://github.com/paritytech/parity/pull/2028) -- Asynchronous RPC support [#2017](https://github.com/paritytech/parity/pull/2017) -- Disable ArchiveDB counter check [#2016](https://github.com/paritytech/parity/pull/2016) -- always process trie death row on commit, add more tracing [#2025](https://github.com/paritytech/parity/pull/2025) -- fixed transaction addresses mapping, fixes #1971 [#2026](https://github.com/paritytech/parity/pull/2026) -- Adding tests for dapps server. [#2021](https://github.com/paritytech/parity/pull/2021) -- builtin trait refactoring [#2018](https://github.com/paritytech/parity/pull/2018) -- Start parity with systemd [#1967](https://github.com/paritytech/parity/pull/1967) -- Control service for IPC [#2013](https://github.com/paritytech/parity/pull/2013) -- LRU cache for dapps [#2006](https://github.com/paritytech/parity/pull/2006) -- CLI for valid hosts for dapps server [#2005](https://github.com/paritytech/parity/pull/2005) -- Make the block header struct's internals private [#2000](https://github.com/paritytech/parity/pull/2000) -- Take control of recovered snapshots, start restoration asynchronously [#2010](https://github.com/paritytech/parity/pull/2010) -- remove internal locking from DBTransaction [#2003](https://github.com/paritytech/parity/pull/2003) -- Snapshot optimizations [#1991](https://github.com/paritytech/parity/pull/1991) -- Revert removing ecies [#2009](https://github.com/paritytech/parity/pull/2009) -- small blooms optimization [#1998](https://github.com/paritytech/parity/pull/1998) -- protection from adding empty traces && assertion in traces db [#1994](https://github.com/paritytech/parity/pull/1994) -- Stratum IPC service [#1959](https://github.com/paritytech/parity/pull/1959) -- Signature cleanup [#1921](https://github.com/paritytech/parity/pull/1921) -- Fixed discovery skipping some nodes [#1996](https://github.com/paritytech/parity/pull/1996) -- Trie query recording and AccountDB factory for no mangling [#1944](https://github.com/paritytech/parity/pull/1944) -- Validating sha3 of a dapp bundle [#1993](https://github.com/paritytech/parity/pull/1993) -- Improve eth_getWork timeout test rpc_get_work_should_timeout [#1992](https://github.com/paritytech/parity/pull/1992) -- Resolving URLs from contract [#1964](https://github.com/paritytech/parity/pull/1964) -- Add timeout for eth_getWork call [#1975](https://github.com/paritytech/parity/pull/1975) -- CLI for Signer interface [#1980](https://github.com/paritytech/parity/pull/1980) -- IPC timeout multiplied [#1990](https://github.com/paritytech/parity/pull/1990) -- Use relative path for IPC sockets [#1983](https://github.com/paritytech/parity/pull/1983) -- Market-orientated transaction pricing [#1963](https://github.com/paritytech/parity/pull/1963) -- Bump clippy [#1982](https://github.com/paritytech/parity/pull/1982) -- Fixing mutual recursive types serialization [#1977](https://github.com/paritytech/parity/pull/1977) -- Fix open on FreeBSD [#1984](https://github.com/paritytech/parity/pull/1984) -- Upgrade hyper dependency to 0.9 [#1973](https://github.com/paritytech/parity/pull/1973) -- Create network-specific nodes files [#1970](https://github.com/paritytech/parity/pull/1970) -- Getting rid of syntex [#1965](https://github.com/paritytech/parity/pull/1965) -- Remove binary specification from hypervisor [#1960](https://github.com/paritytech/parity/pull/1960) -- Stratum protocol general [#1954](https://github.com/paritytech/parity/pull/1954) -- keep track of first block in blockchain [#1937](https://github.com/paritytech/parity/pull/1937) -- introduce ethcore/state module [#1953](https://github.com/paritytech/parity/pull/1953) -- Apply settings to column families [#1956](https://github.com/paritytech/parity/pull/1956) -- move column family constants into db module [#1955](https://github.com/paritytech/parity/pull/1955) -- ECIES without MAC [#1948](https://github.com/paritytech/parity/pull/1948) -- Fix canny warnings [#1951](https://github.com/paritytech/parity/pull/1951) -- Fetchable dapps [#1949](https://github.com/paritytech/parity/pull/1949) -- remove impossible panickers related to infallible db transaction [#1947](https://github.com/paritytech/parity/pull/1947) -- Minor optimizations [#1943](https://github.com/paritytech/parity/pull/1943) -- remove randomness from bigint benches, fix warnings [#1945](https://github.com/paritytech/parity/pull/1945) -- Fix several RPCs [#1926](https://github.com/paritytech/parity/pull/1926) -- Bump clippy, fix warnings [#1939](https://github.com/paritytech/parity/pull/1939) -- DB WAL size limit [#1935](https://github.com/paritytech/parity/pull/1935) -- Use explicit global namespaces in codegen [#1928](https://github.com/paritytech/parity/pull/1928) -- Fix build on master [#1934](https://github.com/paritytech/parity/pull/1934) -- IPC on by default [#1927](https://github.com/paritytech/parity/pull/1927) -- fix util benches compilation [#1931](https://github.com/paritytech/parity/pull/1931) -- Update gitlab-ci [#1929](https://github.com/paritytech/parity/pull/1929) -- ethkey and ethstore use hash structures from bigint [#1851](https://github.com/paritytech/parity/pull/1851) - -## Parity [v1.3.10](https://github.com/paritytech/parity/releases/tag/v1.3.10) (2016-11-04) - -The latest 1.3 series release, now considered stable. - -This includes several additional optimisations and fixes together with provisional support for the upcoming hard fork for EIP155/160/161. - -- Stable branch reset to 1.3.10 [#3156](https://github.com/paritytech/parity/pull/3156) -- Backporting to beta [#3149](https://github.com/paritytech/parity/pull/3149) -- apply post-consolidation migrations after consolidating (BETA) [#3048](https://github.com/paritytech/parity/pull/3048) -- [beta] Fix the brainwallet functionality. (#2994) [#3005](https://github.com/paritytech/parity/pull/3005) -- Bumping json-ipc-server [#2989](https://github.com/paritytech/parity/pull/2989) -- Backports for 1.3.10 [#2987](https://github.com/paritytech/parity/pull/2987) - -## Parity [v1.3.9](https://github.com/paritytech/parity/releases/tag/v1.3.9) (2016-10-21) - -This release enables EIP-150 hard fork for Ethereum Classic chain and resolves a few stability and performance issues, such as: -- Interrupted syncing on the test network. -- Block import delays caused by a large number of incoming transactions. A full re-sync is recommended for performance improvement to take effect. - -Full changes: -- [beta] Resolve morden fork [#2776](https://github.com/paritytech/parity/pull/2776) -- Fixing botched merge [#2767](https://github.com/paritytech/parity/pull/2767) -- Backports for beta [#2764](https://github.com/paritytech/parity/pull/2764) -- Introduce EIP150 hardfork block for ETC [#2736](https://github.com/paritytech/parity/pull/2736) -- [beta] fix issues with no test dir present (#2659) [#2724](https://github.com/paritytech/parity/pull/2724) -- [beta] Bumping jsonrpc-http-server [#2715](https://github.com/paritytech/parity/pull/2715) -- [beta] Fix migration system, better errors [#2661](https://github.com/paritytech/parity/pull/2661) - -## Parity [v1.3.8](https://github.com/paritytech/parity/releases/tag/v1.3.8) (2016-10-15) - -Parity 1.3.8 is our EIP150 hard-fork compliant release. - -Running this will enact a mild change of the protocol at block number 2,463,000 which should occur on Tuesday 18th October 2016 at approximately 12:20 London time (BST). This change alters the gas prices for a number of operations, mainly centring around i/o intensive Merkle trie lookups (`BALANCE`, `EXTCODESIZE` &c.) and state-trie polluters (`SUICIDE`, `CREATE` and `CALL`). These operations were heavily underpriced, an oversight which lead to the recent degradation of network service. The full details of the alteration are specified in [EIP-150](https://github.com/ethereum/EIPs/issues/150). - -Additionally several issues have been fixed including: -- a transaction queue limitation leading to dropped transactions; -- a synchronisation issue leading to stalls when syncing; - -And some small features including database performance improvements and additional logging. - -#### Upgrading private chain specification files. - -All the chain specification files now have EIP-150 rules enabled by default. To continue using the chain add the `eip150Transition` key under `Engine/ethash/params` and set it to a future transition block as shown in [this example](https://github.com/paritytech/parity/blob/85eeb3ea6e5e21ad8e5644241edf82eb8069f536/ethcore/res/ethereum/morden.json#L13). - -The key related to homestead transition has been renamed from `frontierCompatibilityModeLimit` to `homesteadTransition`. - -#### Full changes - -- [beta] EIP150.1c [#2599](https://github.com/paritytech/parity/pull/2599) -- Remove count limit for local transactions [#2634](https://github.com/paritytech/parity/pull/2634) -- Tweak DB and mining defaults [#2598](https://github.com/paritytech/parity/pull/2598) -- Revert "Bloom upgrade in beta" [#2635](https://github.com/paritytech/parity/pull/2635) -- Bloom upgrade in beta [#2609](https://github.com/paritytech/parity/pull/2609) -- Backports to beta [#2628](https://github.com/paritytech/parity/pull/2628) - -## Parity [v1.3.7](https://github.com/paritytech/parity/releases/tag/v1.3.7) (2016-10-12) - -This release contains fixes to reduce memory usage under the DoS attack and improve transaction relay. - -- Configurable history size in beta [#2587](https://github.com/paritytech/parity/pull/2587) -- Backports to beta [#2592](https://github.com/paritytech/parity/pull/2592) - - -## Parity [v1.3.6](https://github.com/paritytech/parity/releases/tag/v1.3.6) (2016-10-11) - -Parity 1.3.6 is another hotfix release to address transaction spam and deal with stability issues. With this release transaction pool gas limit no longer applies to local transactions. Full list of changes is available here: - -- Backports to beta v1.3.6 [#2571](https://github.com/paritytech/parity/pull/2571) -- Use global state cache when mining [#2529](https://github.com/paritytech/parity/pull/2529) -- Transaction queue limited by gas [#2528](https://github.com/paritytech/parity/pull/2528) - -## Parity [v1.3.5](https://github.com/paritytech/parity/releases/tag/v1.3.5) (2016-10-08) - -1.3.5 is a hotfix release for the transaction propagation issue. Transaction pool limit is now calculated based on the block gas limit. - -- Update appveyor rustc [beta] [#2521](https://github.com/paritytech/parity/pull/2521) -- Increase size of transaction queue by default [#2519](https://github.com/paritytech/parity/pull/2519) - -## Parity [v1.3.4](https://github.com/paritytech/parity/releases/tag/v1.3.4) (2016-10-07) - -Parity 1.3.4 release contains more optimizations to internal caching as well as stability improvements. - -It also introduces an ability for miners to choose a transaction ordering strategy: - - --tx-queue-strategy S Prioritization strategy used to order transactions - in the queue. S may be: - gas - Prioritize txs with low gas limit; - gas_price - Prioritize txs with high gas price; - gas_factor - Prioritize txs using gas price - and gas limit ratio [default: gas_factor]. - -- Backport to beta [#2518](https://github.com/paritytech/parity/pull/2518) -- [beta] Fixing RPC Filter conversion to EthFilter [#2501](https://github.com/paritytech/parity/pull/2501) -- [beta] Using pending block only if is not old [#2515](https://github.com/paritytech/parity/pull/2515) -- Backports into beta [#2512](https://github.com/paritytech/parity/pull/2512) -- CLI to specify queue ordering strategy [#2494](https://github.com/paritytech/parity/pull/2494) -- Fix ethstore opening all key files in the directory at once (BETA) [#2472](https://github.com/paritytech/parity/pull/2472) -- Beta backports [#2465](https://github.com/paritytech/parity/pull/2465) -- IPC-library dependency fork & bump for beta [#2455](https://github.com/paritytech/parity/pull/2455) - -## Parity [v1.3.3](https://github.com/paritytech/parity/releases/tag/v1.3.3) (2016-10-04) - -1.3.3 is another hotfix release for the DoS attack - -- Jumptable cache [#2435](https://github.com/paritytech/parity/pull/2435) -- fix broken beta compilation (backport to beta) [#2414](https://github.com/paritytech/parity/pull/2414) -- Run inplace upgrades after version update [#2411](https://github.com/paritytech/parity/pull/2411) - -## Parity [v1.3.2](https://github.com/paritytech/parity/releases/tag/v1.3.2) (2016-09-29) - -This is a hotfix release to address stability and performance issues uncovered during the network DoS attack. Full list of changes is available [here](https://github.com/paritytech/parity/compare/v1.3.1...v1.3.2) - -- Beta Backports [#2396](https://github.com/paritytech/parity/pull/2396) -- Fixing penalization in future [#2493](https://github.com/paritytech/parity/pull/2493) -- A quick fix for missing tree route blocks [#2400](https://github.com/paritytech/parity/pull/2400) -- Cache the fork block header after snapshot restoration [#2391](https://github.com/paritytech/parity/pull/2391) -- correct sync memory usage calculation (BETA) [#2386](https://github.com/paritytech/parity/pull/2386) -- Accounts bloom [#2357](https://github.com/paritytech/parity/pull/2357) -- Disable colors when generating signer token. [#2379](https://github.com/paritytech/parity/pull/2379) -- Fixing jit feature compilation [#2376](https://github.com/paritytech/parity/pull/2376) -- Clear state cache on sealed block import [#2377](https://github.com/paritytech/parity/pull/2377) -- DIV optimization (beta) [#2353](https://github.com/paritytech/parity/pull/2353) -- Canonical state cache [#2308](https://github.com/paritytech/parity/pull/2308) -- Reorder transaction_by_hash to favour canon search [#2331](https://github.com/paritytech/parity/pull/2331) -- Lenient bytes deserialization [#2340](https://github.com/paritytech/parity/pull/2340) -- Penalize transactions with gas above gas limit [#2271](https://github.com/paritytech/parity/pull/2271) -- Peek transaction queue via RPC [#2270](https://github.com/paritytech/parity/pull/2270) -- Handle RLP to string UTF-8 decoding errors (#2217) [#2226](https://github.com/paritytech/parity/pull/2226) -- Fixing compilation without default features [beta] [#2207](https://github.com/paritytech/parity/pull/2207) -- Avoid cloning clean stuff [beta backport] [#2173](https://github.com/paritytech/parity/pull/2173) -- v1.3.2 in beta [#2200](https://github.com/paritytech/parity/pull/2200) - -## Parity [v1.3.1](https://github.com/paritytech/parity/releases/tag/v1.3.1) (2016-09-11) - -1.3.1 includes many [bugfixes](https://github.com/paritytech/parity/commit/2a82fa0a47b00bedfec520a2fdd3cc31aa4ccd8c). Critical ones: -- **Chain reorganisation fix** Transaction receipts / traces were sometimes linked with incorrect block hash. Fixed in https://github.com/paritytech/parity/commit/a9587f8965a32c84973c35ce1c8d51d07044143f -- **Trace overflow fix** Overflow which occurred during tracing. Fixed in https://github.com/paritytech/parity/pull/1979 - -- Backports to beta [#2068](https://github.com/paritytech/parity/pull/2068) -- Fixing serde overflow error (#1977) [#2030](https://github.com/paritytech/parity/pull/2030) -- Simplified db pruning detection in beta [#1924](https://github.com/paritytech/parity/pull/1924) -- Backports to beta [#1919](https://github.com/paritytech/parity/pull/1919) - -## Parity [v1.3.0: "Acuity"](https://github.com/paritytech/parity/releases/tag/v1.3.0) (2016-08-12) - -As well as many bug fixes, 1.3.0 includes a number of important improvements including: -- **Optimisations** Heavily optimised block/transaction processing core - up to 2x faster than 1.2 series. -- **Database compression** Databases take as much as 30% less storage than before. -- **State snapshotting** An installation synchronised from scratch in 1-2 minutes can be made after downloading the 140MB state snapshot. See [the wiki](https://github.com/paritytech/parity/wiki/Getting-Synced) for more information. -- **Process isolation** The networking/chain-synchronisation is now a fully independent process. - -Incremental improvements include: -- Additional [RPCs](https://github.com/paritytech/parity/wiki/JSONRPC) for transaction tracing, state diffing, VM tracing, asynchronous transaction posting, accounts metadata and message signing. -- Improved logging, including for chain reorganisations. -- Added a `--fast-and-loose` option for additional speed-ups which can compromise integrity on a dirty shutdown. -- Column families to ensure maximal inter-database integrity. -- Key naming includes date/time of creation. -- Various improvements to networking robustness and performance. -- Solidity compilation supported through RPC if `solc` is available. -- Various improvements to the miner including [HTTP push work notification](https://github.com/ethcoreparitytech/parity/wiki/Mining#starting-it). - -Full changes: -- Bumping Parity UI [#1920](https://github.com/paritytech/parity/pull/1920) -- Adding entrypoints to docker images [#1909](https://github.com/paritytech/parity/pull/1909) -- Save nodes removed from backing_overlay until commit [#1917](https://github.com/paritytech/parity/pull/1917) -- RPC for importing geth keys [#1916](https://github.com/paritytech/parity/pull/1916) -- Peers RPC + UI displaying active/connected/max peers [#1915](https://github.com/paritytech/parity/pull/1915) -- RPC for deriving address from phrase. [#1912](https://github.com/paritytech/parity/pull/1912) -- adjust polling & connection timeouts for ipc [#1910](https://github.com/paritytech/parity/pull/1910) -- Don't return deleted nodes that are not yet flushed [#1908](https://github.com/paritytech/parity/pull/1908) -- Wallet rpcs [#1898](https://github.com/paritytech/parity/pull/1898) -- Fix binary serialization bug [#1907](https://github.com/paritytech/parity/pull/1907) -- fixed #1889, .DS_Store is no longer treated as key file [#1892](https://github.com/paritytech/parity/pull/1892) -- Purging .derefs, fixing clippy warnings. [#1890](https://github.com/paritytech/parity/pull/1890) -- RocksDB version bump [#1904](https://github.com/paritytech/parity/pull/1904) -- Fix ipc compilation and add ipc feature to test targets [#1902](https://github.com/paritytech/parity/pull/1902) -- Autocreating geth dir if none and geth mode on [#1896](https://github.com/paritytech/parity/pull/1896) -- v1.4.0 in master [#1886](https://github.com/paritytech/parity/pull/1886) -- Adding more details to miner log [#1891](https://github.com/paritytech/parity/pull/1891) -- moved hash.rs to bigint library [#1827](https://github.com/paritytech/parity/pull/1827) -- fixed cache_manager lock order [#1877](https://github.com/paritytech/parity/pull/1877) -- Fixing miner deadlock [#1885](https://github.com/paritytech/parity/pull/1885) -- Updating WS + Increasing token validity [#1882](https://github.com/paritytech/parity/pull/1882) -- take snapshot at specified block and slightly better informants [#1873](https://github.com/paritytech/parity/pull/1873) -- RPC errors & logs [#1845](https://github.com/paritytech/parity/pull/1845) -- Reduce max open files [#1876](https://github.com/paritytech/parity/pull/1876) -- Send new block hashes to all peers [#1875](https://github.com/paritytech/parity/pull/1875) -- Use UntrustedRlp for block verification [#1872](https://github.com/paritytech/parity/pull/1872) -- Update cache usage on commiting block info [#1871](https://github.com/paritytech/parity/pull/1871) -- Validating conversion U256->usize when doing gas calculation (for 32bits) [#1870](https://github.com/paritytech/parity/pull/1870) -- Sync to peers with confirmed fork block only [#1863](https://github.com/paritytech/parity/pull/1863) -- miner and client take spec reference [#1853](https://github.com/paritytech/parity/pull/1853) -- Unlock account with timeout for geth compatibility [#1854](https://github.com/paritytech/parity/pull/1854) -- Fixed reported max height and transaction propagation [#1852](https://github.com/paritytech/parity/pull/1852) -- Snapshot creation and restoration [#1679](https://github.com/paritytech/parity/pull/1679) -- fix deprecated typo [#1850](https://github.com/paritytech/parity/pull/1850) -- Split IO and network crates [#1828](https://github.com/paritytech/parity/pull/1828) -- updated classic JSON spec with classic bootnodes, fixes #1842 [#1847](https://github.com/paritytech/parity/pull/1847) -- protect unsafety in plainhasher; get more unique hashes [#1841](https://github.com/paritytech/parity/pull/1841) -- use mutex in dbtransaction [#1843](https://github.com/paritytech/parity/pull/1843) -- Fix state not using "account_starting_nonce" [#1830](https://github.com/paritytech/parity/pull/1830) -- Supporting blockid in eth_call and trace_call/trace_raw [#1837](https://github.com/paritytech/parity/pull/1837) -- eth_checkTransaction renamed to eth_checkRequest [#1817](https://github.com/paritytech/parity/pull/1817) -- Bump json-ipc-server again [#1839](https://github.com/paritytech/parity/pull/1839) -- Fixing another deadlock in trace db [#1833](https://github.com/paritytech/parity/pull/1833) -- Fix up the VM trace. [#1829](https://github.com/paritytech/parity/pull/1829) -- fixed parsing export params, fixes #1826 [#1834](https://github.com/paritytech/parity/pull/1834) -- More performance optimizations [#1814](https://github.com/paritytech/parity/pull/1814) -- Bumping clippy & fixing warnings [#1823](https://github.com/paritytech/parity/pull/1823) -- removed unused code from util and unnecessary dependency of FixedHash [#1824](https://github.com/paritytech/parity/pull/1824) -- Remove (almost all) panickers from trie module [#1776](https://github.com/paritytech/parity/pull/1776) -- Fixing account naming [#1810](https://github.com/paritytech/parity/pull/1810) -- JournalDB inject [#1806](https://github.com/paritytech/parity/pull/1806) -- No block number in get work while in geth-compat mode. [#1821](https://github.com/paritytech/parity/pull/1821) -- Import wallet fix [#1820](https://github.com/paritytech/parity/pull/1820) -- Supporting eth_sign in Signer [#1787](https://github.com/paritytech/parity/pull/1787) -- Fixing cache update after chain reorg [#1816](https://github.com/paritytech/parity/pull/1816) -- Development mode for Signer UI [#1788](https://github.com/paritytech/parity/pull/1788) -- Miner tweaks [#1797](https://github.com/paritytech/parity/pull/1797) -- Util & ipc clenup [#1807](https://github.com/paritytech/parity/pull/1807) -- Fixing unlock parsing [#1802](https://github.com/paritytech/parity/pull/1802) -- fixed importing presale wallet with encseed longer than 96 bytes [#1801](https://github.com/paritytech/parity/pull/1801) -- DRYing build scripts [#1795](https://github.com/paritytech/parity/pull/1795) -- Allow code from spec json [#1790](https://github.com/paritytech/parity/pull/1790) -- nano-tests (ipc transport) to the CI [#1793](https://github.com/paritytech/parity/pull/1793) -- Commit best block after closing transaction [#1791](https://github.com/paritytech/parity/pull/1791) -- Place thread name in the log output [#1792](https://github.com/paritytech/parity/pull/1792) -- Fix ipc tests and bring to CI [#1789](https://github.com/paritytech/parity/pull/1789) -- dynamic keys pickup [#1779](https://github.com/paritytech/parity/pull/1779) -- ipc version bump [#1783](https://github.com/paritytech/parity/pull/1783) -- Prevent deadlock on trace GC [#1780](https://github.com/paritytech/parity/pull/1780) -- fixed trace_transaction crash when block contained suicide [#1781](https://github.com/paritytech/parity/pull/1781) -- Fix block body migration [#1777](https://github.com/paritytech/parity/pull/1777) -- cache manager and clearing tracing cache [#1769](https://github.com/paritytech/parity/pull/1769) -- Return storage as H256 from RPC. [#1774](https://github.com/paritytech/parity/pull/1774) -- Instant sealing engine [#1767](https://github.com/paritytech/parity/pull/1767) -- fix state unsafety with a mostly-guaranteed handle [#1755](https://github.com/paritytech/parity/pull/1755) -- Gas for mem optimization [#1768](https://github.com/paritytech/parity/pull/1768) -- Min and Max peers setting [#1771](https://github.com/paritytech/parity/pull/1771) -- Disable WAL [#1765](https://github.com/paritytech/parity/pull/1765) -- Add new line when printing start strings [#1766](https://github.com/paritytech/parity/pull/1766) -- Log tweak [#1764](https://github.com/paritytech/parity/pull/1764) -- Remove update_sealing call on importing own block [#1762](https://github.com/paritytech/parity/pull/1762) -- Single DB [#1741](https://github.com/paritytech/parity/pull/1741) -- Tweak format of log so it's not so verbose. [#1758](https://github.com/paritytech/parity/pull/1758) -- Combine mining queue and enabled into single locked datum [#1749](https://github.com/paritytech/parity/pull/1749) -- Collect consensus/null engines into a single module [#1754](https://github.com/paritytech/parity/pull/1754) -- Fix failing deserialization test [#1756](https://github.com/paritytech/parity/pull/1756) -- Stackoverflow fix [#1742](https://github.com/paritytech/parity/pull/1742) -- compaction profile used during migration, fixes #1750 [#1751](https://github.com/paritytech/parity/pull/1751) -- Splitting documentation into separate build job [#1752](https://github.com/paritytech/parity/pull/1752) -- handle keys deserialization errors, fixes #1592 [#1701](https://github.com/paritytech/parity/pull/1701) -- add gitlab-ci yaml [#1753](https://github.com/paritytech/parity/pull/1753) -- Better handling of multiple migrations [#1747](https://github.com/paritytech/parity/pull/1747) -- Disconnect peers on a fork [#1738](https://github.com/paritytech/parity/pull/1738) -- Add RPC & client call to replay a transaction. [#1734](https://github.com/paritytech/parity/pull/1734) -- another version bump for jsonrpc-ipc [#1744](https://github.com/paritytech/parity/pull/1744) -- Trace other types of calls [#1727](https://github.com/paritytech/parity/pull/1727) -- Fixing compilation on latest nightly [#1736](https://github.com/paritytech/parity/pull/1736) -- Blocks and snapshot compression [#1687](https://github.com/paritytech/parity/pull/1687) -- bump json-ipc-server version [#1739](https://github.com/paritytech/parity/pull/1739) -- Use std::sync::Condvar [#1732](https://github.com/paritytech/parity/pull/1732) -- Bump json-ipc-server version [#1733](https://github.com/paritytech/parity/pull/1733) -- bump json-ipc-server version [#1731](https://github.com/paritytech/parity/pull/1731) -- Fixing some clippy warnings [#1728](https://github.com/paritytech/parity/pull/1728) -- Bumping Parity UI [#1682](https://github.com/paritytech/parity/pull/1682) -- Various improvements to tracing & diagnostics. [#1707](https://github.com/paritytech/parity/pull/1707) -- Fixed reading chunked EIP8 handshake [#1712](https://github.com/paritytech/parity/pull/1712) -- Fix for importing blocks from a pipe file [#1724](https://github.com/paritytech/parity/pull/1724) -- Proper errors for binary serializer [#1714](https://github.com/paritytech/parity/pull/1714) -- Use a transaction for writing blocks [#1718](https://github.com/paritytech/parity/pull/1718) -- Exclude generated code from coverage [#1720](https://github.com/paritytech/parity/pull/1720) -- Use single binary for ipc modules [#1710](https://github.com/paritytech/parity/pull/1710) -- Log a chain-reorg. [#1715](https://github.com/paritytech/parity/pull/1715) -- Restore new block informant message [#1716](https://github.com/paritytech/parity/pull/1716) -- Parallel block body download [#1659](https://github.com/paritytech/parity/pull/1659) -- Rotate blockchain cache [#1709](https://github.com/paritytech/parity/pull/1709) -- Fix broken internal names. [#1711](https://github.com/paritytech/parity/pull/1711) -- cli overhaul [#1600](https://github.com/paritytech/parity/pull/1600) -- Key files include timestamp in name. [#1700](https://github.com/paritytech/parity/pull/1700) -- Fixing warnings [#1705](https://github.com/paritytech/parity/pull/1705) -- Ethereum classic [#1706](https://github.com/paritytech/parity/pull/1706) -- Docker Arguments [#1703](https://github.com/paritytech/parity/pull/1703) -- Informant tidyup. [#1699](https://github.com/paritytech/parity/pull/1699) -- Name and meta in accounts [#1695](https://github.com/paritytech/parity/pull/1695) -- Stackoverflow #1686 [#1698](https://github.com/paritytech/parity/pull/1698) -- filtering transactions toAddress includes contract creation [#1697](https://github.com/paritytech/parity/pull/1697) -- Prevent syncing to ancient blocks [#1693](https://github.com/paritytech/parity/pull/1693) -- Enable WAL and disable DB repair [#1696](https://github.com/paritytech/parity/pull/1696) -- Returning error when transaction is rejected (for consistency) [#1667](https://github.com/paritytech/parity/pull/1667) -- Disabling signer when in geth-compatibility mode [#1676](https://github.com/paritytech/parity/pull/1676) -- Suicides tracing [#1688](https://github.com/paritytech/parity/pull/1688) -- small cleanup of substate.rs [#1685](https://github.com/paritytech/parity/pull/1685) -- resolve #411: remove install scripts [#1684](https://github.com/paritytech/parity/pull/1684) -- IPC (feature-gated) [#1654](https://github.com/paritytech/parity/pull/1654) -- Bumping JSONRPC-http-server [#1678](https://github.com/paritytech/parity/pull/1678) -- Fixing hash deserialisation [#1674](https://github.com/paritytech/parity/pull/1674) -- Ping discovery nodes gradually [#1671](https://github.com/paritytech/parity/pull/1671) -- Fixing the deadlock on incoming connection [#1672](https://github.com/paritytech/parity/pull/1672) -- Fixing errors returned by sendTransaction* method family [#1665](https://github.com/paritytech/parity/pull/1665) -- Moved syncing log out of the client [#1670](https://github.com/paritytech/parity/pull/1670) -- Host validation (again) [#1666](https://github.com/paritytech/parity/pull/1666) -- Update install-deps.sh [ci skip] [#1664](https://github.com/paritytech/parity/pull/1664) -- fix typos [#1644](https://github.com/paritytech/parity/pull/1644) -- Size for blocks [#1668](https://github.com/paritytech/parity/pull/1668) -- Revert "Validating Host headers in RPC requests" [#1663](https://github.com/paritytech/parity/pull/1663) -- Validating Host headers in RPC requests [#1658](https://github.com/paritytech/parity/pull/1658) -- fixed failing master [#1662](https://github.com/paritytech/parity/pull/1662) -- Fixing clippy warnings [#1660](https://github.com/paritytech/parity/pull/1660) -- Don't ping all nodes on start [#1656](https://github.com/paritytech/parity/pull/1656) -- More performance optimizations [#1649](https://github.com/paritytech/parity/pull/1649) -- Removing unused client code [#1645](https://github.com/paritytech/parity/pull/1645) -- Asynchronous transactions (polling based for now). [#1652](https://github.com/paritytech/parity/pull/1652) -- Sync stand-alone binary and feature-gated dependencies refactoring [#1637](https://github.com/paritytech/parity/pull/1637) -- Re-enabling Parity UI [#1627](https://github.com/paritytech/parity/pull/1627) -- Blockchain repair on missing state root [#1646](https://github.com/paritytech/parity/pull/1646) -- Multi-mode logging. [#1643](https://github.com/paritytech/parity/pull/1643) -- Pro paths [#1650](https://github.com/paritytech/parity/pull/1650) -- Performance optimizations [#1642](https://github.com/paritytech/parity/pull/1642) -- Removed DAO soft fork traces [#1639](https://github.com/paritytech/parity/pull/1639) -- Compiler version update for windows [#1638](https://github.com/paritytech/parity/pull/1638) -- Delete values immediately from DB overlay [#1631](https://github.com/paritytech/parity/pull/1631) -- DAO hard-fork [#1483](https://github.com/paritytech/parity/pull/1483) -- fix network_start regression [#1629](https://github.com/paritytech/parity/pull/1629) -- Die if the DB is newer than the one supported. [#1630](https://github.com/paritytech/parity/pull/1630) -- Cleanup of colour code. Use is_a_tty. [#1621](https://github.com/paritytech/parity/pull/1621) -- don't batch best block for branches [#1623](https://github.com/paritytech/parity/pull/1623) -- In-memory trie operations [#1408](https://github.com/paritytech/parity/pull/1408) -- Fix "pending" parameter on RPC block requests [#1602](https://github.com/paritytech/parity/pull/1602) -- Allow RPC to use solc to compile solidity [#1607](https://github.com/paritytech/parity/pull/1607) -- IPC RPC deriving for traits [#1599](https://github.com/paritytech/parity/pull/1599) -- Utilize cached kcov if exists [#1619](https://github.com/paritytech/parity/pull/1619) -- Fixing no-ui feature [#1618](https://github.com/paritytech/parity/pull/1618) -- Couple of rocksdb optimizations [#1614](https://github.com/paritytech/parity/pull/1614) -- Miner tests [#1597](https://github.com/paritytech/parity/pull/1597) -- Sync IPC interface [#1584](https://github.com/paritytech/parity/pull/1584) -- Make sure reserved peers are in the node table [#1616](https://github.com/paritytech/parity/pull/1616) -- Fix bloomchain on blockchain repair [#1610](https://github.com/paritytech/parity/pull/1610) -- fixed broken tracing [#1615](https://github.com/paritytech/parity/pull/1615) -- fix benchmark compilation [#1612](https://github.com/paritytech/parity/pull/1612) -- Updating jsonrpc-http-server [#1611](https://github.com/paritytech/parity/pull/1611) -- replace synchronization primitives with those from parking_lot [#1593](https://github.com/paritytech/parity/pull/1593) -- ui compilation feature [#1604](https://github.com/paritytech/parity/pull/1604) -- is_zero() and pow() optimisations for uint [#1608](https://github.com/paritytech/parity/pull/1608) -- Optimizing & Cleaning the build [#1591](https://github.com/paritytech/parity/pull/1591) -- Fix logging [#1590](https://github.com/paritytech/parity/pull/1590) -- remove unnecessary mutex in logging [#1601](https://github.com/paritytech/parity/pull/1601) -- Using streamlined parity-ui repository [#1566](https://github.com/paritytech/parity/pull/1566) -- Optimizing InstructionInfo access. [#1595](https://github.com/paritytech/parity/pull/1595) -- V7 Migration progress indicator [#1594](https://github.com/paritytech/parity/pull/1594) -- bring snapshotting work into master [#1577](https://github.com/paritytech/parity/pull/1577) -- Bump clippy [#1587](https://github.com/paritytech/parity/pull/1587) -- refactoring of handshake messages serialization in ipc [#1586](https://github.com/paritytech/parity/pull/1586) -- expunge &Vec pattern [#1579](https://github.com/paritytech/parity/pull/1579) -- EVM gas for memory tiny optimization [#1578](https://github.com/paritytech/parity/pull/1578) -- cleaned up parity/signer [#1551](https://github.com/paritytech/parity/pull/1551) -- Major sync <-> client interactions refactoring [#1572](https://github.com/paritytech/parity/pull/1572) -- failing test with overlayrecent pruning [#1567](https://github.com/paritytech/parity/pull/1567) -- Enable state queries for OverlayRecent DB [#1575](https://github.com/paritytech/parity/pull/1575) -- have AccountDB use address hash for uniqueness [#1533](https://github.com/paritytech/parity/pull/1533) -- Very basic EVM binary. [#1574](https://github.com/paritytech/parity/pull/1574) -- Some obvious evm & uint optimizations [#1576](https://github.com/paritytech/parity/pull/1576) -- Fixing clippy warnings [#1568](https://github.com/paritytech/parity/pull/1568) -- Miner's gas price gets updated dynamically [#1570](https://github.com/paritytech/parity/pull/1570) -- bringing hypervisor as a crate in ipc dir [#1565](https://github.com/paritytech/parity/pull/1565) -- Init public interface with IO message [#1573](https://github.com/paritytech/parity/pull/1573) -- Uncommenting simple Miner tests [#1571](https://github.com/paritytech/parity/pull/1571) -- Kill lock unwraps [#1558](https://github.com/paritytech/parity/pull/1558) -- Fixing deadlock in miner [#1569](https://github.com/paritytech/parity/pull/1569) -- Idealpeers in log [#1563](https://github.com/paritytech/parity/pull/1563) -- Simple style fix. [#1561](https://github.com/paritytech/parity/pull/1561) -- Enum variants serialisation test&fix [#1559](https://github.com/paritytech/parity/pull/1559) -- Supporting /api/ping for dapps server [#1543](https://github.com/paritytech/parity/pull/1543) -- Client IPC Interface [#1493](https://github.com/paritytech/parity/pull/1493) -- Kill timers when removing IO handler [#1554](https://github.com/paritytech/parity/pull/1554) -- Fix and add info messages [#1552](https://github.com/paritytech/parity/pull/1552) -- Fix indent of #1541 [#1555](https://github.com/paritytech/parity/pull/1555) -- Update sealing just once when externally importing many blocks [#1541](https://github.com/paritytech/parity/pull/1541) -- Remove soft-fork stuff. [#1548](https://github.com/paritytech/parity/pull/1548) -- fix codegen warning [#1550](https://github.com/paritytech/parity/pull/1550) -- Extend migration framework [#1546](https://github.com/paritytech/parity/pull/1546) -- Refactoring dapps to support API endpoints. [#1542](https://github.com/paritytech/parity/pull/1542) -- serde is no longer util dependency [#1534](https://github.com/paritytech/parity/pull/1534) -- mention wiki in README [#1549](https://github.com/paritytech/parity/pull/1549) -- Skipping transactions with invalid nonces when pushing to block. [#1545](https://github.com/paritytech/parity/pull/1545) -- Silent running operating modes [#1477](https://github.com/paritytech/parity/pull/1477) -- util cleanup [#1474](https://github.com/paritytech/parity/pull/1474) -- Calculating gas using usize (if supplied gaslimit fits in usize) [#1518](https://github.com/paritytech/parity/pull/1518) -- add owning NibbleVec [#1536](https://github.com/paritytech/parity/pull/1536) -- Attempt to fix blochchain/extras DBs sync [#1538](https://github.com/paritytech/parity/pull/1538) -- Client API refactoring - limiting errors to crate-level error types [#1525](https://github.com/paritytech/parity/pull/1525) -- IPC codegen enhancement - allow void methods [#1540](https://github.com/paritytech/parity/pull/1540) -- Fixing serving nested files for dapps. [#1539](https://github.com/paritytech/parity/pull/1539) -- Fixed public address config [#1537](https://github.com/paritytech/parity/pull/1537) -- Fixing compilation&clippy warnings [#1531](https://github.com/paritytech/parity/pull/1531) -- creating ethereum dir while in geth mode [#1530](https://github.com/paritytech/parity/pull/1530) -- Bumping clippy [#1532](https://github.com/paritytech/parity/pull/1532) -- Make signer default as long as --unlock isn't used. [#1524](https://github.com/paritytech/parity/pull/1524) -- add client timeout when requesting usd price for gas [#1526](https://github.com/paritytech/parity/pull/1526) -- Fix gitter-url link in README.md [#1528](https://github.com/paritytech/parity/pull/1528) -- Fix error message. [#1527](https://github.com/paritytech/parity/pull/1527) -- BTreeMap binary serialization [#1489](https://github.com/paritytech/parity/pull/1489) -- Save block reference in the queue on notification [#1501](https://github.com/paritytech/parity/pull/1501) -- bigint tests to run on CI [#1522](https://github.com/paritytech/parity/pull/1522) -- Client api cleaning - uncles are returned as rlp [#1516](https://github.com/paritytech/parity/pull/1516) -- Fatdb integration with CLI [#1464](https://github.com/paritytech/parity/pull/1464) -- Optimizing/simplifying shr [#1517](https://github.com/paritytech/parity/pull/1517) -- change IPC codegen to allow attributes [#1500](https://github.com/paritytech/parity/pull/1500) -- Fix warnings [#1514](https://github.com/paritytech/parity/pull/1514) -- FatDB [#1452](https://github.com/paritytech/parity/pull/1452) -- Fix the reseal mechanism. [#1513](https://github.com/paritytech/parity/pull/1513) -- Update Dockerfile ubuntu-aarch64 [#1509](https://github.com/paritytech/parity/pull/1509) -- Update Ubuntu-arm Dockerfile [#1510](https://github.com/paritytech/parity/pull/1510) -- Update Ubuntu-jit Dockerfile [#1511](https://github.com/paritytech/parity/pull/1511) -- Update Ubuntu Dockerfile [#1512](https://github.com/paritytech/parity/pull/1512) -- Update CentOS Dockerfile [#1508](https://github.com/paritytech/parity/pull/1508) -- bump status page v0.5.1 [#1502](https://github.com/paritytech/parity/pull/1502) -- Update CentOS Dockerfile [#1507](https://github.com/paritytech/parity/pull/1507) -- Update Dockerfile ubuntu-aarch64 [#1506](https://github.com/paritytech/parity/pull/1506) -- Update Ubuntu-arm Dockerfile [#1505](https://github.com/paritytech/parity/pull/1505) -- Update Ubuntu-jit Dockerfile [#1504](https://github.com/paritytech/parity/pull/1504) -- Update Ubuntu Dockerfile [#1503](https://github.com/paritytech/parity/pull/1503) -- Optionally clone block behind work-package [#1497](https://github.com/paritytech/parity/pull/1497) -- Fix no colour on windows. [#1498](https://github.com/paritytech/parity/pull/1498) -- Workaround for hyper panic [#1495](https://github.com/paritytech/parity/pull/1495) -- Colourful notification on mine [#1488](https://github.com/paritytech/parity/pull/1488) -- Quick fix for max open files error [#1494](https://github.com/paritytech/parity/pull/1494) -- Work notification over HTTP [#1491](https://github.com/paritytech/parity/pull/1491) -- Sealed block importing and propagation optimization [#1478](https://github.com/paritytech/parity/pull/1478) -- vm factory to mining client [#1487](https://github.com/paritytech/parity/pull/1487) -- topbar dialog fix [#1479](https://github.com/paritytech/parity/pull/1479) -- Minor additions to allow resetting of code. [#1482](https://github.com/paritytech/parity/pull/1482) -- Introduce options for fine-grained management of work queue. [#1484](https://github.com/paritytech/parity/pull/1484) -- Snapshot state restoration [#1308](https://github.com/paritytech/parity/pull/1308) -- Merge master into pv64 branch [#1486](https://github.com/paritytech/parity/pull/1486) -- Ensure we don't reject our own transactions for gasprice. [#1485](https://github.com/paritytech/parity/pull/1485) -- Signing parity executable & windows installer in appveyor [#1481](https://github.com/paritytech/parity/pull/1481) -- Rearrange fork CLI options. [#1476](https://github.com/paritytech/parity/pull/1476) -- give appveyor some breath [#1475](https://github.com/paritytech/parity/pull/1475) -- Ensure we always get the latest work when mining on submitted. [#1469](https://github.com/paritytech/parity/pull/1469) -- Tests for views [#1471](https://github.com/paritytech/parity/pull/1471) -- json ipc version bump [#1470](https://github.com/paritytech/parity/pull/1470) -- verifier is no longer a template type of client [#1467](https://github.com/paritytech/parity/pull/1467) -- Allow configuration of when to reseal blocks. [#1460](https://github.com/paritytech/parity/pull/1460) -- removed unsafe code [#1466](https://github.com/paritytech/parity/pull/1466) -- WS bump + Adding default for value [#1465](https://github.com/paritytech/parity/pull/1465) -- Attempt DB repair if corrupted [#1461](https://github.com/paritytech/parity/pull/1461) -- Database configuration extended [#1454](https://github.com/paritytech/parity/pull/1454) -- Updating WS-RS server [#1459](https://github.com/paritytech/parity/pull/1459) -- Reduced IO messages; removed panics on IO notifications [#1457](https://github.com/paritytech/parity/pull/1457) -- Handle errors when starting parity --signer [#1451](https://github.com/paritytech/parity/pull/1451) -- Fixed losing queued blocks on error [#1453](https://github.com/paritytech/parity/pull/1453) -- Updated to latest hyper with patched mio [#1450](https://github.com/paritytech/parity/pull/1450) -- Retweak BASE and MULTIPLIER in rocksdb config. [#1445](https://github.com/paritytech/parity/pull/1445) -- Removing Miner::default. [#1410](https://github.com/paritytech/parity/pull/1410) -- Don't mine without --author [#1436](https://github.com/paritytech/parity/pull/1436) -- Revert the rescuedao extradata. [#1437](https://github.com/paritytech/parity/pull/1437) -- More conservative settings for rocksdb. [#1440](https://github.com/paritytech/parity/pull/1440) -- v1.3.0 in master [#1421](https://github.com/paritytech/parity/pull/1421) -- Update Ubuntu-arm Dockerfile [#1429](https://github.com/paritytech/parity/pull/1429) -- Create Dockerfile ubuntu-aarch64 [#1430](https://github.com/paritytech/parity/pull/1430) -- Update CentOS Dockerfile [#1424](https://github.com/paritytech/parity/pull/1424) -- Update Ubuntu Dockerfile [#1426](https://github.com/paritytech/parity/pull/1426) -- Update Ubuntu-jit Dockerfile [#1427](https://github.com/paritytech/parity/pull/1427) -- Update SF blocknumber to 1800000. [#1418](https://github.com/paritytech/parity/pull/1418) - -## Parity [v1.2.4](https://github.com/paritytech/parity/releases/tag/v1.2.4) (2016-08-09) - -Parity 1.2.4 Is a maintenance release that fixes a [few](https://github.com/paritytech/parity/pull/1888/commits) issues related to mining and peer synchronization. -This release is marked as stable. - -- Backports for beta [#1888](https://github.com/paritytech/parity/pull/1888) -- BETA: fixed trace_transaction crash when block contained suicide [#1782](https://github.com/paritytech/parity/pull/1782) - -## Parity [v1.2.3](https://github.com/paritytech/parity/releases/tag/v1.2.3) (2016-07-31) - -Parity 1.2.3 is a patch release that addresses network stability issues for both Ethereum HF and Ethereum classic chains and brings a few changes to the transaction tracing API. - -#### Tracing API changes -- Added tracing for `CALLCODE`, `DELEGATECALL` and `SUICIDE` -- `trace_call` returns traces in flat format -- Added 2 new methods: `trace_rawTransaction` and `trace_replayTransaction` - -Note that to continue using tracing features in this version you need to re-sync the blockchain. This can be done by using `parity export $HOME/ethereum-chain-backup.rlp` , deleting the database usually located at `~/.parity/906a34e69aec8c0d` followed by `parity import $HOME/ethereum-chain-backup.rlp`. - -- [beta] Updating UI [#1778](https://github.com/paritytech/parity/pull/1778) -- tracing backport [#1770](https://github.com/paritytech/parity/pull/1770) -- Backport commits to beta [#1763](https://github.com/paritytech/parity/pull/1763) -- Deadlock on incoming connection (#1672) [#1675](https://github.com/paritytech/parity/pull/1675) -- [BETA] Removed DAO soft fork traces [#1640](https://github.com/paritytech/parity/pull/1640) - - -## Parity [v1.2.2](https://github.com/paritytech/parity/releases/tag/v1.2.2) (2016-07-16) - -#### New -- DAO hard-fork. - -DAO hard-fork implementation conforms to the [specification](https://blog.slock.it/hard-fork-specification-24b889e70703) and is enabled by default. - -#### Changed -- `--reseal-on-txs` defaults to `own`. -- DAO soft-fork support has been removed along with related command line options. - -#### Resolved issues -- `--db-cache-size` consuming too much memory. - `eth_getWork` RPC response additionally includes the block number. -- Skipping transactions with invalid nonces when pushing to block. -- Update sealing just once when externally importing many blocks (#1541). -- Transaction tracing skipping simple transactions (#1606). -- Other small fixes and improvements. - -Full changelog - -- DAO hard-fork (#1483) [#1636](https://github.com/paritytech/parity/pull/1636) -- Backports for beta [#1628](https://github.com/paritytech/parity/pull/1628) -- don't batch best block for branches (#1623) [#1626](https://github.com/paritytech/parity/pull/1626) -- Merge bugfixes from master to beta [#1605](https://github.com/paritytech/parity/pull/1605) -- (BETA) using block options cache instead of general cache for rocksdb [#1613](https://github.com/paritytech/parity/pull/1613) -- Backport sealing fixes to beta [#1583](https://github.com/paritytech/parity/pull/1583) -- v1.2.2 in beta [#1581](https://github.com/paritytech/parity/pull/1581) -- Skipping transactions with invalid nonces when pushing to block. (#1545) [#1547](https://github.com/paritytech/parity/pull/1547) - - -## Parity [v1.2.1](https://github.com/paritytech/parity/releases/tag/v1.2.1) (2016-07-01) - -#### New -- Options for more precise mining tuning (see below). -- Informative notification when block mined. -- HTTP signal on new work-package. -- Optimised database insertion for self-mined blocks. -- Short-circuit for local transaction gas-price approval. -- A number of issues related to mining have been fixed. - -##### Mining options -- `--author` is now required for mining. -- `--reseal-on-txs` Specify which transactions should force the node to reseal a block. By default parity updates the seal on incoming transactions to reduce transaction latency. Set this option to `none` to force updates on new blocks only. -- `--reseal-min-period` Can be used to control how often a new pending block is generated if `none` is not selected on prior option. -- `--work-queue-size` Controls how many pending blocks to keep in memory. -- `--relay-set` Can be used to enable more strict transaction verification. -- `--remove-solved` Move solved blocks from the work package queue instead of cloning them. This gives a slightly faster import speed, but means that extra solutions submitted for the same work package will go unused. -- `--notify-work` Accepts a list of URLs that will receive a POST request when new work package is available. The body of the POST message is JSON encoded and has the same format as `eth_getWork` RPC response. - -##### RPC - -`eth_getWork` RPC response additionally includes the block number. - -##### DAO soft-fork - -DAO soft-fork control options have been replaced by the single `--fork` option which disables the soft-fork by default. - -#### Changes - -- v1.2.1 in beta [#1492](https://github.com/paritytech/parity/pull/1492) -- (BETA) add artifacts [#1420](https://github.com/paritytech/parity/pull/1420) - -## Parity [v1.2.0: "Security"](https://github.com/paritytech/parity/releases/tag/v1.2.0) (2016-06-24) - -[Blog post](https://blog.parity.io/announcing-parity-1-2/) - -#### New - -- Transaction signing UI. -- IPC/RPC module. -- Optimised mining support. -- Windows build. -- DAO soft-fork support. - -##### Transaction signing UI - -This is a new framework for signing transactions. It fulfills three requirements: -- You should never have to type your passwords into a Dapp. -- No Javascript code should ever hold a secret. -- No transaction should ever be signed without the consent of the user. - -The feature is enabled through the `--signer` flag. When enabled, the user must ensure at least one "Signer UI" is set-up for managing transaction confirmation. There are two such UIs available; one through a Google Chrome Extension, separately installable and the second through a special web page hosted locally. Set-up must be done once for each such UI, through copying and pasting a token from the output console of Parity into the UI. Specific instructions are given in the UI. - -From this point on, no transaction may ever be signed by Parity except through one of these allowed Signer UIs, and no password should ever be entered anywhere else. - -##### IPC/RPC module and Mist/Geth compatibility - -Should be started with `--geth` to ensure Mist compatibility. - -##### Optimised mining support - -Numerous improvements and optimisations have been added to our mining implementation. A large "active queue" ensures that late-included transactions are included in the mined block without sacrificing older results from latent-reported `ethminer` results. - -##### Windows build - -We're happy to announce full Windows support with 1.2! - -##### Soft-fork - -This release includes support for the proposed [DAO soft-fork](https://docs.google.com/document/d/10RktunzjKNfp6Y8Cu4EhR5V9IqxEZq42LU126EYhWY4/pub). Upon upgrade, all mining nodes can vote for or against the soft fork (this is done through altering the block gas limit; a gas limit of at most 4M results in the soft-fork being triggered). - -By default, nodes vote "for" the DAO soft-fork (and try to reduce the gas limit to 3.1M). To vote against the soft-fork (keeping it at 4.7M), run with `--dont-help-rescue-dao`. Not upgrading is not recommended; if the majority votes with a soft-fork, an upgrade will be necessary to mine on the correct chain. - -#### Changed -- Fast pruning method is now default for a fresh sync. -- Web UI renamed to Dapps UI. -- JSONRPC and Dapps UI enabled by default. -- CLI options ending `-off` renamed to GNU-consistent prefix `--no-`. -- Dynamic gas-pricing (data feed and statistical techniques used to determine optimum gas prices). - -Full changes: - -- Signer enabled by default for UI [#1417](https://github.com/paritytech/parity/pull/1417) -- Remove experimental pruning options. [#1415](https://github.com/paritytech/parity/pull/1415) -- Fixing interface and port for parity ui [#1414](https://github.com/paritytech/parity/pull/1414) -- Configurable gas limit cap. [#1405](https://github.com/paritytech/parity/pull/1405) -- Bumping TopBar, Minimal SignerUI and wallet [#1413](https://github.com/paritytech/parity/pull/1413) -- Sync: Update highest block for progress reporting [#1411](https://github.com/paritytech/parity/pull/1411) -- Tweaked CLI options for the release [#1407](https://github.com/paritytech/parity/pull/1407) -- Further rocksdb tuning [#1409](https://github.com/paritytech/parity/pull/1409) -- Fixing jit compilation [#1406](https://github.com/paritytech/parity/pull/1406) -- Bump clippy [#1403](https://github.com/paritytech/parity/pull/1403) -- Shortcut SF condition when canon known [#1401](https://github.com/paritytech/parity/pull/1401) -- Additional assertions for internal state of queue [#1402](https://github.com/paritytech/parity/pull/1402) -- Replace deprecated hashdb trait names [#1394](https://github.com/paritytech/parity/pull/1394) -- rpc api by default for ipc [#1400](https://github.com/paritytech/parity/pull/1400) -- Ensure judging the SF trigger by relative branch [#1399](https://github.com/paritytech/parity/pull/1399) -- Signer with unlocked account working as expected. [#1398](https://github.com/paritytech/parity/pull/1398) -- Make --signer default. [#1392](https://github.com/paritytech/parity/pull/1392) -- Presale wallet [#1376](https://github.com/paritytech/parity/pull/1376) -- Removing signer connection limit [#1396](https://github.com/paritytech/parity/pull/1396) -- Optional gas price in transactions come from statistics [#1388](https://github.com/paritytech/parity/pull/1388) -- Update README.md with cargo install [ci-skip] [#1389](https://github.com/paritytech/parity/pull/1389) -- Fixing possible overflow during multiplication [#1381](https://github.com/paritytech/parity/pull/1381) -- Update SF to latest spec [#1386](https://github.com/paritytech/parity/pull/1386) -- Sync optimization [#1385](https://github.com/paritytech/parity/pull/1385) -- Fixing order of if statements to avoid overflows. [#1384](https://github.com/paritytech/parity/pull/1384) -- New topbar & signer UI [#1383](https://github.com/paritytech/parity/pull/1383) -- Install trigger for DAO-rescue soft-fork. [#1329](https://github.com/paritytech/parity/pull/1329) -- Rocksdb flush/compact limit [#1375](https://github.com/paritytech/parity/pull/1375) -- CentOS Dockerfile [#1377](https://github.com/paritytech/parity/pull/1377) -- RPC method to return number of unconfirmed transactions... [#1371](https://github.com/paritytech/parity/pull/1371) -- bump jsonrpc-http-server [#1369](https://github.com/paritytech/parity/pull/1369) -- Fix lock order when updating sealing [#1364](https://github.com/paritytech/parity/pull/1364) -- Update sealing on new transactions [#1365](https://github.com/paritytech/parity/pull/1365) -- Fixed panic on aborted connection [#1370](https://github.com/paritytech/parity/pull/1370) -- importing presale wallet [#1368](https://github.com/paritytech/parity/pull/1368) -- Set default database file size large enough [#1363](https://github.com/paritytech/parity/pull/1363) -- Reserved peers rpc API [#1360](https://github.com/paritytech/parity/pull/1360) -- Fixing replacing transaction with lower gas_price result. [#1343](https://github.com/paritytech/parity/pull/1343) -- fixed migration of empty pruning dir [#1362](https://github.com/paritytech/parity/pull/1362) -- Transaction processing queue [#1335](https://github.com/paritytech/parity/pull/1335) -- Fixing last nonce values in case transaction is replaced [#1359](https://github.com/paritytech/parity/pull/1359) -- docopt is an optional dependency of ethkey and ethstore [#1358](https://github.com/paritytech/parity/pull/1358) -- Fixing clippy warnings [#1354](https://github.com/paritytech/parity/pull/1354) -- Reduce locking when syncing [#1357](https://github.com/paritytech/parity/pull/1357) -- removed unnecessary logs [#1356](https://github.com/paritytech/parity/pull/1356) -- Updating parity-dapps [#1353](https://github.com/paritytech/parity/pull/1353) -- moved keystore tests files from util to ethstore [#1352](https://github.com/paritytech/parity/pull/1352) -- removed redundant bigint deps [#1351](https://github.com/paritytech/parity/pull/1351) -- Reopen "reserved peers and reserved-only flag" [#1350](https://github.com/paritytech/parity/pull/1350) -- Configurable rocksdb cache size [#1348](https://github.com/paritytech/parity/pull/1348) -- Fixing future order and errors when reaching limit. [#1346](https://github.com/paritytech/parity/pull/1346) -- Removing priority on local transactions [#1342](https://github.com/paritytech/parity/pull/1342) -- Revert "Reserved peers, reserved-only flag" [#1349](https://github.com/paritytech/parity/pull/1349) -- Sync attack defense: Deactivate peers on invalid block bodies [#1345](https://github.com/paritytech/parity/pull/1345) -- Reserved peers, reserved-only flag [#1347](https://github.com/paritytech/parity/pull/1347) -- CI for ethkey and ethstore [#1341](https://github.com/paritytech/parity/pull/1341) -- Fixed empty block body composition [#1340](https://github.com/paritytech/parity/pull/1340) -- Provide a signer UI token by default. [#1334](https://github.com/paritytech/parity/pull/1334) -- docker uses rustup, fixes #1337 [#1344](https://github.com/paritytech/parity/pull/1344) -- Fixed network service dispose [#1339](https://github.com/paritytech/parity/pull/1339) -- Sync: Cache last sync round block parents [#1331](https://github.com/paritytech/parity/pull/1331) -- secret store separated from util [#1304](https://github.com/paritytech/parity/pull/1304) -- --geth prevent getTransactionReceipt from using pending. [#1325](https://github.com/paritytech/parity/pull/1325) -- Fixing locks order in miner. [#1328](https://github.com/paritytech/parity/pull/1328) -- Update default gas limit, rename field [#1324](https://github.com/paritytech/parity/pull/1324) -- Use constants for DatabaseConfig [#1318](https://github.com/paritytech/parity/pull/1318) -- Fixing clippy warnings [#1321](https://github.com/paritytech/parity/pull/1321) -- Bumping topbar. Fixing ws server closing when suspending [#1312](https://github.com/paritytech/parity/pull/1312) -- Syncing fix [#1320](https://github.com/paritytech/parity/pull/1320) -- Filling-in optional fields of TransactionRequest... [#1305](https://github.com/paritytech/parity/pull/1305) -- Removing MakerOTC and DAO dapps [#1319](https://github.com/paritytech/parity/pull/1319) -- Disabling ethcore_set* APIs by default (+ Status page update) [#1315](https://github.com/paritytech/parity/pull/1315) -- fixed #1180 [#1282](https://github.com/paritytech/parity/pull/1282) -- Network start/stop [#1313](https://github.com/paritytech/parity/pull/1313) -- Additional logging for own transactions in queue [#1311](https://github.com/paritytech/parity/pull/1311) -- DAO Rescue soft fork [#1309](https://github.com/paritytech/parity/pull/1309) -- Appveyor config for windows build+installer [#1302](https://github.com/paritytech/parity/pull/1302) -- Key load avoid warning [#1303](https://github.com/paritytech/parity/pull/1303) -- More meaningful errors when sending transaction [#1290](https://github.com/paritytech/parity/pull/1290) -- Gas price statistics. [#1291](https://github.com/paritytech/parity/pull/1291) -- Fix read-ahead bug. [#1298](https://github.com/paritytech/parity/pull/1298) -- firewall rules for windows installer [#1297](https://github.com/paritytech/parity/pull/1297) -- x64 program files path for installer [#1296](https://github.com/paritytech/parity/pull/1296) -- Fixed loosing peers on incoming connections. [#1293](https://github.com/paritytech/parity/pull/1293) -- fixed #1261, overflow when calculating work [#1283](https://github.com/paritytech/parity/pull/1283) -- snappy and minor block compression [#1286](https://github.com/paritytech/parity/pull/1286) -- clarify build instructions [#1287](https://github.com/paritytech/parity/pull/1287) -- fixed #1255 [#1280](https://github.com/paritytech/parity/pull/1280) -- bump rust-crypto [#1289](https://github.com/paritytech/parity/pull/1289) -- Security audit issues fixed [#1279](https://github.com/paritytech/parity/pull/1279) -- Fixing origin/host validation [#1273](https://github.com/paritytech/parity/pull/1273) -- windows installer + parity start ui cli option [#1284](https://github.com/paritytech/parity/pull/1284) -- ipc lib version bump [#1285](https://github.com/paritytech/parity/pull/1285) -- Syncing improvements [#1274](https://github.com/paritytech/parity/pull/1274) -- removed redundant if condition [#1270](https://github.com/paritytech/parity/pull/1270) -- Naive chunk creation, snapshotting [#1263](https://github.com/paritytech/parity/pull/1263) -- Fixing generating new token while another parity instance is running. [#1272](https://github.com/paritytech/parity/pull/1272) -- README: rustup and windows instructions [#1266](https://github.com/paritytech/parity/pull/1266) -- Windows build [#1253](https://github.com/paritytech/parity/pull/1253) -- removed try_seal from MiningBlockChainClient [#1262](https://github.com/paritytech/parity/pull/1262) -- simplified block opening [#1232](https://github.com/paritytech/parity/pull/1232) -- Clippy bump [#1259](https://github.com/paritytech/parity/pull/1259) -- Fixing uint ASM macros compilation [#1258](https://github.com/paritytech/parity/pull/1258) -- Signer port returned from RPC + Topbar showing count of unconfirmed transactions. [#1252](https://github.com/paritytech/parity/pull/1252) -- codegen - avoid unwraps leading to compilation crash [#1250](https://github.com/paritytech/parity/pull/1250) -- Dapps bump [#1257](https://github.com/paritytech/parity/pull/1257) -- Windows named pipes [#1254](https://github.com/paritytech/parity/pull/1254) -- remove unsafety from util/hash.rs and util/bigint/uint.rs [#1236](https://github.com/paritytech/parity/pull/1236) -- Fixing CORS settings for special values: * & null. [#1247](https://github.com/paritytech/parity/pull/1247) -- JSONRPC test strings avoid using \ char [#1246](https://github.com/paritytech/parity/pull/1246) -- Tests for JSON serialisation of statediff/vmtrace [#1241](https://github.com/paritytech/parity/pull/1241) -- Bumping Dapps & TopBar to newest version. [#1245](https://github.com/paritytech/parity/pull/1245) -- keys import [#1240](https://github.com/paritytech/parity/pull/1240) -- Splitting RPC Apis into more fine-grained sets [#1234](https://github.com/paritytech/parity/pull/1234) -- Refactor triedb constructors to error on invalid state root [#1230](https://github.com/paritytech/parity/pull/1230) -- Signer RPC method to check if signer is enabled [#1238](https://github.com/paritytech/parity/pull/1238) -- Fixing signer behaviour when confirming transaction with wrong password. [#1237](https://github.com/paritytech/parity/pull/1237) -- SystemUIs authorization [#1233](https://github.com/paritytech/parity/pull/1233) -- IPC path for tesetnet with --geth compatibility [#1231](https://github.com/paritytech/parity/pull/1231) -- Transaction tracing for eth_call [#1210](https://github.com/paritytech/parity/pull/1210) -- Removing compilation warnings [#1227](https://github.com/paritytech/parity/pull/1227) -- Allowing connections only from chrome-extension and self-hosted client [#1226](https://github.com/paritytech/parity/pull/1226) -- Clippy bump & fixing warnings [#1219](https://github.com/paritytech/parity/pull/1219) -- Bumping serde & syntex [#1216](https://github.com/paritytech/parity/pull/1216) -- Minimal Signer UI (System UI) exposed over websockets. [#1211](https://github.com/paritytech/parity/pull/1211) -- Switch RPC namespace form ethcore_ to trace_ [#1208](https://github.com/paritytech/parity/pull/1208) -- Verify the state root exists before creating a State [#1217](https://github.com/paritytech/parity/pull/1217) -- Integrate state diffing into the ethcore JSONRPC [#1206](https://github.com/paritytech/parity/pull/1206) -- Updating topbar to latest version [#1220](https://github.com/paritytech/parity/pull/1220) -- Loading local Dapps from FS. [#1214](https://github.com/paritytech/parity/pull/1214) -- Ipc serialization & protocol fixes [#1188](https://github.com/paritytech/parity/pull/1188) -- Have Ext::ret take self by value [#1187](https://github.com/paritytech/parity/pull/1187) -- Simple WebSockets notification about new request [#1202](https://github.com/paritytech/parity/pull/1202) -- Removing leftovers of ethminer [#1207](https://github.com/paritytech/parity/pull/1207) -- fixed #1204 [#1205](https://github.com/paritytech/parity/pull/1205) -- VM tracing and JSON RPC endpoint for it. [#1169](https://github.com/paritytech/parity/pull/1169) -- devtools helpers extended [#1186](https://github.com/paritytech/parity/pull/1186) -- Networking refactoring [#1172](https://github.com/paritytech/parity/pull/1172) -- Client & Miner refactoring [#1195](https://github.com/paritytech/parity/pull/1195) -- update readme [#1201](https://github.com/paritytech/parity/pull/1201) -- Simple signing queue, confirmation APIs exposed in signer WebSockets. [#1182](https://github.com/paritytech/parity/pull/1182) -- Using ordered hashmap to keep the order of dapps on home screen [#1199](https://github.com/paritytech/parity/pull/1199) -- Disabling `ethcore` by default, adding x-frame-options header to dapps. [#1197](https://github.com/paritytech/parity/pull/1197) -- transaction count verifier tests [#1196](https://github.com/paritytech/parity/pull/1196) -- expunge x! and xx! from the codebase [#1192](https://github.com/paritytech/parity/pull/1192) -- Database service upgrade (from the ipc branch) [#1185](https://github.com/paritytech/parity/pull/1185) -- stop eth_syncing from returning true forever [#1181](https://github.com/paritytech/parity/pull/1181) -- Sync fixes and tweaks [#1164](https://github.com/paritytech/parity/pull/1164) -- Exposing RPC over Signer WebSockets [#1167](https://github.com/paritytech/parity/pull/1167) -- implement missing rpc methods and tests [#1171](https://github.com/paritytech/parity/pull/1171) -- json ipc server version bump [#1170](https://github.com/paritytech/parity/pull/1170) -- Updated dependencies for windows build [#1173](https://github.com/paritytech/parity/pull/1173) -- Framework for improved RPC unit tests [#1141](https://github.com/paritytech/parity/pull/1141) -- remove all possible unsafe code in crypto [#1168](https://github.com/paritytech/parity/pull/1168) -- Base for Signer Websockets server [#1158](https://github.com/paritytech/parity/pull/1158) -- Write queue to speed-up db ipc [#1160](https://github.com/paritytech/parity/pull/1160) -- Fixing few clippy warnings [#1163](https://github.com/paritytech/parity/pull/1163) -- Change eth_signAndSendTransaction to personal_SignAndSendTransaction [#1154](https://github.com/paritytech/parity/pull/1154) -- Support "earliest" and specific block parameters in RPC where possible [#1149](https://github.com/paritytech/parity/pull/1149) -- migration fixes [#1155](https://github.com/paritytech/parity/pull/1155) -- Empty trusted signer crate with it's general purpose described. [#1150](https://github.com/paritytech/parity/pull/1150) -- More bootnodes for morden. [#1153](https://github.com/paritytech/parity/pull/1153) -- move existing rpc tests into mocked module [#1151](https://github.com/paritytech/parity/pull/1151) -- Bloomchain [#1014](https://github.com/paritytech/parity/pull/1014) -- Renaming dapps repos. Updating dapps [#1142](https://github.com/paritytech/parity/pull/1142) -- fixed pending transactions [#1147](https://github.com/paritytech/parity/pull/1147) -- Basic benches to provide metrics for ipc optimizations [#1145](https://github.com/paritytech/parity/pull/1145) -- Fixing clippy warnings [#1148](https://github.com/paritytech/parity/pull/1148) -- correct signature of SecTrieDB::raw_mut [#1143](https://github.com/paritytech/parity/pull/1143) -- Merge to master and start hypervisor for import/export [#1138](https://github.com/paritytech/parity/pull/1138) -- Bumping clippy. Fixing warnings [#1139](https://github.com/paritytech/parity/pull/1139) -- Display progress when importing [#1136](https://github.com/paritytech/parity/pull/1136) -- foundation of simple db migration [#1128](https://github.com/paritytech/parity/pull/1128) -- Fixpending [#1074](https://github.com/paritytech/parity/pull/1074) -- Sync: Propagate uncles and fix status reporting [#1134](https://github.com/paritytech/parity/pull/1134) -- Coloured, padding logging. [#1133](https://github.com/paritytech/parity/pull/1133) -- Importing [#1132](https://github.com/paritytech/parity/pull/1132) -- Have `die_with_error` use `fmt::Display` rather than Debug [#1116](https://github.com/paritytech/parity/pull/1116) -- Exporting [#1129](https://github.com/paritytech/parity/pull/1129) -- Sign and send transaction [#1124](https://github.com/paritytech/parity/pull/1124) -- Fixing unused imports warnings [#1125](https://github.com/paritytech/parity/pull/1125) -- Adding info messages on mined blocks [#1127](https://github.com/paritytech/parity/pull/1127) -- Fix styling - don't mix spaces with tabs!!! [#1123](https://github.com/paritytech/parity/pull/1123) -- Fix is_syncing so it's false as long as the update is trivial. [#1122](https://github.com/paritytech/parity/pull/1122) -- Relock unlocked accounts after first use [#1120](https://github.com/paritytech/parity/pull/1120) -- Avoid importing keys into wrong place. [#1119](https://github.com/paritytech/parity/pull/1119) -- Implement receipt's gasUsed field [#1118](https://github.com/paritytech/parity/pull/1118) -- New dapps & query parameter handling [#1113](https://github.com/paritytech/parity/pull/1113) -- pretty print trace error [#1098](https://github.com/paritytech/parity/pull/1098) -- New syncing strategy [#1095](https://github.com/paritytech/parity/pull/1095) -- ethcore-db crate [#1097](https://github.com/paritytech/parity/pull/1097) -- Fix the default for pruning. [#1107](https://github.com/paritytech/parity/pull/1107) -- Make Id/ID and db/Db/DB usage consistent [#1105](https://github.com/paritytech/parity/pull/1105) -- Miner holds it's own copy of spec/engine [#1091](https://github.com/paritytech/parity/pull/1091) -- Apps listing API & Home webapp. [#1101](https://github.com/paritytech/parity/pull/1101) -- CLI option for using JITEVM [#1103](https://github.com/paritytech/parity/pull/1103) -- Fix up the seal fields in RPC output [#1096](https://github.com/paritytech/parity/pull/1096) -- Fixing some warnings [#1102](https://github.com/paritytech/parity/pull/1102) -- fixed incorrect decoding of header seal_fields. added tests. #1090 [#1094](https://github.com/paritytech/parity/pull/1094) -- Bumping Clippy [#1093](https://github.com/paritytech/parity/pull/1093) -- Injectable topbar support. [#1092](https://github.com/paritytech/parity/pull/1092) -- New syncing part 1: Block collection [#1088](https://github.com/paritytech/parity/pull/1088) -- Moving all Client public API types to separate mod & binary serialization codegen for that mod [#1051](https://github.com/paritytech/parity/pull/1051) -- Subdomains support in content server (webapps server). [#1082](https://github.com/paritytech/parity/pull/1082) -- Fix uncle getter [#1087](https://github.com/paritytech/parity/pull/1087) -- Provide fallback for usd-per-eth option when offline. [#1085](https://github.com/paritytech/parity/pull/1085) -- path centralized [#1083](https://github.com/paritytech/parity/pull/1083) -- Limiting result of the execution to execution-specific errors [#1071](https://github.com/paritytech/parity/pull/1071) -- Configurable keys security [#1080](https://github.com/paritytech/parity/pull/1080) -- comma delimeting multiple cors headers [#1078](https://github.com/paritytech/parity/pull/1078) -- Update error message [#1081](https://github.com/paritytech/parity/pull/1081) -- Updating dapp-wallet [#1076](https://github.com/paritytech/parity/pull/1076) -- Fixed connecting to local nodes on startup [#1070](https://github.com/paritytech/parity/pull/1070) -- Validate signature in Tx queue [#1068](https://github.com/paritytech/parity/pull/1068) -- moving deps to ethcore/hyper and bumping jsonrpc-http-server version [#1067](https://github.com/paritytech/parity/pull/1067) -- Updating status page. Bringing back wallet [#1064](https://github.com/paritytech/parity/pull/1064) -- Fix --geth IPC for MacOS. [#1062](https://github.com/paritytech/parity/pull/1062) -- Fixing formatter for defaultExtraData [#1060](https://github.com/paritytech/parity/pull/1060) -- --geth IPC compatibility [#1059](https://github.com/paritytech/parity/pull/1059) -- Moving dependencies to ethcore & uniforming syntax libs through all crates [#1050](https://github.com/paritytech/parity/pull/1050) -- update hyper branch mio [#1054](https://github.com/paritytech/parity/pull/1054) -- IPC lib update [#1047](https://github.com/paritytech/parity/pull/1047) -- Updating hyper-mio revision [#1048](https://github.com/paritytech/parity/pull/1048) -- Bump ipc-lib version [#1046](https://github.com/paritytech/parity/pull/1046) -- Tidy up CLI options and make JSONRPC & webapps on by default. [#1045](https://github.com/paritytech/parity/pull/1045) -- Fixing clippy warnings [#1044](https://github.com/paritytech/parity/pull/1044) -- Fixing RPC modules compatibility [#1041](https://github.com/paritytech/parity/pull/1041) -- Fixing hyper-mio revision [#1043](https://github.com/paritytech/parity/pull/1043) -- Updating locations of webapp stuff [#1040](https://github.com/paritytech/parity/pull/1040) -- JSON-RPC over IPC [#1039](https://github.com/paritytech/parity/pull/1039) -- Update nix/mio for ARM [#1036](https://github.com/paritytech/parity/pull/1036) -- Basic Authority [#991](https://github.com/paritytech/parity/pull/991) -- Prioritizing of local transaction [#1023](https://github.com/paritytech/parity/pull/1023) -- Version 1.2 [#1030](https://github.com/paritytech/parity/pull/1030) -- Bumping status page [#1033](https://github.com/paritytech/parity/pull/1033) - -## Parity [v1.1.0](https://github.com/paritytech/parity/releases/tag/v1.1.0) (2016-05-02) - -Parity 1.1.0 introduces: - -- Transaction tracing. Parity now optionally indexes & stores message-call/"internal transaction" information and provides additional RPC for querying. -- Web interface for logs, status & JSON RPC. -- Improved JSON RPC compatibility. -- Reduced memory footprint. -- Optimized EVM interpreter performance. - -Full Changes: - -- Exposing default extra data via ethcore RPC [#1032](https://github.com/paritytech/parity/pull/1032) -- Net etiquette [#1028](https://github.com/paritytech/parity/pull/1028) -- Bumping clippy & fixing warnings [#1024](https://github.com/paritytech/parity/pull/1024) -- Tracedb interface && cli [#997](https://github.com/paritytech/parity/pull/997) -- Switching to geth-attach supporting version of rpc core and server [#1022](https://github.com/paritytech/parity/pull/1022) -- Fixing status page displaying homestead [#1020](https://github.com/paritytech/parity/pull/1020) -- Core tracedb functionality. [#996](https://github.com/paritytech/parity/pull/996) -- RPC method for supported modules [#1019](https://github.com/paritytech/parity/pull/1019) -- Updating status page [#1015](https://github.com/paritytech/parity/pull/1015) -- Disabling wallet [#1017](https://github.com/paritytech/parity/pull/1017) -- More detailed fatal error reporting [#1016](https://github.com/paritytech/parity/pull/1016) -- Support 'pending' block in RPC [#1007](https://github.com/paritytech/parity/pull/1007) -- Enable pending block when there is local transaction pending. [#1005](https://github.com/paritytech/parity/pull/1005) -- updating key files permissions on save [#1010](https://github.com/paritytech/parity/pull/1010) -- IPC JSON RPC (for external interface) [#1009](https://github.com/paritytech/parity/pull/1009) -- Fixing Firefox authorization issues [#1013](https://github.com/paritytech/parity/pull/1013) -- cargo update [#1012](https://github.com/paritytech/parity/pull/1012) -- Switching to rust-url@1.0.0 [#1011](https://github.com/paritytech/parity/pull/1011) -- Exception handling in RPC & WebApps [#988](https://github.com/paritytech/parity/pull/988) -- Fixed uint deserialization from hex [#1008](https://github.com/paritytech/parity/pull/1008) -- Tweak timeout and packet size to handle slow networks better [#1004](https://github.com/paritytech/parity/pull/1004) -- db key is generic and can be made smaller [#1006](https://github.com/paritytech/parity/pull/1006) -- IPC with new serialization [#998](https://github.com/paritytech/parity/pull/998) -- make jsonrpc api engine agnostic [#1001](https://github.com/paritytech/parity/pull/1001) -- updated cargo.lock [#1002](https://github.com/paritytech/parity/pull/1002) -- updated parity dependencies [#993](https://github.com/paritytech/parity/pull/993) -- Auto (with codegen) binary serializer [#980](https://github.com/paritytech/parity/pull/980) -- Fixing transaction queue last_nonces update [#995](https://github.com/paritytech/parity/pull/995) -- import route contains ommited blocks [#994](https://github.com/paritytech/parity/pull/994) -- fixed encoding 0u8 [#992](https://github.com/paritytech/parity/pull/992) -- Use latest netstats [#989](https://github.com/paritytech/parity/pull/989) -- RPC shared external miner [#984](https://github.com/paritytech/parity/pull/984) -- Additional RPC methods for settings [#983](https://github.com/paritytech/parity/pull/983) -- Fixing transaction_queue deadlock [#985](https://github.com/paritytech/parity/pull/985) -- Refactoring of `parity/main.rs` [#981](https://github.com/paritytech/parity/pull/981) -- Fixing clippy warnings. [#982](https://github.com/paritytech/parity/pull/982) -- Bumping status page [#977](https://github.com/paritytech/parity/pull/977) -- querying extras separated to its own module [#972](https://github.com/paritytech/parity/pull/972) -- Exposing application logs via RPC. [#976](https://github.com/paritytech/parity/pull/976) -- Addressing binary serialization for db types [#966](https://github.com/paritytech/parity/pull/966) -- removed redundant unwraps [#935](https://github.com/paritytech/parity/pull/935) -- fixed transaction queue merge conflict [#975](https://github.com/paritytech/parity/pull/975) -- Configurable limit for transaction queue (CLI & Ethcore-RPC) [#974](https://github.com/paritytech/parity/pull/974) -- Enforce limit caused `last_nonce` to return incorrect values. [#973](https://github.com/paritytech/parity/pull/973) -- Even more detailed errors for transaction queue [#969](https://github.com/paritytech/parity/pull/969) -- temporary fix of panic in blockchain garbage collection [#970](https://github.com/paritytech/parity/pull/970) -- IPC codegen - some minor fixes & enhancements [#967](https://github.com/paritytech/parity/pull/967) -- Additional logging for transactions [#968](https://github.com/paritytech/parity/pull/968) -- refactored blockchain extras keys building [#963](https://github.com/paritytech/parity/pull/963) -- Using hyper-mio branch in webapps. [#957](https://github.com/paritytech/parity/pull/957) -- Remove nanomsg from build-dependencies [#965](https://github.com/paritytech/parity/pull/965) -- Fix build for --target=armv7-unknown-linux-gnueabihf [#964](https://github.com/paritytech/parity/pull/964) -- IPC RPC codegen extra feature [#962](https://github.com/paritytech/parity/pull/962) -- IPC RPC codegen for generic implementation [#961](https://github.com/paritytech/parity/pull/961) -- using db_path directory when upgrading [#960](https://github.com/paritytech/parity/pull/960) -- IPC hypervisor [#958](https://github.com/paritytech/parity/pull/958) -- Removing a transaction from queue now removes all from this sender with lower nonces. [#950](https://github.com/paritytech/parity/pull/950) -- bump status page version 0.1.7 [#955](https://github.com/paritytech/parity/pull/955) -- Changing cors header to be optional [#956](https://github.com/paritytech/parity/pull/956) -- Update ARM Dockerfile [#959](https://github.com/paritytech/parity/pull/959) -- Sensible gas limits for eth_sendTransaction [#953](https://github.com/paritytech/parity/pull/953) -- Fix upgrade script and make parity run when no .parity dir. [#954](https://github.com/paritytech/parity/pull/954) -- Tracing and docs for --pruning=auto. [#952](https://github.com/paritytech/parity/pull/952) -- IPC serialization for custom parameters [#946](https://github.com/paritytech/parity/pull/946) -- default filter from block should be Latest, not Earliest [#948](https://github.com/paritytech/parity/pull/948) -- README.md: removes sudo from multirust installation [#943](https://github.com/paritytech/parity/pull/943) -- Disable long lines formatting + ethash example. [#939](https://github.com/paritytech/parity/pull/939) -- Ethcore-specific RPC methods for altering miner parameters. [#934](https://github.com/paritytech/parity/pull/934) -- Use ethcore nanomsg bindings [#941](https://github.com/paritytech/parity/pull/941) -- Update IPC codegen to latest syntax libs [#938](https://github.com/paritytech/parity/pull/938) -- IPC documentation [#937](https://github.com/paritytech/parity/pull/937) -- Bumping clippy and fixing warnings. [#936](https://github.com/paritytech/parity/pull/936) -- Pruning auto [#927](https://github.com/paritytech/parity/pull/927) -- IPC persistent client link [#933](https://github.com/paritytech/parity/pull/933) -- IPC persistent client link [#930](https://github.com/paritytech/parity/pull/930) -- IPC handshake (negotiating protocol/api version) [#928](https://github.com/paritytech/parity/pull/928) -- Upgrade logic between versions [#914](https://github.com/paritytech/parity/pull/914) -- executive tracing cleanup [#903](https://github.com/paritytech/parity/pull/903) -- Ethcore-specific RPC methods [#923](https://github.com/paritytech/parity/pull/923) -- Parameter to allow user to force the sealing mechanism [#918](https://github.com/paritytech/parity/pull/918) -- updated dependencies [#921](https://github.com/paritytech/parity/pull/921) -- Fixed send transaction deadlock [#920](https://github.com/paritytech/parity/pull/920) -- --unlock is comma-delimited. [#916](https://github.com/paritytech/parity/pull/916) -- fixed eth_getLogs [#915](https://github.com/paritytech/parity/pull/915) -- create provided custom dir for keys if none [#912](https://github.com/paritytech/parity/pull/912) -- spec loading cleanup [#858](https://github.com/paritytech/parity/pull/858) -- WebApps HTTP Basic Auth Support [#906](https://github.com/paritytech/parity/pull/906) -- Removing match on constant [#888](https://github.com/paritytech/parity/pull/888) -- Update auth.rs [#907](https://github.com/paritytech/parity/pull/907) -- Enabling webapps compilation by default [#904](https://github.com/paritytech/parity/pull/904) -- fixed #895 [#898](https://github.com/paritytech/parity/pull/898) -- Support for compile-time included WebApplications. [#899](https://github.com/paritytech/parity/pull/899) -- Propagate transaction queue [#894](https://github.com/paritytech/parity/pull/894) -- Use new json RPC server [#901](https://github.com/paritytech/parity/pull/901) -- Gracefully dying when trying to enable RPC and app is compiled without it. [#900](https://github.com/paritytech/parity/pull/900) -- Additional logging and friendlier error messages [#893](https://github.com/paritytech/parity/pull/893) -- Avoid signalling readiness when app is about to be closed. [#897](https://github.com/paritytech/parity/pull/897) -- fixed #875 and added tests for eth_sendTransaction [#890](https://github.com/paritytech/parity/pull/890) -- passing key path to all invocations [#891](https://github.com/paritytech/parity/pull/891) -- Fixed eth_call nonce and gas handling [#892](https://github.com/paritytech/parity/pull/892) -- ipc rpc with nano transport (simple duplex) [#886](https://github.com/paritytech/parity/pull/886) -- Bumping clippy and fixing warnings [#889](https://github.com/paritytech/parity/pull/889) -- More descriptive expectations to transaction queue consistency. [#878](https://github.com/paritytech/parity/pull/878) -- uint bug - replace add with or [#879](https://github.com/paritytech/parity/pull/879) -- Fixing typo in bigint [#877](https://github.com/paritytech/parity/pull/877) -- update misleading cli help msg for author [#874](https://github.com/paritytech/parity/pull/874) -- Find geth data store cross-platform. [#871](https://github.com/paritytech/parity/pull/871) -- Import geth 1.4.0 keys [#872](https://github.com/paritytech/parity/pull/872) -- Syntax helpers for IPC RPC (part 2) [#854](https://github.com/paritytech/parity/pull/854) -- Fixed bootnode URL and error message [#870](https://github.com/paritytech/parity/pull/870) -- replace popcnt with mov (861) [#867](https://github.com/paritytech/parity/pull/867) -- weekly dependencies update [#865](https://github.com/paritytech/parity/pull/865) -- Remove unused mut [#866](https://github.com/paritytech/parity/pull/866) -- fixed #855 [#864](https://github.com/paritytech/parity/pull/864) -- simplified trace from functions, removed clippy warnings [#862](https://github.com/paritytech/parity/pull/862) -- Update deprecated HashDB methods in docs. [#857](https://github.com/paritytech/parity/pull/857) -- refactored loading transaction json tests [#853](https://github.com/paritytech/parity/pull/853) -- reorganised price info lookup [#852](https://github.com/paritytech/parity/pull/852) -- Publish locally-made transactions to peers. [#850](https://github.com/paritytech/parity/pull/850) -- Add generalbeck's token [#847](https://github.com/paritytech/parity/pull/847) -- Fix response for mining. [#846](https://github.com/paritytech/parity/pull/846) -- USD-based pricing of gas. [#843](https://github.com/paritytech/parity/pull/843) -- Parity can accept older work packages [#811](https://github.com/paritytech/parity/pull/811) -- Caching for computing seed hashes (#541) [#841](https://github.com/paritytech/parity/pull/841) -- checking transaction queue for pending transaction [#838](https://github.com/paritytech/parity/pull/838) -- refactored loading of state tests [#817](https://github.com/paritytech/parity/pull/817) -- tests for deserialization of transaction from issue #835 [#837](https://github.com/paritytech/parity/pull/837) -- unlocks with no expiration [on top of 833] [#834](https://github.com/paritytech/parity/pull/834) -- Unlock accounts on CLI. [#833](https://github.com/paritytech/parity/pull/833) -- Make BlockNumber optional, fix eth_call [#829](https://github.com/paritytech/parity/pull/829) -- Test socket to common test code (ethcore-devtools) [#831](https://github.com/paritytech/parity/pull/831) -- Use network id for the web3_net_version return. [#822](https://github.com/paritytech/parity/pull/822) -- json-rpc web3_sha3 [#824](https://github.com/paritytech/parity/pull/824) -- remove some unused files [#819](https://github.com/paritytech/parity/pull/819) -- debug symbols for master/beta [#818](https://github.com/paritytech/parity/pull/818) -- Syntax helpers for IPC RPC [#809](https://github.com/paritytech/parity/pull/809) -- refactored loading of execution tests [#803](https://github.com/paritytech/parity/pull/803) -- Rustfmt.toml [#805](https://github.com/paritytech/parity/pull/805) -- install-partiy runs brew reinstall parity on osx [#810](https://github.com/paritytech/parity/pull/810) -- Fix mining from spinning [#807](https://github.com/paritytech/parity/pull/807) - -## Parity [v1.0.2](https://github.com/paritytech/parity/releases/tag/v1.0.2) (2016-04-11) - -Parity 1.0.2 release improves Json RPC compatibility and fixes a number of stability issues. - -- Flush password prompt [#1031](https://github.com/paritytech/parity/pull/1031) -- [beta] dependencies update [#949](https://github.com/paritytech/parity/pull/949) -- Master to beta v1.0.2 [#922](https://github.com/paritytech/parity/pull/922) -- Master to beta 1.0.2 [#908](https://github.com/paritytech/parity/pull/908) - -## Parity [v1.0.1](https://github.com/paritytech/parity/releases/tag/v1.0.1) (2016-03-28) - -Parity 1.0.1 update fixes a number of issues with Json RPC, transaction propagation and syncing. - -- Imporved sync error handling [#905](https://github.com/paritytech/parity/pull/905) -- Publish locally-made transactions to peers. [#851](https://github.com/paritytech/parity/pull/851) -- Merge fixes from master to beta [#845](https://github.com/paritytech/parity/pull/845) -- Full sync restart on bad block [#844](https://github.com/paritytech/parity/pull/844) -- Make BlockNumber optional, fix eth_call [#828](https://github.com/paritytech/parity/pull/828) -- Web3sha3 beta [#826](https://github.com/paritytech/parity/pull/826) -- Use network id for the web3_net_version return. [#821](https://github.com/paritytech/parity/pull/821) -- Fix mining from spinning [#806](https://github.com/paritytech/parity/pull/806) -- Merge master to beta [#796](https://github.com/paritytech/parity/pull/796) - -## Parity [v1.0.0](https://github.com/paritytech/parity/releases/tag/v1.0.0) (2016-03-24) - -Parity 1.0.0 release adds the following features: - -- Standard JsonRPC interface. -- Full Homestead compatibility. -- Transaction management. -- Mining with external miner. -- Account management. -- Geth key chain compatibility. -- Additional command line options. -- State trie pruning. -- Cache and queue footprint. -- Network discovery & NAT traversal. -- Custom chain specification files. - -Note that in this release the state database is in archive (full) mode by default. Run with one of the `--pruning` options to enable pruning. - -- First part of multi-mining support [#804](https://github.com/paritytech/parity/pull/804) -- Fixing future-current transactions clash [#802](https://github.com/paritytech/parity/pull/802) -- Increase threads to num_cpus & fix author reporting [#800](https://github.com/paritytech/parity/pull/800) -- another batch of rpc improvements [#798](https://github.com/paritytech/parity/pull/798) -- Avoid tracing DELEGATECALL and CALLCODE. Plus tests for it. [#794](https://github.com/paritytech/parity/pull/794) -- complete getting started steps for OS X [#793](https://github.com/paritytech/parity/pull/793) -- Auto detect available port (with fixed test) [#788](https://github.com/paritytech/parity/pull/788) -- eth_getTransactionReceipt [#792](https://github.com/paritytech/parity/pull/792) -- Comprehensive tests for tracing transactions [#791](https://github.com/paritytech/parity/pull/791) -- Disable preparing work package if miners don't ask for it. [#771](https://github.com/paritytech/parity/pull/771) -- Listen on all interfaces for JSONRPC by default. [#786](https://github.com/paritytech/parity/pull/786) -- eth_call [#783](https://github.com/paritytech/parity/pull/783) -- Revert "Auto detect available port" [#789](https://github.com/paritytech/parity/pull/789) -- added output to execution result [#777](https://github.com/paritytech/parity/pull/777) -- Auto detect available port [#782](https://github.com/paritytech/parity/pull/782) -- Allow 0x prefix for --author. [#785](https://github.com/paritytech/parity/pull/785) -- updated dependencies, moved rpctest to its own submodule [#784](https://github.com/paritytech/parity/pull/784) -- use ethjson module to load chain json tests [#778](https://github.com/paritytech/parity/pull/778) -- Tracing implemented. [#772](https://github.com/paritytech/parity/pull/772) -- test ethjson module on travis [#780](https://github.com/paritytech/parity/pull/780) -- batch of rpc fixes [#775](https://github.com/paritytech/parity/pull/775) -- rpctest executable [#757](https://github.com/paritytech/parity/pull/757) -- Refactoring error transaction_queue error handling and `update_sealing` method. [#753](https://github.com/paritytech/parity/pull/753) -- Avoid importing transactions with gas above 1.1*block_gas_limit to transaction queue [#760](https://github.com/paritytech/parity/pull/760) -- Removing transactions that failed to be pushed to block. [#752](https://github.com/paritytech/parity/pull/752) -- Updating clippy [#766](https://github.com/paritytech/parity/pull/766) -- Attempting to add all transactions to mined block [#754](https://github.com/paritytech/parity/pull/754) -- Prettier version w/o git dir; Use rustc compile time version [#761](https://github.com/paritytech/parity/pull/761) -- Stop adding transactions to queue while not fully synced [#751](https://github.com/paritytech/parity/pull/751) -- Verify sender's balance before importing transaction to queue [#746](https://github.com/paritytech/parity/pull/746) -- Returning number of transactions pending in block not queue [#750](https://github.com/paritytech/parity/pull/750) -- Speeding up build [#733](https://github.com/paritytech/parity/pull/733) -- adding check for a sync when giving work to miner [#742](https://github.com/paritytech/parity/pull/742) -- json deserialization module [#745](https://github.com/paritytech/parity/pull/745) -- Update install-parity.sh [#749](https://github.com/paritytech/parity/pull/749) -- Restart sync on getting old unknown header [#747](https://github.com/paritytech/parity/pull/747) -- Missing return for #737 [#744](https://github.com/paritytech/parity/pull/744) -- Enact block with uncles test [#741](https://github.com/paritytech/parity/pull/741) -- Fix outdated libc version on dependency [#740](https://github.com/paritytech/parity/pull/740) -- Fixing possible race in transaction queue [#735](https://github.com/paritytech/parity/pull/735) -- Sync fixed again [#737](https://github.com/paritytech/parity/pull/737) -- Don't change best block until extras is committed. [#734](https://github.com/paritytech/parity/pull/734) -- stable only until travis speedup [#736](https://github.com/paritytech/parity/pull/736) -- Optimizing uint operations (architecture independent) [#629](https://github.com/paritytech/parity/pull/629) -- Add RLP, not a data item. [#725](https://github.com/paritytech/parity/pull/725) -- PV63 receipts response [#687](https://github.com/paritytech/parity/pull/687) -- another batch of rpc tests [#723](https://github.com/paritytech/parity/pull/723) -- dockerfiles update [#726](https://github.com/paritytech/parity/pull/726) -- Lock reports to avoid out of order badness. [#721](https://github.com/paritytech/parity/pull/721) -- Fixed handshake leak [#722](https://github.com/paritytech/parity/pull/722) -- Allow configuration of target gas limit. [#719](https://github.com/paritytech/parity/pull/719) -- Version 1.1 in master [#714](https://github.com/paritytech/parity/pull/714) -- Silence UDP warnings [#720](https://github.com/paritytech/parity/pull/720) -- Rpc personal tests [#715](https://github.com/paritytech/parity/pull/715) -- Fixing warnings [#704](https://github.com/paritytech/parity/pull/704) -- docopts cleanups [#713](https://github.com/paritytech/parity/pull/713) -- Removed rocksdb build dependency [#717](https://github.com/paritytech/parity/pull/717) -- Fixed splitting Neighbours packet [#710](https://github.com/paritytech/parity/pull/710) -- management of account expiration & memory [#701](https://github.com/paritytech/parity/pull/701) -- Remove EarlyMerge from user docs. [#708](https://github.com/paritytech/parity/pull/708) -- Fixes and traces for refcountdb. [#705](https://github.com/paritytech/parity/pull/705) -- Check for NULL_RLP in AccountDB [#706](https://github.com/paritytech/parity/pull/706) -- ethminer as crate [#700](https://github.com/paritytech/parity/pull/700) -- Old ref-counted DB code [#692](https://github.com/paritytech/parity/pull/692) -- next batch of rpc tests and fixes [#699](https://github.com/paritytech/parity/pull/699) -- implemented eth_geStorageAt rpc method, added more tests for rpc [#695](https://github.com/paritytech/parity/pull/695) -- Fix JournalDB era marker [#690](https://github.com/paritytech/parity/pull/690) -- More sync fixes [#685](https://github.com/paritytech/parity/pull/685) -- mark some key tests as heavy [#694](https://github.com/paritytech/parity/pull/694) -- Limit incoming connections [#693](https://github.com/paritytech/parity/pull/693) -- Updating clippy [#688](https://github.com/paritytech/parity/pull/688) -- eth_accounts, eth_getBalance rpc functions && tests [#691](https://github.com/paritytech/parity/pull/691) -- state query for archive jdb [#683](https://github.com/paritytech/parity/pull/683) -- Fix for option 1 of JournalDB [#658](https://github.com/paritytech/parity/pull/658) -- Rename into something that is a little more descriptive. [#689](https://github.com/paritytech/parity/pull/689) -- JournalDB with in-memory overlay (option2) [#634](https://github.com/paritytech/parity/pull/634) -- additional (failing) SecretStore test [#682](https://github.com/paritytech/parity/pull/682) -- Updating clippy & fixing warnings. [#670](https://github.com/paritytech/parity/pull/670) -- rpc web3 tests [#681](https://github.com/paritytech/parity/pull/681) -- Making personal json-rpc configurable via cli [#677](https://github.com/paritytech/parity/pull/677) -- RPC Pending Transactions Filter [#661](https://github.com/paritytech/parity/pull/661) -- Rearrange journaldb infrastructure to make more extensible [#678](https://github.com/paritytech/parity/pull/678) -- JournalDB -> Box, and it's a trait. [#673](https://github.com/paritytech/parity/pull/673) -- fix warning for transaction_queue.add usage [#676](https://github.com/paritytech/parity/pull/676) -- Adding std::mem back (only for asm) [#680](https://github.com/paritytech/parity/pull/680) -- update readme to exclude beta step (stable is ok) [#679](https://github.com/paritytech/parity/pull/679) -- fixed U256 and transaction request deserialization [#675](https://github.com/paritytech/parity/pull/675) -- More geth compatibility. [#666](https://github.com/paritytech/parity/pull/666) -- Removing running clippy by default on nightly. [#671](https://github.com/paritytech/parity/pull/671) -- rpc net submodule tests [#667](https://github.com/paritytech/parity/pull/667) -- Client module overhaul [#665](https://github.com/paritytech/parity/pull/665) -- Rpc transaction signing [#587](https://github.com/paritytech/parity/pull/587) -- Transaction queue exposed via JSON rpc. [#652](https://github.com/paritytech/parity/pull/652) -- Remove unneeded locking [#499](https://github.com/paritytech/parity/pull/499) -- extend sync status interface to sync provider [#664](https://github.com/paritytech/parity/pull/664) -- --archive is default. --pruning is option. [#663](https://github.com/paritytech/parity/pull/663) -- jsonrpc uses client and sync interfaces [#641](https://github.com/paritytech/parity/pull/641) -- Expose transaction insertion in sync lib [#609](https://github.com/paritytech/parity/pull/609) -- Removing get prefix from poll_info [#660](https://github.com/paritytech/parity/pull/660) -- Tx queue update height bug [#657](https://github.com/paritytech/parity/pull/657) -- Tx_queue_docs -> To master [#651](https://github.com/paritytech/parity/pull/651) -- blockchain import_route [#645](https://github.com/paritytech/parity/pull/645) -- Stop workers before stopping event loop [#655](https://github.com/paritytech/parity/pull/655) -- Validate sender before importing to queue [#650](https://github.com/paritytech/parity/pull/650) -- Gas price threshold for transactions [#640](https://github.com/paritytech/parity/pull/640) -- `dev` feature enabled when compiling without `--release` [#627](https://github.com/paritytech/parity/pull/627) -- Don't call mark_as_bad needlessly [#648](https://github.com/paritytech/parity/pull/648) -- Fixed sync handling large forks [#647](https://github.com/paritytech/parity/pull/647) -- Additional documentation for transaction queue [#631](https://github.com/paritytech/parity/pull/631) -- Transaction Queue Integration [#607](https://github.com/paritytech/parity/pull/607) -- Keys cli [#639](https://github.com/paritytech/parity/pull/639) -- fix build warning [#643](https://github.com/paritytech/parity/pull/643) -- updated jsonrpc-core and http-server libs [#642](https://github.com/paritytech/parity/pull/642) -- jsonrpc panics gracefully shutdown client [#638](https://github.com/paritytech/parity/pull/638) -- Fixing CLI parameters [#633](https://github.com/paritytech/parity/pull/633) -- Normal CLI options with geth. [#628](https://github.com/paritytech/parity/pull/628) -- Do not remove the peer immediatelly on send error [#626](https://github.com/paritytech/parity/pull/626) -- Jsonrpc block behind [#622](https://github.com/paritytech/parity/pull/622) -- Remove println!s. [#624](https://github.com/paritytech/parity/pull/624) -- JournalDB option 1 fix [#613](https://github.com/paritytech/parity/pull/613) -- Network tracing cleanup [#611](https://github.com/paritytech/parity/pull/611) -- Revert "Transaction Queue integration" [#602](https://github.com/paritytech/parity/pull/602) -- fix benches compilation [#601](https://github.com/paritytech/parity/pull/601) -- Transaction Queue integration [#595](https://github.com/paritytech/parity/pull/595) -- verifier trait improvements [#597](https://github.com/paritytech/parity/pull/597) -- build on rust stable [#600](https://github.com/paritytech/parity/pull/600) -- Geth import silent if no geth [#599](https://github.com/paritytech/parity/pull/599) -- Additional journaldb logging and assert [#593](https://github.com/paritytech/parity/pull/593) -- Uncle inclusion in block authoring. [#578](https://github.com/paritytech/parity/pull/578) -- Fixed potential deadlock on startup [#592](https://github.com/paritytech/parity/pull/592) -- Fixing an overflow panic [#591](https://github.com/paritytech/parity/pull/591) -- Fixed one more case of sync stalling [#590](https://github.com/paritytech/parity/pull/590) -- JournalDB can now operate in "archive" mode [#589](https://github.com/paritytech/parity/pull/589) -- Secret store integration with client [#586](https://github.com/paritytech/parity/pull/586) -- fix build on nightly rust [#588](https://github.com/paritytech/parity/pull/588) -- deserialization for uint generic [#585](https://github.com/paritytech/parity/pull/585) -- TransactionsQueue implementation [#559](https://github.com/paritytech/parity/pull/559) -- JSON-RPC personal service (follows #582) [#583](https://github.com/paritytech/parity/pull/583) -- making key directory thread-safe [#582](https://github.com/paritytech/parity/pull/582) -- verifier trait [#581](https://github.com/paritytech/parity/pull/581) -- shrink_to_fit after removing hashes. [#580](https://github.com/paritytech/parity/pull/580) -- support for rpc polling [#504](https://github.com/paritytech/parity/pull/504) -- limit serde codegen only to rpc types submodule [#569](https://github.com/paritytech/parity/pull/569) -- fork test for Issue test/568 [#573](https://github.com/paritytech/parity/pull/573) -- Fixing clippy warnings = small refactoring of `request_blocks` [#560](https://github.com/paritytech/parity/pull/560) -- Improved journaldb logging [#571](https://github.com/paritytech/parity/pull/571) -- Additional check to ancient enactments. [#570](https://github.com/paritytech/parity/pull/570) -- chainfilter shouldnt exclude to_block from results [#564](https://github.com/paritytech/parity/pull/564) -- Fix coverage test run [#567](https://github.com/paritytech/parity/pull/567) -- Mining [#547](https://github.com/paritytech/parity/pull/547) -- fix uint warnings [#565](https://github.com/paritytech/parity/pull/565) -- Finished blockchain generator. [#562](https://github.com/paritytech/parity/pull/562) -- fixed broken master [#563](https://github.com/paritytech/parity/pull/563) -- uint to separate crate [#544](https://github.com/paritytech/parity/pull/544) -- improved test chain generator [#554](https://github.com/paritytech/parity/pull/554) -- Fixing spelling in propagade->propagate [#558](https://github.com/paritytech/parity/pull/558) -- Changing RefCell to Cell in transaction. [#557](https://github.com/paritytech/parity/pull/557) -- Fix for morden consensus. [#556](https://github.com/paritytech/parity/pull/556) -- blockchain generator [#550](https://github.com/paritytech/parity/pull/550) -- Sparse Table Implementation (Row, Col) -> Val [#545](https://github.com/paritytech/parity/pull/545) -- fixup install script [#548](https://github.com/paritytech/parity/pull/548) -- Fixing clippy warnings [#546](https://github.com/paritytech/parity/pull/546) -- ignore out directory [#543](https://github.com/paritytech/parity/pull/543) -- u256 full multiplication [#539](https://github.com/paritytech/parity/pull/539) -- Fix panic when downloading stales, update homestead transition [#537](https://github.com/paritytech/parity/pull/537) -- changing x64 asm config [#534](https://github.com/paritytech/parity/pull/534) -- uncomment state transition tests [#533](https://github.com/paritytech/parity/pull/533) -- jsonrpc uses weak pointers to client [#532](https://github.com/paritytech/parity/pull/532) -- Morden switch to Homestead rules at #494,000. [#531](https://github.com/paritytech/parity/pull/531) -- Blockchain module cleanup [#524](https://github.com/paritytech/parity/pull/524) -- Multiplication issue + very exhaustive tests for it [#528](https://github.com/paritytech/parity/pull/528) -- EIP-8 [#498](https://github.com/paritytech/parity/pull/498) -- Make "random" trie tests fully deterministic. [#527](https://github.com/paritytech/parity/pull/527) -- udpated serde to version 0.7.0 [#526](https://github.com/paritytech/parity/pull/526) -- Better memory management [#516](https://github.com/paritytech/parity/pull/516) -- Typo [#523](https://github.com/paritytech/parity/pull/523) -- U512 add/sub optimize [#521](https://github.com/paritytech/parity/pull/521) -- Account management + geth keystore import (no utility crate added) [#509](https://github.com/paritytech/parity/pull/509) -- Delayed UPnP initialization [#505](https://github.com/paritytech/parity/pull/505) -- Fixing marking blocks as bad & SyncMessage bugs + small client refactoring. [#503](https://github.com/paritytech/parity/pull/503) -- optimization of U256 [#515](https://github.com/paritytech/parity/pull/515) -- Removed rocksdb from build scripts and instructions [#520](https://github.com/paritytech/parity/pull/520) -- RocksDB abstraction layer + Hash index for state DB [#464](https://github.com/paritytech/parity/pull/464) -- bloomfilter [#418](https://github.com/paritytech/parity/pull/418) -- Fixed a race condition when connecting peer disconnects immediately [#519](https://github.com/paritytech/parity/pull/519) -- ignore intellij idea project files as well [#518](https://github.com/paritytech/parity/pull/518) -- updated version of unicase [#517](https://github.com/paritytech/parity/pull/517) -- jsonrpc security, cors headers, fixed #359 [#493](https://github.com/paritytech/parity/pull/493) -- Rust implementations to replace data tables (#161) [#482](https://github.com/paritytech/parity/pull/482) -- fix issue with starting requested block number was not included itself [#512](https://github.com/paritytech/parity/pull/512) -- fixed travis --org GH_TOKEN [#510](https://github.com/paritytech/parity/pull/510) -- Improved log format [#506](https://github.com/paritytech/parity/pull/506) -- Log address on failed connection attempt [#502](https://github.com/paritytech/parity/pull/502) -- Bumping clippy and fixing warnings. [#501](https://github.com/paritytech/parity/pull/501) -- Bumping versions. Fixes #496 [#500](https://github.com/paritytech/parity/pull/500) -- Manage final user-input errors. [#494](https://github.com/paritytech/parity/pull/494) -- Remove unneeded code, fix minor potential issue with length. [#495](https://github.com/paritytech/parity/pull/495) -- Remove "unknown" from version string. [#488](https://github.com/paritytech/parity/pull/488) -- Include git commit date & hash. [#486](https://github.com/paritytech/parity/pull/486) -- Use proper version string. [#485](https://github.com/paritytech/parity/pull/485) -- Networking fixes [#480](https://github.com/paritytech/parity/pull/480) -- Fix potential deadlock on node table update [#484](https://github.com/paritytech/parity/pull/484) -- Squash more warnings [#481](https://github.com/paritytech/parity/pull/481) -- dev/test/build tools to separate crate [#477](https://github.com/paritytech/parity/pull/477) -- Back to original slab crate [#479](https://github.com/paritytech/parity/pull/479) -- Better user errors. [#476](https://github.com/paritytech/parity/pull/476) -- UDP Discovery [#440](https://github.com/paritytech/parity/pull/440) -- update readme with rust override [#475](https://github.com/paritytech/parity/pull/475) -- fixed warnings on rust beta [#474](https://github.com/paritytech/parity/pull/474) -- Secret store (part2 - encrypted key/value svc) [#449](https://github.com/paritytech/parity/pull/449) -- Kill bad test. [#473](https://github.com/paritytech/parity/pull/473) -- Make clippy an optional dependency [#422](https://github.com/paritytech/parity/pull/422) -- parity compiling fine [#469](https://github.com/paritytech/parity/pull/469) -- compiling ethcore on beta [#468](https://github.com/paritytech/parity/pull/468) -- Utils compiling in beta [#467](https://github.com/paritytech/parity/pull/467) -- Get rid of lru_cache dependency [#466](https://github.com/paritytech/parity/pull/466) -- Add daemonization. [#459](https://github.com/paritytech/parity/pull/459) -- Master upgrade [#448](https://github.com/paritytech/parity/pull/448) -- Remove contributing stuff now that we have CLA bot. [#447](https://github.com/paritytech/parity/pull/447) -- Add Morden bootnode. [#446](https://github.com/paritytech/parity/pull/446) -- beta fixes to master [#441](https://github.com/paritytech/parity/pull/441) -- Secret store (part1 - key management) [#423](https://github.com/paritytech/parity/pull/423) -- Use 1100000 as the homestead transition, fix build instructions. [#438](https://github.com/paritytech/parity/pull/438) -- More sync and propagation fixes [#420](https://github.com/paritytech/parity/pull/420) -- back to cargo crates [#436](https://github.com/paritytech/parity/pull/436) -- Fixing clippy warnings [#435](https://github.com/paritytech/parity/pull/435) -- preserving root cargo lock [#434](https://github.com/paritytech/parity/pull/434) -- Nightly fix [#432](https://github.com/paritytech/parity/pull/432) -- nightly fixes [#431](https://github.com/paritytech/parity/pull/431) -- Delay Homestead transition from 1,000,000. [#429](https://github.com/paritytech/parity/pull/429) -- Nightly fix effort (still should fail) [#428](https://github.com/paritytech/parity/pull/428) -- clippy version update, docopt-macro moving to fork [#425](https://github.com/paritytech/parity/pull/425) -- Network/Sync fixes and optimizations [#416](https://github.com/paritytech/parity/pull/416) -- Use latest era instead of end era as journal marker [#414](https://github.com/paritytech/parity/pull/414) -- api changes [#402](https://github.com/paritytech/parity/pull/402) -- Option for no init nodes. [#408](https://github.com/paritytech/parity/pull/408) -- Fixed block_bodies not returning a list [#406](https://github.com/paritytech/parity/pull/406) -- Fix test. [#405](https://github.com/paritytech/parity/pull/405) -- Allow path to be configured. [#404](https://github.com/paritytech/parity/pull/404) -- Upnp [#400](https://github.com/paritytech/parity/pull/400) -- eth_syncing, fixed #397 [#398](https://github.com/paritytech/parity/pull/398) -- Using modified version of ctrlc that catches SIGTERM [#399](https://github.com/paritytech/parity/pull/399) -- Catching panics. [#396](https://github.com/paritytech/parity/pull/396) -- jsonrpc [#391](https://github.com/paritytech/parity/pull/391) -- Externalities tests (still clumsy) [#394](https://github.com/paritytech/parity/pull/394) -- excluding test code itself from coverage [#395](https://github.com/paritytech/parity/pull/395) -- Additional tweaks to options. [#390](https://github.com/paritytech/parity/pull/390) -- --chain option for setting which network to go on. [#388](https://github.com/paritytech/parity/pull/388) -- Ethash unit tests final [#387](https://github.com/paritytech/parity/pull/387) -- jsonrpc [#374](https://github.com/paritytech/parity/pull/374) -- Editorconfig file. [#384](https://github.com/paritytech/parity/pull/384) -- Coverage effort [in progress] [#382](https://github.com/paritytech/parity/pull/382) -- making root kcov runner simular to the one running on CI [#380](https://github.com/paritytech/parity/pull/380) -- add gcc as a dependency to dockerfiles [#381](https://github.com/paritytech/parity/pull/381) -- Check for handshake expiration before attempting connection replace [#375](https://github.com/paritytech/parity/pull/375) -- Blocks propagation [#364](https://github.com/paritytech/parity/pull/364) -- Network params. [#376](https://github.com/paritytech/parity/pull/376) -- Add parity-node-zero to bootnodes. [#373](https://github.com/paritytech/parity/pull/373) -- kcov uses travis_job_id instead of coveralls token [#370](https://github.com/paritytech/parity/pull/370) -- Add parity-node-zero.ethcore.io to boot nodes. [#371](https://github.com/paritytech/parity/pull/371) - -## Parity [v1.0.0-rc1](https://github.com/paritytech/parity/releases/tag/v1.0.0-rc1) (2016-03-15) - -First Parity 1.0.0 release candidate. - -- Version 1.0 in beta [#712](https://github.com/paritytech/parity/pull/712) -- Fix test for beta [#617](https://github.com/paritytech/parity/pull/617) -- JournalDB fix option 1 for beta [#614](https://github.com/paritytech/parity/pull/614) -- Failing test. [#606](https://github.com/paritytech/parity/pull/606) -- Fix transition points [#604](https://github.com/paritytech/parity/pull/604) -- (BETA) Update README.md [#549](https://github.com/paritytech/parity/pull/549) -- (BETA) instructions for beta release channel [#456](https://github.com/paritytech/parity/pull/456) -- (BETA) fix nightly - remerge [#454](https://github.com/paritytech/parity/pull/454) -- (BETA) fixing nightly version for beta [#452](https://github.com/paritytech/parity/pull/452) - -## Parity [beta-0.9.1](https://github.com/paritytech/parity/releases/tag/beta-0.9.1) (2016-02-16) - -Homestead transition block changed to 1100000. - -- Beta patch to 0.9.1 [#445](https://github.com/paritytech/parity/pull/445) -- Delay homestead transition [#430](https://github.com/paritytech/parity/pull/430) -- (BETA) https link in the installer (?) [#392](https://github.com/paritytech/parity/pull/392) -- beta: Check for handshake expiration before attempting replace [#377](https://github.com/paritytech/parity/pull/377) - -## Parity [beta-0.9](https://github.com/paritytech/parity/releases/tag/beta-0.9) (2016-02-08) - -First Parity Beta 0.9 released. - -- Panic on missing counters; Client cleanup [#368](https://github.com/paritytech/parity/pull/368) -- Update README for new PPAs. [#369](https://github.com/paritytech/parity/pull/369) -- block_queue::clear should be more thorough [#365](https://github.com/paritytech/parity/pull/365) -- Fixed an issue with forked counters [#363](https://github.com/paritytech/parity/pull/363) -- Install parity [#362](https://github.com/paritytech/parity/pull/362) -- DB directory versioning [#358](https://github.com/paritytech/parity/pull/358) -- Raise FD limit for MacOS [#357](https://github.com/paritytech/parity/pull/357) -- Travis slack integration. [#356](https://github.com/paritytech/parity/pull/356) -- SignedTransaction structure [#350](https://github.com/paritytech/parity/pull/350) -- License [#354](https://github.com/paritytech/parity/pull/354) -- Performance optimizations [#353](https://github.com/paritytech/parity/pull/353) -- Gitter in README. [#355](https://github.com/paritytech/parity/pull/355) -- test efforts, receipt requests [#352](https://github.com/paritytech/parity/pull/352) -- sync tests setup & local module coverage [#348](https://github.com/paritytech/parity/pull/348) -- install parity script [#347](https://github.com/paritytech/parity/pull/347) -- evmjit homestead merge [#342](https://github.com/paritytech/parity/pull/342) -- Fixed sync stalling on fork [#343](https://github.com/paritytech/parity/pull/343) -- Remerge 264 [#334](https://github.com/paritytech/parity/pull/334) -- Ethsync tests bfix [#339](https://github.com/paritytech/parity/pull/339) -- Fix default options. [#335](https://github.com/paritytech/parity/pull/335) -- sync queue limit hotfix [#338](https://github.com/paritytech/parity/pull/338) -- Network tests, separate local coverage for utils [#333](https://github.com/paritytech/parity/pull/333) -- fix parity version so netstats can parse it [#332](https://github.com/paritytech/parity/pull/332) -- reveal surprise [#331](https://github.com/paritytech/parity/pull/331) -- Revert removal of `new_code`. [#330](https://github.com/paritytech/parity/pull/330) -- Network mod tests first part [#329](https://github.com/paritytech/parity/pull/329) -- Look ma no `dead_code` [#323](https://github.com/paritytech/parity/pull/323) -- Fixing JIT, Updating hook to run `ethcore` tests. [#326](https://github.com/paritytech/parity/pull/326) -- Final docs [#327](https://github.com/paritytech/parity/pull/327) -- update install-deps.sh [#316](https://github.com/paritytech/parity/pull/316) -- Finish all my docs. Fix previous test compilation. [#320](https://github.com/paritytech/parity/pull/320) -- Additional evm tests (extops, call, jumps) and some docs [#317](https://github.com/paritytech/parity/pull/317) -- More documentation. [#318](https://github.com/paritytech/parity/pull/318) -- Additional documentation. [#315](https://github.com/paritytech/parity/pull/315) -- unused functions cleanup [#310](https://github.com/paritytech/parity/pull/310) -- update ethcore.github.io documentation automatically [#311](https://github.com/paritytech/parity/pull/311) -- Another try with travis ci credentials [#314](https://github.com/paritytech/parity/pull/314) -- Document some stuff. [#309](https://github.com/paritytech/parity/pull/309) -- Check block parent on import; Peer timeouts [#303](https://github.com/paritytech/parity/pull/303) -- Increasing coverage for evm. [#306](https://github.com/paritytech/parity/pull/306) -- ethcore docs [#301](https://github.com/paritytech/parity/pull/301) -- Replacing secure token for deployment [#305](https://github.com/paritytech/parity/pull/305) -- doc.sh [#299](https://github.com/paritytech/parity/pull/299) -- Building beta-* and stable-* tags [#302](https://github.com/paritytech/parity/pull/302) -- Deploying artifacts for tags (release/beta) [#300](https://github.com/paritytech/parity/pull/300) -- cov.sh to show coverage locally [#298](https://github.com/paritytech/parity/pull/298) -- benchmark fixes [#297](https://github.com/paritytech/parity/pull/297) -- Include JSONRPC CLI options. [#296](https://github.com/paritytech/parity/pull/296) -- travis.yml fixes [#293](https://github.com/paritytech/parity/pull/293) -- Improve version string. [#295](https://github.com/paritytech/parity/pull/295) -- Fixed block queue test [#294](https://github.com/paritytech/parity/pull/294) -- Util docs [#292](https://github.com/paritytech/parity/pull/292) -- fixed building docs [#289](https://github.com/paritytech/parity/pull/289) -- update travis to build PRs only against master [#290](https://github.com/paritytech/parity/pull/290) -- Coverage effort [#272](https://github.com/paritytech/parity/pull/272) -- updated docker containers [#288](https://github.com/paritytech/parity/pull/288) -- rpc module fixes [#287](https://github.com/paritytech/parity/pull/287) -- Test for Receipt RLP. [#282](https://github.com/paritytech/parity/pull/282) -- Building from source guide [#284](https://github.com/paritytech/parity/pull/284) -- Fixed neted empty list RLP encoding [#283](https://github.com/paritytech/parity/pull/283) -- Fix CALLDATACOPY (and bonus CODECOPY, too!). [#279](https://github.com/paritytech/parity/pull/279) -- added travis && coveralls badge to README.md [#280](https://github.com/paritytech/parity/pull/280) -- coveralls coverage [#277](https://github.com/paritytech/parity/pull/277) -- Travis [in progress] [#257](https://github.com/paritytech/parity/pull/257) -- Travis on reorganized repo [#276](https://github.com/paritytech/parity/pull/276) -- umbrella project [#275](https://github.com/paritytech/parity/pull/275) -- Ethash disk cache [#273](https://github.com/paritytech/parity/pull/273) -- Parity executable name and version [#274](https://github.com/paritytech/parity/pull/274) -- Dockerfile [#195](https://github.com/paritytech/parity/pull/195) -- Garbage collection test fix [#267](https://github.com/paritytech/parity/pull/267) -- Fix stCallCreateCallCodeTest, add more tests [#271](https://github.com/paritytech/parity/pull/271) -- Moved sync out of ethcore crate; Added block validation [#265](https://github.com/paritytech/parity/pull/265) -- RLP encoder refactoring [#252](https://github.com/paritytech/parity/pull/252) -- Chain sync tests and minor refactoring [#264](https://github.com/paritytech/parity/pull/264) -- Common log init function [#263](https://github.com/paritytech/parity/pull/263) -- changed max vm depth from 128 to 64, change homestead block to 1_000_000 [#262](https://github.com/paritytech/parity/pull/262) -- fixed blockchain tests crash on log init [#261](https://github.com/paritytech/parity/pull/261) -- Blockchain tests and some helpers for guarding temp directory [#256](https://github.com/paritytech/parity/pull/256) -- Fix logging and random tests. [#260](https://github.com/paritytech/parity/pull/260) -- Fix difficulty calculation algo. [#259](https://github.com/paritytech/parity/pull/259) -- fix submodule version [#258](https://github.com/paritytech/parity/pull/258) -- temp dir spawn refactoring [#246](https://github.com/paritytech/parity/pull/246) -- fixed tests submodule branch [#254](https://github.com/paritytech/parity/pull/254) -- rpc net methods returns real peer count && protocol version [#253](https://github.com/paritytech/parity/pull/253) -- Add homestead & random tests. [#245](https://github.com/paritytech/parity/pull/245) -- Fixing suicide with self-refund to be consistent with CPP. [#247](https://github.com/paritytech/parity/pull/247) -- stubs for rpc methods [#251](https://github.com/paritytech/parity/pull/251) -- clippy, missing docs, renaming etc. [#244](https://github.com/paritytech/parity/pull/244) -- impl missing methods in tests [#243](https://github.com/paritytech/parity/pull/243) -- General tests and some helpers [#239](https://github.com/paritytech/parity/pull/239) -- Note additional tests are fixed, fix doc test. [#242](https://github.com/paritytech/parity/pull/242) -- jsonrpc http server [#193](https://github.com/paritytech/parity/pull/193) -- Ethash nonce is H64 not a u64 [#240](https://github.com/paritytech/parity/pull/240) -- Fix import for bcMultiChainTest [#236](https://github.com/paritytech/parity/pull/236) -- Client basic tests [#232](https://github.com/paritytech/parity/pull/232) -- Fix ensure_db_good() and flush_queue(), block refactoring, check block format, be strict. [#231](https://github.com/paritytech/parity/pull/231) -- Rlp [#207](https://github.com/paritytech/parity/pull/207) -- Schedule documentation [#219](https://github.com/paritytech/parity/pull/219) -- U256<->H256 Conversion [#206](https://github.com/paritytech/parity/pull/206) -- Spawning new thread when we are reaching stack limit [#217](https://github.com/paritytech/parity/pull/217) -- Blockchain tests [#211](https://github.com/paritytech/parity/pull/211) -- fixed failing sync test [#218](https://github.com/paritytech/parity/pull/218) -- Removing println [#216](https://github.com/paritytech/parity/pull/216) -- Cleaning readme [#212](https://github.com/paritytech/parity/pull/212) -- Fixing delegatecall [#196](https://github.com/paritytech/parity/pull/196) -- Autogenerate the Args from the docopt macro. [#205](https://github.com/paritytech/parity/pull/205) -- Networking fixes [#202](https://github.com/paritytech/parity/pull/202) -- Argument parsing from CLI [#204](https://github.com/paritytech/parity/pull/204) -- Removed wildcard from clippy version [#203](https://github.com/paritytech/parity/pull/203) -- Fixed tests and tweaked sync progress report [#201](https://github.com/paritytech/parity/pull/201) -- Heavy tests [#199](https://github.com/paritytech/parity/pull/199) -- Mutithreaded IO [#198](https://github.com/paritytech/parity/pull/198) -- Populating last_hashes [#197](https://github.com/paritytech/parity/pull/197) -- Fixing clippy stuff [#170](https://github.com/paritytech/parity/pull/170) -- basic .travis.yml [#194](https://github.com/paritytech/parity/pull/194) -- Generating coverage reports. [#190](https://github.com/paritytech/parity/pull/190) -- Adding doc requests comments [#192](https://github.com/paritytech/parity/pull/192) -- moved src/bin/client.rs -> src/bin/client/main.rs [#185](https://github.com/paritytech/parity/pull/185) -- removed overflowing_shr [#188](https://github.com/paritytech/parity/pull/188) -- fixed wrapping ops on latest nightly [#187](https://github.com/paritytech/parity/pull/187) -- Pruned state DB [#176](https://github.com/paritytech/parity/pull/176) -- Memory management for cache [#180](https://github.com/paritytech/parity/pull/180) -- Implement signs having low-s. [#183](https://github.com/paritytech/parity/pull/183) -- Introduce sha3 crate and use it in ethash [#178](https://github.com/paritytech/parity/pull/178) -- Multithreaded block queue [#173](https://github.com/paritytech/parity/pull/173) -- Iterator for NibbleSlice and TrieDB. [#171](https://github.com/paritytech/parity/pull/171) -- Handling all possible overflows [#145](https://github.com/paritytech/parity/pull/145) -- Global secp256k1 context [#164](https://github.com/paritytech/parity/pull/164) -- Ethash [#152](https://github.com/paritytech/parity/pull/152) -- Move util into here [#153](https://github.com/paritytech/parity/pull/153) -- EVM Interpreter [#103](https://github.com/paritytech/parity/pull/103) -- Homestead transition support, maybe. [#141](https://github.com/paritytech/parity/pull/141) -- externalities refactor [#131](https://github.com/paritytech/parity/pull/131) -- More open files. [#140](https://github.com/paritytech/parity/pull/140) -- Single array for logs output. [#133](https://github.com/paritytech/parity/pull/133) -- Client app event handler [#132](https://github.com/paritytech/parity/pull/132) -- Various consensus fixes. [#130](https://github.com/paritytech/parity/pull/130) -- callcode builtins tests pass [#127](https://github.com/paritytech/parity/pull/127) -- Client state syncing [#119](https://github.com/paritytech/parity/pull/119) -- Split externalities from executive. [#126](https://github.com/paritytech/parity/pull/126) -- executive error on not enoguh base gas [#124](https://github.com/paritytech/parity/pull/124) -- Gav [#125](https://github.com/paritytech/parity/pull/125) -- builtin sets excepted to true [#123](https://github.com/paritytech/parity/pull/123) -- More state tests. [#122](https://github.com/paritytech/parity/pull/122) -- updated to rocksdb wrapper version 0.3 [#121](https://github.com/paritytech/parity/pull/121) -- out_of_gas -> excepted [#120](https://github.com/paritytech/parity/pull/120) -- Parametrizing evm::Factory [#111](https://github.com/paritytech/parity/pull/111) -- stLogs tests passing [#118](https://github.com/paritytech/parity/pull/118) -- Fix executive. [#117](https://github.com/paritytech/parity/pull/117) -- Fixes for marek's shooting from the hip. [#116](https://github.com/paritytech/parity/pull/116) -- Executive revert fix [#115](https://github.com/paritytech/parity/pull/115) -- Fix storage/account and add butress test. [#114](https://github.com/paritytech/parity/pull/114) -- Refactored Pod & Diff types into separate files, JSON infrastructure revamp. [#113](https://github.com/paritytech/parity/pull/113) -- Fix storage stuff and introduce per-item dirty-tracking. [#112](https://github.com/paritytech/parity/pull/112) -- Check logs in state tests. [#109](https://github.com/paritytech/parity/pull/109) -- executive gas calculation fixes [#108](https://github.com/paritytech/parity/pull/108) -- proper gas calculation in executive [#107](https://github.com/paritytech/parity/pull/107) -- Fixing MaxDepth param for executive [#105](https://github.com/paritytech/parity/pull/105) -- Fix determination of state roots. [#106](https://github.com/paritytech/parity/pull/106) -- transact substracts tx_gas [#104](https://github.com/paritytech/parity/pull/104) -- Pretty-print and fix for state. [#102](https://github.com/paritytech/parity/pull/102) -- Tier step price. [#101](https://github.com/paritytech/parity/pull/101) -- Refactor Diff datastructures. [#100](https://github.com/paritytech/parity/pull/100) -- externalities use u256 instead of u64 for gas calculation [#99](https://github.com/paritytech/parity/pull/99) -- Executive tests [#97](https://github.com/paritytech/parity/pull/97) -- State conensus tests now print mismatching diff on fail. [#98](https://github.com/paritytech/parity/pull/98) -- State testing framework. First test is failing. [#96](https://github.com/paritytech/parity/pull/96) -- executive tests [#95](https://github.com/paritytech/parity/pull/95) -- Use U512s for ether cost calculation, complete transaction API [#94](https://github.com/paritytech/parity/pull/94) -- Utils for consensus test decoding and better layout. [#93](https://github.com/paritytech/parity/pull/93) -- executive fixes + tests [#89](https://github.com/paritytech/parity/pull/89) -- All transaction tests pass. Nicer testing framework. [#92](https://github.com/paritytech/parity/pull/92) -- Block verification tests; BlockProvider blockchain trait for testing [#88](https://github.com/paritytech/parity/pull/88) -- State::exists, docs and tests. [#87](https://github.com/paritytech/parity/pull/87) -- Add tests module, add two more transaction tests. [#86](https://github.com/paritytech/parity/pull/86) -- bring back removed tests, removed build warnings [#82](https://github.com/paritytech/parity/pull/82) -- Nicer transaction validation API. Nicer OutOfBounds API in general. [#85](https://github.com/paritytech/parity/pull/85) -- Transaction fixes and consensus tests (all passing) [#84](https://github.com/paritytech/parity/pull/84) -- fixed getting block info in evmjit + tests [#81](https://github.com/paritytech/parity/pull/81) -- evm tests cleanup [#80](https://github.com/paritytech/parity/pull/80) -- renamed VmFactory -> Factory [#77](https://github.com/paritytech/parity/pull/77) -- fixed rust-evmjit description of improper_ctypes usage [#76](https://github.com/paritytech/parity/pull/76) -- jit feature enabled by default [#75](https://github.com/paritytech/parity/pull/75) -- evm [#52](https://github.com/paritytech/parity/pull/52) -- state clone [#74](https://github.com/paritytech/parity/pull/74) -- Block Verification (no tests yet) [#72](https://github.com/paritytech/parity/pull/72) -- Improvements to LogEntry and Transaction [#73](https://github.com/paritytech/parity/pull/73) -- Use getter in header in preparation for a Header trait; additional testing in enact_block(). [#64](https://github.com/paritytech/parity/pull/64) -- BlockChain sync and Client app [#55](https://github.com/paritytech/parity/pull/55) -- Block enactment (including test) [#63](https://github.com/paritytech/parity/pull/63) -- Block complete. Needs tests. [#62](https://github.com/paritytech/parity/pull/62) -- More on OpenBlock::close; State::kill_account added [#61](https://github.com/paritytech/parity/pull/61) -- Remove genesis module, add more chain specs and separate out ethereum-specific stuff [#60](https://github.com/paritytech/parity/pull/60) -- State::new_contract, camelCase engine params, missing param [#59](https://github.com/paritytech/parity/pull/59) -- Use reorganisation [#58](https://github.com/paritytech/parity/pull/58) -- Initial Ethash/Block skeleton implementations. [#57](https://github.com/paritytech/parity/pull/57) -- Spec with tested Morden genesis decoder and builtins. [#54](https://github.com/paritytech/parity/pull/54) -- Move all chain parameters into `engine_params` [#50](https://github.com/paritytech/parity/pull/50) -- jit ffi improvements [please review] [#51](https://github.com/paritytech/parity/pull/51) -- blockchain [please review] [#34](https://github.com/paritytech/parity/pull/34) -- Move information from networkparams.rs into spec.rs [#48](https://github.com/paritytech/parity/pull/48) -- Move bulking out in Engine/Params. [#47](https://github.com/paritytech/parity/pull/47) -- Removed need for mutation in State. [#46](https://github.com/paritytech/parity/pull/46) -- State::code and State::storage_at + tests. [#45](https://github.com/paritytech/parity/pull/45) -- State functions for balance and nonce operations [#44](https://github.com/paritytech/parity/pull/44) -- Account::storage_at, Account::ensure_cached and tests. [#43](https://github.com/paritytech/parity/pull/43) -- Additional tests. [#42](https://github.com/paritytech/parity/pull/42) -- seal todo done [#41](https://github.com/paritytech/parity/pull/41) -- missing rustc_serialize crate && rlp `as_list` function [#40](https://github.com/paritytech/parity/pull/40) -- More methods in Account, documentation and tests. [#39](https://github.com/paritytech/parity/pull/39) -- Minor reworking of Account. [#38](https://github.com/paritytech/parity/pull/38) -- Add Account and State classes. [#37](https://github.com/paritytech/parity/pull/37) -- Revert regressions [#36](https://github.com/paritytech/parity/pull/36) +- Beta Backports ([#8136](https://github.com/paritytech/parity/pull/8136)) + - Support parity protocol. ([#8035](https://github.com/paritytech/parity/pull/8035)) + - updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059)) + - updater: apply exponential backoff after download failure + - updater: reset backoff on new release + - Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067)) + - Enable code size limit on kovan + - Fix formatting. + - Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060)) + - Limit ingress connections + - Optimized handshakes logging + - WASM libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970)) + - update wasmi, parity-wasm, wasm-utils to latest version + - Update to new wasmi & error handling + - also utilize new stack limiter + - fix typo + - replace dependency url + - Cargo.lock update + - add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084)) + - revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066)) + - Revert "fix traces, removed bloomchain crate, closes [#7228](https://github.com/paritytech/parity/issues/7228), closes [#7167](https://github.com/paritytech/parity/issues/7167)" + - Revert "fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))" + - fixed broken logs + - bring back old lock order + - remove migration v13 + - revert CURRENT_VERSION to 12 in migration.rs + - more dos protection ([#8104](https://github.com/paritytech/parity/pull/8104)) + - Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113)) + - Use `subtle::slices_equal` for constant time comparison. + - Also update the existing version of subtle in `ethcrypto` from 0.1 to 0.5 + - Test specifically for InvalidPassword error. + - fix trace filter returning returning unrelated reward calls, closes #8070 ([#8098](https://github.com/paritytech/parity/pull/8098)) + - network: init discovery using healthy nodes ([#8061](https://github.com/paritytech/parity/pull/8061)) + - network: init discovery using healthy nodes + - network: fix style grumble + - network: fix typo + - Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) + - ethcore: postpone Kovan hard fork + - util: update version fork metadata + - Disable UI by default. ([#8105](https://github.com/paritytech/parity/pull/8105)) + - dapps: update parity-ui dependencies ([#8160](https://github.com/paritytech/parity/pull/8160)) +- Probe changes one step deeper ([#8134](https://github.com/paritytech/parity/pull/8134)) ([#8135](https://github.com/paritytech/parity/pull/8135)) +- Beta backports ([#8053](https://github.com/paritytech/parity/pull/8053)) + - CI: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968)) + - Fix cache + - Only clean locked cargo cache on windows + - fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026)) + - fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031)) + - fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032)) + - fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052)) + - Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841)) + - Add test chain spec for musicoin byzantium testnet + - Add MCIP-6 Byzyantium transition to Musicoin spec + - Update mcip6_byz.json + - ethcore: update musicoin byzantium block number + - ethcore: update musicoin bootnodes + - Update musicoin.json + - More bootnodes. +- Make 1.10 beta ([#8022](https://github.com/paritytech/parity/pull/8022)) + - Make 1.10 beta + - Fix gitlab builds +- SecretStore: secretstore_generateDocumentKey RPC ([#7864](https://github.com/paritytech/parity/pull/7864)) +- SecretStore: ECDSA session for cases when 2*t < N ([#7739](https://github.com/paritytech/parity/pull/7739)) +- bump tiny-keccak ([#8019](https://github.com/paritytech/parity/pull/8019)) +- Remove un-necessary comment ([#8014](https://github.com/paritytech/parity/pull/8014)) +- clean up account fmt::Debug ([#7983](https://github.com/paritytech/parity/pull/7983)) +- improve quality of vote_collector module ([#7984](https://github.com/paritytech/parity/pull/7984)) +- ExecutedBlock cleanup ([#7991](https://github.com/paritytech/parity/pull/7991)) +- Hardware-wallet/usb-subscribe-refactor ([#7860](https://github.com/paritytech/parity/pull/7860)) +- remove wildcard imports from views, make tests more idiomatic ([#7986](https://github.com/paritytech/parity/pull/7986)) +- moved PerfTimer to a separate crate - "trace-time" ([#7985](https://github.com/paritytech/parity/pull/7985)) +- clean up ethcore::spec module imports ([#7990](https://github.com/paritytech/parity/pull/7990)) +- rpc: don't include current block in new_block_filter ([#7982](https://github.com/paritytech/parity/pull/7982)) +- fix traces, removed bloomchain crate ([#7979](https://github.com/paritytech/parity/pull/7979)) +- simplify compression and move it out of rlp crate ([#7957](https://github.com/paritytech/parity/pull/7957)) +- removed old migrations ([#7974](https://github.com/paritytech/parity/pull/7974)) +- Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977)) +- fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934)) +- Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965)) +- Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953)) +- Add changelog for 1.8.10 stable and 1.9.3 beta ([#7947](https://github.com/paritytech/parity/pull/7947)) +- kvdb-rocksdb: remove buffered operations when committing transaction ([#7950](https://github.com/paritytech/parity/pull/7950)) +- Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952)) +- removed redundant Bloom conversions ([#7932](https://github.com/paritytech/parity/pull/7932)) +- simplify RefInfo fmt ([#7929](https://github.com/paritytech/parity/pull/7929)) +- Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849)) +- bring back trie and triehash benches ([#7926](https://github.com/paritytech/parity/pull/7926)) +- removed redundant PodAccount::new method ([#7928](https://github.com/paritytech/parity/pull/7928)) +- removed dummy wrapper structure - LogGroupPosition ([#7922](https://github.com/paritytech/parity/pull/7922)) +- spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933)) +- simplify Client::filter_traces method ([#7936](https://github.com/paritytech/parity/pull/7936)) +- gitlab cache ([#7921](https://github.com/paritytech/parity/pull/7921)) +- Fix a division by zero in light client RPC handler ([#7917](https://github.com/paritytech/parity/pull/7917)) +- triehash optimisations ([#7920](https://github.com/paritytech/parity/pull/7920)) +- removed redundant Blockchain::db method ([#7919](https://github.com/paritytech/parity/pull/7919)) +- removed redundant Blockchain::rewind method ([#7918](https://github.com/paritytech/parity/pull/7918)) +- Pending transactions subscription ([#7906](https://github.com/paritytech/parity/pull/7906)) +- removed redundant otry! macro from ethcore ([#7916](https://github.com/paritytech/parity/pull/7916)) +- Make block generator easier to use ([#7888](https://github.com/paritytech/parity/pull/7888)) +- ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905)) +- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867)) +- Fix gitlab ([#7901](https://github.com/paritytech/parity/pull/7901)) +- Gitlb snap master patch ([#7900](https://github.com/paritytech/parity/pull/7900)) +- fix snap build master ([#7896](https://github.com/paritytech/parity/pull/7896)) +- Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873)) +- Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884)) +- Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848)) +- SecretStore: fixed test ([#7878](https://github.com/paritytech/parity/pull/7878)) +- Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846)) +- Forward-port snap fixes ([#7831](https://github.com/paritytech/parity/pull/7831)) +- Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883)) +- Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881)) +- Fix string typo: "develoopment" -> "development" ([#7874](https://github.com/paritytech/parity/pull/7874)) +- Update the instructions to install the stable snap ([#7876](https://github.com/paritytech/parity/pull/7876)) +- SecretStore: 'broadcast' decryption session ([#7843](https://github.com/paritytech/parity/pull/7843)) +- Flush keyfiles. Resolves #7632 ([#7868](https://github.com/paritytech/parity/pull/7868)) +- Read registry_address from given block ([#7866](https://github.com/paritytech/parity/pull/7866)) +- Clean up docs formatting for Wasm runtime ([#7869](https://github.com/paritytech/parity/pull/7869)) +- WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842)) +- Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855)) +- ethabi version 5 ([#7723](https://github.com/paritytech/parity/pull/7723)) +- Light client: randomize the peer we dispatch requests to ([#7844](https://github.com/paritytech/parity/pull/7844)) +- Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832)) +- Add new EF ropstens nodes. ([#7824](https://github.com/paritytech/parity/pull/7824)) +- refactor stratum to remove retain cycle ([#7827](https://github.com/paritytech/parity/pull/7827)) +- Bump jsonrpc. ([#7828](https://github.com/paritytech/parity/pull/7828)) +- Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830)) +- Update references to UI shell & wallet ([#7808](https://github.com/paritytech/parity/pull/7808)) +- Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812)) +- Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796)) +- SecretStore: ignore removed authorities when running auto-migration ([#7674](https://github.com/paritytech/parity/pull/7674)) +- Fix build ([#7807](https://github.com/paritytech/parity/pull/7807)) +- Move js & js-old code to github.com/parity-js ([#7685](https://github.com/paritytech/parity/pull/7685)) +- More changelogs :) ([#7782](https://github.com/paritytech/parity/pull/7782)) +- Actualized API set in help ([#7790](https://github.com/paritytech/parity/pull/7790)) +- Removed obsolete file ([#7788](https://github.com/paritytech/parity/pull/7788)) +- Update ropsten bootnodes ([#7776](https://github.com/paritytech/parity/pull/7776)) +- CHANGELOG for 1.9.1 and 1.8.8 ([#7775](https://github.com/paritytech/parity/pull/7775)) +- Enable byzantium features on non-ethash chains ([#7753](https://github.com/paritytech/parity/pull/7753)) +- Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695)) +- Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716)) +- Removes redundant parentheses ([#7721](https://github.com/paritytech/parity/pull/7721)) +- Transaction-pool fixes ([#7741](https://github.com/paritytech/parity/pull/7741)) +- More visible download link in README.md ([#7707](https://github.com/paritytech/parity/pull/7707)) +- Changelog for 1.9.0 ([#7664](https://github.com/paritytech/parity/pull/7664)) +- Add scroll when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677)) +- SecretStore: return HTTP 403 (access denied) if consensus is unreachable ([#7656](https://github.com/paritytech/parity/pull/7656)) +- Moved StopGaurd to it's own crate ([#7635](https://github.com/paritytech/parity/pull/7635)) + +## Previous releases + +- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (_stable_) +- [CHANGELOG-1.8](docs/CHANGELOG-1.8.md) (EOL: 2018-03-22) +- [CHANGELOG-1.7](docs/CHANGELOG-1.7.md) (EOL: 2018-01-25) +- [CHANGELOG-1.6](docs/CHANGELOG-1.6.md) (EOL: 2017-10-15) +- [CHANGELOG-1.5](docs/CHANGELOG-1.5.md) (EOL: 2017-07-28) +- [CHANGELOG-1.4](docs/CHANGELOG-1.4.md) (EOL: 2017-03-13) +- [CHANGELOG-1.3](docs/CHANGELOG-1.3.md) (EOL: 2017-01-19) +- [CHANGELOG-1.2](docs/CHANGELOG-1.2.md) (EOL: 2016-11-07) +- [CHANGELOG-1.1](docs/CHANGELOG-1.1.md) (EOL: 2016-08-12) +- [CHANGELOG-1.0](docs/CHANGELOG-1.0.md) (EOL: 2016-06-24) +- [CHANGELOG-0.9](docs/CHANGELOG-0.9.md) (EOL: 2016-05-02) diff --git a/Cargo.lock b/Cargo.lock index e2108d1866e7d71340eb3cf5b0aa82d9a38a5036..211fbbd61cd8a4aed6501418cb087750ff245c9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,41 +1,14 @@ -[root] -name = "wasm" -version = "0.1.0" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "vm 0.1.0", - "wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)", -] - -[[package]] -name = "advapi32-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ansi_term" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "antidote" -version = "1.0.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -46,16 +19,15 @@ dependencies = [ "ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "arrayvec" -version = "0.3.20" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -63,7 +35,7 @@ name = "aster" version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -72,45 +44,29 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -124,51 +80,54 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "bigint" -version = "4.1.2" +name = "base64" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "bincode" -version = "0.8.0" +name = "base64" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "bit-set" -version = "0.2.0" +name = "bigint" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "bit-set" -version = "0.4.0" +name = "bincode" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "bit-vec" -version = "0.4.3" +name = "bit-set" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "bitflags" -version = "0.5.0" +name = "bit-vec" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -187,55 +146,53 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "blastfig" -version = "0.3.3" +name = "bitflags" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "bloomable" -version = "0.1.0" +name = "bloomchain" +version = "0.2.0" dependencies = [ - "ethcore-bigint 0.1.3", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (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 = "bloomchain" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bn" version = "0.4.4" -source = "git+https://github.com/paritytech/bn#b97e95a45f4484a41a515338c4f0e093bf6675e0" +source = "git+https://github.com/paritytech/bn#964b48fad5dffbaa124c2f10699e76faf5846c4e" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "byteorder" -version = "0.5.3" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "byteorder" -version = "1.0.0" +name = "bytes" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "bytes" -version = "0.4.4" +name = "cc" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cfg-if" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -244,64 +201,52 @@ version = "0.1.0" dependencies = [ "ethjson 0.1.0", "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clap" -version = "2.24.2" +version = "2.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "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" +name = "coco" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (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.28 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "common-types" version = "0.1.0" dependencies = [ - "bloomable 0.1.0", - "ethcore-util 1.8.0", + "ethcore-bytes 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", - "rlp 0.2.0", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "rlp 0.2.1", "rlp_derive 0.1.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -319,30 +264,13 @@ name = "cookie" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam" -version = "0.2.10" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -351,12 +279,11 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "crypt32-sys" +name = "ct-logs" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -365,7 +292,7 @@ version = "1.1.1" source = "git+https://github.com/paritytech/rust-ctrlc.git#b523017108bb2d571a7a69bd97bc406e63bc7a9d" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -376,537 +303,602 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "daemonize" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.2.3" +source = "git+https://github.com/paritytech/daemonize#df00295f03450326613f2d616059fd44434a0d74" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "dbghelp-sys" -version = "0.2.0" +name = "difference" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "deque" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "dir" +version = "0.1.0" dependencies = [ - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "journaldb 0.1.0", ] -[[package]] -name = "difference" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "docopt" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "dtoa" -version = "0.4.0" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "edit-distance" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "either" -version = "1.0.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "elastic-array" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.5.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "eth-secp256k1" -version = "0.5.6" -source = "git+https://github.com/paritytech/rust-secp256k1#b6b67055edc929057e97d64f036c78ad91f58a7f" +version = "0.5.7" +source = "git+https://github.com/paritytech/rust-secp256k1#db81cfea59014b4d176f10f86ed52e1a130b6822" dependencies = [ - "arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethabi" -version = "2.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethabi-contract" +version = "5.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ethabi-derive" +version = "5.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethash" -version = "1.8.0" +version = "1.11.0" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha3 0.1.0", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethbloom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bloomable 0.1.0", - "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bloomchain 0.2.0", "bn 0.4.4 (git+https://github.com/paritytech/bn)", - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (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)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.8.0", + "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethash 1.11.0", "ethcore-bloom-journal 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-stratum 1.8.0", - "ethcore-util 1.8.0", + "ethcore-bytes 0.1.0", + "ethcore-io 1.11.0", + "ethcore-logger 1.11.0", + "ethcore-miner 1.11.0", + "ethcore-stratum 1.11.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", - "ethkey 0.2.0", - "ethstore 0.1.0", + "ethkey 0.3.0", + "ethstore 0.2.0", "evm 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "hardware-wallet 1.8.0", - "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", - "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "native-contracts 0.1.0", - "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "price-info 1.7.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hardware-wallet 1.11.0", + "hashdb 0.1.1", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.5.10 (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", + "kvdb-rocksdb 0.1.0", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "macros 0.1.0", + "memory-cache 0.1.0", + "memorydb 0.1.1", + "migration 0.1.0", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-machine 0.1.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie 0.1.0", + "price-info 1.11.0", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "rlp_compress 0.1.0", "rlp_derive 0.1.0", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", "stats 0.1.0", + "stop-guard 0.1.0", "table 0.1.0", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "trace-time 0.1.0", + "trie-standardmap 0.1.0", + "triehash 0.1.0", + "unexpected 0.1.0", "using_queue 0.1.0", + "util-error 0.1.0", "vm 0.1.0", "wasm 0.1.0", ] [[package]] -name = "ethcore-bigint" -version = "0.1.3" +name = "ethcore-bloom-journal" +version = "0.1.0" dependencies = [ - "bigint 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "plain_hasher 0.1.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ethcore-bloom-journal" +name = "ethcore-bytes" version = "0.1.0" -dependencies = [ - "siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "ethcore-devtools" -version = "1.8.0" -dependencies = [ - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", -] +version = "1.11.0" [[package]] name = "ethcore-io" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ethcore-ipc" -version = "1.8.0" -dependencies = [ - "ethcore-devtools 1.8.0", - "ethcore-util 1.8.0", - "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethcore-ipc-codegen" -version = "1.8.0" -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)", - "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ethcore-ipc-hypervisor" -version = "1.2.0" +name = "ethcore-light" +version = "1.11.0" dependencies = [ - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethcore-io 1.11.0", + "ethcore-network 1.11.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "kvdb 0.1.0", + "kvdb-memorydb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-cache 0.1.0", + "memorydb 0.1.1", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie 0.1.0", + "plain_hasher 0.1.0", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "rlp_derive 0.1.0", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "stats 0.1.0", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "triehash 0.1.0", + "vm 0.1.0", ] [[package]] -name = "ethcore-ipc-nano" -version = "1.8.0" +name = "ethcore-logger" +version = "1.11.0" dependencies = [ - "ethcore-ipc 1.8.0", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ethcore-ipc-tests" +name = "ethcore-migrations" version = "0.1.0" dependencies = [ - "ethcore-devtools 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-util 1.8.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "migration 0.1.0", ] [[package]] -name = "ethcore-light" -version = "1.8.0" +name = "ethcore-miner" +version = "1.11.0" dependencies = [ - "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", - "evm 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "rlp_derive 0.1.0", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "stats 0.1.0", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "vm 0.1.0", + "common-types 0.1.0", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethash 1.11.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", + "keccak-hash 0.1.0", + "linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "table 0.1.0", + "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ethcore-logger" -version = "1.8.0" +name = "ethcore-network" +version = "1.11.0" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-io 1.11.0", + "ethcrypto 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", ] [[package]] -name = "ethcore-network" -version = "1.8.0" -dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", +name = "ethcore-network-devp2p" +version = "1.11.0" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0", + "ethcore-io 1.11.0", + "ethcore-logger 1.11.0", + "ethcore-network 1.11.0", "ethcrypto 0.1.0", - "ethkey 0.2.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", "igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-secretstore" version = "1.0.0" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-devtools 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethcore-logger 1.11.0", "ethcrypto 0.1.0", - "ethkey 0.2.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "native-contracts 0.1.0", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "ethsync 1.11.0", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "kvdb 0.1.0", + "kvdb-rocksdb 0.1.0", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethcore-service" +version = "0.1.0" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-io 1.11.0", + "kvdb 0.1.0", + "kvdb-rocksdb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "stop-guard 0.1.0", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethcore-stratum" -version = "1.8.0" -dependencies = [ - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-devtools 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-tcp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +version = "1.11.0" +dependencies = [ + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-logger 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "keccak-hash 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "ethcore-util" -version = "1.8.0" +name = "ethcore-transaction" +version = "0.1.0" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", - "ethcore-bigint 0.1.3", - "ethcore-bloom-journal 0.1.0", - "ethcore-devtools 1.8.0", - "ethcore-logger 1.8.0", - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethjson 0.1.0", + "ethkey 0.3.0", + "evm 0.1.0", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 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)", - "sha3 0.1.0", - "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unexpected 0.1.0", ] [[package]] name = "ethcrypto" version = "0.1.0" dependencies = [ - "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", - "ethcore-bigint 0.1.3", - "ethkey 0.2.0", + "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "subtle 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)", + "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethereum-types" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ethbloom 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "uint 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ethereum-types-serialize" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethjson" version = "0.1.0" dependencies = [ - "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bigint 0.1.3", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethkey" -version = "0.2.0" +version = "0.3.0" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", - "ethcore-bigint 0.1.3", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethkey-cli" version = "0.1.0" dependencies = [ - "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethkey 0.2.0", + "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", "panic_hook 0.1.0", + "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethstore" -version = "0.1.0" +version = "0.2.0" dependencies = [ - "ethcore-bigint 0.1.3", + "dir 0.1.0", "ethcrypto 0.1.0", - "ethkey 0.2.0", - "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wordlist 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethstore-cli" version = "0.1.0" dependencies = [ - "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethstore 0.1.0", + "dir 0.1.0", + "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethstore 0.2.0", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ethsync" -version = "1.8.0" -dependencies = [ - "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-light 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", - "ethkey 0.2.0", - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", +version = "1.11.0" +dependencies = [ + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethcore-io 1.11.0", + "ethcore-light 1.11.0", + "ethcore-network 1.11.0", + "ethcore-network-devp2p 1.11.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "kvdb 0.1.0", + "kvdb-memorydb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "macros 0.1.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "plain_hasher 0.1.0", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "triehash 0.1.0", ] [[package]] @@ -914,42 +906,43 @@ name = "evm" version = "0.1.0" dependencies = [ "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "common-types 0.1.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", - "ethjson 0.1.0", - "evmjit 1.8.0", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "evmjit 1.11.0", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memory-cache 0.1.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", - "wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)", ] [[package]] name = "evmbin" version = "0.1.0" dependencies = [ - "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-util 1.8.0", + "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", "evm 0.1.0", "panic_hook 0.1.0", + "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", ] [[package]] name = "evmjit" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -957,28 +950,40 @@ name = "fdlimit" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fetch" version = "0.1.0" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fixed-hash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (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 = "flate2" -version = "0.2.14" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -987,44 +992,52 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "foreign-types" -version = "0.2.0" +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.11" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures-cpupool" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "gcc" -version = "0.3.51" +name = "futures-timer" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "gdi32-sys" -version = "0.2.0" +name = "gcc" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getopts" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1034,14 +1047,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "globset" -version = "0.1.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1051,31 +1064,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hardware-wallet" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "ethcore-bigint 0.1.3", - "ethkey 0.2.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)", +] + +[[package]] +name = "hashdb" +version = "0.1.1" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "heapsize" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "heck" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1086,15 +1109,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hidapi" version = "0.3.1" -source = "git+https://github.com/paritytech/hidapi-rs#9a127c1dca7e327e4fdd428406a76c9f5ef48563" +source = "git+https://github.com/paritytech/hidapi-rs#e77ea09c98f29ea8855dd9cd9461125a28ca9125" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "httparse" -version = "1.1.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1103,56 +1126,86 @@ version = "0.10.0-a.0" source = "git+https://github.com/paritytech/hyper#da10f69a4924cd44e98a8d1f9562bd7534d13dcc" dependencies = [ "cookie 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "rotor 0.6.3 (git+https://github.com/tailhook/rotor)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "spmc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper" -version = "0.10.5" +version = "0.10.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "hyper-native-tls" -version = "0.2.2" +name = "hyper" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-rustls" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ct-logs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "idna" -version = "0.1.0" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1160,10 +1213,10 @@ name = "igd" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1173,163 +1226,171 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "iovec" -version = "0.1.0" +name = "interleaved-ordered" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "ipc-common-types" -version = "1.8.0" +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-util 1.8.0", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ipnetwork" -version = "0.12.6" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "isatty" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itertools" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.3.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "journaldb" +version = "0.1.0" +dependencies = [ + "ethcore-bytes 0.1.0", + "ethcore-logger 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "kvdb 0.1.0", + "kvdb-memorydb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.1", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "plain_hasher 0.1.0", + "rlp 0.2.1", + "util-error 0.1.0", +] + [[package]] name = "jsonrpc-core" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" +version = "8.0.1" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-http-server" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" dependencies = [ - "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ipc-server" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-macros" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" dependencies = [ - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jsonrpc-minihttp-server" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" -dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)", - "tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-pubsub" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" dependencies = [ - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-server-utils" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-tcp-server" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" -dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" +dependencies = [ + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "jsonrpc-ws-server" -version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" -dependencies = [ - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +version = "8.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11#06bec6ab682ec4ce16d7e7daf2612870c4272028" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ws 0.7.1 (git+https://github.com/tomusdrw/ws-rs)", + "ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)", +] + +[[package]] +name = "keccak-hash" +version = "0.1.0" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1341,6 +1402,39 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "kvdb" +version = "0.1.0" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0", +] + +[[package]] +name = "kvdb-memorydb" +version = "0.1.0" +dependencies = [ + "kvdb 0.1.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kvdb-rocksdb" +version = "0.1.0" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "language-tags" version = "0.2.2" @@ -1348,172 +1442,225 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazy_static" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "lazycell" -version = "0.4.0" +name = "lazy_static" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazycell" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.21" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "libflate" -version = "0.1.9" +name = "libusb" +version = "0.3.0" +source = "git+https://github.com/paritytech/libusb-rs#442708954a720bc89a9cf41e7be021a778bdbc27" +dependencies = [ + "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libusb-sys 0.2.4 (git+https://github.com/paritytech/libusb-sys)", +] + +[[package]] +name = "libusb-sys" +version = "0.2.4" +source = "git+https://github.com/paritytech/libusb-sys#14bdb698003731b6344a79e1d814704e44363e7c" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "linked-hash-map" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "linked-hash-map" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "local-encoding" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libusb" -version = "0.3.0" -source = "git+https://github.com/paritytech/libusb-rs#47c3d09cab346d629328d4bd691ed3509ffb8cbb" +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lru-cache" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "macros" +version = "0.1.0" + +[[package]] +name = "matches" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "libusb-sys 0.2.3 (git+https://github.com/paritytech/libusb-sys)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "libusb-sys" -version = "0.2.3" -source = "git+https://github.com/paritytech/libusb-sys#c10b1180646c9dc3f23a9b6bb825abcd3b7487ce" +name = "memmap" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "linked-hash-map" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "memory-cache" +version = "0.1.0" +dependencies = [ + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "linked-hash-map" +name = "memory_units" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "local-encoding" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "memorydb" +version = "0.1.1" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "plain_hasher 0.1.0", + "rlp 0.2.1", ] [[package]] -name = "log" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lru-cache" +name = "migration" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0", + "kvdb-rocksdb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "macros 0.1.0", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "matches" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memchr" -version = "1.0.1" +name = "mime" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime" -version = "0.2.0" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime_guess" -version = "1.6.1" +version = "2.0.0-alpha.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz-sys" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.8" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio-named-pipes" version = "0.1.4" -source = "git+https://github.com/alexcrichton/mio-named-pipes#903dc2f7eac6700c62bfdda258a599db13a9228f" +source = "git+https://github.com/alexcrichton/mio-named-pipes#9c1bbb985b74374d3b7eda76937279f8e977ef81" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio-uds" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miow" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1522,18 +1669,18 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "msdos_time" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1547,215 +1694,142 @@ dependencies = [ [[package]] name = "multihash" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ring 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nanomsg" -version = "0.5.1" -source = "git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7#673b79beef6e149273899850d7692335a481a920" -dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", -] - -[[package]] -name = "nanomsg-sys" -version = "0.5.0" -source = "git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7#673b79beef6e149273899850d7692335a481a920" -dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-contract-generator" -version = "0.1.0" -dependencies = [ - "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "heck 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "native-contracts" -version = "0.1.0" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bigint 0.1.3", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "native-contract-generator 0.1.0", -] - -[[package]] -name = "native-tls" -version = "0.1.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "net2" -version = "0.2.29" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-filter" -version = "1.8.0" -dependencies = [ - "ethcore 1.8.0", - "ethcore-io 1.8.0", - "ethcore-network 1.8.0", - "ethcore-util 1.8.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "native-contracts 0.1.0", +version = "1.11.0" +dependencies = [ + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethcore-io 1.11.0", + "ethcore-network-devp2p 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb-memorydb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "node-health" version = "0.1.0" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ntp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nodrop" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nom" -version = "1.2.2" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ntp" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.32" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-bigint 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-bigint" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-complex" -version = "0.1.32" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.32" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "num-rational" -version = "0.1.32" +name = "num-traits" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "num-traits" -version = "0.1.32" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.2.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "number_prefix" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "odds" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ole32-sys" version = "0.2.0" @@ -1765,30 +1839,6 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "openssl" -version = "0.9.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-sys" -version = "0.9.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "order-stat" version = "0.1.3" @@ -1799,7 +1849,7 @@ name = "ordered-float" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1815,223 +1865,278 @@ dependencies = [ name = "panic_hook" version = "0.1.0" dependencies = [ - "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)", - "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-hypervisor 1.2.0", - "ethcore-ipc-nano 1.8.0", - "ethcore-ipc-tests 0.1.0", - "ethcore-light 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-network 1.8.0", + "daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)", + "dir 0.1.0", + "docopt 0.8.3 (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.11.0", + "ethcore-bytes 0.1.0", + "ethcore-io 1.11.0", + "ethcore-light 1.11.0", + "ethcore-logger 1.11.0", + "ethcore-migrations 0.1.0", + "ethcore-miner 1.11.0", + "ethcore-network 1.11.0", "ethcore-secretstore 1.0.0", - "ethcore-stratum 1.8.0", - "ethcore-util 1.8.0", - "ethkey 0.2.0", - "ethsync 1.8.0", + "ethcore-service 0.1.0", + "ethcore-stratum 1.11.0", + "ethcore-transaction 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", + "ethsync 1.11.0", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)", - "isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "node-filter 1.8.0", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", + "isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "journaldb 0.1.0", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "keccak-hash 0.1.0", + "kvdb 0.1.0", + "kvdb-rocksdb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "migration 0.1.0", + "node-filter 1.11.0", "node-health 0.1.0", - "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "panic_hook 0.1.0", - "parity-dapps 1.8.0", - "parity-hash-fetch 1.8.0", - "parity-ipfs-api 1.8.0", + "parity-dapps 1.11.0", + "parity-hash-fetch 1.11.0", + "parity-ipfs-api 1.11.0", "parity-local-store 0.1.0", "parity-reactor 0.1.0", - "parity-rpc 1.8.0", + "parity-rpc 1.11.0", "parity-rpc-client 1.4.0", - "parity-updater 1.8.0", + "parity-updater 1.11.0", + "parity-version 1.11.0", "parity-whisper 0.1.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "path 0.1.0", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "registrar 0.0.1", + "rlp 0.2.1", + "rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rpc-cli 1.4.0", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-dapps" -version = "1.8.0" +version = "1.11.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.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-devtools 1.8.0", - "ethcore-util 1.8.0", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0", + "ethcore-devtools 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "fetch 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "keccak-hash 0.1.0", + "linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (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)", "node-health 0.1.0", - "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.8.0", + "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-hash-fetch 1.11.0", "parity-reactor 0.1.0", - "parity-ui 1.8.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-ui 1.11.0", + "parity-version 1.11.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "registrar 0.0.1", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "zip 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-dapps-glue" -version = "1.7.0" +version = "1.9.1" +dependencies = [ + "aster 0.41.0 (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)", + "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-dapps-glue" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.6.1 (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)", "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-hash-fetch" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-util 1.8.0", + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "fetch 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-contracts 0.1.0", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.4 (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)", "parity-reactor 0.1.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "registrar 0.0.1", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-ipfs-api" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-util 1.8.0", - "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", + "cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-local-store" version = "0.1.0" dependencies = [ - "ethcore 1.8.0", - "ethcore-io 1.8.0", - "ethcore-util 1.8.0", - "ethkey 0.2.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-io 1.11.0", + "ethcore-transaction 0.1.0", + "ethkey 0.3.0", + "kvdb 0.1.0", + "kvdb-memorydb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-machine" +version = "0.1.0" +dependencies = [ + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-reactor" version = "0.1.0" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-rpc" -version = "1.8.0" -dependencies = [ - "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.8.0", - "ethcore 1.8.0", - "ethcore-devtools 1.8.0", - "ethcore-io 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-light 1.8.0", - "ethcore-logger 1.8.0", - "ethcore-util 1.8.0", +version = "1.11.0" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethash 1.11.0", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethcore-devtools 1.11.0", + "ethcore-io 1.11.0", + "ethcore-light 1.11.0", + "ethcore-logger 1.11.0", + "ethcore-miner 1.11.0", + "ethcore-network 1.11.0", + "ethcore-transaction 0.1.0", "ethcrypto 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", - "ethkey 0.2.0", - "ethstore 0.1.0", - "ethsync 1.8.0", + "ethkey 0.3.0", + "ethstore 0.2.0", + "ethsync 1.11.0", "fetch 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hardware-wallet 1.11.0", + "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-ipc-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "keccak-hash 0.1.0", + "kvdb-memorydb 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "macros 0.1.0", + "multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "node-health 0.1.0", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "parity-reactor 0.1.0", - "parity-updater 1.8.0", + "parity-updater 1.11.0", + "parity-version 1.11.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie 0.1.0", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "vm 0.1.0", ] @@ -2040,18 +2145,17 @@ dependencies = [ name = "parity-rpc-client" version = "1.4.0" dependencies = [ - "ethcore-util 1.8.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-rpc 1.8.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "keccak-hash 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-rpc 1.11.0", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2059,69 +2163,101 @@ name = "parity-tokio-ipc" version = "0.1.5" source = "git+https://github.com/nikvolf/parity-tokio-ipc#d6c5b3cfcc913a1b9cf0f0562a10b083ceb9fb7c" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-named-pipes 0.1.0 (git+https://github.com/nikvolf/tokio-named-pipes)", - "tokio-uds 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-ui" -version = "1.8.0" +version = "1.11.0" dependencies = [ - "parity-ui-dev 1.8.0", - "parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)", - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-ui-dev 1.9.0 (git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2)", + "parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87)", + "parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4b6f112412716cd05123d32eeb7fda448288a6c6)", + "parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=bd25b41cd642c6b822d820dded3aa601a29aa079)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-ui-dev" -version = "1.8.0" +version = "1.9.0" +source = "git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2#eecaadcb9e421bce31e91680d14a20bbd38f92a2" +dependencies = [ + "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-ui-old-dev" +version = "1.9.0" +source = "git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87#65deb02e7c007a0fd8aab0c089c93e3fd1de6f87" +dependencies = [ + "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parity-ui-old-precompiled" +version = "1.9.0" +source = "git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4b6f112412716cd05123d32eeb7fda448288a6c6#4b6f112412716cd05123d32eeb7fda448288a6c6" dependencies = [ - "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-ui-precompiled" -version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#d809723e58bcb36c0f8d2eca5ca94abbb3690544" +version = "1.9.0" +source = "git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=bd25b41cd642c6b822d820dded3aa601a29aa079#bd25b41cd642c6b822d820dded3aa601a29aa079" dependencies = [ - "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-updater" -version = "1.8.0" -dependencies = [ - "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore 1.8.0", - "ethcore-ipc 1.8.0", - "ethcore-ipc-codegen 1.8.0", - "ethcore-util 1.8.0", - "ethsync 1.8.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "ipc-common-types 1.8.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-hash-fetch 1.8.0", - "parity-reactor 0.1.0", +version = "1.11.0" +dependencies = [ + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore 1.11.0", + "ethcore-bytes 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethsync 1.11.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-hash-fetch 1.11.0", + "parity-version 1.11.0", + "parking_lot 0.5.4 (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 = "1.11.0" +dependencies = [ + "ethcore-bytes 0.1.0", + "rlp 0.2.1", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (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.12.1" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2129,60 +2265,57 @@ name = "parity-whisper" version = "0.1.0" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bigint 0.1.3", - "ethcore-network 1.8.0", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-network 1.11.0", "ethcrypto 0.1.0", - "ethkey 0.2.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "ring 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parity-wordlist" -version = "1.0.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot" -version = "0.4.0" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.2.0" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2190,50 +2323,70 @@ dependencies = [ name = "path" version = "0.1.0" +[[package]] +name = "patricia-trie" +version = "0.1.0" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bytes 0.1.0", + "ethcore-logger 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.1", + "keccak-hash 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.1", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "trie-standardmap 0.1.0", + "triehash 0.1.0", +] + +[[package]] +name = "percent-encoding" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "phf" -version = "0.7.14" +version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.14" +version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.14" +version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.14" +version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pkg-config" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "plain_hasher" version = "0.1.0" dependencies = [ "crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2251,13 +2404,15 @@ dependencies = [ [[package]] name = "price-info" -version = "1.7.0" +version = "1.11.0" dependencies = [ "fetch 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2265,14 +2420,14 @@ name = "primal" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "primal-check 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "primal-check 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "primal-sieve 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "primal-bit" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2280,10 +2435,10 @@ dependencies = [ [[package]] name = "primal-check" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2293,20 +2448,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "primal-sieve" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "primal-bit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "primal-bit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "protobuf" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pulldown-cmark" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pwasm-run-test" +version = "0.1.0" +dependencies = [ + "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-logger 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethjson 0.1.0", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vm 0.1.0", + "wasm 0.1.0", +] + +[[package]] +name = "pwasm-utils" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2314,8 +2513,8 @@ name = "quasi" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2324,9 +2523,9 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2339,122 +2538,152 @@ dependencies = [ [[package]] name = "quick-error" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "quine-mc_cluskey" -version = "0.2.2" +name = "quote" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "quote" -version = "0.3.15" +name = "rand" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rand" -version = "0.3.14" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon" -version = "0.7.0" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.0.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_syscall" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "regex" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "regex-syntax" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "registrar" +version = "0.0.1" +dependencies = [ + "ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", +] [[package]] -name = "reqwest" -version = "0.6.2" +name = "relay" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ring" -version = "0.9.5" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rlp" -version = "0.2.0" +version = "0.2.1" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bigint 0.1.3", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (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 = "rlp_compress" +version = "0.1.0" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", +] + [[package]] name = "rlp_derive" version = "0.1.0" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.1", + "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rocksdb" version = "0.4.5" -source = "git+https://github.com/paritytech/rust-rocksdb#4364caec4dd5da1a1d78c39276774ee65bf55c7d" +source = "git+https://github.com/paritytech/rust-rocksdb#ecf06adf3148ab10f6f7686b724498382ff4f36e" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rocksdb-sys 0.3.0 (git+https://github.com/paritytech/rust-rocksdb)", ] @@ -2462,10 +2691,12 @@ dependencies = [ [[package]] name = "rocksdb-sys" version = "0.3.0" -source = "git+https://github.com/paritytech/rust-rocksdb#4364caec4dd5da1a1d78c39276774ee65bf55c7d" +source = "git+https://github.com/paritytech/rust-rocksdb#ecf06adf3148ab10f6f7686b724498382ff4f36e" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)", ] [[package]] @@ -2473,32 +2704,21 @@ name = "rotor" version = "0.6.3" source = "git+https://github.com/tailhook/rotor#80ce2e4cd82fdc7f88bb2d737407fa5106799790" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rpassword" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rpassword" -version = "0.3.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rprompt 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2506,29 +2726,33 @@ dependencies = [ name = "rpc-cli" version = "1.4.0" dependencies = [ - "bigint 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-util 1.8.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-rpc 1.8.0", + "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-rpc 1.11.0", "parity-rpc-client 1.4.0", - "rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rprompt" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rust-crypto" version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2538,84 +2762,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc_version" -version = "0.1.7" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "rustc_version" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "schannel" -version = "0.1.5" +name = "rustls" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sct 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "scoped-tls" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "secur32-sys" +name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "security-framework-sys" -version = "0.1.14" +name = "scoped-tls" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "semver" -version = "0.1.20" +name = "scopeguard" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "semver" -version = "0.2.3" +name = "sct" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2633,26 +2825,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.9" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.9" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.15.1" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2660,29 +2853,18 @@ name = "serde_ignored" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_urlencoded" -version = "0.5.1" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2690,13 +2872,6 @@ name = "sha1" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "sha3" -version = "0.1.0" -dependencies = [ - "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "shell32-sys" version = "0.1.1" @@ -2708,7 +2883,12 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.1.1" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "siphasher" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2731,8 +2911,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallvec" -version = "0.1.8" +name = "slab" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2742,15 +2922,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "snappy" +version = "0.1.0" +source = "git+https://github.com/paritytech/rust-snappy#858eac97192ea25d18d3f3626a8cc13ca0b175bb" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)", +] + +[[package]] +name = "snappy-sys" +version = "0.1.0" +source = "git+https://github.com/paritytech/rust-snappy#858eac97192ea25d18d3f3626a8cc13ca0b175bb" +dependencies = [ + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "spmc" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2762,9 +2960,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "stats" version = "0.1.0" dependencies = [ - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "stop-guard" +version = "0.1.0" + [[package]] name = "strsim" version = "0.6.0" @@ -2772,69 +2974,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "subtle" -version = "0.1.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "syn" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synom" -version = "0.11.3" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex" -version = "0.58.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_errors" -version = "0.58.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_pos" -version = "0.58.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syntex_syntax" -version = "0.58.0" +version = "0.58.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 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)", + "syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2857,12 +3048,12 @@ name = "tempdir" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2871,95 +3062,81 @@ dependencies = [ [[package]] name = "term_size" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "termios" -version = "0.2.2" +name = "textwrap" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "thread-id" -version = "3.0.0" +name = "thread_local" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "thread_local" -version = "0.3.3" +name = "threadpool" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "time" -version = "0.1.35" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny-keccak" -version = "1.3.1" +version = "1.4.1" 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 = "tokio-core" -version = "0.1.6" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-minihttp" -version = "0.1.0" -source = "git+https://github.com/tomusdrw/tokio-minihttp#67a400060bd29e51beaf206c552845255b6f699f" -dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2967,43 +3144,39 @@ name = "tokio-named-pipes" version = "0.1.0" source = "git+https://github.com/nikvolf/tokio-named-pipes#0b9b728eaeb0a6673c287ac7692be398fd651752" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-proto" -version = "0.1.0" -source = "git+https://github.com/tomusdrw/tokio-proto#f6ee08cb594fa2fc1b4178eaaca0855d66e68fd3" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-proto" -version = "0.1.0" +name = "tokio-rustls" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3011,48 +3184,47 @@ name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "toml" -version = "0.1.28" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "toml" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +name = "trace-time" +version = "0.1.0" dependencies = [ - "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3060,12 +3232,51 @@ name = "traitobject" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "transaction-pool" +version = "1.11.0" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (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" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trezor-sys" +version = "1.0.0" +source = "git+https://github.com/paritytech/trezor-sys#8a401705e58c83db6c29c199d9577b78fde40709" +dependencies = [ + "protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trie-standardmap" +version = "0.1.0" +dependencies = [ + "ethcore-bytes 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "rlp 0.2.1", +] + +[[package]] +name = "triehash" +version = "0.1.0" +dependencies = [ + "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "keccak-hash 0.1.0", + "rlp 0.2.1", + "trie-standardmap 0.1.0", ] [[package]] @@ -3073,30 +3284,53 @@ name = "typeable" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "uint" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unexpected" +version = "0.1.0" + [[package]] name = "unicase" -version = "1.4.0" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-bidi" -version = "0.2.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-normalization" -version = "0.1.2" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3109,6 +3343,11 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "0.1.1" @@ -3118,26 +3357,26 @@ dependencies = [ ] [[package]] -name = "untrusted" -version = "0.5.0" +name = "unreachable" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "url" -version = "1.2.0" +name = "untrusted" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "user32-sys" -version = "0.2.0" +name = "url" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3149,6 +3388,17 @@ name = "utf8-ranges" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "util-error" +version = "0.1.0" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kvdb 0.1.0", + "rlp 0.2.1", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vec_map" version = "0.8.0" @@ -3165,25 +3415,31 @@ dependencies = [ [[package]] name = "vergen" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "version_check" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vm" version = "0.1.0" dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", - "ethcore-util 1.8.0", + "ethcore-bytes 0.1.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethjson 0.1.0", - "evmjit 1.8.0", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", + "keccak-hash 0.1.0", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia-trie 0.1.0", + "rlp 0.2.1", ] [[package]] @@ -3192,15 +3448,46 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "wasm-utils" +name = "wasm" version = "0.1.0" -source = "git+https://github.com/paritytech/wasm-utils#9462bcc0680f0ec2c876abdf75bae981dd4344a5" dependencies = [ - "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-logger 1.11.0", + "ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "vm 0.1.0", + "wasmi 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasmi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "webpki-roots" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3208,25 +3495,44 @@ name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ws" -version = "0.7.1" -source = "git+https://github.com/tomusdrw/ws-rs#f8306a798b7541d64624299a83a2c934f173beed" -dependencies = [ - "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", +version = "0.7.5" +source = "git+https://github.com/tomusdrw/ws-rs#f12d19c4c19422fc79af28a3181f598bc07ecd1e" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3240,15 +3546,15 @@ dependencies = [ [[package]] name = "xdg" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "xml-rs" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3256,286 +3562,293 @@ name = "xmltree" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "zip" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", + "msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a" -"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" -"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum app_dirs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7d1c0d48a81bbb13043847f957971f4d87c81542d80ece5e84ba3cba4058fd4" -"checksum arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d89f1b0e242270b5b797778af0c8d182a1a2ccac5d8d6fadf414223cc0fab096" +"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef" "checksum aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfdf7355d9db158df68f976ed030ab0f6578af811f5a7bb6dcf221ec24e0e0" "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" -"checksum backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "346d7644f0b5f9bc73082d3b2236b69a05fd35cce0cfa3724e184e6a5c9e2a2f" -"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76" -"checksum backtrace-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3a0d842ea781ce92be2bf78a9b38883948542749640b8378b3b2f03d1fd9f1ff" +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "c63ea141ef8fdb10409d0f5daf30ac51f84ef43bff66f16627773d2a292cd189" "checksum base-x 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f59103b47307f76e03bef1633aec7fa9e29bfb5aa6daf5a334f94233c71f6c1" "checksum base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b9605ba46d61df0410d8ac686b0007add8172eba90e8e909c347856fe794d8c" -"checksum bigint 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c9f1cd09cdcafcccdab1fd58797d39b7d4d203238b2e3768807590723bdf0" +"checksum base64 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96434f987501f0ed4eb336a411e0631ecd1afa11574fe148587adc4ff96143c9" +"checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" +"checksum bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5442186ef6560f30f1ee4b9c1e4c87a35a6879d3644550cc248ec2b955eb5fcd" "checksum bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e103c8b299b28a9c6990458b7013dc4a8356a9b854c51b9883241f5866fac36e" -"checksum bit-set 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6e1e6fb1c9e3d6fcdec57216a74eaa03e41f52a22f13a16438251d8e88b89da" "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" -"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d" -"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23" +"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" -"checksum blastfig 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "09640e0509d97d5cdff03a9f5daf087a8e04c735c3b113a75139634a19cfc7b2" -"checksum bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f421095d2a76fc24cd3fb3f912b90df06be7689912b1bdb423caefae59c258d" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum bn 0.4.4 (git+https://github.com/paritytech/bn)" = "" -"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" -"checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" -"checksum bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8b24f16593f445422331a5eed46b72f7f171f910fead4f2ea8f17e727e9c5c14" -"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c" -"checksum cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "34aa7da06f10541fbca6850719cdaa8fa03060a5d2fb33840f149cf8133a00c7" -"checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" -"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 byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d85ee025368e69063c420cbb2ed9f852cb03a5e69b73be021e65726ce03585b6" +"checksum clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f4a2b3bb7ef3c672d7c13d15613211d5a6976b6892c598b0fcb5d40765f19c2" +"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" -"checksum core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "20a6d0448d3a99d977ae4a2aa5a98d886a923e863e81ad9ff814645b6feb3bbd" -"checksum core-foundation-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "05eed248dc504a5391c63794fe4fb64f46f071280afaa1b73308f3c0ce4574c5" -"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" +"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda" -"checksum crypt32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e34988f7e069e0b2f3bfc064295161e489b2d4e04a2e4248fb94360cdf00b4ec" +"checksum ct-logs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61cd11fb222fecf889f4531855c614548e92e8bd2eb178e35296885df5ee9a7c" "checksum ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)" = "" "checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" -"checksum daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "271ec51b7e0bee92f0d04601422c73eb76ececf197026711c97ad25038a010cf" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" +"checksum daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)" = "" "checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8" -"checksum docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5b93718f8b3e5544fcc914c43de828ca6c6ace23e0332c6080a2977b49787a" -"checksum dtoa 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5edd69c67b2f8e0911629b7e6b8a34cb3956613cd7c6e6414966dee349c2db4f" -"checksum either 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2b503c86dad62aaf414ecf2b8c527439abedb3f8d812537f0b12bfd6f32a91" -"checksum elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "258ff6a9a94f648d0379dbd79110e057edbb53eb85cc237e33eadf8e5a30df85" -"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83" -"checksum error-chain 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5c82c815138e278b8dcdeffc49f27ea6ffb528403e9dea4194f2e3dd40b143" -"checksum eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)" = "" -"checksum ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3d62319ee0f35abf20afe8859dd2668195912614346447bb2dee9fb8da7c62" +"checksum docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d8acd393692c503b168471874953a2531df0e9ab77d0b6bbc582395743300a4a" +"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" +"checksum edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a34f5204fbc13582de418611cf3a7dcdd07c6d312a5b631597ba72c06b9d9c9" +"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" +"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" +"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" +"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)" = "" +"checksum ethabi 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d8385a48c8ed984778dcca27efc0de162a191a14ed733a41a07d9b0cfaa999e" +"checksum ethabi-contract 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca2263c24359e827348ac99aa1f2e28ba5bab0d6c0b83941fa252de8a9e9c073" +"checksum ethabi-derive 5.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "057f76ceb314191b2e7fcd6e2129d75816e80912e73ccc8324baa3b9e259bce3" +"checksum ethbloom 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f240172b976e2421fa5485e45cd45287bbdb56d742aa3a1d77005c49071a8518" +"checksum ethereum-types 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bad6fb0e4ab648f4d8d8314c340c47f9e805b085b78be1b8da4676534cb419df" +"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" "checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa" -"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb" +"checksum fixed-hash 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21c520ebc46522d519aec9cba2b7115d49cea707d771b772c46bec61aa0daeb8" +"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" -"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" -"checksum futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51e7f9c150ba7fd4cee9df8bf6ea3dea5b63b68955ddad19ccd35b71dcfb4d" -"checksum futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a283c84501e92cade5ea673a2a7ca44f71f209ccdd302a3e0896f50083d2c5ff" -"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" -"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" -"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5cedfe9b6dc756220782cc1ba5bcb1fa091cdcba155e40d3556159c3db58043" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum globset 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90d069fe6beb9be359ef505650b3f73228c5591a3c4b1f32be2f4f44459ffa3a" +"checksum globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "464627f948c3190ae3d04b1bc6d7dca2f785bda0ac01278e6db129ad383dbeb6" "checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1" -"checksum heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c7593b1522161003928c959c20a2ca421c68e940d63d75573316a009e48a6d4" -"checksum heck 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f807d2f64cc044a6bcf250ff23e59be0deec7a16612c014f962a06fa7e020f9" +"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461" +"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "" -"checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae" +"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07" "checksum hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)" = "" -"checksum hyper 0.10.5 (registry+https://github.com/rust-lang/crates.io-index)" = "43a15e3273b2133aaac0150478ab443fb89f15c3de41d8d93d8f3bb14bf560f6" -"checksum hyper-native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "afe68f772f0497a7205e751626bb8e1718568b58534b6108c73a74ef80483409" -"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" +"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2" +"checksum hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)" = "df4dd5dae401458087396b6db7fabc4d6760aa456a5fa8e92bda549f39cae661" +"checksum hyper-rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6cdc1751771a14b8175764394f025e309a28c825ed9eaf97fa62bb831dc8c5" +"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76" "checksum integer-encoding 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a053c9c7dcb7db1f2aa012c37dc176c62e4cdf14898dee0eecc606de835b8acb" -"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be" -"checksum ipnetwork 0.12.6 (registry+https://github.com/rust-lang/crates.io-index)" = "232e76922883005380e831068f731ef0305541c9f77b30df3a1635047b16f370" -"checksum isatty 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7408a548dc0e406b7912d9f84c261cc533c1866e047644a811c133c56041ac0c" -"checksum itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d95557e7ba6b71377b0f2c3b3ae96c53f1b75a926a6901a500f557a370af730a" -"checksum itoa 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91fd9dc2c587067de817fec4ad355e3818c3d893a78cab32a0a474c7a15bb8d5" -"checksum jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-tcp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" -"checksum jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" +"checksum interleaved-ordered 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "141340095b15ed7491bd3d4ced9d20cebfb826174b6bb03386381f62b01e3d77" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2134e210e2a024b5684f90e1556d5f71a1ce7f8b12e9ac9924c67fb36f63b336" +"checksum isatty 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fa500db770a99afe2a0f2229be2a3d09c7ed9d7e4e8440bf71253141994e240f" +"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc" +"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-ipc-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" +"checksum jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" -"checksum lazycell 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec38a5c22f1ef3e30d2642aa875620d60edeef36cef43c4739d86215ce816331" -"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" -"checksum libflate 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "59fa4619e0f202f63fde6046eafe0e754e829369c5e892abeca0c22a12dcfec9" +"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" +"checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" +"checksum libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" "checksum libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)" = "" -"checksum libusb-sys 0.2.3 (git+https://github.com/paritytech/libusb-sys)" = "" -"checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48" -"checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" +"checksum libusb-sys 0.2.4 (git+https://github.com/paritytech/libusb-sys)" = "" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" +"checksum linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2aab0478615bb586559b0114d94dd8eca4fdbb73b443adcb0d00b61692b4bf" "checksum local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1ceb20f39ff7ae42f3ff9795f3986b1daad821caaa1e1732a0944103a5a1a66" -"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" -"checksum lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656fa4dfcb02bcf1063c592ba3ff6a5303ee1f2afe98c8a889e8b1a77c6dfdb7" -"checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" -"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74cc2587bf97c49f3f5bab62860d6abf3902ca73b66b51d9b049fbdcd727bd2" -"checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6" -"checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" -"checksum mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ba718a36791275c6782c0445a5f79b5ef4e68c01a4e60ac04aae28290e4957" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" +"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" +"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +"checksum mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e3d709ffbb330e1566dc2f2a3c9b58a5ad4a381f740b810cd305dc3f089bc160" +"checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae" +"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" +"checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe" "checksum mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)" = "" -"checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de" -"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" +"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8" +"checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958" "checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6" -"checksum multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d14363c7695e2e5adbbb8fe139d806a19b8b13f02b9b1fb770fab0c12edaff58" -"checksum nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" -"checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" -"checksum native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e94a2fc65a44729fe969cc973da87c1052ae3f000b2cb33029f14aeb85550d5" -"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" -"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" -"checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e" -"checksum ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d23f30ae7da76e2c6c2f5de53f298aa9a3911d3955ab2c349eb944caedceb088" -"checksum num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c04bd954dbf96f76bab6e5bd6cef6f1ce1262d15268ce4f926d2b5b778fa7af2" -"checksum num-bigint 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "41655c8d667be847a0b72fe0888857a7b3f052f691cf40852be5fcf87b274a65" -"checksum num-complex 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ccac67baf893ac97474f8d70eff7761dabb1f6c66e71f8f1c67a6859218db810" -"checksum num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "fb24d9bfb3f222010df27995441ded1e954f8f69cd35021f6bef02ca9552fb92" -"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c" -"checksum num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "48cdcc9ff4ae2a8296805ac15af88b3d88ce62128ded0cb74ffb63a587502a84" -"checksum num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39" -"checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3" -"checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77" -"checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1" +"checksum multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d49add5f49eb08bfc4d01ff286b84a48f53d45314f165c2d6efe477222d24f3" +"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" +"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2" +"checksum ntp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "143149743832c6543b60a8ef2a26cd9122dfecec2b767158e852a7beecf6d7a0" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum num-bigint 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "81b483ea42927c463e191802e7334556b48e7875297564c0e9951bd3a0ae53e3" +"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" +"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" +"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" +"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d" +"checksum number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "59a14be9c211cb9c602bad35ac99f41e9a84b44d71b8cbd3040e3bd02a214902" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b34cd77cf91301fff3123fbd46b065c3b728b17a392835de34c397315dce5586" -"checksum openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e035022a50faa380bd7ccdbd184d946ce539ebdb0a358780de92a995882af97a" "checksum order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efa535d5117d3661134dbf1719b6f0ffe06f2375843b13935db186cd094105eb" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1d06f6ee0fda786df3784a96ee3f0629f529b91cbfb7d142f6410e6bcd1ce2c" +"checksum parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "261c025c67ba416e9fe63aa9b3236520ce3c74cfbe43590c9cdcec4ccc8180e4" "checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "" -"checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)" = "" -"checksum parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "51104c8b8da5cd0ebe0ab765dfab37bc1927b4a01a3d870b0fe09d9ee65e35ea" -"checksum parity-wordlist 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52142d717754f7ff7ef0fc8da1bdce4f302dd576fb9bf8b727d6a5fdef33348d" -"checksum parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aebb68eebde2c99f89592d925288600fde220177e46b5c9a91ca218d245aeedf" -"checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" -"checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" -"checksum phf_codegen 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8af7ae7c3f75a502292b491e5cc0a1f69e3407744abe6e57e2a3b712bb82f01d" -"checksum phf_generator 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "db005608fd99800c8c74106a7c894cf582055b689aa14a79462cefdcb7dc1cc3" -"checksum phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fee4d039930e4f45123c9b15976cf93a499847b6483dc09c42ea0ec4940f2aa6" -"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum parity-ui-dev 1.9.0 (git+https://github.com/parity-js/shell.git?rev=eecaadcb9e421bce31e91680d14a20bbd38f92a2)" = "" +"checksum parity-ui-old-dev 1.9.0 (git+https://github.com/parity-js/dapp-wallet.git?rev=65deb02e7c007a0fd8aab0c089c93e3fd1de6f87)" = "" +"checksum parity-ui-old-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git?rev=4b6f112412716cd05123d32eeb7fda448288a6c6)" = "" +"checksum parity-ui-precompiled 1.9.0 (git+https://github.com/js-dist-paritytech/parity-master-1-10-shell.git?rev=bd25b41cd642c6b822d820dded3aa601a29aa079)" = "" +"checksum parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a93ad771f67ce8a6af64c6444a99c07b15f4674203657496fc31244ffb1de2c3" +"checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693" +"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" +"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595" +"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" +"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" +"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" +"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 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" -"checksum primal-bit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "464a91febc06166783d4f5ba3577b5ed8dda8e421012df80bfe48a971ed7be8f" -"checksum primal-check 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "647c81b67bb9551a7b88d0bcd785ac35b7d0bf4b2f358683d7c2375d04daec51" +"checksum primal-bit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "686a64e2f50194c64942992af5799e6b6e8775b8f88c607d72ed0a2fd58b9b21" +"checksum primal-check 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e65f96c0a171f887198c274392c99a116ef65aa7f53f3b6d4902f493965c2d1" "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" -"checksum primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7aa73fd87e5984a00bdb4c1b14d3d5d6d0bad01b2caaaf924c16ab7260ac946c" +"checksum primal-sieve 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c0911abe7b63ddec27527ba7579c3017f645eb992be6ddbfad605e34aca01876" +"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" +"checksum protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "568a15e4d572d9a5e63ae3a55f84328c984842887db179b40b4cc6a608bac6a4" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" +"checksum pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54d440c3b56eee028aa5d4f18cbed8c6e0c9ae23563b93f344beb7e73854ea02" "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" "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.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" -"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" -"checksum rayon 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8c83adcb08e5b922e804fe1918142b422602ef11f2fd670b0b52218cb5984a20" -"checksum rayon-core 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "767d91bacddf07d442fe39257bf04fd95897d1c47c545d009f6beb03efd038f8" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" -"checksum regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" -"checksum reqwest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1d56dbe269dbe19d716b76ec8c3efce8ef84e974f5b7e5527463e8c0507d4e17" -"checksum ring 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "873ec7c2b7c9bf58024eb8f1bbc40a6499cd23c1adc59532f4af9e355f1de0f3" +"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" +"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" +"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" +"checksum rayon 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed02d09394c94ffbdfdc755ad62a132e94c3224a8354e78a1200ced34df12edf" +"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53" +"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a" +"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" "checksum rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)" = "" "checksum rocksdb-sys 0.3.0 (git+https://github.com/paritytech/rust-rocksdb)" = "" "checksum rotor 0.6.3 (git+https://github.com/tailhook/rotor)" = "" -"checksum rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5d3a99497c5c544e629cc8b359ae5ede321eba5fa8e5a8078f3ced727a976c3f" -"checksum rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab6e42be826e215f30ff830904f8f4a0933c6e2ae890e1af8b408f5bae60081e" +"checksum rpassword 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b273c91bd242ca03ad6d71c143b6f17a48790e61f21a6c78568fa2b6774a24a4" +"checksum rprompt 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1601f32bc5858aae3cbfa1c645c96c4d820cc5c16be0194f089560c00b6eb625" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" -"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e114e275f7c9b5d50bb52b28f9aac1921209f02aa6077c8b255e21eefaf8ffa" -"checksum schannel 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e45ac5e9e4698c1c138d2972bedcd90b81fe1efeba805449d2bdd54512de5f9" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" +"checksum rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc9f2e05fd6a3ce1530cd5dbcc553d2f94d7749fe3e4f5b443668eddd842889e" +"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" -"checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" -"checksum security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "42ddf098d78d0b64564b23ee6345d07573e7d10e52ad86875d89ddf5f8378a02" -"checksum security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "5bacdada57ea62022500c457c8571c17dfb5e6240b7c8eac5916ffa8c7138a55" -"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 scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918" +"checksum sct 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1137b767bbe1c4d30656993bdd97422ed41255d9400b105d735f8c7d9e800632" "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.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a" -"checksum serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639" -"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4763b773978e495252615e814d2ad04773b2c1f85421c7913869a537f35cb406" +"checksum serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8ab31f00ae5574bb643c196d5e302961c122da1c768604c6d16a35c5d551948a" +"checksum serde_derive_internals 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc848d073be32cd982380c06587ea1d433bc1a4c4a111de07ec2286a3ddade8" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" -"checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d" -"checksum siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c44e42fa187b5a8782489cf7740cc27c3125806be2bf33563cf5e02e9533fcd" +"checksum siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "833011ca526bd88f16778d32c699d325a9ad302fa06381cd66f7be63351d3f6d" +"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24ebf8a06f5f8bae61ae5bbc7af7aac4ef6907ae975130faba1199e5fe82256a" "checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410" +"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e40af10aafe98b4d8294ae8388d8a5cd0707c65d364872efe72d063ec44bee0" -"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf" +"checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d" +"checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" +"checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "" +"checksum spmc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cd1f11d1fb5fd41834e55ce0b85a186efbf2f2afd9fdb09e2c8d72f9bff1ad1a" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum subtle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b811576c12506ff3f6da145585dc833edc32ee34c9fc021127d90e8134cc05c" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35f3cc9d446323ef8fefad933b65cd6de271d29fa14a2e9d036a084770c6d6d5" -"checksum syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3af03823ea45d420dd2c1a44bb074e13ea55f9b99afe960fd58eb4069b7f6cad" -"checksum syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e502a4a904d9f37cf975dbdbb0b08f2d111322f6792bda6eb095b4112c9a24b" -"checksum syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cf936464c3863952ea3fab848860ea891eba8647b6008b04c36f0bb007192a3" +"checksum subtle 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc7f6353c2ee5407358d063a14cccc1630804527090a6fb5a9489ce4924280fb" +"checksum syn 0.12.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8c5bc2d6ff27891209efa5f63e9de78648d7801f085e4653701a692ce938d6fd" +"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e" +"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" +"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" +"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" -"checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" -"checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a" -"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" -"checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292" -"checksum tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "99e958104a67877907c1454386d5482fe8e965a55d60be834a15a44328e7dc76" -"checksum tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "48f55df1341bb92281f229a6030bc2abffde2c7a44c6d6b802b7687dd8be0775" -"checksum tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)" = "" +"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327" +"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" +"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" +"checksum tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "58911ed5eb275a8fd2f1f0418ed360a42f59329864b64e1e95377a9024498c01" +"checksum tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "52b4e32d8edbf29501aabb3570f027c6ceb00ccef6538f4bddba0200503e74e8" +"checksum tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ab83e7adb5677e42e405fa4ceff75659d93c4d7d7dd22f52fcec59ee9f02af" "checksum tokio-named-pipes 0.1.0 (git+https://github.com/nikvolf/tokio-named-pipes)" = "" -"checksum tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)" = "" -"checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808" +"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" +"checksum tokio-rustls 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9263e472d976e4345e50c6cce4cfe6b17c71593ea593cce1df26f1efd36debb" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86f33def658c14724fc13ec6289b3875a8152ee8ae767a5b1ccbded363b03db8" -"checksum tokio-uds 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bd209039933255ea77c6d7a1d18abc20b997d161acb900acca6eb74cdd049f31" -"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6" -"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" +"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" +"checksum tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6116c71be48f8f1656551fd16458247fdd6c03201d7893ad81189055fcde03e8" +"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" +"checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" -"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f" -"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172" -"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" +"checksum uint 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53a4340c35703f926ec365c6797bb4a7a10bb6b9affe29ca385c9d804401f5e3" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b65243989ef6aacd9c0d6bd2b822765c3361d8ed352185a6f3a41f3a718c673" -"checksum url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afe9ec54bc4db14bc8744b7fed060d785ac756791450959b2248443319d5b119" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0795a11576d29ae80525a3fda315bf7b534f8feb9d34101e5fe63fb95bb2fd24" -"checksum vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56b639f935488eb40f06d17c3e3bcc3054f6f75d264e187b1107c8d1cba8d31c" +"checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)" = "" +"checksum wasmi 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dedfb4cbfba1e1921b12ed05762d9d5ae99ce40e72b98bbf271561ef487e8c7" +"checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2" +"checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum ws 0.7.1 (git+https://github.com/tomusdrw/ws-rs)" = "" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453" -"checksum xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65e74b96bd3179209dc70a980da6df843dff09e46eee103a0376c0949257e3ef" +"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" +"checksum xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec6c39eaa68382c8e31e35239402c0a9489d4141a8ceb0c716099a0b515b562" "checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082" -"checksum zip 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "3ceb33a75b3d0608942302eed325b59d2c3ed777cc6c01627ae14e5697c6a31c" +"checksum zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c0deac03fc7d43abcf19f2c2db6bd9289f9ea3d31f350e26eb0ed8b4117983c1" diff --git a/Cargo.toml b/Cargo.toml index 06abd7b3169e750f9d729609ee7847548eee0139..d1c7b250cfa8e1d738a929dd04e08dc8352293aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,25 @@ [package] description = "Parity Ethereum client" name = "parity" -version = "1.8.0" +# NOTE Make sure to update util/version/Cargo.toml as well +version = "1.11.0" license = "GPL-3.0" authors = ["Parity Technologies "] -build = "build.rs" [dependencies] log = "0.3" env_logger = "0.4" rustc-hex = "1.0" docopt = "0.8" -time = "0.1" +clap = "2" +term_size = "0.3" +textwrap = "0.9" num_cpus = "1.2" number_prefix = "0.2" -rpassword = "0.2.1" +rpassword = "1.0" semver = "0.6" -ansi_term = "0.9" +ansi_term = "0.10" +parking_lot = "0.5" regex = "0.2" isatty = "0.1" toml = "0.4" @@ -29,19 +32,20 @@ futures-cpupool = "0.1" fdlimit = "0.1" ws2_32-sys = "0.2" ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" } -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } +jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" } ethsync = { path = "sync" } ethcore = { path = "ethcore" } -ethcore-util = { path = "util" } +ethcore-bytes = { path = "util/bytes" } ethcore-io = { path = "util/io" } -ethcore-devtools = { path = "devtools" } -ethcore-ipc = { path = "ipc/rpc" } -ethcore-ipc-nano = { path = "ipc/nano" } -ethcore-ipc-hypervisor = { path = "ipc/hypervisor" } ethcore-light = { path = "ethcore/light" } ethcore-logger = { path = "logger" } -ethcore-stratum = { path = "stratum" } +ethcore-migrations = { path = "ethcore/migrations" } +ethcore-miner = { path = "miner" } ethcore-network = { path = "util/network" } +ethcore-service = { path = "ethcore/service" } +ethcore-stratum = { path = "stratum" } +ethcore-transaction = { path = "ethcore/transaction" } +ethereum-types = "0.2" node-filter = { path = "ethcore/node_filter" } ethkey = { path = "ethkey" } node-health = { path = "dapps/node-health" } @@ -54,27 +58,35 @@ 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" } +dir = { path = "util/dir" } +panic_hook = { path = "util/panic_hook" } +keccak-hash = { path = "util/hash" } +migration = { path = "util/migration" } +kvdb = { path = "util/kvdb" } +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 } +registrar = { path = "registrar" } + [build-dependencies] rustc_version = "0.2" [dev-dependencies] -ethcore-ipc-tests = { path = "ipc/tests" } pretty_assertions = "0.1" ipnetwork = "0.12.6" +tempdir = "0.3" [target.'cfg(windows)'.dependencies] winapi = "0.2" [target.'cfg(not(windows))'.dependencies] -daemonize = "0.2" +daemonize = { git = "https://github.com/paritytech/daemonize" } [features] default = ["ui-precompiled"] @@ -88,16 +100,14 @@ ui-precompiled = [ ] ui-enabled = ["dapps"] dapps = ["parity-dapps"] -ipc = ["ethcore/ipc", "ethsync/ipc"] 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"] +final = ["parity-version/final"] [[bin]] path = "parity/main.rs" @@ -112,4 +122,15 @@ lto = false panic = "abort" [workspace] -members = ["ethstore/cli", "ethkey/cli", "evmbin", "whisper", "chainspec", "dapps/node-health"] +members = [ + "chainspec", + "dapps/js-glue", + "ethcore/wasm/run", + "ethcore/types", + "ethkey/cli", + "ethstore/cli", + "evmbin", + "miner", + "transaction-pool", + "whisper" +] diff --git a/README.md b/README.md index 24178edbef17f55382867d4ab1f87fa550313b3f..1e4a12bf02d78d52afcd3ac5c924e27cdcfcec8e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,12 @@ -# [Parity](https://parity.io/parity.html) - fast, light, and robust Ethereum client +# Parity - fast, light, and robust Ethereum client + +## [» Download the latest release «](https://github.com/paritytech/parity/releases/latest) [![build status](https://gitlab.parity.io/parity/parity/badges/master/build.svg)](https://gitlab.parity.io/parity/parity/commits/master) +[![codecov](https://codecov.io/gh/paritytech/parity/branch/master/graph/badge.svg)](https://codecov.io/gh/paritytech/parity) [![Snap Status](https://build.snapcraft.io/badge/paritytech/parity.svg)](https://build.snapcraft.io/user/paritytech/parity) [![GPLv3](https://img.shields.io/badge/license-GPL%20v3-green.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html) -- [Download the latest release here.](https://github.com/paritytech/parity/releases) ### Join the chat! @@ -14,7 +16,12 @@ Get in touch with us on Gitter: [![Gitter: Parity/Miners](https://img.shields.io/badge/gitter-parity/miners-4AB495.svg)](https://gitter.im/paritytech/parity/miners) [![Gitter: Parity-PoA](https://img.shields.io/badge/gitter-parity--poa-4AB495.svg)](https://gitter.im/paritytech/parity-poa) -Be sure to check out [our wiki](https://github.com/paritytech/parity/wiki) and the [internal documentation](https://paritytech.github.io/parity/ethcore/index.html) for more information. +Or join our community on Matrix: +[![Riot: +Parity](https://img.shields.io/badge/riot-%2Bparity%3Amatrix.parity.io-orange.svg)](https://riot.im/app/#/group/+parity:matrix.parity.io) + +Official website: https://parity.io + +Be sure to check out [our wiki](https://wiki.parity.io) for more information. ---- @@ -22,26 +29,28 @@ Be sure to check out [our wiki](https://github.com/paritytech/parity/wiki) and t Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. -Parity comes with a built-in wallet. To access [Parity Wallet](http://web3.site/) simply go to http://web3.site/ (if you don't have access to the internet, but still want to use the service, you can also use http://127.0.0.1:8180/). It includes various functionality allowing you to: +Parity comes with a built-in wallet, to install it please follow [these instructions](https://wiki.parity.io/Parity-Wallet). It includes various functionality allowing you to: - create and manage your Ethereum accounts; - manage your Ether and any Ethereum tokens; - create and register your own tokens; - and much more. -By default, Parity will also run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number of RPC APIs. +From Parity Ethereum client version >=1.10, the User Interface (UI) is accessible in a separate application called Parity UI. To keep using the UI in the browser (deprecated), [follow these steps](https://wiki.parity.io/FAQ-Basic-Operations,-Configuration,-and-Synchronization.md#the-parity-ui-application-isnt-working-the-way-i-want). -If you run into an issue while using parity, feel free to file one in this repository or hop on our [gitter chat room](https://gitter.im/paritytech/parity) to ask a question. We are glad to help! +By default, Parity will also run a JSONRPC server on `127.0.0.1:8545` and a websockets server on `127.0.0.1:8546`. This is fully configurable and supports a number of APIs. -**For security-critical issues**, please refer to the security policy outlined in `SECURITY.MD`. +If you run into an issue while using Parity, feel free to file one in this repository or hop on our [Gitter](https://gitter.im/paritytech/parity) or [Riot](https://riot.im/app/#/group/+parity:matrix.parity.io) chat room to ask a question. We are glad to help! -Parity's current release is 1.7. You can download it at https://github.com/paritytech/parity/releases or follow the instructions below to build from source. +**For security-critical issues**, please refer to the security policy outlined in [SECURITY.MD](SECURITY.md). + +Parity's current release is 1.9. You can download it at https://github.com/paritytech/parity/releases or follow the instructions below to build from source. ---- ## Build dependencies -**Parity requires Rust version 1.19.0 to build** +**Parity requires Rust version 1.23.0 to build** We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have rustup, you can install it like this: @@ -51,21 +60,22 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do ``` Parity also requires `gcc`, `g++`, `libssl-dev`/`openssl`, `libudev-dev` and `pkg-config` packages to be installed. + - OSX: ```bash $ curl https://sh.rustup.rs -sSf | sh ``` `clang` is required. It comes with Xcode command line tools or can be installed with homebrew. -- Windows - Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from +- Windows + Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the rustup installer from https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the msvc toolchain: - ``` + ```bash $ rustup default stable-x86_64-pc-windows-msvc - ``` + ``` -Once you have rustup, install parity or download and build from source +Once you have rustup, install Parity or download and build from source ---- @@ -74,10 +84,20 @@ Once you have rustup, install parity or download and build from source In any of the [supported Linux distros](https://snapcraft.io/docs/core/install): ```bash -sudo snap install parity --edge +sudo snap install parity +``` + +Or, if you want to contribute testing the upcoming release: + +```bash +sudo snap install parity --beta ``` -(Note that this is an experimental and unstable release, at the moment) +And to test the latest code landed into the master branch: + +```bash +sudo snap install parity --edge +``` ---- @@ -93,11 +113,39 @@ $ 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 + +```bash +$ git checkout stable +``` + +or + +```bash +$ git checkout beta +``` + +first. + ---- ## Simple one-line installer for Mac and Ubuntu @@ -106,9 +154,18 @@ $ ~/.cargo/bin/cargo build --release bash <(curl https://get.parity.io -Lk) ``` +The one-line installer always defaults to the latest beta release. To install a stable release, run: + +```bash +bash <(curl https://get.parity.io -Lk) -r stable +``` + ## Start Parity + ### Manually + To start Parity manually, just run + ```bash $ ./target/release/parity ``` @@ -116,11 +173,9 @@ $ ./target/release/parity and Parity will begin syncing the Ethereum blockchain. ### Using systemd service file + To start Parity as a regular user using systemd init: -1. Copy `parity/scripts/parity.service` to your +1. Copy `./scripts/parity.service` to your systemd user directory (usually `~/.config/systemd/user`). -2. To pass any argument to Parity, write a `~/.parity/parity.conf` file this way: -`ARGS="ARG1 ARG2 ARG3"`. - - Example: `ARGS="ui --identity MyMachine"`. +2. To configure Parity, write a `/etc/parity/config.toml` config file, see [Configuring Parity](https://paritytech.github.io/wiki/Configuring-Parity) for details. diff --git a/SECURITY.md b/SECURITY.md index 8257cf733ab85624d6375d3af07688a859857948..3f977bd1b0a06fda3c9597085244b768e99df9a7 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,13 +1,49 @@ # Security Policy -For security inquiries or vulnerability reports, please send a message to security@parity.io. +Parity Technologies is committed to resolving security vulnerabilities in our software quickly and carefully. We take the necessary steps to minimize risk, provide timely information, and deliver vulnerability fixes and mitigations required to address security issues. -Please use a descriptive subject line so we can identify the report as such. +## Reporting a Vulnerability -If you send a report, we will respond to the e-mail within 48 hours, and provide regular updates from that time onwards. +Security vulnerabilities in Parity software should be reported by email to security@parity.io. If you think your report might be eligible for the Parity Bug Bounty Program, your email should be send to bugbounty@parity.io. -If you would like to encrypt your report, please use the PGP key provided below. -It is also reproduced [on MIT's key server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) +Your report should include the following: + +- your name +- description of the vulnerability +- attack scenario (if any) +- components +- reproduction +- other details + +Try to include as much information in your report as you can, including a description of the vulnerability, its potential impact, and steps for reproducing it. Be sure to use a descriptive subject line. + +You'll receive a response to your email within two business days indicating the next steps in handling your report. We encourage finders to use encrypted communication channels to protect the confidentiality of vulnerability reports. You can encrypt your report using our public key. This key is [on MIT's key server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) server and reproduced below. + +After the initial reply to your report, our team will endeavor to keep you informed of the progress being made towards a fix. These updates will be sent at least every five business days. + +Thank you for taking the time to responsibly disclose any vulnerabilities you find. + +## Responsible Investigation and Reporting + +Responsible investigation and reporting includes, but isn't limited to, the following: + +- Don't violate the privacy of other users, destroy data, etc. +- Don’t defraud or harm Parity Technologies Ltd or its users during your research; you should make a good faith effort to not interrupt or degrade our services. +- Don't target our physical security measures, or attempt to use social engineering, spam, distributed denial of service (DDOS) attacks, etc. +- Initially report the bug only to us and not to anyone else. +- Give us a reasonable amount of time to fix the bug before disclosing it to anyone else, and give us adequate written warning before disclosing it to anyone else. +- In general, please investigate and report bugs in a way that makes a reasonable, good faith effort not to be disruptive or harmful to us or our users. Otherwise your actions might be interpreted as an attack rather than an effort to be helpful. + +## Bug Bounty Program + +Our Bug Bounty Program allows us to recognise and reward members of the Parity community for helping us find and address significant bugs, in accordance with the terms of the Parity Bug Bounty Program. A detailed description on eligibility, rewards, legal information and terms & conditions for contributors can be found on [our website](https://paritytech.io/bug-bounty.html). + + + + + + +## Plaintext PGP Key ``` -----BEGIN PGP PUBLIC KEY BLOCK----- @@ -42,13 +78,3 @@ ETBD1Q== =K9Qw -----END PGP PUBLIC KEY BLOCK----- ``` - -Important Legal Information: - -Your submission might be eligible for a bug bounty. The bug bounty program is an experimental and discretionary rewards program for the Parity community to reward those who are helping to improve the Parity software. Rewards are at the sole discretion of Parity Technologies Ltd.. - -We are not able to issue rewards to individuals who are on sanctions lists or who are in countries on sanctions lists (e.g. North Korea, Iran, etc). - -You are responsible for all taxes. All rewards are subject to applicable law. - -Finally, your testing must not violate any law or compromise any data that is not yours. diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index b1751c6161b54dd9323e41274aa0c1a7aec1c846..e5b25a203f9665c22c775a1a884fd4754a5cc130 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Parity Dapps crate" name = "parity-dapps" -version = "1.8.0" +version = "1.11.0" license = "GPL-3.0" authors = ["Parity Technologies "] @@ -10,40 +10,39 @@ authors = ["Parity Technologies "] [dependencies] base32 = "0.3" futures = "0.1" -linked-hash-map = "0.3" +futures-cpupool = "0.1" +linked-hash-map = "0.5" log = "0.3" -parity-dapps-glue = "1.7" -mime = "0.2" -mime_guess = "1.6.1" -rand = "0.3" +parity-dapps-glue = "1.9" +parking_lot = "0.5" +mime_guess = "2.0.0-alpha.2" +rand = "0.4" rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -time = "0.1.35" -unicase = "1.3" -url = "1.0" +unicase = "1.4" zip = { version = "0.1", default-features = false } itertools = "0.5" -jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } -jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } +jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" } +jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" } -ethcore-util = { path = "../util" } +ethcore-bytes = { path = "../util/bytes" } +ethereum-types = "0.2" fetch = { path = "../util/fetch" } node-health = { path = "./node-health" } parity-hash-fetch = { path = "../hash-fetch" } parity-reactor = { path = "../util/reactor" } parity-ui = { path = "./ui" } - -clippy = { version = "0.0.103", optional = true} +keccak-hash = { path = "../util/hash" } +parity-version = { path = "../util/version" } +registrar = { path = "../registrar" } [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"] diff --git a/dapps/js-glue/Cargo.toml b/dapps/js-glue/Cargo.toml index 0f4c929681e42752ba59938bc3e96268a0f12ee5..efe92bbda6ae02357ce7bee0b1bfc2d6e8557b43 100644 --- a/dapps/js-glue/Cargo.toml +++ b/dapps/js-glue/Cargo.toml @@ -1,7 +1,7 @@ [package] description = "Base Package for all Parity built-in dapps" name = "parity-dapps-glue" -version = "1.7.0" +version = "1.9.1" license = "GPL-3.0" authors = ["Parity Technologies "] build = "build.rs" @@ -12,19 +12,16 @@ syntex = { version = "0.58", optional = true } [dependencies] glob = { version = "0.2.11" } -mime_guess = { version = "1.6.1" } +mime_guess = { version = "2.0.0-alpha.2" } aster = { version = "0.41", default-features = false } 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.90", 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 = [] diff --git a/dapps/js-glue/src/codegen.rs b/dapps/js-glue/src/codegen.rs index 3d8c934600267ab4d66b3d4983acc2d516577578..c6e948820fce03ed2baabc734ddbe0bf94a7b7bf 100644 --- a/dapps/js-glue/src/codegen.rs +++ b/dapps/js-glue/src/codegen.rs @@ -101,6 +101,7 @@ fn implement_webapp(cx: &ExtCtxt, builder: &aster::AstBuilder, item: &Item, push let files_impl = quote_item!(cx, impl $type_name { + #[allow(unused_mut)] fn files() -> ::std::collections::HashMap<&'static str, File> { let mut files = ::std::collections::HashMap::new(); $statements diff --git a/dapps/js-glue/src/js.rs b/dapps/js-glue/src/js.rs index 49ccdd26fe3c05a441d3ada657c21d662ecce352..d1d1cdda9139dc3a8307a42904ecd8185fd3b6b0 100644 --- a/dapps/js-glue/src/js.rs +++ b/dapps/js-glue/src/js.rs @@ -25,7 +25,7 @@ mod platform { use std::process::Command; pub static NPM_CMD: &'static str = "npm"; - pub fn handle_fd(cmd: &mut Command) -> &mut Command { + pub fn handle_cmd(cmd: &mut Command) -> &mut Command { cmd } } @@ -34,14 +34,14 @@ mod platform { mod platform { use std::process::{Command, Stdio}; - pub static NPM_CMD: &'static str = "npm.cmd"; + pub static NPM_CMD: &'static str = "cmd.exe"; // NOTE [ToDr] For some reason on windows - // We cannot have any file descriptors open when running a child process - // during build phase. - pub fn handle_fd(cmd: &mut Command) -> &mut Command { + // The command doesn't have %~dp0 set properly + // and it cannot load globally installed node.exe + pub fn handle_cmd(cmd: &mut Command) -> &mut Command { cmd.stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) + .arg("/c") + .arg("npm.cmd") } } @@ -58,7 +58,7 @@ pub fn build(_path: &str, _dest: &str) { #[cfg(not(feature = "use-precompiled-js"))] pub fn build(path: &str, dest: &str) { - let child = platform::handle_fd(&mut Command::new(platform::NPM_CMD)) + let child = platform::handle_cmd(&mut Command::new(platform::NPM_CMD)) .arg("install") .arg("--no-progress") .current_dir(path) @@ -66,7 +66,7 @@ pub fn build(path: &str, dest: &str) { .unwrap_or_else(|e| die("Installing node.js dependencies with npm", e)); assert!(child.success(), "There was an error installing dependencies."); - let child = platform::handle_fd(&mut Command::new(platform::NPM_CMD)) + let child = platform::handle_cmd(&mut Command::new(platform::NPM_CMD)) .arg("run") .arg("build") .env("NODE_ENV", "production") diff --git a/dapps/node-health/Cargo.toml b/dapps/node-health/Cargo.toml index ff13e859328ca4b2ee92dd388c1a4297fe222db8..5688c8f76a106d9e19cc6159395d940e98289331 100644 --- a/dapps/node-health/Cargo.toml +++ b/dapps/node-health/Cargo.toml @@ -9,8 +9,8 @@ authors = ["Parity Technologies "] futures = "0.1" futures-cpupool = "0.1" log = "0.3" -ntp = "0.2.0" -parking_lot = "0.4" +ntp = "0.3.0" +parking_lot = "0.5" serde = "1.0" serde_derive = "1.0" time = "0.1.35" diff --git a/dapps/node-health/src/health.rs b/dapps/node-health/src/health.rs index 3b3563d6bdc67024bff1d4b752d5f8b3cc02ea72..ec53d2e29441e6c01c6742c90b543bae701bcc72 100644 --- a/dapps/node-health/src/health.rs +++ b/dapps/node-health/src/health.rs @@ -18,7 +18,7 @@ use std::sync::Arc; use std::time; -use futures::{Future, BoxFuture}; +use futures::Future; use futures::sync::oneshot; use types::{HealthInfo, HealthStatus, Health}; use time::{TimeChecker, MAX_DRIFT}; @@ -44,7 +44,7 @@ impl NodeHealth { } /// Query latest health report. - pub fn health(&self) -> BoxFuture { + pub fn health(&self) -> Box + Send> { trace!(target: "dapps", "Checking node health."); // Check timediff let sync_status = self.sync_status.clone(); @@ -63,7 +63,7 @@ impl NodeHealth { }, ); - rx.map_err(|err| { + Box::new(rx.map_err(|err| { warn!(target: "dapps", "Health request cancelled: {:?}", err); }).and_then(move |time| { // Check peers @@ -117,6 +117,6 @@ impl NodeHealth { }; Ok(Health { peers, sync, time}) - }).boxed() + })) } } diff --git a/dapps/node-health/src/time.rs b/dapps/node-health/src/time.rs index 05c48ce4745901c0bc6c550782e624620a8f13c7..c3da050a47fddc63d4403ed1a03c4e1957933d62 100644 --- a/dapps/node-health/src/time.rs +++ b/dapps/node-health/src/time.rs @@ -37,7 +37,7 @@ use std::collections::VecDeque; use std::sync::atomic::{self, AtomicUsize}; use std::sync::Arc; -use futures::{self, Future, BoxFuture}; +use futures::{self, Future}; use futures::future::{self, IntoFuture}; use futures_cpupool::{CpuPool, CpuFuture}; use ntp; @@ -193,7 +193,9 @@ 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 = Box + Send>; #[derive(Debug, Clone)] /// A time checker. @@ -224,7 +226,7 @@ impl TimeChecker where ::Future: Send + 'sta pub fn update(&self) -> BoxFuture { trace!(target: "dapps", "Updating time from NTP."); let last_result = self.last_result.clone(); - self.ntp.drift().into_future().then(move |res| { + Box::new(self.ntp.drift().into_future().then(move |res| { let res = res.map(|d| d.num_milliseconds()); if let Err(Error::NoServersAvailable) = res { @@ -255,7 +257,7 @@ impl TimeChecker where ::Future: Send + 'sta let res = select_result(results.iter()); *last_result.write() = (valid_till, results); res - }).boxed() + })) } /// Returns a current time drift or error if last request to NTP server failed. @@ -264,7 +266,7 @@ impl TimeChecker where ::Future: Send + 'sta { let res = self.last_result.read(); if res.0 > time::Instant::now() { - return futures::done(select_result(res.1.iter())).boxed(); + return Box::new(futures::done(select_result(res.1.iter()))); } } // or update and return result diff --git a/dapps/src/api/api.rs b/dapps/src/api/api.rs index 03ba859f8d32685f3794165ee7744e9b0476bb78..a9f9af293b0e0acad5780706214a15556f3ae3af 100644 --- a/dapps/src/api/api.rs +++ b/dapps/src/api/api.rs @@ -16,144 +16,82 @@ use std::sync::Arc; -use hyper::{server, net, Decoder, Encoder, Next, Control}; -use hyper::method::Method; -use hyper::status::StatusCode; +use hyper::{Method, StatusCode}; -use api::{response, types}; +use api::response; use apps::fetcher::Fetcher; -use handlers::{self, extract_url}; -use endpoint::{Endpoint, Handler, EndpointPath}; -use node_health::{NodeHealth, HealthStatus, Health}; -use parity_reactor::Remote; +use endpoint::{Endpoint, Request, Response, EndpointPath}; +use futures::{future, Future}; +use node_health::{NodeHealth, HealthStatus}; #[derive(Clone)] pub struct RestApi { fetcher: Arc, health: NodeHealth, - remote: Remote, +} + +impl Endpoint for RestApi { + fn respond(&self, mut path: EndpointPath, req: Request) -> Response { + if let Method::Options = *req.method() { + return Box::new(future::ok(response::empty())); + } + + let endpoint = path.app_params.get(0).map(String::to_owned); + let hash = path.app_params.get(1).map(String::to_owned); + + // at this point path.app_id contains 'api', adjust it to the hash properly, otherwise + // we will try and retrieve 'api' as the hash when doing the /api/content route + if let Some(ref hash) = hash { + path.app_id = hash.to_owned(); + } + + trace!(target: "dapps", "Handling /api request: {:?}/{:?}", endpoint, hash); + match endpoint.as_ref().map(String::as_str) { + Some("ping") => Box::new(future::ok(response::ping(req))), + Some("health") => self.health(), + Some("content") => self.resolve_content(hash.as_ref().map(String::as_str), path, req), + _ => Box::new(future::ok(response::not_found())), + } + } } impl RestApi { pub fn new( fetcher: Arc, health: NodeHealth, - remote: Remote, ) -> Box { Box::new(RestApi { fetcher, health, - remote, }) } -} - -impl Endpoint for RestApi { - fn to_async_handler(&self, path: EndpointPath, control: Control) -> Box { - Box::new(RestApiRouter::new((*self).clone(), path, control)) - } -} - -struct RestApiRouter { - api: RestApi, - path: Option, - control: Option, - handler: Box, -} - -impl RestApiRouter { - fn new(api: RestApi, path: EndpointPath, control: Control) -> Self { - RestApiRouter { - path: Some(path), - control: Some(control), - api: api, - handler: Box::new(response::as_json_error(StatusCode::NotFound, &types::ApiError { - code: "404".into(), - title: "Not Found".into(), - detail: "Resource you requested has not been found.".into(), - })), - } - } - fn resolve_content(&self, hash: Option<&str>, path: EndpointPath, control: Control) -> Option> { + fn resolve_content(&self, hash: Option<&str>, path: EndpointPath, req: Request) -> Response { trace!(target: "dapps", "Resolving content: {:?} from path: {:?}", hash, path); match hash { - Some(hash) if self.api.fetcher.contains(hash) => { - Some(self.api.fetcher.to_async_handler(path, control)) + Some(hash) if self.fetcher.contains(hash) => { + self.fetcher.respond(path, req) }, - _ => None + _ => Box::new(future::ok(response::not_found())), } } - fn health(&self, control: Control) -> Box { - let map = move |health: Result, ()>| { - let status = match health { - Ok(Ok(ref health)) => { - if [&health.peers.status, &health.sync.status].iter().any(|x| *x != &HealthStatus::Ok) { - StatusCode::PreconditionFailed // HTTP 412 - } else { - StatusCode::Ok // HTTP 200 - } - }, - _ => StatusCode::ServiceUnavailable, // HTTP 503 - }; - - response::as_json(status, &health) - }; - let health = self.api.health.health(); - let remote = self.api.remote.clone(); - Box::new(handlers::AsyncHandler::new(health, map, remote, control)) - } -} - -impl server::Handler for RestApiRouter { - fn on_request(&mut self, request: server::Request) -> Next { - if let Method::Options = *request.method() { - self.handler = response::empty(); - return Next::write(); - } - - // TODO [ToDr] Consider using `path.app_params` instead - let url = extract_url(&request); - if url.is_none() { - // Just return 404 if we can't parse URL - return Next::write(); - } - - let url = url.expect("Check for None early-exists above; qed"); - let mut path = self.path.take().expect("on_request called only once, and path is always defined in new; qed"); - let control = self.control.take().expect("on_request called only once, and control is always defined in new; qed"); - - let endpoint = url.path.get(1).map(|v| v.as_str()); - let hash = url.path.get(2).map(|v| v.as_str()); - // at this point path.app_id contains 'api', adjust it to the hash properly, otherwise - // we will try and retrieve 'api' as the hash when doing the /api/content route - if let Some(ref hash) = hash { path.app_id = hash.clone().to_owned() } - - let handler = endpoint.and_then(|v| match v { - "ping" => Some(response::ping()), - "health" => Some(self.health(control)), - "content" => self.resolve_content(hash, path, control), - _ => None - }); - - // Overwrite default - if let Some(h) = handler { - self.handler = h; - } - - self.handler.on_request(request) - } - - fn on_request_readable(&mut self, decoder: &mut Decoder) -> Next { - self.handler.on_request_readable(decoder) - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { - self.handler.on_response(res) - } - - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - self.handler.on_response_writable(encoder) + fn health(&self) -> Response { + Box::new(self.health.health() + .then(|health| { + let status = match health { + Ok(ref health) => { + if [&health.peers.status, &health.sync.status].iter().any(|x| *x != &HealthStatus::Ok) { + StatusCode::PreconditionFailed // HTTP 412 + } else { + StatusCode::Ok // HTTP 200 + } + }, + _ => StatusCode::ServiceUnavailable, // HTTP 503 + }; + + Ok(response::as_json(status, &health).into()) + }) + ) } } diff --git a/dapps/src/api/response.rs b/dapps/src/api/response.rs index 6ecc2df6033c0c0f52ca018fe19a3038c593372a..c8d25c14450060896a2224f9cd0351d4b7b03fa7 100644 --- a/dapps/src/api/response.rs +++ b/dapps/src/api/response.rs @@ -16,27 +16,28 @@ use serde::Serialize; use serde_json; -use hyper::status::StatusCode; +use hyper::{self, mime, StatusCode}; -use endpoint::Handler; use handlers::{ContentHandler, EchoHandler}; -pub fn empty() -> Box { - Box::new(ContentHandler::ok("".into(), mime!(Text/Plain))) +pub fn empty() -> hyper::Response { + ContentHandler::ok("".into(), mime::TEXT_PLAIN).into() } -pub fn as_json(status: StatusCode, val: &T) -> ContentHandler { +pub fn as_json(status: StatusCode, val: &T) -> hyper::Response { let json = serde_json::to_string(val) .expect("serialization to string is infallible; qed"); - ContentHandler::new(status, json, mime!(Application/Json)) + ContentHandler::new(status, json, mime::APPLICATION_JSON).into() } -pub fn as_json_error(status: StatusCode, val: &T) -> ContentHandler { - let json = serde_json::to_string(val) - .expect("serialization to string is infallible; qed"); - ContentHandler::new(status, json, mime!(Application/Json)) +pub fn ping(req: hyper::Request) -> hyper::Response { + EchoHandler::new(req).into() } -pub fn ping() -> Box { - Box::new(EchoHandler::default()) +pub fn not_found() -> hyper::Response { + as_json(StatusCode::NotFound, &::api::types::ApiError { + code: "404".into(), + title: "Not Found".into(), + detail: "Resource you requested has not been found.".into(), + }) } diff --git a/dapps/src/apps/app.rs b/dapps/src/apps/app.rs index 1d2c9dca6a9cf57c62dd17fb68998b36a05830c6..c75346124c72bbe10bd518cc4905ffe8c187c57b 100644 --- a/dapps/src/apps/app.rs +++ b/dapps/src/apps/app.rs @@ -14,42 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use endpoint::EndpointInfo; - #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields)] pub struct App { - pub id: String, + pub id: Option, pub name: String, pub description: String, pub version: String, pub author: String, #[serde(rename="iconUrl")] pub icon_url: String, + #[serde(rename="localUrl")] + pub local_url: Option, + #[serde(rename="allowJsEval")] + pub allow_js_eval: Option, } impl App { - /// Creates `App` instance from `EndpointInfo` and `id`. - pub fn from_info(id: &str, info: &EndpointInfo) -> Self { - App { - id: id.to_owned(), - name: info.name.to_owned(), - description: info.description.to_owned(), - version: info.version.to_owned(), - author: info.author.to_owned(), - icon_url: info.icon_url.to_owned(), - } - } -} - -impl Into for App { - fn into(self) -> EndpointInfo { - EndpointInfo { - name: self.name, - description: self.description, - version: self.version, - author: self.author, - icon_url: self.icon_url, - } + pub fn with_id(&self, id: &str) -> Self { + let mut app = self.clone(); + app.id = Some(id.into()); + app } } diff --git a/dapps/src/apps/cache.rs b/dapps/src/apps/cache.rs index 5bc01da8e5894365d2a1d271cbc0ab37be8ac654..c81d4d9af9daf70ec956fe9d134cb66b1181699c 100644 --- a/dapps/src/apps/cache.rs +++ b/dapps/src/apps/cache.rs @@ -19,12 +19,12 @@ use std::fs; use linked_hash_map::LinkedHashMap; -use page::LocalPageEndpoint; +use page::local; use handlers::FetchControl; pub enum ContentStatus { Fetching(FetchControl), - Ready(LocalPageEndpoint), + Ready(local::Dapp), } #[derive(Default)] diff --git a/dapps/src/apps/fetcher/installers.rs b/dapps/src/apps/fetcher/installers.rs index 82c91c859b3d8e4f4a09258dfab3cf274099972c..2c067d493c9d68790c23918862b2f344eb45c423 100644 --- a/dapps/src/apps/fetcher/installers.rs +++ b/dapps/src/apps/fetcher/installers.rs @@ -18,16 +18,18 @@ use zip; use std::{fs, fmt}; use std::io::{self, Read, Write}; use std::path::PathBuf; -use fetch::{self, Mime}; -use util::H256; +use ethereum_types::H256; +use fetch; +use futures_cpupool::CpuPool; +use hash::keccak_buffer; +use mime_guess::Mime; -use util::sha3::sha3; -use page::{LocalPageEndpoint, PageCache}; -use handlers::{ContentValidator, ValidatorResponse}; use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest, serialize_manifest, Manifest}; +use handlers::{ContentValidator, ValidatorResponse}; +use page::{local, PageCache}; use Embeddable; -type OnDone = Box) + Send>; +type OnDone = Box) + Send>; fn write_response_and_check_hash( id: &str, @@ -52,14 +54,14 @@ fn write_response_and_check_hash( // Now write the response let mut file = io::BufWriter::new(fs::File::create(&content_path)?); - let mut reader = io::BufReader::new(response); + let mut reader = io::BufReader::new(fetch::BodyReader::new(response)); io::copy(&mut reader, &mut file)?; file.flush()?; // Validate hash - // TODO [ToDr] calculate sha3 in-flight while reading the response + // TODO [ToDr] calculate keccak in-flight while reading the response let mut file = io::BufReader::new(fs::File::open(&content_path)?); - let hash = sha3(&mut file)?; + let hash = keccak_buffer(&mut file)?; if id == hash { Ok((file.into_inner(), content_path)) } else { @@ -75,15 +77,17 @@ pub struct Content { mime: Mime, content_path: PathBuf, on_done: OnDone, + pool: CpuPool, } impl Content { - pub fn new(id: String, mime: Mime, content_path: PathBuf, on_done: OnDone) -> Self { + pub fn new(id: String, mime: Mime, content_path: PathBuf, on_done: OnDone, pool: CpuPool) -> Self { Content { - id: id, - mime: mime, - content_path: content_path, - on_done: on_done, + id, + mime, + content_path, + on_done, + pool, } } } @@ -91,12 +95,15 @@ impl Content { impl ContentValidator for Content { type Error = ValidationError; - fn validate_and_install(&self, response: fetch::Response) -> Result { - let validate = |content_path: PathBuf| { + fn validate_and_install(self, response: fetch::Response) -> Result { + let pool = self.pool; + let id = self.id.clone(); + let mime = self.mime; + let validate = move |content_path: PathBuf| { // Create dir - let (_, content_path) = write_response_and_check_hash(self.id.as_str(), content_path.clone(), self.id.as_str(), response)?; + let (_, content_path) = write_response_and_check_hash(&id, content_path, &id, response)?; - Ok(LocalPageEndpoint::single_file(content_path, self.mime.clone(), PageCache::Enabled)) + Ok(local::Dapp::single_file(pool, content_path, mime, PageCache::Enabled)) }; // Prepare path for a file @@ -118,15 +125,17 @@ pub struct Dapp { dapps_path: PathBuf, on_done: OnDone, embeddable_on: Embeddable, + pool: CpuPool, } impl Dapp { - pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, embeddable_on: Embeddable) -> Self { + pub fn new(id: String, dapps_path: PathBuf, on_done: OnDone, embeddable_on: Embeddable, pool: CpuPool) -> Self { Dapp { id, dapps_path, on_done, embeddable_on, + pool, } } @@ -158,16 +167,19 @@ impl Dapp { impl ContentValidator for Dapp { type Error = ValidationError; - fn validate_and_install(&self, response: fetch::Response) -> Result { - let validate = |dapp_path: PathBuf| { - let (file, zip_path) = write_response_and_check_hash(self.id.as_str(), dapp_path.clone(), &format!("{}.zip", self.id), response)?; + fn validate_and_install(self, response: fetch::Response) -> Result { + let id = self.id.clone(); + let pool = self.pool; + let embeddable_on = self.embeddable_on; + let validate = move |dapp_path: PathBuf| { + let (file, zip_path) = write_response_and_check_hash(&id, dapp_path.clone(), &format!("{}.zip", id), response)?; trace!(target: "dapps", "Opening dapp bundle at {:?}", zip_path); // Unpack archive let mut zip = zip::ZipArchive::new(file)?; // First find manifest file let (mut manifest, manifest_dir) = Self::find_manifest(&mut zip)?; // Overwrite id to match hash - manifest.id = self.id.clone(); + manifest.id = Some(id); // Unpack zip for i in 0..zip.len() { @@ -198,7 +210,7 @@ impl ContentValidator for Dapp { let mut manifest_file = fs::File::create(manifest_path)?; manifest_file.write_all(manifest_str.as_bytes())?; // Create endpoint - let endpoint = LocalPageEndpoint::new(dapp_path, manifest.clone().into(), PageCache::Enabled, self.embeddable_on.clone()); + let endpoint = local::Dapp::new(pool, dapp_path, manifest.into(), PageCache::Enabled, embeddable_on); Ok(endpoint) }; diff --git a/dapps/src/apps/fetcher/mod.rs b/dapps/src/apps/fetcher/mod.rs index 5b91da1a32d34449d27aa62ae8a6f0cf291a21c9..8ed3024fdf2a1c0b7dffb2972c1de1d32194f86c 100644 --- a/dapps/src/apps/fetcher/mod.rs +++ b/dapps/src/apps/fetcher/mod.rs @@ -23,28 +23,26 @@ mod installers; use std::{fs, env}; use std::path::PathBuf; use std::sync::Arc; -use rustc_hex::FromHex; +use futures::{future, Future}; +use futures_cpupool::CpuPool; use fetch::{Client as FetchClient, Fetch}; use hash_fetch::urlhint::{URLHintContract, URLHint, URLHintResult}; -use parity_reactor::Remote; -use hyper; -use hyper::status::StatusCode; +use hyper::StatusCode; +use ethereum_types::H256; use {Embeddable, SyncStatus, random_filename}; -use util::Mutex; -use page::LocalPageEndpoint; +use parking_lot::Mutex; +use page::local; use handlers::{ContentHandler, ContentFetcherHandler}; -use endpoint::{Endpoint, EndpointPath, Handler}; +use endpoint::{self, Endpoint, EndpointPath}; use apps::cache::{ContentCache, ContentStatus}; /// Limit of cached dapps/content const MAX_CACHED_DAPPS: usize = 20; -pub trait Fetcher: Send + Sync + 'static { +pub trait Fetcher: Endpoint + 'static { fn contains(&self, content_id: &str) -> bool; - - fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box; } pub struct ContentFetcher { @@ -53,8 +51,8 @@ pub struct ContentFetcher>, sync: Arc, embeddable_on: Embeddable, - remote: Remote, fetch: F, + pool: CpuPool, only_content: bool, } @@ -66,24 +64,23 @@ impl Drop for ContentFetcher { } impl ContentFetcher { - pub fn new( resolver: R, - sync_status: Arc, - remote: Remote, + sync: Arc, fetch: F, + pool: CpuPool, ) -> Self { let mut cache_path = env::temp_dir(); cache_path.push(random_filename()); ContentFetcher { - cache_path: cache_path, - resolver: resolver, - sync: sync_status, + cache_path, + resolver, + sync, cache: Arc::new(Mutex::new(ContentCache::default())), embeddable_on: None, - remote: remote, - fetch: fetch, + fetch, + pool, only_content: true, } } @@ -98,24 +95,34 @@ impl ContentFetcher { self } - fn still_syncing(embeddable: Embeddable) -> Box { - Box::new(ContentHandler::error( + fn not_found(embeddable: Embeddable) -> endpoint::Response { + Box::new(future::ok(ContentHandler::error( + StatusCode::NotFound, + "Resource Not Found", + "Requested resource was not found.", + None, + embeddable, + ).into())) + } + + fn still_syncing(embeddable: Embeddable) -> endpoint::Response { + Box::new(future::ok(ContentHandler::error( StatusCode::ServiceUnavailable, "Sync In Progress", "Your node is still syncing. We cannot resolve any content before it's fully synced.", Some("Refresh"), embeddable, - )) + ).into())) } - fn dapps_disabled(address: Embeddable) -> Box { - Box::new(ContentHandler::error( + fn dapps_disabled(address: Embeddable) -> endpoint::Response { + Box::new(future::ok(ContentHandler::error( StatusCode::ServiceUnavailable, "Network Dapps Not Available", "This interface doesn't support network dapps for security reasons.", None, address, - )) + ).into())) } #[cfg(test)] @@ -125,9 +132,7 @@ impl ContentFetcher { // resolve contract call synchronously. // TODO: port to futures-based hyper and make it all async. - fn resolve(&self, content_id: Vec) -> Option { - use futures::Future; - + fn resolve(&self, content_id: H256) -> Option { self.resolver.resolve(content_id) .wait() .unwrap_or_else(|e| { warn!("Error resolving content-id: {}", e); None }) @@ -144,15 +149,17 @@ impl Fetcher for ContentFetcher { } } // fallback to resolver - if let Ok(content_id) = content_id.from_hex() { + if let Ok(content_id) = content_id.parse() { // if there is content or we are syncing return true self.sync.is_major_importing() || self.resolve(content_id).is_some() } else { false } } +} - fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box { +impl Endpoint for ContentFetcher { + fn respond(&self, path: EndpointPath, req: endpoint::Request) -> endpoint::Response { let mut cache = self.cache.lock(); let content_id = path.app_id.clone(); @@ -161,22 +168,22 @@ impl Fetcher for ContentFetcher { match status { // Just serve the content Some(&mut ContentStatus::Ready(ref endpoint)) => { - (None, endpoint.to_async_handler(path, control)) + (None, endpoint.to_response(&path)) }, // Content is already being fetched Some(&mut ContentStatus::Fetching(ref fetch_control)) if !fetch_control.is_deadline_reached() => { trace!(target: "dapps", "Content fetching in progress. Waiting..."); - (None, fetch_control.to_async_handler(path, control)) + (None, fetch_control.to_response(path)) }, // We need to start fetching the content _ => { trace!(target: "dapps", "Content unavailable. Fetching... {:?}", content_id); - let content_hex = content_id.from_hex().expect("to_handler is called only when `contains` returns true."); + let content_hex = content_id.parse().expect("to_handler is called only when `contains` returns true."); let content = self.resolve(content_hex); let cache = self.cache.clone(); let id = content_id.clone(); - let on_done = move |result: Option| { + let on_done = move |result: Option| { let mut cache = cache.lock(); match result { Some(endpoint) => cache.insert(id.clone(), ContentStatus::Ready(endpoint)), @@ -193,41 +200,62 @@ impl Fetcher for ContentFetcher { Some(URLHintResult::Dapp(_)) if self.only_content => { (None, Self::dapps_disabled(self.embeddable_on.clone())) }, - Some(URLHintResult::Dapp(dapp)) => { - let handler = ContentFetcherHandler::new( - dapp.url(), - path, - control, - installers::Dapp::new( - content_id.clone(), - self.cache_path.clone(), - Box::new(on_done), - self.embeddable_on.clone(), - ), - self.embeddable_on.clone(), - self.remote.clone(), - self.fetch.clone(), - ); - - (Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as Box) - }, - Some(URLHintResult::Content(content)) => { - let handler = ContentFetcherHandler::new( - content.url, - path, - control, - installers::Content::new( - content_id.clone(), - content.mime, - self.cache_path.clone(), - Box::new(on_done), - ), - self.embeddable_on.clone(), - self.remote.clone(), - self.fetch.clone(), - ); - - (Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as Box) + 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(), + self.pool.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(), + self.pool.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(), + self.pool.clone(), + ) + }, + }; + + (Some(ContentStatus::Fetching(handler.fetch_control())), Box::new(handler) as endpoint::Response) }, None if self.sync.is_major_importing() => { (None, Self::still_syncing(self.embeddable_on.clone())) @@ -235,13 +263,7 @@ impl Fetcher for ContentFetcher { None => { // This may happen when sync status changes in between // `contains` and `to_handler` - (None, Box::new(ContentHandler::error( - StatusCode::NotFound, - "Resource Not Found", - "Requested resource was not found.", - None, - self.embeddable_on.clone(), - )) as Box) + (None, Self::not_found(self.embeddable_on.clone())) }, } }, @@ -261,23 +283,22 @@ impl Fetcher for ContentFetcher { mod tests { use std::env; use std::sync::Arc; - use util::Bytes; - use fetch::{Fetch, Client}; - use futures::{future, Future, BoxFuture}; + use fetch::Client; + use futures::{future, Future}; use hash_fetch::urlhint::{URLHint, URLHintResult}; - use parity_reactor::Remote; + use ethereum_types::H256; use apps::cache::ContentStatus; use endpoint::EndpointInfo; - use page::LocalPageEndpoint; + use page::local; use super::{ContentFetcher, Fetcher}; use {SyncStatus}; #[derive(Clone)] struct FakeResolver; impl URLHint for FakeResolver { - fn resolve(&self, _id: Bytes) -> BoxFuture, String> { - future::ok(None).boxed() + fn resolve(&self, _id: H256) -> Box, Error = String> + Send> { + Box::new(future::ok(None)) } } @@ -291,15 +312,24 @@ mod tests { #[test] fn should_true_if_contains_the_app() { // given + let pool = ::futures_cpupool::CpuPool::new(1); let path = env::temp_dir(); - let fetcher = ContentFetcher::new(FakeResolver, Arc::new(FakeSync(false)), Remote::new_sync(), Client::new().unwrap()) - .allow_dapps(true); - let handler = LocalPageEndpoint::new(path, EndpointInfo { + let fetcher = ContentFetcher::new( + FakeResolver, + Arc::new(FakeSync(false)), + Client::new().unwrap(), + pool.clone(), + ).allow_dapps(true); + + let handler = local::Dapp::new(pool, path, EndpointInfo { + id: None, name: "fake".into(), description: "".into(), version: "".into(), author: "".into(), icon_url: "".into(), + local_url: Some("".into()), + allow_js_eval: None, }, Default::default(), None); // when diff --git a/dapps/src/apps/fs.rs b/dapps/src/apps/fs.rs index eb9f65130c2b91480de096e6d2d3fc99fecc374e..3d93a2fae1a372221d3520bcfa82d16c158deafa 100644 --- a/dapps/src/apps/fs.rs +++ b/dapps/src/apps/fs.rs @@ -19,9 +19,11 @@ use std::io; use std::io::Read; use std::fs; use std::path::{Path, PathBuf}; -use page::{LocalPageEndpoint, PageCache}; -use endpoint::{Endpoint, EndpointInfo}; +use futures_cpupool::CpuPool; + use apps::manifest::{MANIFEST_FILENAME, deserialize_manifest}; +use endpoint::{Endpoint, EndpointInfo}; +use page::{local, PageCache}; use Embeddable; struct LocalDapp { @@ -44,16 +46,18 @@ fn read_manifest(name: &str, mut path: PathBuf) -> EndpointInfo { // Try to deserialize manifest deserialize_manifest(s) }) - .map(Into::into) .unwrap_or_else(|e| { warn!(target: "dapps", "Cannot read manifest file at: {:?}. Error: {:?}", path, e); EndpointInfo { + id: None, name: name.into(), description: name.into(), version: "0.0.0".into(), author: "?".into(), icon_url: "icon.png".into(), + local_url: None, + allow_js_eval: Some(false), } }) } @@ -61,14 +65,14 @@ fn read_manifest(name: &str, mut path: PathBuf) -> EndpointInfo { /// Returns Dapp Id and Local Dapp Endpoint for given filesystem path. /// Parses the path to extract last component (for name). /// `None` is returned when path is invalid or non-existent. -pub fn local_endpoint>(path: P, embeddable: Embeddable) -> Option<(String, Box)> { +pub fn local_endpoint>(path: P, embeddable: Embeddable, pool: CpuPool) -> Option<(String, Box)> { let path = path.as_ref().to_owned(); path.canonicalize().ok().and_then(|path| { let name = path.file_name().and_then(|name| name.to_str()); name.map(|name| { let dapp = local_dapp(name.into(), path.clone()); - (dapp.id, Box::new(LocalPageEndpoint::new( - dapp.path, dapp.info, PageCache::Disabled, embeddable.clone()) + (dapp.id, Box::new(local::Dapp::new( + pool.clone(), dapp.path, dapp.info, PageCache::Disabled, embeddable.clone()) )) }) }) @@ -86,13 +90,13 @@ fn local_dapp(name: String, path: PathBuf) -> LocalDapp { } /// Returns endpoints for Local Dapps found for given filesystem path. -/// Scans the directory and collects `LocalPageEndpoints`. -pub fn local_endpoints>(dapps_path: P, embeddable: Embeddable) -> BTreeMap> { +/// Scans the directory and collects `local::Dapp`. +pub fn local_endpoints>(dapps_path: P, embeddable: Embeddable, pool: CpuPool) -> BTreeMap> { let mut pages = BTreeMap::>::new(); for dapp in local_dapps(dapps_path.as_ref()) { pages.insert( dapp.id, - Box::new(LocalPageEndpoint::new(dapp.path, dapp.info, PageCache::Disabled, embeddable.clone())) + Box::new(local::Dapp::new(pool.clone(), dapp.path, dapp.info, PageCache::Disabled, embeddable.clone())) ); } pages diff --git a/dapps/src/apps/manifest.rs b/dapps/src/apps/manifest.rs index 9461149804321937377afd321b481536602986db..e320482195da5c1feb093ef29368fb1390054869 100644 --- a/dapps/src/apps/manifest.rs +++ b/dapps/src/apps/manifest.rs @@ -20,8 +20,13 @@ pub use apps::App as Manifest; pub const MANIFEST_FILENAME: &'static str = "manifest.json"; pub fn deserialize_manifest(manifest: String) -> Result { - serde_json::from_str::(&manifest).map_err(|e| format!("{:?}", e)) - // TODO [todr] Manifest validation (especialy: id (used as path)) + let mut manifest = serde_json::from_str::(&manifest).map_err(|e| format!("{:?}", e))?; + if manifest.id.is_none() { + return Err("App 'id' is missing.".into()); + } + manifest.allow_js_eval = Some(manifest.allow_js_eval.unwrap_or(false)); + + Ok(manifest) } pub fn serialize_manifest(manifest: &Manifest) -> Result { diff --git a/dapps/src/apps/mod.rs b/dapps/src/apps/mod.rs index c38c6784a5ed4ce74ff708ad6a9a4ca68c01d5f8..c065a08474cc4735b413edc7e4adfdd0723edf0e 100644 --- a/dapps/src/apps/mod.rs +++ b/dapps/src/apps/mod.rs @@ -18,12 +18,12 @@ use std::path::PathBuf; use std::sync::Arc; use endpoint::{Endpoints, Endpoint}; -use page::PageEndpoint; +use futures_cpupool::CpuPool; +use page; use proxypac::ProxyPac; use web::Web; use fetch::Fetch; use parity_dapps::WebApp; -use parity_reactor::Remote; use parity_ui; use {WebProxyTokens, ParentFrameSettings}; @@ -43,12 +43,12 @@ pub const UTILS_PATH: &'static str = "parity-utils"; pub const WEB_PATH: &'static str = "web"; pub const URL_REFERER: &'static str = "__referer="; -pub fn utils() -> Box { - Box::new(PageEndpoint::with_prefix(parity_ui::App::default(), UTILS_PATH.to_owned())) +pub fn utils(pool: CpuPool) -> Box { + Box::new(page::builtin::Dapp::new(pool, parity_ui::App::default())) } -pub fn ui() -> Box { - Box::new(PageEndpoint::with_fallback_to_index(parity_ui::App::default())) +pub fn ui(pool: CpuPool) -> Box { + Box::new(page::builtin::Dapp::with_fallback_to_index(pool, parity_ui::App::default())) } pub fn ui_redirection(embeddable: Option) -> Box { @@ -61,14 +61,14 @@ pub fn all_endpoints( dapps_domain: &str, embeddable: Option, web_proxy_tokens: Arc, - remote: Remote, fetch: F, + pool: CpuPool, ) -> (Vec, Endpoints) { // fetch fs dapps at first to avoid overwriting builtins - let mut pages = fs::local_endpoints(dapps_path.clone(), embeddable.clone()); + let mut pages = fs::local_endpoints(dapps_path.clone(), embeddable.clone(), pool.clone()); let local_endpoints: Vec = pages.keys().cloned().collect(); for path in extra_dapps { - if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), embeddable.clone()) { + if let Some((id, endpoint)) = fs::local_endpoint(path.clone(), embeddable.clone(), pool.clone()) { pages.insert(id, endpoint); } else { warn!(target: "dapps", "Ignoring invalid dapp at {}", path.display()); @@ -76,17 +76,20 @@ pub fn all_endpoints( } // NOTE [ToDr] Dapps will be currently embeded on 8180 - insert::(&mut pages, "ui", Embeddable::Yes(embeddable.clone())); + insert::(&mut pages, "ui", Embeddable::Yes(embeddable.clone()), pool.clone()); + // old version + insert::(&mut pages, "v1", Embeddable::Yes(embeddable.clone()), pool.clone()); + pages.insert("proxy".into(), ProxyPac::boxed(embeddable.clone(), dapps_domain.to_owned())); - pages.insert(WEB_PATH.into(), Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), remote.clone(), fetch.clone())); + pages.insert(WEB_PATH.into(), Web::boxed(embeddable.clone(), web_proxy_tokens.clone(), fetch.clone(), pool.clone())); (local_endpoints, pages) } -fn insert(pages: &mut Endpoints, id: &str, embed_at: Embeddable) { +fn insert(pages: &mut Endpoints, id: &str, embed_at: Embeddable, pool: CpuPool) { pages.insert(id.to_owned(), Box::new(match embed_at { - Embeddable::Yes(address) => PageEndpoint::new_safe_to_embed(T::default(), address), - Embeddable::No => PageEndpoint::new(T::default()), + Embeddable::Yes(address) => page::builtin::Dapp::new_safe_to_embed(pool, T::default(), address), + Embeddable::No => page::builtin::Dapp::new(pool, T::default()), })); } diff --git a/dapps/src/apps/ui.rs b/dapps/src/apps/ui.rs index 06a815a8a2236ccc7485bfb5f836ccd56d0b75c2..39da14e5b97509e918e821b702152ae51c8904db 100644 --- a/dapps/src/apps/ui.rs +++ b/dapps/src/apps/ui.rs @@ -16,9 +16,10 @@ //! UI redirections -use hyper::{Control, StatusCode}; +use hyper::StatusCode; +use futures::future; -use endpoint::{Endpoint, Handler, EndpointPath}; +use endpoint::{Endpoint, Request, Response, EndpointPath}; use {handlers, Embeddable}; /// Redirection to UI server. @@ -37,19 +38,20 @@ impl Redirection { } impl Endpoint for Redirection { - fn to_async_handler(&self, _path: EndpointPath, _control: Control) -> Box { - if let Some(ref frame) = self.embeddable_on { + fn respond(&self, _path: EndpointPath, req: Request) -> Response { + Box::new(future::ok(if let Some(ref frame) = self.embeddable_on { trace!(target: "dapps", "Redirecting to signer interface."); - handlers::Redirection::boxed(&format!("http://{}:{}", &frame.host, frame.port)) + let protocol = req.uri().scheme().unwrap_or("http"); + handlers::Redirection::new(format!("{}://{}:{}", protocol, &frame.host, frame.port)).into() } else { trace!(target: "dapps", "Signer disabled, returning 404."); - Box::new(handlers::ContentHandler::error( + handlers::ContentHandler::error( StatusCode::NotFound, "404 Not Found", "Your homepage is not available when Trusted Signer is disabled.", Some("You can still access dapps by writing a correct address, though. Re-enable Signer to get your homepage back."), None, - )) - } + ).into() + })) } } diff --git a/dapps/src/endpoint.rs b/dapps/src/endpoint.rs index ea5825b74952ccddf4848b5aebc29c91cbe40d95..fd05445c2a240105073eb1dd7f283f79174b299a 100644 --- a/dapps/src/endpoint.rs +++ b/dapps/src/endpoint.rs @@ -18,37 +18,32 @@ use std::collections::BTreeMap; -use hyper::{self, server, net}; +use futures::Future; +use hyper; #[derive(Debug, PartialEq, Default, Clone)] pub struct EndpointPath { pub app_id: String, pub app_params: Vec, + pub query: Option, pub host: String, pub port: u16, pub using_dapps_domains: bool, } -#[derive(Debug, PartialEq, Clone)] -pub struct EndpointInfo { - pub name: String, - pub description: String, - pub version: String, - pub author: String, - pub icon_url: String, +impl EndpointPath { + pub fn has_no_params(&self) -> bool { + self.app_params.is_empty() || self.app_params.iter().all(|x| x.is_empty()) + } } +pub type EndpointInfo = ::apps::App; pub type Endpoints = BTreeMap>; -pub type Handler = server::Handler + Send; +pub type Response = Box + Send>; +pub type Request = hyper::Request; pub trait Endpoint : Send + Sync { fn info(&self) -> Option<&EndpointInfo> { None } - fn to_handler(&self, _path: EndpointPath) -> Box { - panic!("This Endpoint is asynchronous and requires Control object."); - } - - fn to_async_handler(&self, path: EndpointPath, _control: hyper::Control) -> Box { - self.to_handler(path) - } + fn respond(&self, path: EndpointPath, req: Request) -> Response; } diff --git a/dapps/src/handlers/async.rs b/dapps/src/handlers/async.rs deleted file mode 100644 index d68c55cce169772bf0eb9afe5b687f39db7ff088..0000000000000000000000000000000000000000 --- a/dapps/src/handlers/async.rs +++ /dev/null @@ -1,112 +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 . - -//! Async Content Handler -//! Temporary solution until we switch to future-based server. -//! Wraps a future and converts it to hyper::server::Handler; - -use std::{mem, time}; -use std::sync::mpsc; -use futures::Future; -use hyper::{server, Decoder, Encoder, Next, Control}; -use hyper::net::HttpStream; - -use handlers::ContentHandler; -use parity_reactor::Remote; - -const TIMEOUT_SECS: u64 = 15; - -enum State { - Initial(F, M, Remote, Control), - Waiting(mpsc::Receiver>, M), - Done(ContentHandler), - Invalid, -} - -pub struct AsyncHandler { - state: State, -} - -impl AsyncHandler { - pub fn new(future: F, map: M, remote: Remote, control: Control) -> Self { - AsyncHandler { - state: State::Initial(future, map, remote, control), - } - } -} - -impl server::Handler for AsyncHandler, M> where - F: Future + Send + 'static, - M: FnOnce(Result, ()>) -> ContentHandler, - T: Send + 'static, - E: Send + 'static, -{ - fn on_request(&mut self, _request: server::Request) -> Next { - if let State::Initial(future, map, remote, control) = mem::replace(&mut self.state, State::Invalid) { - let (tx, rx) = mpsc::sync_channel(1); - let control2 = control.clone(); - let tx2 = tx.clone(); - remote.spawn_with_timeout(move || future.then(move |result| { - // Send a result (ignore errors if the connection was dropped) - let _ = tx.send(Ok(result)); - // Resume handler - let _ = control.ready(Next::read()); - - Ok(()) - }), time::Duration::from_secs(TIMEOUT_SECS), move || { - // Notify about error - let _ = tx2.send(Err(())); - // Resume handler - let _ = control2.ready(Next::read()); - }); - - self.state = State::Waiting(rx, map); - } - - Next::wait() - } - - fn on_request_readable(&mut self, _decoder: &mut Decoder) -> Next { - if let State::Waiting(rx, map) = mem::replace(&mut self.state, State::Invalid) { - match rx.try_recv() { - Ok(result) => { - self.state = State::Done(map(result)); - }, - Err(err) => { - warn!("Resuming handler in incorrect state: {:?}", err); - } - } - } - - Next::write() - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { - if let State::Done(ref mut handler) = self.state { - handler.on_response(res) - } else { - Next::end() - } - } - - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - if let State::Done(ref mut handler) = self.state { - handler.on_response_writable(encoder) - } else { - Next::end() - } - } -} diff --git a/dapps/src/handlers/content.rs b/dapps/src/handlers/content.rs index 300f4b61aa14444a6c4be7cd9c9392bb0ff4831e..c7eccf474e44daae2904f0d656ff8d1be09f6e00 100644 --- a/dapps/src/handlers/content.rs +++ b/dapps/src/handlers/content.rs @@ -16,32 +16,29 @@ //! Simple Content Handler -use hyper::{header, server, Decoder, Encoder, Next}; -use hyper::net::HttpStream; -use hyper::mime::Mime; -use hyper::status::StatusCode; +use hyper::{self, mime, header}; +use hyper::StatusCode; -use util::version; +use parity_version::version; use handlers::add_security_headers; use Embeddable; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct ContentHandler { code: StatusCode, content: String, - mimetype: Mime, - write_pos: usize, + mimetype: mime::Mime, safe_to_embed_on: Embeddable, } impl ContentHandler { - pub fn ok(content: String, mimetype: Mime) -> Self { + pub fn ok(content: String, mimetype: mime::Mime) -> Self { Self::new(StatusCode::Ok, content, mimetype) } pub fn html(code: StatusCode, content: String, embeddable_on: Embeddable) -> Self { - Self::new_embeddable(code, content, mime!(Text/Html), embeddable_on) + Self::new_embeddable(code, content, mime::TEXT_HTML, embeddable_on) } pub fn error( @@ -60,57 +57,32 @@ impl ContentHandler { ), embeddable_on) } - pub fn new(code: StatusCode, content: String, mimetype: Mime) -> Self { + pub fn new(code: StatusCode, content: String, mimetype: mime::Mime) -> Self { Self::new_embeddable(code, content, mimetype, None) } pub fn new_embeddable( code: StatusCode, content: String, - mimetype: Mime, + mimetype: mime::Mime, safe_to_embed_on: Embeddable, ) -> Self { ContentHandler { code, content, mimetype, - write_pos: 0, safe_to_embed_on, } } } -impl server::Handler for ContentHandler { - fn on_request(&mut self, _request: server::Request) -> Next { - Next::write() - } - - fn on_request_readable(&mut self, _decoder: &mut Decoder) -> Next { - Next::write() - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { - res.set_status(self.code); - res.headers_mut().set(header::ContentType(self.mimetype.clone())); - add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.take()); - Next::write() - } - - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - let bytes = self.content.as_bytes(); - if self.write_pos == bytes.len() { - return Next::end(); - } - - match encoder.write(&bytes[self.write_pos..]) { - Ok(bytes) => { - self.write_pos += bytes; - Next::write() - }, - Err(e) => match e.kind() { - ::std::io::ErrorKind::WouldBlock => Next::write(), - _ => Next::end() - }, - } +impl Into for ContentHandler { + fn into(self) -> hyper::Response { + let mut res = hyper::Response::new() + .with_status(self.code) + .with_header(header::ContentType(self.mimetype)) + .with_body(self.content); + add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on, false); + res } } diff --git a/dapps/src/handlers/echo.rs b/dapps/src/handlers/echo.rs index 1e00f2eec911d73b128f6daa7e77e3e89c82d1fa..375f047906fea1e065743adfa8440a11a7c97a04 100644 --- a/dapps/src/handlers/echo.rs +++ b/dapps/src/handlers/echo.rs @@ -16,45 +16,31 @@ //! Echo Handler -use std::io::Read; -use hyper::{server, Decoder, Encoder, Next}; -use hyper::net::HttpStream; -use super::ContentHandler; +use hyper::{self, header}; -#[derive(Default)] +use handlers::add_security_headers; + +#[derive(Debug)] pub struct EchoHandler { - content: String, - handler: Option, + request: hyper::Request, } -impl server::Handler for EchoHandler { - fn on_request(&mut self, _: server::Request) -> Next { - Next::read() - } - - fn on_request_readable(&mut self, decoder: &mut Decoder) -> Next { - match decoder.read_to_string(&mut self.content) { - Ok(0) => { - self.handler = Some(ContentHandler::ok(self.content.clone(), mime!(Application/Json))); - Next::write() - }, - Ok(_) => Next::read(), - Err(e) => match e.kind() { - ::std::io::ErrorKind::WouldBlock => Next::read(), - _ => Next::end(), - } +impl EchoHandler { + pub fn new(request: hyper::Request) -> Self { + EchoHandler { + request, } } +} - fn on_response(&mut self, res: &mut server::Response) -> Next { - self.handler.as_mut() - .expect("handler always set in on_request, which is before now; qed") - .on_response(res) - } +impl Into for EchoHandler { + fn into(self) -> hyper::Response { + let content_type = self.request.headers().get().cloned(); + let mut res = hyper::Response::new() + .with_header(content_type.unwrap_or(header::ContentType::json())) + .with_body(self.request.body()); - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - self.handler.as_mut() - .expect("handler always set in on_request, which is before now; qed") - .on_response_writable(encoder) + add_security_headers(res.headers_mut(), None, false); + res } } diff --git a/dapps/src/handlers/fetch.rs b/dapps/src/handlers/fetch.rs index 7740247d95a8758a2010681d4e5b6a5617f4c3bd..179bb4884c7e9f27ee319c6ced1fd6c1818a1f75 100644 --- a/dapps/src/handlers/fetch.rs +++ b/dapps/src/handlers/fetch.rs @@ -16,57 +16,39 @@ //! Hyper Server Handler that fetches a file during a request (proxy). -use std::fmt; -use std::sync::{mpsc, Arc}; +use std::{fmt, mem}; +use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Instant, Duration}; use fetch::{self, Fetch}; -use futures::Future; -use parity_reactor::Remote; -use util::Mutex; +use futures::sync::oneshot; +use futures::{self, Future}; +use futures_cpupool::CpuPool; +use hyper::{self, Method, StatusCode}; +use parking_lot::Mutex; -use hyper::{server, Decoder, Encoder, Next, Method, Control}; -use hyper::net::HttpStream; -use hyper::uri::RequestUri; -use hyper::status::StatusCode; - -use endpoint::EndpointPath; +use endpoint::{self, EndpointPath}; use handlers::{ContentHandler, StreamingHandler}; -use page::{LocalPageEndpoint, PageHandlerWaiting}; +use page::local; use {Embeddable}; const FETCH_TIMEOUT: u64 = 300; pub enum ValidatorResponse { - Local(LocalPageEndpoint), - Streaming(StreamingHandler), + Local(local::Dapp), + Streaming(StreamingHandler), } -pub trait ContentValidator: Send + 'static { +pub trait ContentValidator: Sized + Send + 'static { type Error: fmt::Debug + fmt::Display; - fn validate_and_install(&self, fetch::Response) -> Result; -} - -enum FetchState { - Waiting, - NotStarted(String), - Error(ContentHandler), - InProgress(mpsc::Receiver), - Streaming(StreamingHandler), - Done(LocalPageEndpoint, Box), + fn validate_and_install(self, fetch::Response) -> Result; } -enum WaitResult { - Error(ContentHandler), - Done(LocalPageEndpoint), - NonAwaitable, -} - -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct FetchControl { abort: Arc, - listeners: Arc)>>>, + listeners: Arc>>>, deadline: Instant, } @@ -81,14 +63,30 @@ impl Default for FetchControl { } impl FetchControl { + pub fn is_deadline_reached(&self) -> bool { + self.deadline < Instant::now() + } + + pub fn abort(&self) { + self.abort.store(true, Ordering::SeqCst); + } + + pub fn to_response(&self, path: EndpointPath) -> endpoint::Response { + let (tx, receiver) = oneshot::channel(); + self.listeners.lock().push(tx); + + Box::new(WaitingHandler { + path, + state: WaitState::Waiting(receiver), + }) + } + fn notify WaitResult>(&self, status: F) { let mut listeners = self.listeners.lock(); - for (control, sender) in listeners.drain(..) { + for sender in listeners.drain(..) { trace!(target: "dapps", "Resuming request waiting for content..."); - if let Err(e) = sender.send(status()) { - trace!(target: "dapps", "Waiting listener notification failed: {:?}", e); - } else { - let _ = control.ready(Next::read()); + if let Err(_) = sender.send(status()) { + trace!(target: "dapps", "Waiting listener notification failed."); } } } @@ -98,92 +96,79 @@ impl FetchControl { FetchState::Error(ref handler) => self.notify(|| WaitResult::Error(handler.clone())), FetchState::Done(ref endpoint, _) => self.notify(|| WaitResult::Done(endpoint.clone())), FetchState::Streaming(_) => self.notify(|| WaitResult::NonAwaitable), - FetchState::NotStarted(_) | FetchState::InProgress(_) | FetchState::Waiting => {}, + FetchState::InProgress(_) => {}, + FetchState::Empty => {}, } } +} - pub fn is_deadline_reached(&self) -> bool { - self.deadline < Instant::now() - } - pub fn abort(&self) { - self.abort.store(true, Ordering::SeqCst); - } - - pub fn to_async_handler(&self, path: EndpointPath, control: Control) -> Box + Send> { - let (tx, rx) = mpsc::channel(); - self.listeners.lock().push((control, tx)); +enum WaitState { + Waiting(oneshot::Receiver), + Done(endpoint::Response), +} - Box::new(WaitingHandler { - receiver: rx, - state: FetchState::Waiting, - uri: RequestUri::default(), - path: path, - }) - } +#[derive(Debug)] +enum WaitResult { + Error(ContentHandler), + Done(local::Dapp), + NonAwaitable, } pub struct WaitingHandler { - receiver: mpsc::Receiver, - state: FetchState, - uri: RequestUri, path: EndpointPath, + state: WaitState, } -impl server::Handler for WaitingHandler { - fn on_request(&mut self, request: server::Request) -> Next { - self.uri = request.uri().clone(); - Next::wait() - } - - fn on_request_readable(&mut self, decoder: &mut Decoder) -> Next { - let result = self.receiver.try_recv().ok(); - self.state = match result { - Some(WaitResult::Error(handler)) => FetchState::Error(handler), - Some(WaitResult::Done(endpoint)) => { - let mut page_handler = endpoint.to_page_handler(self.path.clone()); - page_handler.set_uri(&self.uri); - FetchState::Done(endpoint, page_handler) - }, - _ => { - warn!("A result for waiting request was not received."); - FetchState::Waiting - }, - }; - - match self.state { - FetchState::Done(_, ref mut handler) => handler.on_request_readable(decoder), - FetchState::Streaming(ref mut handler) => handler.on_request_readable(decoder), - FetchState::Error(ref mut handler) => handler.on_request_readable(decoder), - _ => Next::write(), - } - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { - match self.state { - FetchState::Done(_, ref mut handler) => handler.on_response(res), - FetchState::Streaming(ref mut handler) => handler.on_response(res), - FetchState::Error(ref mut handler) => handler.on_response(res), - _ => Next::end(), - } - } +impl Future for WaitingHandler { + type Item = hyper::Response; + type Error = hyper::Error; + + fn poll(&mut self) -> futures::Poll { + loop { + let new_state = match self.state { + WaitState::Waiting(ref mut receiver) => { + let result = try_ready!(receiver.poll().map_err(|_| hyper::Error::Timeout)); + + match result { + WaitResult::Error(handler) => { + return Ok(futures::Async::Ready(handler.into())); + }, + WaitResult::NonAwaitable => { + let errors = Errors { embeddable_on: None }; + return Ok(futures::Async::Ready(errors.streaming().into())); + }, + WaitResult::Done(endpoint) => { + WaitState::Done(endpoint.to_response(&self.path).into()) + }, + } + }, + WaitState::Done(ref mut response) => { + return response.poll() + }, + }; - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - match self.state { - FetchState::Done(_, ref mut handler) => handler.on_response_writable(encoder), - FetchState::Streaming(ref mut handler) => handler.on_response_writable(encoder), - FetchState::Error(ref mut handler) => handler.on_response_writable(encoder), - _ => Next::end(), + self.state = new_state; } } } -#[derive(Clone)] +#[derive(Debug, Clone)] struct Errors { embeddable_on: Embeddable, } impl Errors { + fn streaming(&self) -> ContentHandler { + ContentHandler::error( + StatusCode::BadGateway, + "Streaming Error", + "This content is being streamed in other place.", + None, + self.embeddable_on.clone(), + ) + } + fn download_error(&self, e: E) -> ContentHandler { ContentHandler::error( StatusCode::BadGateway, @@ -225,67 +210,105 @@ impl Errors { } } -pub struct ContentFetcherHandler { +enum FetchState { + Error(ContentHandler), + InProgress(Box + Send>), + Streaming(hyper::Response), + Done(local::Dapp, endpoint::Response), + Empty, +} + +impl fmt::Debug for FetchState { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + use self::FetchState::*; + + write!(fmt, "FetchState(")?; + match *self { + Error(ref error) => write!(fmt, "error: {:?}", error), + InProgress(_) => write!(fmt, "in progress"), + Streaming(ref res) => write!(fmt, "streaming: {:?}", res), + Done(ref endpoint, _) => write!(fmt, "done: {:?}", endpoint), + Empty => write!(fmt, "?"), + }?; + write!(fmt, ")") + } +} + +#[derive(Debug)] +pub struct ContentFetcherHandler { fetch_control: FetchControl, - control: Control, - remote: Remote, status: FetchState, - fetch: F, - installer: Option, - path: EndpointPath, errors: Errors, } -impl ContentFetcherHandler { - pub fn new( - url: String, +impl ContentFetcherHandler { + pub fn fetch_control(&self) -> FetchControl { + self.fetch_control.clone() + } + + pub fn new( + method: &hyper::Method, + url: &str, path: EndpointPath, - control: Control, installer: H, embeddable_on: Embeddable, - remote: Remote, fetch: F, + pool: CpuPool, ) -> Self { - ContentFetcherHandler { - fetch_control: FetchControl::default(), - control, - remote, - fetch, - status: FetchState::NotStarted(url), - installer: Some(installer), - path, - errors: Errors { - embeddable_on, + let fetch_control = FetchControl::default(); + let errors = Errors { embeddable_on }; + + // Validation of method + let status = match *method { + // Start fetching content + Method::Get => { + trace!(target: "dapps", "Fetching content from: {:?}", url); + FetchState::InProgress(Self::fetch_content( + pool, + fetch, + url, + fetch_control.abort.clone(), + path, + errors.clone(), + installer, + )) }, - } - } + // or return error + _ => FetchState::Error(errors.method_not_allowed()), + }; - pub fn fetch_control(&self) -> FetchControl { - self.fetch_control.clone() + ContentFetcherHandler { + fetch_control, + status, + errors, + } } - fn fetch_content(&self, uri: RequestUri, url: &str, installer: H) -> mpsc::Receiver { - let (tx, rx) = mpsc::channel(); - let abort = self.fetch_control.abort.clone(); - - let path = self.path.clone(); - let tx2 = tx.clone(); - let control = self.control.clone(); - let errors = self.errors.clone(); - - let future = self.fetch.fetch_with_abort(url, abort.into()).then(move |result| { + fn fetch_content( + pool: CpuPool, + fetch: F, + url: &str, + abort: Arc, + path: EndpointPath, + errors: Errors, + installer: H, + ) -> Box + Send> { + // Start fetching the content + let pool2 = pool.clone(); + let future = fetch.fetch(url, abort.into()).then(move |result| { trace!(target: "dapps", "Fetching content finished. Starting validation: {:?}", result); - let new_state = match result { + Ok(match result { Ok(response) => match installer.validate_and_install(response) { Ok(ValidatorResponse::Local(endpoint)) => { trace!(target: "dapps", "Validation OK. Returning response."); - let mut handler = endpoint.to_page_handler(path); - handler.set_uri(&uri); - FetchState::Done(endpoint, handler) + let response = endpoint.to_response(&path); + FetchState::Done(endpoint, response) }, - Ok(ValidatorResponse::Streaming(handler)) => { + Ok(ValidatorResponse::Streaming(stream)) => { trace!(target: "dapps", "Validation OK. Streaming response."); - FetchState::Streaming(handler) + let (reading, response) = stream.into_response(); + pool.spawn(reading).forget(); + FetchState::Streaming(response) }, Err(e) => { trace!(target: "dapps", "Error while validating content: {:?}", e); @@ -296,100 +319,55 @@ impl ContentFetcherHandler { warn!(target: "dapps", "Unable to fetch content: {:?}", e); FetchState::Error(errors.download_error(e)) }, - }; - // Content may be resolved when the connection is already dropped. - let _ = tx2.send(new_state); - // Ignoring control errors - let _ = control.ready(Next::read()); - Ok(()) as Result<(), ()> + }) }); // make sure to run within fetch thread pool. - let future = self.fetch.process(future); - // spawn to event loop - let control = self.control.clone(); - let errors = self.errors.clone(); - self.remote.spawn_with_timeout(|| future, Duration::from_secs(FETCH_TIMEOUT), move || { - // Notify about the timeout - let _ = tx.send(FetchState::Error(errors.timeout_error())); - // Ignoring control errors - let _ = control.ready(Next::read()); - }); - - rx + Box::new(pool2.spawn(future)) } } -impl server::Handler for ContentFetcherHandler { - fn on_request(&mut self, request: server::Request) -> Next { - let status = if let FetchState::NotStarted(ref url) = self.status { - let uri = request.uri().clone(); - let installer = self.installer.take().expect("Installer always set initialy; installer used only in on_request; on_request invoked only once; qed"); - - Some(match *request.method() { - // Start fetching content - Method::Get => { - trace!(target: "dapps", "Fetching content from: {:?}", url); - let receiver = self.fetch_content(uri, url, installer); - FetchState::InProgress(receiver) - }, - // or return error - _ => FetchState::Error(self.errors.method_not_allowed()), - }) - } else { None }; - - if let Some(status) = status { - self.fetch_control.set_status(&status); - self.status = status; - } +impl Future for ContentFetcherHandler { + type Item = hyper::Response; + type Error = hyper::Error; - Next::read() - } + fn poll(&mut self) -> futures::Poll { + loop { + trace!(target: "dapps", "Polling status: {:?}", self.status); + self.status = match mem::replace(&mut self.status, FetchState::Empty) { + FetchState::Error(error) => { + return Ok(futures::Async::Ready(error.into())); + }, + FetchState::Streaming(response) => { + return Ok(futures::Async::Ready(response)); + }, + any => any, + }; - fn on_request_readable(&mut self, decoder: &mut Decoder) -> Next { - let (status, next) = match self.status { - // Request may time out - FetchState::InProgress(_) if self.fetch_control.is_deadline_reached() => { - trace!(target: "dapps", "Fetching dapp failed because of timeout."); - (Some(FetchState::Error(self.errors.timeout_error())), Next::write()) - }, - FetchState::InProgress(ref receiver) => { - // Check if there is an answer - let rec = receiver.try_recv(); - match rec { - // just return the new state - Ok(state) => (Some(state), Next::write()), - // wait some more - _ => (None, Next::wait()) - } - }, - FetchState::Error(ref mut handler) => (None, handler.on_request_readable(decoder)), - _ => (None, Next::write()), - }; + let status = match self.status { + // Request may time out + FetchState::InProgress(_) if self.fetch_control.is_deadline_reached() => { + trace!(target: "dapps", "Fetching dapp failed because of timeout."); + FetchState::Error(self.errors.timeout_error()) + }, + FetchState::InProgress(ref mut receiver) => { + // Check if there is a response + trace!(target: "dapps", "Polling streaming response."); + try_ready!(receiver.poll().map_err(|err| { + warn!(target: "dapps", "Error while fetching response: {:?}", err); + hyper::Error::Timeout + })) + }, + FetchState::Done(_, ref mut response) => { + return response.poll() + }, + FetchState::Empty => panic!("Future polled twice."), + _ => unreachable!(), + }; - if let Some(status) = status { + trace!(target: "dapps", "New status: {:?}", status); self.fetch_control.set_status(&status); self.status = status; } - - next - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { - match self.status { - FetchState::Done(_, ref mut handler) => handler.on_response(res), - FetchState::Streaming(ref mut handler) => handler.on_response(res), - FetchState::Error(ref mut handler) => handler.on_response(res), - _ => Next::end(), - } - } - - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - match self.status { - FetchState::Done(_, ref mut handler) => handler.on_response_writable(encoder), - FetchState::Streaming(ref mut handler) => handler.on_response_writable(encoder), - FetchState::Error(ref mut handler) => handler.on_response_writable(encoder), - _ => Next::end(), - } } } diff --git a/dapps/src/handlers/mod.rs b/dapps/src/handlers/mod.rs index a8beabe846c33a8077ac0d6e3c6b261f89e43260..f78f46c76471d0e11236290c44f723af41aef6f8 100644 --- a/dapps/src/handlers/mod.rs +++ b/dapps/src/handlers/mod.rs @@ -16,80 +16,84 @@ //! Hyper handlers implementations. -mod async; mod content; mod echo; mod fetch; +mod reader; mod redirect; mod streaming; -pub use self::async::AsyncHandler; pub use self::content::ContentHandler; pub use self::echo::EchoHandler; pub use self::fetch::{ContentFetcherHandler, ContentValidator, FetchControl, ValidatorResponse}; +pub use self::reader::Reader; pub use self::redirect::Redirection; pub use self::streaming::StreamingHandler; use std::iter; use itertools::Itertools; -use url::Url; -use hyper::{server, header, net, uri}; +use hyper::header; use {apps, address, Embeddable}; /// Adds security-related headers to the Response. -pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embeddable) { - headers.set_raw("X-XSS-Protection", vec![b"1; mode=block".to_vec()]); - headers.set_raw("X-Content-Type-Options", vec![b"nosniff".to_vec()]); +pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embeddable, allow_js_eval: bool) { + headers.set_raw("X-XSS-Protection", "1; mode=block"); + headers.set_raw("X-Content-Type-Options", "nosniff"); // Embedding header: if let None = embeddable_on { - headers.set_raw("X-Frame-Options", vec![b"SAMEORIGIN".to_vec()]); + headers.set_raw("X-Frame-Options", "SAMEORIGIN"); } // Content Security Policy headers - headers.set_raw("Content-Security-Policy", vec![ + headers.set_raw("Content-Security-Policy", String::new() + // Restrict everything to the same origin by default. + + "default-src 'self';" // Allow connecting to WS servers and HTTP(S) servers. // We could be more restrictive and allow only RPC server URL. - b"connect-src http: https: ws: wss:;".to_vec(), + + "connect-src http: https: ws: wss:;" // Allow framing any content from HTTP(S). // Again we could only allow embedding from RPC server URL. // (deprecated) - b"frame-src 'self' http: https:;".to_vec(), + + "frame-src 'self' http: https:;" // Allow framing and web workers from HTTP(S). - b"child-src 'self' http: https:;".to_vec(), + + "child-src 'self' http: https:;" // We allow data: blob: and HTTP(s) images. // We could get rid of wildcarding HTTP and only allow RPC server URL. // (http required for local dapps icons) - b"img-src 'self' 'unsafe-inline' data: blob: http: https:;".to_vec(), + + "img-src 'self' 'unsafe-inline' data: blob: http: https:;" // Allow style from data: blob: and HTTPS. - b"style-src 'self' 'unsafe-inline' data: blob: https:;".to_vec(), + + "style-src 'self' 'unsafe-inline' data: blob: https:;" // Allow fonts from data: and HTTPS. - b"font-src 'self' data: https:;".to_vec(), - // Allow inline scripts and scripts eval (webpack/jsconsole) - { + + "font-src 'self' data: https:;" + // Disallow objects + + "object-src 'none';" + // Allow scripts + + { let script_src = embeddable_on.as_ref() .map(|e| e.extra_script_src.iter() .map(|&(ref host, port)| address(host, port)) .join(" ") ).unwrap_or_default(); - format!( - "script-src 'self' 'unsafe-inline' 'unsafe-eval' {};", - script_src - ).into_bytes() - }, + let eval = if allow_js_eval { " 'unsafe-eval'" } else { "" }; + + &format!( + "script-src 'self' {}{};", + script_src, + eval + ) + } // Same restrictions as script-src with additional // blob: that is required for camera access (worker) - b"worker-src 'self' 'unsafe-inline' 'unsafe-eval' https: blob:;".to_vec(), - // Restrict everything else to the same origin. - b"default-src 'self';".to_vec(), + + "worker-src 'self' https: blob:;" // Run in sandbox mode (although it's not fully safe since we allow same-origin and script) - b"sandbox allow-same-origin allow-forms allow-modals allow-popups allow-presentation allow-scripts;".to_vec(), - // Disallow subitting forms from any dapps - b"form-action 'none';".to_vec(), + + "sandbox allow-same-origin allow-forms allow-modals allow-popups allow-presentation allow-scripts;" + // Disallow submitting forms from any dapps + + "form-action 'none';" // Never allow mixed content - b"block-all-mixed-content;".to_vec(), + + "block-all-mixed-content;" // Specify if the site can be embedded. - match embeddable_on { + + &match embeddable_on { Some(ref embed) => { let std = address(&embed.host, embed.port); let proxy = format!("{}.{}", apps::HOME_PAGE, embed.dapps_domain); @@ -112,43 +116,6 @@ pub fn add_security_headers(headers: &mut header::Headers, embeddable_on: Embedd format!("frame-ancestors {};", ancestors) }, None => format!("frame-ancestors 'self';"), - }.into_bytes(), - ]); -} - - -/// Extracts URL part from the Request. -pub fn extract_url(req: &server::Request) -> Option { - convert_uri_to_url(req.uri(), req.headers().get::()) -} - -/// Extracts URL given URI and Host header. -pub fn convert_uri_to_url(uri: &uri::RequestUri, host: Option<&header::Host>) -> Option { - match *uri { - uri::RequestUri::AbsoluteUri(ref url) => { - match Url::from_generic_url(url.clone()) { - Ok(url) => Some(url), - _ => None, - } - }, - uri::RequestUri::AbsolutePath { ref path, ref query } => { - let query = match *query { - Some(ref query) => format!("?{}", query), - None => "".into(), - }; - // Attempt to prepend the Host header (mandatory in HTTP/1.1) - let url_string = match host { - Some(ref host) => { - format!("http://{}:{}{}{}", host.hostname, host.port.unwrap_or(80), path, query) - }, - None => return None, - }; - - match Url::parse(&url_string) { - Ok(url) => Some(url), - _ => None, - } - }, - _ => None, - } + } + ); } diff --git a/dapps/src/handlers/reader.rs b/dapps/src/handlers/reader.rs new file mode 100644 index 0000000000000000000000000000000000000000..85a351c7b0c934f832d33cc038a3aa1351f44f0d --- /dev/null +++ b/dapps/src/handlers/reader.rs @@ -0,0 +1,73 @@ +// 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 . + +//! A chunk-producing io::Read wrapper. + +use std::io::{self, Read}; + +use futures::{self, sink, Sink, Future}; +use futures::sync::mpsc; +use hyper; + +type Sender = mpsc::Sender>; + +const MAX_CHUNK_SIZE: usize = 32 * 1024; + +/// A Reader is essentially a stream of `hyper::Chunks`. +/// The chunks are read from given `io::Read` instance. +/// +/// Unfortunately `hyper` doesn't allow you to pass `Stream` +/// directly to the response, so you need to create +/// a `Body::pair()` and send over chunks using `sink::Send`. +/// Also `Chunks` need to take `Vec` by value, so we need +/// to allocate it for each chunk being sent. +pub struct Reader { + buffer: [u8; MAX_CHUNK_SIZE], + content: io::BufReader, + sending: sink::Send, +} + +impl Reader { + pub fn pair(content: R, initial: Vec) -> (Self, hyper::Body) { + let (tx, rx) = hyper::Body::pair(); + let reader = Reader { + buffer: [0; MAX_CHUNK_SIZE], + content: io::BufReader::new(content), + sending: tx.send(Ok(initial.into())), + }; + + (reader, rx) + } +} + +impl Future for Reader { + type Item = (); + type Error = (); + + fn poll(&mut self) -> futures::Poll { + loop { + let next = try_ready!(self.sending.poll().map_err(|err| { + warn!(target: "dapps", "Unable to send next chunk: {:?}", err); + })); + + self.sending = match self.content.read(&mut self.buffer) { + Ok(0) => return Ok(futures::Async::Ready(())), + Ok(read) => next.send(Ok(self.buffer[..read].to_vec().into())), + Err(err) => next.send(Err(hyper::Error::Io(err))), + } + } + } +} diff --git a/dapps/src/handlers/redirect.rs b/dapps/src/handlers/redirect.rs index 09e8f9c5000fb0d79adaf70956dbb9ca06f320cf..cb1eda2dd555706effa224f83af19916adf99b94 100644 --- a/dapps/src/handlers/redirect.rs +++ b/dapps/src/handlers/redirect.rs @@ -16,9 +16,7 @@ //! HTTP Redirection hyper handler -use hyper::{header, server, Decoder, Encoder, Next}; -use hyper::net::HttpStream; -use hyper::status::StatusCode; +use hyper::{self, header, StatusCode}; #[derive(Clone)] pub struct Redirection { @@ -26,36 +24,18 @@ pub struct Redirection { } impl Redirection { - pub fn new(url: &str) -> Self { + pub fn new>(url: T) -> Self { Redirection { - to_url: url.to_owned() + to_url: url.into() } } - - pub fn boxed(url: &str) -> Box { - Box::new(Self::new(url)) - } } -impl server::Handler for Redirection { - fn on_request(&mut self, _request: server::Request) -> Next { - Next::write() - } - - fn on_request_readable(&mut self, _decoder: &mut Decoder) -> Next { - Next::write() - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { +impl Into for Redirection { + fn into(self) -> hyper::Response { // Don't use `MovedPermanently` here to prevent browser from caching the redirections. - res.set_status(StatusCode::Found); - res.headers_mut().set(header::Location(self.to_url.to_owned())); - Next::write() - } - fn on_response_writable(&mut self, _encoder: &mut Encoder) -> Next { - Next::end() + hyper::Response::new() + .with_status(StatusCode::Found) + .with_header(header::Location::new(self.to_url)) } } - - - diff --git a/dapps/src/handlers/streaming.rs b/dapps/src/handlers/streaming.rs index 5981cf221f7fd1ee640555044c8ac1d00733d8f2..269e4c5d2a730a57d4a024543857ac23b5b2901f 100644 --- a/dapps/src/handlers/streaming.rs +++ b/dapps/src/handlers/streaming.rs @@ -16,87 +16,43 @@ //! Content Stream Response -use std::io::{self, Read}; +use std::io; +use hyper::{self, header, mime, StatusCode}; -use hyper::{header, server, Decoder, Encoder, Next}; -use hyper::net::HttpStream; -use hyper::mime::Mime; -use hyper::status::StatusCode; - -use handlers::add_security_headers; +use handlers::{add_security_headers, Reader}; use Embeddable; -const BUFFER_SIZE: usize = 1024; - -pub struct StreamingHandler { - buffer: [u8; BUFFER_SIZE], - buffer_leftover: usize, +pub struct StreamingHandler { + initial: Vec, + content: R, status: StatusCode, - content: io::BufReader, - mimetype: Mime, + mimetype: mime::Mime, safe_to_embed_on: Embeddable, } impl StreamingHandler { - pub fn new(content: R, status: StatusCode, mimetype: Mime, embeddable_on: Embeddable) -> Self { + pub fn new(content: R, status: StatusCode, mimetype: mime::Mime, safe_to_embed_on: Embeddable) -> Self { StreamingHandler { - buffer: [0; BUFFER_SIZE], - buffer_leftover: 0, - status: status, - content: io::BufReader::new(content), - mimetype: mimetype, - safe_to_embed_on: embeddable_on, + initial: Vec::new(), + content, + status, + mimetype, + safe_to_embed_on, } } pub fn set_initial_content(&mut self, content: &str) { - assert_eq!(self.buffer_leftover, 0); - let bytes = content.as_bytes(); - self.buffer_leftover = bytes.len(); - self.buffer[0..self.buffer_leftover].copy_from_slice(bytes); - } -} - -impl server::Handler for StreamingHandler { - fn on_request(&mut self, _request: server::Request) -> Next { - Next::write() + self.initial = content.as_bytes().to_vec(); } - fn on_request_readable(&mut self, _decoder: &mut Decoder) -> Next { - Next::write() - } + pub fn into_response(self) -> (Reader, hyper::Response) { + let (reader, body) = Reader::pair(self.content, self.initial); + let mut res = hyper::Response::new() + .with_status(self.status) + .with_header(header::ContentType(self.mimetype)) + .with_body(body); + add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on, false); - fn on_response(&mut self, res: &mut server::Response) -> Next { - res.set_status(self.status); - res.headers_mut().set(header::ContentType(self.mimetype.clone())); - add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.take()); - Next::write() - } - - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - fn handle_error(e: io::Error) -> Next { - match e.kind() { - ::std::io::ErrorKind::WouldBlock => Next::write(), - _ => Next::end(), - } - } - - let write_pos = self.buffer_leftover; - match self.content.read(&mut self.buffer[write_pos..]) { - Err(e) => handle_error(e), - Ok(read) => match encoder.write(&self.buffer[..write_pos + read]) { - Err(e) => handle_error(e), - Ok(0) => Next::end(), - Ok(wrote) => { - self.buffer_leftover = write_pos + read - wrote; - if self.buffer_leftover > 0 { - for i in self.buffer_leftover..write_pos + read { - self.buffer.swap(i, i - self.buffer_leftover); - } - } - Next::write() - }, - }, - } + (reader, res) } } diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 073db5121442e27a436f15864994edca99043f52..482ee3959580f2a91cffc20c0817feedd28ad57a 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -16,45 +16,48 @@ //! 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; +extern crate futures_cpupool; extern crate itertools; extern crate linked_hash_map; extern crate mime_guess; +extern crate parking_lot; extern crate rand; extern crate rustc_hex; extern crate serde; extern crate serde_json; -extern crate time; extern crate unicase; -extern crate url as url_lib; extern crate zip; -extern crate jsonrpc_core; extern crate jsonrpc_http_server; -extern crate ethcore_util as util; +extern crate ethcore_bytes as bytes; +extern crate ethereum_types; extern crate fetch; extern crate node_health; extern crate parity_dapps_glue as parity_dapps; extern crate parity_hash_fetch as hash_fetch; -extern crate parity_reactor; extern crate parity_ui; +extern crate keccak_hash as hash; +extern crate parity_version; +extern crate registrar; #[macro_use] -extern crate log; +extern crate futures; #[macro_use] -extern crate mime; +extern crate log; #[macro_use] extern crate serde_derive; +#[cfg(test)] +extern crate env_logger; #[cfg(test)] extern crate ethcore_devtools as devtools; #[cfg(test)] -extern crate env_logger; +extern crate jsonrpc_core; +#[cfg(test)] +extern crate parity_reactor; mod endpoint; mod apps; @@ -63,7 +66,6 @@ mod router; mod handlers; mod api; mod proxypac; -mod url; mod web; #[cfg(test)] mod tests; @@ -72,15 +74,14 @@ use std::collections::HashMap; use std::mem; use std::path::PathBuf; use std::sync::Arc; -use util::RwLock; - +use futures_cpupool::CpuPool; use jsonrpc_http_server::{self as http, hyper, Origin}; +use parking_lot::RwLock; use fetch::Fetch; use node_health::NodeHealth; -use parity_reactor::Remote; -pub use hash_fetch::urlhint::ContractClient; +pub use registrar::{RegistrarClient, Asynchronous}; pub use node_health::SyncStatus; @@ -101,19 +102,24 @@ pub struct Endpoints { endpoints: Arc>, dapps_path: PathBuf, embeddable: Option, + pool: Option, } impl Endpoints { /// Returns a current list of app endpoints. pub fn list(&self) -> Vec { self.endpoints.read().iter().filter_map(|(ref k, ref e)| { - e.info().map(|ref info| apps::App::from_info(k, info)) + e.info().map(|ref info| info.with_id(k)) }).collect() } /// Check for any changes in the local dapps folder and update. pub fn refresh_local_dapps(&self) { - let new_local = apps::fs::local_endpoints(&self.dapps_path, self.embeddable.clone()); + let pool = match self.pool.as_ref() { + None => return, + Some(pool) => pool, + }; + let new_local = apps::fs::local_endpoints(&self.dapps_path, self.embeddable.clone(), pool.clone()); let old_local = mem::replace(&mut *self.local_endpoints.write(), new_local.keys().cloned().collect()); let (_, to_remove): (_, Vec<_>) = old_local .into_iter() @@ -147,26 +153,26 @@ impl Middleware { /// Creates new middleware for UI server. pub fn ui( + pool: CpuPool, health: NodeHealth, - remote: Remote, dapps_domain: &str, - registrar: Arc, + registrar: Arc>, sync_status: Arc, fetch: F, ) -> Self { let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new( hash_fetch::urlhint::URLHintContract::new(registrar), sync_status.clone(), - remote.clone(), fetch.clone(), + pool.clone(), ).embeddable_on(None).allow_dapps(false)); let special = { let mut special = special_endpoints( + pool.clone(), health, content_fetcher.clone(), - remote.clone(), ); - special.insert(router::SpecialEndpoint::Home, Some(apps::ui())); + special.insert(router::SpecialEndpoint::Home, Some(apps::ui(pool.clone()))); special }; let router = router::Router::new( @@ -185,15 +191,15 @@ impl Middleware { /// Creates new Dapps server middleware. pub fn dapps( + pool: CpuPool, health: NodeHealth, - remote: Remote, ui_address: Option<(String, u16)>, extra_embed_on: Vec<(String, u16)>, extra_script_src: Vec<(String, u16)>, dapps_path: PathBuf, extra_dapps: Vec, dapps_domain: &str, - registrar: Arc, + registrar: Arc>, sync_status: Arc, web_proxy_tokens: Arc, fetch: F, @@ -202,8 +208,8 @@ impl Middleware { let content_fetcher = Arc::new(apps::fetcher::ContentFetcher::new( hash_fetch::urlhint::URLHintContract::new(registrar), sync_status.clone(), - remote.clone(), fetch.clone(), + pool.clone(), ).embeddable_on(embeddable.clone()).allow_dapps(true)); let (local_endpoints, endpoints) = apps::all_endpoints( dapps_path.clone(), @@ -211,21 +217,22 @@ impl Middleware { dapps_domain, embeddable.clone(), web_proxy_tokens, - remote.clone(), fetch.clone(), + pool.clone(), ); let endpoints = Endpoints { endpoints: Arc::new(RwLock::new(endpoints)), dapps_path, local_endpoints: Arc::new(RwLock::new(local_endpoints)), embeddable: embeddable.clone(), + pool: Some(pool.clone()), }; let special = { let mut special = special_endpoints( + pool.clone(), health, content_fetcher.clone(), - remote.clone(), ); special.insert( router::SpecialEndpoint::Home, @@ -250,23 +257,22 @@ impl Middleware { } impl http::RequestMiddleware for Middleware { - fn on_request(&self, req: &hyper::server::Request, control: &hyper::Control) -> http::RequestMiddlewareAction { - self.router.on_request(req, control) + fn on_request(&self, req: hyper::Request) -> http::RequestMiddlewareAction { + self.router.on_request(req) } } fn special_endpoints( + pool: CpuPool, health: NodeHealth, content_fetcher: Arc, - remote: Remote, ) -> HashMap>> { let mut special = HashMap::new(); special.insert(router::SpecialEndpoint::Rpc, None); - special.insert(router::SpecialEndpoint::Utils, Some(apps::utils())); + special.insert(router::SpecialEndpoint::Utils, Some(apps::utils(pool))); special.insert(router::SpecialEndpoint::Api, Some(api::RestApi::new( content_fetcher, health, - remote, ))); special } diff --git a/dapps/src/page/builtin.rs b/dapps/src/page/builtin.rs index c01c49d21a0c1686f05685d433363274d8af578b..827fe27a3b4e15e09151beec80ffc1261f0fbab1 100644 --- a/dapps/src/page/builtin.rs +++ b/dapps/src/page/builtin.rs @@ -14,71 +14,62 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +use std::io; +use futures::future; +use futures_cpupool::CpuPool; +use hyper::mime::{self, Mime}; +use itertools::Itertools; +use parity_dapps::{WebApp, Info}; + +use endpoint::{Endpoint, EndpointInfo, EndpointPath, Request, Response}; use page::{handler, PageCache}; -use std::sync::Arc; -use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler}; -use parity_dapps::{WebApp, File, Info}; use Embeddable; -pub struct PageEndpoint { +pub struct Dapp { + /// futures cpu pool + pool: CpuPool, /// Content of the files - pub app: Arc, - /// Prefix to strip from the path (when `None` deducted from `app_id`) - pub prefix: Option, + app: T, /// Safe to be loaded in frame by other origin. (use wisely!) safe_to_embed_on: Embeddable, info: EndpointInfo, fallback_to_index_html: bool, } -impl PageEndpoint { - /// Creates new `PageEndpoint` for builtin (compile time) Dapp. - pub fn new(app: T) -> Self { +impl Dapp { + /// Creates new `Dapp` for builtin (compile time) Dapp. + pub fn new(pool: CpuPool, app: T) -> Self { let info = app.info(); - PageEndpoint { - app: Arc::new(app), - prefix: None, + Dapp { + pool, + app, safe_to_embed_on: None, info: EndpointInfo::from(info), fallback_to_index_html: false, } } - /// Creates a new `PageEndpoint` for builtin (compile time) Dapp. + /// Creates a new `Dapp` for builtin (compile time) Dapp. /// Instead of returning 404 this endpoint will always server index.html. - pub fn with_fallback_to_index(app: T) -> Self { + pub fn with_fallback_to_index(pool: CpuPool, app: T) -> Self { let info = app.info(); - PageEndpoint { - app: Arc::new(app), - prefix: None, + Dapp { + pool, + app, safe_to_embed_on: None, info: EndpointInfo::from(info), fallback_to_index_html: true, } } - /// Create new `PageEndpoint` and specify prefix that should be removed before looking for a file. - /// It's used only for special endpoints (i.e. `/parity-utils/`) - /// So `/parity-utils/inject.js` will be resolved to `/inject.js` is prefix is set. - pub fn with_prefix(app: T, prefix: String) -> Self { - let info = app.info(); - PageEndpoint { - app: Arc::new(app), - prefix: Some(prefix), - safe_to_embed_on: None, - info: EndpointInfo::from(info), - fallback_to_index_html: false, - } - } - - /// Creates new `PageEndpoint` which can be safely used in iframe + /// Creates new `Dapp` which can be safely used in iframe /// even from different origin. It might be dangerous (clickjacking). /// Use wisely! - pub fn new_safe_to_embed(app: T, address: Embeddable) -> Self { + pub fn new_safe_to_embed(pool: CpuPool, app: T, address: Embeddable) -> Self { let info = app.info(); - PageEndpoint { - app: Arc::new(app), - prefix: None, + Dapp { + pool, + app, safe_to_embed_on: address, info: EndpointInfo::from(info), fallback_to_index_html: false, @@ -86,96 +77,84 @@ impl PageEndpoint { } } -impl Endpoint for PageEndpoint { - +impl Endpoint for Dapp { fn info(&self) -> Option<&EndpointInfo> { Some(&self.info) } - fn to_handler(&self, path: EndpointPath) -> Box { - Box::new(handler::PageHandler { - app: BuiltinDapp::new(self.app.clone(), self.fallback_to_index_html), - prefix: self.prefix.clone(), - path: path, - file: handler::ServedFile::new(self.safe_to_embed_on.clone()), + fn respond(&self, path: EndpointPath, _req: Request) -> Response { + trace!(target: "dapps", "Builtin file path: {:?}", path); + let file_path = if path.has_no_params() { + "index.html".to_owned() + } else { + path.app_params.into_iter().filter(|x| !x.is_empty()).join("/") + }; + trace!(target: "dapps", "Builtin file: {:?}", file_path); + + let file = { + let file = |path| self.app.file(path).map(|file| { + let content_type = match file.content_type.parse() { + Ok(mime) => mime, + Err(_) => { + warn!(target: "dapps", "invalid MIME type: {}", file.content_type); + mime::TEXT_HTML + }, + }; + BuiltinFile { + content_type, + content: io::Cursor::new(file.content), + } + }); + let res = file(&file_path); + if self.fallback_to_index_html { + res.or_else(|| file("index.html")) + } else { + res + } + }; + + let (reader, response) = handler::PageHandler { + file, cache: PageCache::Disabled, safe_to_embed_on: self.safe_to_embed_on.clone(), - }) + allow_js_eval: self.info.allow_js_eval.clone().unwrap_or(false), + }.into_response(); + + self.pool.spawn(reader).forget(); + + Box::new(future::ok(response)) } } impl From for EndpointInfo { fn from(info: Info) -> Self { EndpointInfo { + id: None, name: info.name.into(), description: info.description.into(), author: info.author.into(), icon_url: info.icon_url.into(), + local_url: None, version: info.version.into(), + allow_js_eval: None, } } } -struct BuiltinDapp { - app: Arc, - fallback_to_index_html: bool, -} - -impl BuiltinDapp { - fn new(app: Arc, fallback_to_index_html: bool) -> Self { - BuiltinDapp { - app: app, - fallback_to_index_html: fallback_to_index_html, - } - } -} - -impl handler::Dapp for BuiltinDapp { - type DappFile = BuiltinDappFile; - - fn file(&self, path: &str) -> Option { - let file = |path| self.app.file(path).map(|_| { - BuiltinDappFile { - app: self.app.clone(), - path: path.into(), - write_pos: 0, - } - }); - let res = file(path); - if self.fallback_to_index_html { - res.or_else(|| file("index.html")) - } else { - res - } - } -} - -struct BuiltinDappFile { - app: Arc, - path: String, - write_pos: usize, -} -impl BuiltinDappFile { - fn file(&self) -> &File { - self.app.file(&self.path).expect("Check is done when structure is created.") - } +struct BuiltinFile { + content_type: Mime, + content: io::Cursor<&'static [u8]>, } -impl handler::DappFile for BuiltinDappFile { - fn content_type(&self) -> &str { - self.file().content_type - } - - fn is_drained(&self) -> bool { - self.write_pos == self.file().content.len() - } +impl handler::DappFile for BuiltinFile { + type Reader = io::Cursor<&'static [u8]>; - fn next_chunk(&mut self) -> &[u8] { - &self.file().content[self.write_pos..] + fn content_type(&self) -> &Mime { + &self.content_type } - fn bytes_written(&mut self, bytes: usize) { - self.write_pos += bytes; + fn into_reader(self) -> Self::Reader { + self.content } } diff --git a/dapps/src/page/handler.rs b/dapps/src/page/handler.rs index ba38c64dc2640154357524da9c36a16736c871bf..a4bd6d71b3eba02878d9153a9d4040a629517b91 100644 --- a/dapps/src/page/handler.rs +++ b/dapps/src/page/handler.rs @@ -14,61 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use time::{self, Duration}; +use std::io; +use std::time::{Duration, SystemTime}; +use hyper::{self, header, StatusCode}; +use hyper::mime::{self, Mime}; -use hyper::header; -use hyper::server; -use hyper::uri::RequestUri; -use hyper::net::HttpStream; -use hyper::status::StatusCode; -use hyper::{Decoder, Encoder, Next}; -use endpoint::EndpointPath; -use handlers::{ContentHandler, add_security_headers}; +use apps; +use handlers::{Reader, ContentHandler, add_security_headers}; use {Embeddable}; /// Represents a file that can be sent to client. /// Implementation should keep track of bytes already sent internally. -pub trait DappFile: Send { - /// Returns a content-type of this file. - fn content_type(&self) -> &str; - - /// Checks if all bytes from that file were written. - fn is_drained(&self) -> bool; +pub trait DappFile { + /// A reader type returned by this file. + type Reader: io::Read; - /// Fetch next chunk to write to the client. - fn next_chunk(&mut self) -> &[u8]; - - /// How many files have been written to the client. - fn bytes_written(&mut self, bytes: usize); -} - -/// Dapp as a (dynamic) set of files. -pub trait Dapp: Send + 'static { - /// File type - type DappFile: DappFile; - - /// Returns file under given path. - fn file(&self, path: &str) -> Option; -} - -/// Currently served by `PageHandler` file -pub enum ServedFile { - /// File from dapp - File(T::DappFile), - /// Error (404) - Error(ContentHandler), -} + /// Returns a content-type of this file. + fn content_type(&self) -> &Mime; -impl ServedFile { - pub fn new(embeddable_on: Embeddable) -> Self { - ServedFile::Error(ContentHandler::error( - StatusCode::NotFound, - "404 Not Found", - "Requested dapp resource was not found.", - None, - embeddable_on, - )) - } + /// Convert this file into io::Read instance. + fn into_reader(self) -> Self::Reader where Self: Sized; } /// Defines what cache headers should be appended to returned resources. @@ -84,194 +49,68 @@ impl Default for PageCache { } } -/// A generic type for `PageHandler` allowing to set the URL. -/// Used by dapps fetching to set the URL after the content was downloaded. -pub trait PageHandlerWaiting: server::Handler + Send { - fn set_uri(&mut self, uri: &RequestUri); -} - /// A handler for a single webapp. /// Resolves correct paths and serves as a plumbing code between /// hyper server and dapp. -pub struct PageHandler { - /// A Dapp. - pub app: T, +pub struct PageHandler { /// File currently being served - pub file: ServedFile, - /// Optional prefix to strip from path. - pub prefix: Option, - /// Requested path. - pub path: EndpointPath, + pub file: Option, /// Flag indicating if the file can be safely embeded (put in iframe). pub safe_to_embed_on: Embeddable, /// Cache settings for this page. pub cache: PageCache, + /// Allow JS unsafe-eval. + pub allow_js_eval: bool, } -impl PageHandlerWaiting for PageHandler { - fn set_uri(&mut self, uri: &RequestUri) { - trace!(target: "dapps", "Setting URI: {:?}", uri); - self.file = match *uri { - RequestUri::AbsolutePath { ref path, .. } => { - self.app.file(&self.extract_path(path)) - }, - RequestUri::AbsoluteUri(ref url) => { - self.app.file(&self.extract_path(url.path())) - }, - _ => None, - }.map_or_else(|| ServedFile::new(self.safe_to_embed_on.clone()), |f| ServedFile::File(f)); - } -} - -impl PageHandler { - fn extract_path(&self, path: &str) -> String { - let app_id = &self.path.app_id; - let prefix = "/".to_owned() + self.prefix.as_ref().unwrap_or(app_id); - let prefix_with_slash = prefix.clone() + "/"; - let query_pos = path.find('?').unwrap_or_else(|| path.len()); - - // Index file support - match path == "/" || path == &prefix || path == &prefix_with_slash { - true => "index.html".to_owned(), - false => if path.starts_with(&prefix_with_slash) { - path[prefix_with_slash.len()..query_pos].to_owned() - } else if path.starts_with("/") { - path[1..query_pos].to_owned() - } else { - path[0..query_pos].to_owned() - } - } - } -} - -impl server::Handler for PageHandler { - fn on_request(&mut self, req: server::Request) -> Next { - self.set_uri(req.uri()); - Next::write() - } - - fn on_request_readable(&mut self, _decoder: &mut Decoder) -> Next { - Next::write() - } - - fn on_response(&mut self, res: &mut server::Response) -> Next { - match self.file { - ServedFile::File(ref f) => { - res.set_status(StatusCode::Ok); - - if let PageCache::Enabled = self.cache { - let mut headers = res.headers_mut(); - let validity = Duration::days(365); - headers.set(header::CacheControl(vec![ - header::CacheDirective::Public, - header::CacheDirective::MaxAge(validity.num_seconds() as u32), - ])); - headers.set(header::Expires(header::HttpDate(time::now() + validity))); - } - - match f.content_type().parse() { - Ok(mime) => res.headers_mut().set(header::ContentType(mime)), - Err(()) => debug!(target: "dapps", "invalid MIME type: {}", f.content_type()), - } - - // Security headers: - add_security_headers(&mut res.headers_mut(), self.safe_to_embed_on.take()); - Next::write() - }, - ServedFile::Error(ref mut handler) => { - handler.on_response(res) - } - } - } - - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - match self.file { - ServedFile::Error(ref mut handler) => handler.on_response_writable(encoder), - ServedFile::File(ref f) if f.is_drained() => Next::end(), - ServedFile::File(ref mut f) => match encoder.write(f.next_chunk()) { - Ok(bytes) => { - f.bytes_written(bytes); - Next::write() - }, - Err(e) => match e.kind() { - ::std::io::ErrorKind::WouldBlock => Next::write(), - _ => Next::end(), - }, +impl PageHandler { + pub fn into_response(self) -> (Option>, hyper::Response) { + let file = match self.file { + None => return (None, ContentHandler::error( + StatusCode::NotFound, + "File not found", + "Requested file has not been found.", + None, + self.safe_to_embed_on, + ).into()), + Some(file) => file, + }; + + let mut res = hyper::Response::new() + .with_status(StatusCode::Ok); + + // headers + { + let mut headers = res.headers_mut(); + + if let PageCache::Enabled = self.cache { + let validity_secs = 365u32 * 24 * 3600; + let validity = Duration::from_secs(validity_secs as u64); + headers.set(header::CacheControl(vec![ + header::CacheDirective::Public, + header::CacheDirective::MaxAge(validity_secs), + ])); + headers.set(header::Expires(header::HttpDate::from(SystemTime::now() + validity))); } - } - } -} - - - -#[cfg(test)] -mod test { - use super::*; - pub struct TestWebAppFile; + headers.set(header::ContentType(file.content_type().to_owned())); - impl DappFile for TestWebAppFile { - fn content_type(&self) -> &str { - unimplemented!() + add_security_headers(&mut headers, self.safe_to_embed_on, self.allow_js_eval); } - fn is_drained(&self) -> bool { - unimplemented!() - } + let initial_content = if file.content_type().to_owned() == mime::TEXT_HTML { + let content = &format!( + r#""#, + apps::UTILS_PATH, + ); - fn next_chunk(&mut self) -> &[u8] { - unimplemented!() - } + content.as_bytes().to_vec() + } else { + Vec::new() + }; - fn bytes_written(&mut self, _bytes: usize) { - unimplemented!() - } + let (reader, body) = Reader::pair(file.into_reader(), initial_content); + res.set_body(body); + (Some(reader), res) } - - #[derive(Default)] - pub struct TestWebapp; - - impl Dapp for TestWebapp { - type DappFile = TestWebAppFile; - - fn file(&self, _path: &str) -> Option { - None - } - } -} - -#[test] -fn should_extract_path_with_appid() { - - // given - let path1 = "/"; - let path2= "/test.css"; - let path3 = "/app/myfile.txt"; - let path4 = "/app/myfile.txt?query=123"; - let page_handler = PageHandler { - app: test::TestWebapp, - prefix: None, - path: EndpointPath { - app_id: "app".to_owned(), - app_params: vec![], - host: "".to_owned(), - port: 8080, - using_dapps_domains: true, - }, - file: ServedFile::new(None), - cache: Default::default(), - safe_to_embed_on: None, - }; - - // when - let res1 = page_handler.extract_path(path1); - let res2 = page_handler.extract_path(path2); - let res3 = page_handler.extract_path(path3); - let res4 = page_handler.extract_path(path4); - - // then - assert_eq!(&res1, "index.html"); - assert_eq!(&res2, "test.css"); - assert_eq!(&res3, "myfile.txt"); - assert_eq!(&res4, "myfile.txt"); } diff --git a/dapps/src/page/local.rs b/dapps/src/page/local.rs index 8d52e86dd1f26ecab2e273360957ba1be6a5d746..a1746efcd2172f5f82ee896a8bccffc2d2ef99d3 100644 --- a/dapps/src/page/local.rs +++ b/dapps/src/page/local.rs @@ -15,16 +15,18 @@ // along with Parity. If not, see . use mime_guess; -use std::io::{Seek, Read, SeekFrom}; -use std::fs; +use std::{fs, fmt}; use std::path::{Path, PathBuf}; -use page::handler::{self, PageCache, PageHandlerWaiting}; -use endpoint::{Endpoint, EndpointInfo, EndpointPath, Handler}; -use mime::Mime; +use futures::{future}; +use futures_cpupool::CpuPool; +use page::handler::{self, PageCache}; +use endpoint::{Endpoint, EndpointInfo, EndpointPath, Request, Response}; +use hyper::mime::Mime; use Embeddable; -#[derive(Debug, Clone)] -pub struct LocalPageEndpoint { +#[derive(Clone)] +pub struct Dapp { + pool: CpuPool, path: PathBuf, mime: Option, info: Option, @@ -32,23 +34,37 @@ pub struct LocalPageEndpoint { embeddable_on: Embeddable, } -impl LocalPageEndpoint { - pub fn new(path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_on: Embeddable) -> Self { - LocalPageEndpoint { - path: path, +impl fmt::Debug for Dapp { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Dapp") + .field("path", &self.path) + .field("mime", &self.mime) + .field("info", &self.info) + .field("cache", &self.cache) + .field("embeddable_on", &self.embeddable_on) + .finish() + } +} + +impl Dapp { + pub fn new(pool: CpuPool, path: PathBuf, info: EndpointInfo, cache: PageCache, embeddable_on: Embeddable) -> Self { + Dapp { + pool, + path, mime: None, info: Some(info), - cache: cache, - embeddable_on: embeddable_on, + cache, + embeddable_on, } } - pub fn single_file(path: PathBuf, mime: Mime, cache: PageCache) -> Self { - LocalPageEndpoint { - path: path, + pub fn single_file(pool: CpuPool, path: PathBuf, mime: Mime, cache: PageCache) -> Self { + Dapp { + pool, + path, mime: Some(mime), info: None, - cache: cache, + cache, embeddable_on: None, } } @@ -57,125 +73,76 @@ impl LocalPageEndpoint { self.path.clone() } - fn page_handler_with_mime(&self, path: EndpointPath, mime: &Mime) -> handler::PageHandler { - handler::PageHandler { - app: LocalSingleFile { path: self.path.clone(), mime: format!("{}", mime) }, - prefix: None, - path: path, - file: handler::ServedFile::new(None), - safe_to_embed_on: self.embeddable_on.clone(), - cache: self.cache, + fn get_file(&self, path: &EndpointPath) -> Option { + if let Some(ref mime) = self.mime { + return LocalFile::from_path(&self.path, mime.to_owned()); } - } - fn page_handler(&self, path: EndpointPath) -> handler::PageHandler { - handler::PageHandler { - app: LocalDapp { path: self.path.clone() }, - prefix: None, - path: path, - file: handler::ServedFile::new(None), - safe_to_embed_on: self.embeddable_on.clone(), - cache: self.cache, - } - } + let mut file_path = self.path.to_owned(); - pub fn to_page_handler(&self, path: EndpointPath) -> Box { - if let Some(ref mime) = self.mime { - Box::new(self.page_handler_with_mime(path, mime)) + if path.has_no_params() { + file_path.push("index.html"); } else { - Box::new(self.page_handler(path)) + for part in &path.app_params { + file_path.push(part); + } } - } -} -impl Endpoint for LocalPageEndpoint { - fn info(&self) -> Option<&EndpointInfo> { - self.info.as_ref() + let mime = mime_guess::guess_mime_type(&file_path); + LocalFile::from_path(&file_path, mime) } - fn to_handler(&self, path: EndpointPath) -> Box { - if let Some(ref mime) = self.mime { - Box::new(self.page_handler_with_mime(path, mime)) - } else { - Box::new(self.page_handler(path)) - } - } -} -struct LocalSingleFile { - path: PathBuf, - mime: String, -} + pub fn to_response(&self, path: &EndpointPath) -> Response { + let (reader, response) = handler::PageHandler { + file: self.get_file(path), + cache: self.cache, + safe_to_embed_on: self.embeddable_on.clone(), + allow_js_eval: self.info.as_ref().and_then(|x| x.allow_js_eval).unwrap_or(false), + }.into_response(); -impl handler::Dapp for LocalSingleFile { - type DappFile = LocalFile; + self.pool.spawn(reader).forget(); - fn file(&self, _path: &str) -> Option { - LocalFile::from_path(&self.path, Some(&self.mime)) + Box::new(future::ok(response)) } } -struct LocalDapp { - path: PathBuf, -} - -impl handler::Dapp for LocalDapp { - type DappFile = LocalFile; +impl Endpoint for Dapp { + fn info(&self) -> Option<&EndpointInfo> { + self.info.as_ref() + } - fn file(&self, file_path: &str) -> Option { - let mut path = self.path.clone(); - for part in file_path.split('/') { - path.push(part); - } - LocalFile::from_path(&path, None) + fn respond(&self, path: EndpointPath, _req: Request) -> Response { + self.to_response(&path) } } struct LocalFile { - content_type: String, - buffer: [u8; 4096], + content_type: Mime, file: fs::File, - len: u64, - pos: u64, } impl LocalFile { - fn from_path>(path: P, mime: Option<&str>) -> Option { + fn from_path>(path: P, content_type: Mime) -> Option { + trace!(target: "dapps", "Local file: {:?}", path.as_ref()); // Check if file exists fs::File::open(&path).ok().map(|file| { - let content_type = mime.map(|mime| mime.to_owned()) - .unwrap_or_else(|| mime_guess::guess_mime_type(path).to_string()); - let len = file.metadata().ok().map_or(0, |meta| meta.len()); LocalFile { - content_type: content_type, - buffer: [0; 4096], - file: file, - pos: 0, - len: len, + content_type, + file, } }) } } impl handler::DappFile for LocalFile { - fn content_type(&self) -> &str { - &self.content_type - } + type Reader = fs::File; - fn is_drained(&self) -> bool { - self.pos == self.len - } - - fn next_chunk(&mut self) -> &[u8] { - let _ = self.file.seek(SeekFrom::Start(self.pos)); - if let Ok(n) = self.file.read(&mut self.buffer) { - &self.buffer[0..n] - } else { - &self.buffer[0..0] - } + fn content_type(&self) -> &Mime { + &self.content_type } - fn bytes_written(&mut self, bytes: usize) { - self.pos += bytes as u64; + fn into_reader(self) -> Self::Reader { + self.file } } diff --git a/dapps/src/page/mod.rs b/dapps/src/page/mod.rs index 868cd00a386719f415b348d5c594157a47df73c0..420707bfe1955513d59dd8299c72d3638b1345c4 100644 --- a/dapps/src/page/mod.rs +++ b/dapps/src/page/mod.rs @@ -15,11 +15,9 @@ // along with Parity. If not, see . -mod builtin; -mod local; +pub mod builtin; +pub mod local; mod handler; -pub use self::local::LocalPageEndpoint; -pub use self::builtin::PageEndpoint; -pub use self::handler::{PageCache, PageHandlerWaiting}; +pub use self::handler::PageCache; diff --git a/dapps/src/proxypac.rs b/dapps/src/proxypac.rs index 5bffe649c90a5c7597f4d3ee3eb9fbacf21a8d98..85ac11423a11ed4525ab80f2e19af88c184c8da9 100644 --- a/dapps/src/proxypac.rs +++ b/dapps/src/proxypac.rs @@ -16,9 +16,11 @@ //! Serving ProxyPac file -use endpoint::{Endpoint, Handler, EndpointPath}; -use handlers::ContentHandler; use apps::HOME_PAGE; +use endpoint::{Endpoint, Request, Response, EndpointPath}; +use futures::future; +use handlers::ContentHandler; +use hyper::mime; use {address, Embeddable}; pub struct ProxyPac { @@ -33,7 +35,7 @@ impl ProxyPac { } impl Endpoint for ProxyPac { - fn to_handler(&self, path: EndpointPath) -> Box { + fn respond(&self, path: EndpointPath, _req: Request) -> Response { let ui = self.embeddable .as_ref() .map(|ref parent| address(&parent.host, parent.port)) @@ -57,7 +59,9 @@ function FindProxyForURL(url, host) {{ "#, HOME_PAGE, self.dapps_domain, path.host, path.port, ui); - Box::new(ContentHandler::ok(content, mime!(Application/Javascript))) + Box::new(future::ok( + ContentHandler::ok(content, mime::TEXT_JAVASCRIPT).into() + )) } } diff --git a/dapps/src/router.rs b/dapps/src/router.rs index 2b74d51dfde2cbf1d29fa9505647e4495cc70136..e5770ca72b8f77578d21cdf646499da8930e3af2 100644 --- a/dapps/src/router.rs +++ b/dapps/src/router.rs @@ -17,18 +17,16 @@ //! Router implementation //! Dispatch requests to proper application. -use std::cmp; use std::sync::Arc; use std::collections::HashMap; -use url::{Url, Host}; -use hyper::{self, server, header, Control}; -use hyper::net::HttpStream; +use futures::future; +use hyper::{self, header, Uri}; use jsonrpc_http_server as http; use apps; use apps::fetcher::Fetcher; -use endpoint::{Endpoint, EndpointPath, Handler}; +use endpoint::{self, Endpoint, EndpointPath}; use Endpoints; use handlers; use Embeddable; @@ -43,6 +41,13 @@ pub enum SpecialEndpoint { None, } +enum Response { + Some(endpoint::Response), + None(hyper::Request), +} + +/// An endpoint router. +/// Dispatches the request to particular Endpoint by requested uri/path. pub struct Router { endpoints: Option, fetch: Arc, @@ -52,11 +57,10 @@ pub struct Router { } impl Router { - fn resolve_request(&self, req: &server::Request, control: Control, refresh_dapps: bool) -> (bool, Option>) { + fn resolve_request(&self, req: hyper::Request, refresh_dapps: bool) -> (bool, Response) { // Choose proper handler depending on path / domain - let url = handlers::extract_url(req); - let endpoint = extract_endpoint(&url, &self.dapps_domain); - let referer = extract_referer_endpoint(req, &self.dapps_domain); + let endpoint = extract_endpoint(req.uri(), req.headers().get(), &self.dapps_domain); + let referer = extract_referer_endpoint(&req, &self.dapps_domain); let is_utils = endpoint.1 == SpecialEndpoint::Utils; let is_get_request = *req.method() == hyper::Method::Get; let is_head_request = *req.method() == hyper::Method::Head; @@ -64,47 +68,51 @@ impl Router { .as_ref() .map_or(false, |endpoints| endpoints.endpoints.read().contains_key(dapp)); - trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", url, req); - debug!(target: "dapps", "Handling endpoint request: {:?}", endpoint); + trace!(target: "dapps", "Routing request to {:?}. Details: {:?}", req.uri(), req); + debug!(target: "dapps", "Handling endpoint request: {:?}, referer: {:?}", endpoint, referer); (is_utils, match (endpoint.0, endpoint.1, referer) { // Handle invalid web requests that we can recover from - (ref path, SpecialEndpoint::None, Some((ref referer, ref referer_url))) + (ref path, SpecialEndpoint::None, Some(ref referer)) if referer.app_id == apps::WEB_PATH && has_dapp(apps::WEB_PATH) && !is_web_endpoint(path) => { - trace!(target: "dapps", "Redirecting to correct web request: {:?}", referer_url); - let len = cmp::min(referer_url.path.len(), 2); // /web// - let base = referer_url.path[..len].join("/"); - let requested = url.map(|u| u.path.join("/")).unwrap_or_default(); - Some(handlers::Redirection::boxed(&format!("/{}/{}", base, requested))) + let token = referer.app_params.get(0).map(String::as_str).unwrap_or(""); + let requested = req.uri().path(); + let query = req.uri().query().map_or_else(String::new, |query| format!("?{}", query)); + let redirect_url = format!("/{}/{}{}{}", apps::WEB_PATH, token, requested, query); + trace!(target: "dapps", "Redirecting to correct web request: {:?}", redirect_url); + Response::Some(Box::new(future::ok( + handlers::Redirection::new(redirect_url).into() + ))) }, // First check special endpoints (ref path, ref endpoint, _) if self.special.contains_key(endpoint) => { trace!(target: "dapps", "Resolving to special endpoint."); - self.special.get(endpoint) - .expect("special known to contain key; qed") - .as_ref() - .map(|special| special.to_async_handler(path.clone().unwrap_or_default(), control)) + let special = self.special.get(endpoint).expect("special known to contain key; qed"); + match *special { + Some(ref special) => Response::Some(special.respond(path.clone().unwrap_or_default(), req)), + None => Response::None(req), + } }, // Then delegate to dapp (Some(ref path), _, _) if has_dapp(&path.app_id) => { trace!(target: "dapps", "Resolving to local/builtin dapp."); - Some(self.endpoints + Response::Some(self.endpoints .as_ref() .expect("endpoints known to be set; qed") .endpoints .read() .get(&path.app_id) .expect("endpoints known to contain key; qed") - .to_async_handler(path.clone(), control)) + .respond(path.clone(), req)) }, // Try to resolve and fetch the dapp (Some(ref path), _, _) if self.fetch.contains(&path.app_id) => { trace!(target: "dapps", "Resolving to fetchable content."); - Some(self.fetch.to_async_handler(path.clone(), control)) + Response::Some(self.fetch.respond(path.clone(), req)) }, // 404 for non-existent content (only if serving endpoints and not homepage) (Some(ref path), _, _) @@ -117,45 +125,51 @@ impl Router { if refresh_dapps { debug!(target: "dapps", "Refreshing dapps and re-trying."); self.endpoints.as_ref().map(|endpoints| endpoints.refresh_local_dapps()); - return self.resolve_request(req, control, false) + return self.resolve_request(req, false); } else { - Some(Box::new(handlers::ContentHandler::error( + Response::Some(Box::new(future::ok(handlers::ContentHandler::error( hyper::StatusCode::NotFound, "404 Not Found", "Requested content was not found.", None, self.embeddable_on.clone(), - ))) + ).into()))) } }, // Any other GET|HEAD requests to home page. _ if (is_get_request || is_head_request) && self.special.contains_key(&SpecialEndpoint::Home) => { - self.special.get(&SpecialEndpoint::Home) - .expect("special known to contain key; qed") - .as_ref() - .map(|special| special.to_async_handler(Default::default(), control)) + trace!(target: "dapps", "Resolving to home page."); + let special = self.special.get(&SpecialEndpoint::Home).expect("special known to contain key; qed"); + match *special { + Some(ref special) => { + let mut endpoint = EndpointPath::default(); + endpoint.app_params = req.uri().path().split('/').map(str::to_owned).collect(); + Response::Some(special.respond(endpoint, req)) + }, + None => Response::None(req), + } }, // RPC by default _ => { trace!(target: "dapps", "Resolving to RPC call."); - None + Response::None(req) } }) } } impl http::RequestMiddleware for Router { - fn on_request(&self, req: &server::Request, control: &Control) -> http::RequestMiddlewareAction { - let control = control.clone(); + fn on_request(&self, req: hyper::Request) -> http::RequestMiddlewareAction { let is_origin_set = req.headers().get::().is_some(); - let (is_utils, handler) = self.resolve_request(req, control, self.endpoints.is_some()); - match handler { - Some(handler) => http::RequestMiddlewareAction::Respond { + let (is_utils, response) = self.resolve_request(req, self.endpoints.is_some()); + match response { + Response::Some(response) => http::RequestMiddlewareAction::Respond { should_validate_hosts: !is_utils, - handler: handler, + response, }, - None => http::RequestMiddlewareAction::Proceed { + Response::None(request) => http::RequestMiddlewareAction::Proceed { should_continue_on_invalid_cors: !is_origin_set, + request, }, } } @@ -186,41 +200,44 @@ fn is_web_endpoint(path: &Option) -> bool { } } -fn extract_referer_endpoint(req: &server::Request, dapps_domain: &str) -> Option<(EndpointPath, Url)> { +fn extract_referer_endpoint(req: &hyper::Request, dapps_domain: &str) -> Option { let referer = req.headers().get::(); - let url = referer.and_then(|referer| Url::parse(&referer.0).ok()); + let url = referer.and_then(|referer| referer.parse().ok()); url.and_then(|url| { - let option = Some(url); - extract_url_referer_endpoint(&option, dapps_domain).or_else(|| { - extract_endpoint(&option, dapps_domain).0.map(|endpoint| (endpoint, option.expect("Just wrapped; qed"))) + extract_url_referer_endpoint(&url, dapps_domain).or_else(|| { + extract_endpoint(&url, None, dapps_domain).0 }) }) } -fn extract_url_referer_endpoint(url: &Option, dapps_domain: &str) -> Option<(EndpointPath, Url)> { - let query = url.as_ref().and_then(|url| url.query.as_ref()); - match (url, query) { - (&Some(ref url), Some(ref query)) if query.starts_with(apps::URL_REFERER) => { - let referer_url = format!("http://{}:{}/{}", url.host, url.port, &query[apps::URL_REFERER.len()..]); +fn extract_url_referer_endpoint(url: &Uri, dapps_domain: &str) -> Option { + let query = url.query(); + match query { + Some(query) if query.starts_with(apps::URL_REFERER) => { + let scheme = url.scheme().unwrap_or("http"); + let host = url.host().unwrap_or("unknown"); + let port = default_port(url, None); + let referer_url = format!("{}://{}:{}/{}", scheme, host, port, &query[apps::URL_REFERER.len()..]); debug!(target: "dapps", "Recovering referer from query parameter: {}", referer_url); - let referer_url = Url::parse(&referer_url).ok(); - extract_endpoint(&referer_url, dapps_domain).0.map(|endpoint| { - (endpoint, referer_url.expect("Endpoint returned only when url `is_some`").clone()) - }) + if let Some(referer_url) = referer_url.parse().ok() { + extract_endpoint(&referer_url, None, dapps_domain).0 + } else { + None + } }, _ => None, } } -fn extract_endpoint(url: &Option, dapps_domain: &str) -> (Option, SpecialEndpoint) { - fn special_endpoint(url: &Url) -> SpecialEndpoint { - if url.path.len() <= 1 { +fn extract_endpoint(url: &Uri, extra_host: Option<&header::Host>, dapps_domain: &str) -> (Option, SpecialEndpoint) { + fn special_endpoint(path: &[&str]) -> SpecialEndpoint { + if path.len() <= 1 { return SpecialEndpoint::None; } - match url.path[0].as_ref() { + match path[0].as_ref() { apps::RPC_PATH => SpecialEndpoint::Rpc, apps::API_PATH => SpecialEndpoint::Api, apps::UTILS_PATH => SpecialEndpoint::Utils, @@ -229,114 +246,162 @@ fn extract_endpoint(url: &Option, dapps_domain: &str) -> (Option match url.host { - Host::Domain(ref domain) if domain.ends_with(dapps_domain) => { - let id = &domain[0..(domain.len() - dapps_domain.len())]; - let (id, params) = if let Some(split) = id.rfind('.') { - let (params, id) = id.split_at(split); - (id[1..].to_owned(), [params.to_owned()].into_iter().chain(&url.path).cloned().collect()) - } else { - (id.to_owned(), url.path.clone()) - }; - - (Some(EndpointPath { - app_id: id, - app_params: params, - host: domain.clone(), - port: url.port, - using_dapps_domains: true, - }), special_endpoint(url)) - }, - _ if url.path.len() > 1 => { - let id = url.path[0].to_owned(); - (Some(EndpointPath { - app_id: id, - app_params: url.path[1..].to_vec(), - host: format!("{}", url.host), - port: url.port, - using_dapps_domains: false, - }), special_endpoint(url)) - }, - _ => (None, special_endpoint(url)), + let port = default_port(url, extra_host.as_ref().and_then(|h| h.port())); + let host = url.host().or_else(|| extra_host.as_ref().map(|h| h.hostname())); + let query = url.query().map(str::to_owned); + let mut path_segments = url.path().split('/').skip(1).collect::>(); + trace!( + target: "dapps", + "Extracting endpoint from: {:?} (dapps: {}). Got host {:?}:{} with path {:?}", + url, dapps_domain, host, port, path_segments + ); + match host { + Some(host) if host.ends_with(dapps_domain) => { + let id = &host[0..(host.len() - dapps_domain.len())]; + let special = special_endpoint(&path_segments); + + // remove special endpoint id from params + if special != SpecialEndpoint::None { + path_segments.remove(0); + } + + let (app_id, app_params) = if let Some(split) = id.rfind('.') { + let (params, id) = id.split_at(split); + path_segments.insert(0, params); + (id[1..].to_owned(), path_segments) + } else { + (id.to_owned(), path_segments) + }; + + (Some(EndpointPath { + app_id, + app_params: app_params.into_iter().map(Into::into).collect(), + query, + host: host.to_owned(), + port, + using_dapps_domains: true, + }), special) + }, + Some(host) if path_segments.len() > 1 => { + let special = special_endpoint(&path_segments); + let id = path_segments.remove(0); + (Some(EndpointPath { + app_id: id.to_owned(), + app_params: path_segments.into_iter().map(Into::into).collect(), + query, + host: host.to_owned(), + port, + using_dapps_domains: false, + }), special) }, - _ => (None, SpecialEndpoint::None) + _ => (None, special_endpoint(&path_segments)), } } -#[test] -fn should_extract_endpoint() { - let dapps_domain = ".web3.site"; - assert_eq!(extract_endpoint(&None, dapps_domain), (None, SpecialEndpoint::None)); - - // With path prefix - assert_eq!( - extract_endpoint(&Url::parse("http://localhost:8080/status/index.html").ok(), dapps_domain), - (Some(EndpointPath { - app_id: "status".to_owned(), - app_params: vec!["index.html".to_owned()], - host: "localhost".to_owned(), - port: 8080, - using_dapps_domains: false, - }), SpecialEndpoint::None) - ); +fn default_port(url: &Uri, extra_port: Option) -> u16 { + let scheme = url.scheme().unwrap_or("http"); + url.port().or(extra_port).unwrap_or_else(|| match scheme { + "http" => 80, + "https" => 443, + _ => 80, + }) +} - // With path prefix - assert_eq!( - extract_endpoint(&Url::parse("http://localhost:8080/rpc/").ok(), dapps_domain), - (Some(EndpointPath { - app_id: "rpc".to_owned(), - app_params: vec!["".to_owned()], - host: "localhost".to_owned(), - port: 8080, - using_dapps_domains: false, - }), SpecialEndpoint::Rpc) - ); +#[cfg(test)] +mod tests { + use super::{SpecialEndpoint, EndpointPath, extract_endpoint}; - assert_eq!( - extract_endpoint(&Url::parse("http://my.status.web3.site/parity-utils/inject.js").ok(), dapps_domain), - (Some(EndpointPath { - app_id: "status".to_owned(), - app_params: vec!["my".to_owned(), "parity-utils".into(), "inject.js".into()], - host: "my.status.web3.site".to_owned(), - port: 80, - using_dapps_domains: true, - }), SpecialEndpoint::Utils) - ); + #[test] + fn should_extract_endpoint() { + let dapps_domain = ".web3.site"; - // By Subdomain - assert_eq!( - extract_endpoint(&Url::parse("http://status.web3.site/test.html").ok(), dapps_domain), - (Some(EndpointPath { - app_id: "status".to_owned(), - app_params: vec!["test.html".to_owned()], - host: "status.web3.site".to_owned(), - port: 80, - using_dapps_domains: true, - }), SpecialEndpoint::None) - ); + // With path prefix + assert_eq!( + extract_endpoint(&"http://localhost:8080/status/index.html?q=1".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "status".to_owned(), + app_params: vec!["index.html".to_owned()], + query: Some("q=1".into()), + host: "localhost".to_owned(), + port: 8080, + using_dapps_domains: false, + }), SpecialEndpoint::None) + ); - // RPC by subdomain - assert_eq!( - extract_endpoint(&Url::parse("http://my.status.web3.site/rpc/").ok(), dapps_domain), - (Some(EndpointPath { - app_id: "status".to_owned(), - app_params: vec!["my".to_owned(), "rpc".into(), "".into()], - host: "my.status.web3.site".to_owned(), - port: 80, - using_dapps_domains: true, - }), SpecialEndpoint::Rpc) - ); + // With path prefix + assert_eq!( + extract_endpoint(&"http://localhost:8080/rpc/".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "rpc".to_owned(), + app_params: vec!["".to_owned()], + query: None, + host: "localhost".to_owned(), + port: 8080, + using_dapps_domains: false, + }), SpecialEndpoint::Rpc) + ); - // API by subdomain - assert_eq!( - extract_endpoint(&Url::parse("http://my.status.web3.site/api/").ok(), dapps_domain), - (Some(EndpointPath { - app_id: "status".to_owned(), - app_params: vec!["my".to_owned(), "api".into(), "".into()], - host: "my.status.web3.site".to_owned(), - port: 80, - using_dapps_domains: true, - }), SpecialEndpoint::Api) - ); + assert_eq!( + extract_endpoint(&"http://my.status.web3.site/parity-utils/inject.js".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "status".to_owned(), + app_params: vec!["my".into(), "inject.js".into()], + query: None, + host: "my.status.web3.site".to_owned(), + port: 80, + using_dapps_domains: true, + }), SpecialEndpoint::Utils) + ); + + assert_eq!( + extract_endpoint(&"http://my.status.web3.site/inject.js".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "status".to_owned(), + app_params: vec!["my".into(), "inject.js".into()], + query: None, + host: "my.status.web3.site".to_owned(), + port: 80, + using_dapps_domains: true, + }), SpecialEndpoint::None) + ); + + // By Subdomain + assert_eq!( + extract_endpoint(&"http://status.web3.site/test.html".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "status".to_owned(), + app_params: vec!["test.html".to_owned()], + query: None, + host: "status.web3.site".to_owned(), + port: 80, + using_dapps_domains: true, + }), SpecialEndpoint::None) + ); + + // RPC by subdomain + assert_eq!( + extract_endpoint(&"http://my.status.web3.site/rpc/".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "status".to_owned(), + app_params: vec!["my".into(), "".into()], + query: None, + host: "my.status.web3.site".to_owned(), + port: 80, + using_dapps_domains: true, + }), SpecialEndpoint::Rpc) + ); + + // API by subdomain + assert_eq!( + extract_endpoint(&"http://my.status.web3.site/api/".parse().unwrap(), None, dapps_domain), + (Some(EndpointPath { + app_id: "status".to_owned(), + app_params: vec!["my".into(), "".into()], + query: None, + host: "my.status.web3.site".to_owned(), + port: 80, + using_dapps_domains: true, + }), SpecialEndpoint::Api) + ); + } } diff --git a/dapps/src/tests/api.rs b/dapps/src/tests/api.rs index b75cd25f29e226d964d21f3e6b157fe30e19efdc..3ae3f7cbbf88da4febf11e689c13f2ecb845d6cc 100644 --- a/dapps/src/tests/api.rs +++ b/dapps/src/tests/api.rs @@ -49,6 +49,7 @@ fn should_handle_ping() { "\ POST /api/ping HTTP/1.1\r\n\ Host: home.parity\r\n\ + Content-Type: application/json\r\n\ Connection: close\r\n\ \r\n\ {} diff --git a/dapps/src/tests/fetch.rs b/dapps/src/tests/fetch.rs index f123231554c86e97e923750ab16bfea99ef602c9..59eeaf8d662e6fcef7df2a3d3197845609dac380 100644 --- a/dapps/src/tests/fetch.rs +++ b/dapps/src/tests/fetch.rs @@ -18,7 +18,7 @@ use devtools::http_client; use rustc_hex::FromHex; use tests::helpers::{ serve_with_registrar, serve_with_registrar_and_sync, serve_with_fetch, - serve_with_registrar_and_fetch, serve_with_registrar_and_fetch_and_threads, + serve_with_registrar_and_fetch, request, assert_security_headers_for_embed, }; @@ -166,26 +166,31 @@ 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

Hello Gavcoin!

-"# +0 + +"#), + "Expected Gavcoin body: {}", + response1.body ); response2.assert_status("HTTP/1.1 200 OK"); assert_security_headers_for_embed(&response2.headers); assert_eq!( response2.body, - r#"BE + r#"EA { "id": "9c94e154dab8acf859b30ee80fc828fb1d38359d938751b65db71d460588d82a", "name": "Gavcoin", "description": "Gavcoin", "version": "1.0.0", "author": "", - "iconUrl": "icon.png" + "iconUrl": "icon.png", + "localUrl": null, + "allowJsEval": false } 0 @@ -257,7 +262,7 @@ fn should_not_request_content_twice() { use std::thread; // given - let (server, fetch, registrar) = serve_with_registrar_and_fetch_and_threads(true); + let (server, fetch, registrar) = serve_with_registrar_and_fetch(); let gavcoin = GAVCOIN_ICON.from_hex().unwrap(); registrar.set_result( "2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e".parse().unwrap(), diff --git a/dapps/src/tests/helpers/fetch.rs b/dapps/src/tests/helpers/fetch.rs index e6e875c51441c5853fbedb24115afc58ec50bbc6..dfe523200e45e06005b49cc47c95b5af874a57c0 100644 --- a/dapps/src/tests/helpers/fetch.rs +++ b/dapps/src/tests/helpers/fetch.rs @@ -14,12 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::{io, thread, time}; +use std::{thread, time}; use std::sync::{atomic, mpsc, Arc}; -use util::Mutex; +use parking_lot::Mutex; +use hyper; use futures::{self, Future}; -use fetch::{self, Fetch}; +use fetch::{self, Fetch, Url}; pub struct FetchControl { sender: mpsc::Sender<()>, @@ -94,13 +95,10 @@ impl FakeFetch { } impl Fetch for FakeFetch { - type Result = futures::BoxFuture; + type Result = Box + Send>; - fn new() -> Result where Self: Sized { - Ok(FakeFetch::default()) - } - - fn fetch_with_abort(&self, url: &str, _abort: fetch::Abort) -> Self::Result { + fn fetch(&self, url: &str, abort: fetch::Abort) -> Self::Result { + let u = Url::parse(url).unwrap(); self.requested.lock().push(url.into()); let manual = self.manual.clone(); let response = self.response.clone(); @@ -111,12 +109,10 @@ impl Fetch for FakeFetch { // wait for manual resume let _ = rx.recv(); } - let data = response.lock().take().unwrap_or(b"Some content"); - let cursor = io::Cursor::new(data); - tx.send(fetch::Response::from_reader(cursor)).unwrap(); + tx.send(fetch::Response::new(u, hyper::Response::new().with_body(data), abort)).unwrap(); }); - rx.map_err(|_| fetch::Error::Aborted).boxed() + Box::new(rx.map_err(|_| fetch::Error::Aborted)) } } diff --git a/dapps/src/tests/helpers/mod.rs b/dapps/src/tests/helpers/mod.rs index 6f4652351ab9c9381c8dc15e233d629cbda5422c..3a1311578c7c776c28e21c334a223981b7cf2d35 100644 --- a/dapps/src/tests/helpers/mod.rs +++ b/dapps/src/tests/helpers/mod.rs @@ -14,20 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::env; -use std::str; +use std::{env, io, str}; use std::net::SocketAddr; use std::path::{Path, PathBuf}; use std::sync::Arc; use env_logger::LogBuilder; use jsonrpc_core::IoHandler; use jsonrpc_http_server::{self as http, Host, DomainsValidation}; +use parity_reactor::Remote; use devtools::http_client; -use hash_fetch::urlhint::ContractClient; +use registrar::{RegistrarClient, Asynchronous}; use fetch::{Fetch, Client as FetchClient}; use node_health::{NodeHealth, TimeChecker, CpuPool}; -use parity_reactor::Remote; use {Middleware, SyncStatus, WebProxyTokens}; @@ -55,7 +54,7 @@ fn init_logger() { } } -pub fn init_server(process: F, io: IoHandler, remote: Remote) -> (Server, Arc) where +pub fn init_server(process: F, io: IoHandler) -> (Server, Arc) where F: FnOnce(ServerBuilder) -> ServerBuilder, B: Fetch, { @@ -64,11 +63,9 @@ pub fn init_server(process: F, io: IoHandler, remote: Remote) -> (Server, let mut dapps_path = env::temp_dir(); dapps_path.push("non-existent-dir-to-prevent-fs-files-from-loading"); - let server = process(ServerBuilder::new( - &dapps_path, registrar.clone(), remote, - )) - .signer_address(Some(("127.0.0.1".into(), SIGNER_PORT))) - .start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), io).unwrap(); + let mut builder = ServerBuilder::new(FetchClient::new().unwrap(), &dapps_path, registrar.clone()); + builder.signer_address = Some(("127.0.0.1".into(), SIGNER_PORT)); + let server = process(builder).start_unsecured_http(&"127.0.0.1:0".parse().unwrap(), io).unwrap(); ( server, registrar, @@ -76,34 +73,34 @@ pub fn init_server(process: F, io: IoHandler, remote: Remote) -> (Server, } pub fn serve_with_rpc(io: IoHandler) -> Server { - init_server(|builder| builder, io, Remote::new_sync()).0 + init_server(|builder| builder, io).0 } pub fn serve_hosts(hosts: Option>) -> Server { let hosts = hosts.map(|hosts| hosts.into_iter().map(Into::into).collect()); - init_server(|builder| builder.allowed_hosts(hosts.into()), Default::default(), Remote::new_sync()).0 + init_server(|mut builder| { + builder.allowed_hosts = hosts.into(); + builder + }, Default::default()).0 } pub fn serve_with_registrar() -> (Server, Arc) { - init_server(|builder| builder, Default::default(), Remote::new_sync()) + init_server(|builder| builder, Default::default()) } pub fn serve_with_registrar_and_sync() -> (Server, Arc) { - init_server(|builder| { - builder.sync_status(Arc::new(FakeSync(true))) - }, Default::default(), Remote::new_sync()) + init_server(|mut builder| { + builder.sync_status = Arc::new(FakeSync(true)); + builder + }, Default::default()) } pub fn serve_with_registrar_and_fetch() -> (Server, FakeFetch, Arc) { - serve_with_registrar_and_fetch_and_threads(false) -} - -pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (Server, FakeFetch, Arc) { let fetch = FakeFetch::default(); let f = fetch.clone(); let (server, reg) = init_server(move |builder| { builder.fetch(f.clone()) - }, Default::default(), if multi_threaded { Remote::new_thread_per_future() } else { Remote::new_sync() }); + }, Default::default()); (server, fetch, reg) } @@ -111,19 +108,25 @@ pub fn serve_with_registrar_and_fetch_and_threads(multi_threaded: bool) -> (Serv pub fn serve_with_fetch(web_token: &'static str, domain: &'static str) -> (Server, FakeFetch) { let fetch = FakeFetch::default(); let f = fetch.clone(); - let (server, _) = init_server(move |builder| { - builder - .fetch(f.clone()) - .web_proxy_tokens(Arc::new(move |token| { - if &token == web_token { Some(domain.into()) } else { None } - })) - }, Default::default(), Remote::new_sync()); + let (server, _) = init_server(move |mut builder| { + builder.web_proxy_tokens = Arc::new(move |token| { + if &token == web_token { Some(domain.into()) } else { None } + }); + builder.fetch(f.clone()) + }, Default::default()); (server, fetch) } pub fn serve() -> Server { - init_server(|builder| builder, Default::default(), Remote::new_sync()).0 + init_server(|builder| builder, Default::default()).0 +} + +pub fn serve_ui() -> Server { + init_server(|mut builder| { + builder.serve_ui = true; + builder + }, Default::default()).0 } pub fn request(server: Server, request: &str) -> http_client::Response { @@ -141,18 +144,18 @@ pub fn assert_security_headers_for_embed(headers: &[String]) { /// Webapps HTTP+RPC server build. pub struct ServerBuilder { dapps_path: PathBuf, - registrar: Arc, + registrar: Arc>, sync_status: Arc, web_proxy_tokens: Arc, signer_address: Option<(String, u16)>, allowed_hosts: DomainsValidation, - remote: Remote, - fetch: Option, + fetch: T, + serve_ui: bool, } impl ServerBuilder { /// Construct new dapps server - pub fn new>(dapps_path: P, registrar: Arc, remote: Remote) -> Self { + pub fn new>(fetch: FetchClient, dapps_path: P, registrar: Arc>) -> Self { ServerBuilder { dapps_path: dapps_path.as_ref().to_owned(), registrar: registrar, @@ -160,8 +163,8 @@ impl ServerBuilder { web_proxy_tokens: Arc::new(|_| None), signer_address: None, allowed_hosts: DomainsValidation::Disabled, - remote: remote, - fetch: None, + fetch: fetch, + serve_ui: false, } } } @@ -176,41 +179,14 @@ impl ServerBuilder { web_proxy_tokens: self.web_proxy_tokens, signer_address: self.signer_address, allowed_hosts: self.allowed_hosts, - remote: self.remote, - fetch: Some(fetch), + fetch: fetch, + serve_ui: self.serve_ui, } } - /// Change default sync status. - pub fn sync_status(mut self, status: Arc) -> Self { - self.sync_status = status; - self - } - - /// Change default web proxy tokens validator. - pub fn web_proxy_tokens(mut self, tokens: Arc) -> Self { - self.web_proxy_tokens = tokens; - self - } - - /// Change default signer port. - pub fn signer_address(mut self, signer_address: Option<(String, u16)>) -> Self { - self.signer_address = signer_address; - self - } - - /// Change allowed hosts. - /// `None` - All hosts are allowed - /// `Some(whitelist)` - Allow only whitelisted hosts (+ listen address) - pub fn allowed_hosts(mut self, allowed_hosts: DomainsValidation) -> Self { - self.allowed_hosts = allowed_hosts; - self - } - /// Asynchronously start server with no authentication, /// returns result with `Server` handle on success or an error. - pub fn start_unsecured_http(self, addr: &SocketAddr, io: IoHandler) -> Result { - let fetch = self.fetch_client(); + pub fn start_unsecured_http(self, addr: &SocketAddr, io: IoHandler) -> io::Result { Server::start_http( addr, io, @@ -221,17 +197,11 @@ impl ServerBuilder { self.registrar, self.sync_status, self.web_proxy_tokens, - self.remote, - fetch, + Remote::new_sync(), + self.fetch, + self.serve_ui, ) } - - fn fetch_client(&self) -> T { - match self.fetch.clone() { - Some(fetch) => fetch, - None => T::new().unwrap(), - } - } } const DAPPS_DOMAIN: &'static str = "web3.site"; @@ -249,34 +219,47 @@ impl Server { signer_address: Option<(String, u16)>, dapps_path: PathBuf, extra_dapps: Vec, - registrar: Arc, + registrar: Arc>, sync_status: Arc, web_proxy_tokens: Arc, remote: Remote, fetch: F, - ) -> Result { + serve_ui: bool, + ) -> io::Result { let health = NodeHealth::new( sync_status.clone(), TimeChecker::new::(&[], CpuPool::new(1)), remote.clone(), ); - let middleware = Middleware::dapps( - health, - remote, - signer_address, - vec![], - vec![], - dapps_path, - extra_dapps, - DAPPS_DOMAIN.into(), - registrar, - sync_status, - web_proxy_tokens, - fetch, - ); + let pool = ::futures_cpupool::CpuPool::new(1); + let middleware = if serve_ui { + Middleware::ui( + pool, + health, + DAPPS_DOMAIN.into(), + registrar, + sync_status, + fetch, + ) + } else { + Middleware::dapps( + pool, + health, + signer_address, + vec![], + vec![], + dapps_path, + extra_dapps, + DAPPS_DOMAIN.into(), + registrar, + sync_status, + web_proxy_tokens, + fetch, + ) + }; let mut allowed_hosts: Option> = allowed_hosts.into(); - allowed_hosts.as_mut().map(|mut hosts| { + allowed_hosts.as_mut().map(|hosts| { hosts.push(format!("http://*.{}:*", DAPPS_DOMAIN).into()); hosts.push(format!("http://*.{}", DAPPS_DOMAIN).into()); }); @@ -295,9 +278,7 @@ impl Server { pub fn addr(&self) -> &SocketAddr { self.server.as_ref() .expect("server is always Some at the start; it's consumed only when object is dropped; qed") - .addrs() - .first() - .expect("You cannot start the server without binding to at least one address; qed") + .address() } } diff --git a/dapps/src/tests/helpers/registrar.rs b/dapps/src/tests/helpers/registrar.rs index d7890675b9341a1bb9bff8d3e8bbd3c9c5e24a3b..8668d43b131be00076ca0fb4e984cd69d1c22d09 100644 --- a/dapps/src/tests/helpers/registrar.rs +++ b/dapps/src/tests/helpers/registrar.rs @@ -17,10 +17,12 @@ use std::str; use std::sync::Arc; use std::collections::HashMap; -use rustc_hex::FromHex; -use hash_fetch::urlhint::ContractClient; -use util::{Bytes, Address, Mutex, H256, ToPretty}; +use ethereum_types::{H256, Address}; +use bytes::{Bytes, ToPretty}; +use registrar::{RegistrarClient, Asynchronous}; +use parking_lot::Mutex; +use rustc_hex::FromHex; const REGISTRAR: &'static str = "8e4e9b13d4b45cb0befc93c3061b1408f67316b2"; const URLHINT: &'static str = "deadbeefcafe0000000000000000000000000000"; @@ -59,12 +61,14 @@ impl FakeRegistrar { } } -impl ContractClient for FakeRegistrar { - fn registrar(&self) -> Result { +impl RegistrarClient for FakeRegistrar { + type Call = Asynchronous; + + fn registrar_address(&self) -> Result { Ok(REGISTRAR.parse().unwrap()) } - fn call(&self, address: Address, data: Bytes) -> ::futures::BoxFuture { + fn call_contract(&self, address: Address, data: Bytes) -> Self::Call { let call = (address.to_hex(), data.to_hex()); self.calls.lock().push(call.clone()); let res = self.responses.lock().get(&call).cloned().expect(&format!("No response for call: {:?}", call)); diff --git a/dapps/src/tests/home.rs b/dapps/src/tests/home.rs new file mode 100644 index 0000000000000000000000000000000000000000..0ee0653648220ca5211078bd5af9039820fc129c --- /dev/null +++ b/dapps/src/tests/home.rs @@ -0,0 +1,91 @@ +// 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 . + +use tests::helpers::{serve_ui, request, assert_security_headers}; + +#[test] +fn should_serve_home_js() { + // given + let server = serve_ui(); + + // when + let response = request(server, + "\ + GET /inject.js 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", "application/javascript"); + assert_eq!(response.body.contains("function(){"), true, "Expected function in: {}", response.body); + assert_security_headers(&response.headers); +} + +#[test] +fn should_serve_home() { + // 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_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">"#), + true, + "Expected inject script tag in: {}", + response.body + ); + assert_security_headers(&response.headers); +} diff --git a/dapps/src/tests/mod.rs b/dapps/src/tests/mod.rs index 089318483ac15e10022653f8ada6d5d0fda7bae9..a47294392ea8e1b5b9f2df39c2681a7f8b9f7132 100644 --- a/dapps/src/tests/mod.rs +++ b/dapps/src/tests/mod.rs @@ -20,6 +20,7 @@ mod helpers; mod api; mod fetch; +mod home; mod redirection; mod rpc; mod validation; diff --git a/dapps/src/tests/redirection.rs b/dapps/src/tests/redirection.rs index 81d3ec76cc8d7e8c737f943813418fde66cdfffc..b7f72009f72f987394d53960aad62a6079e02f09 100644 --- a/dapps/src/tests/redirection.rs +++ b/dapps/src/tests/redirection.rs @@ -201,6 +201,7 @@ fn should_serve_utils() { // then response.assert_status("HTTP/1.1 200 OK"); - assert_eq!(response.body.contains("function(){"), true); + response.assert_header("Content-Type", "application/javascript"); + assert_eq!(response.body.contains("function(){"), true, "Expected function in: {}", response.body); assert_security_headers(&response.headers); } diff --git a/dapps/src/tests/validation.rs b/dapps/src/tests/validation.rs index fb68cf5ed832ac0f162ad97d43c000ee7375b42a..bd97c940a04c67f38cc89f125741462d5e688f66 100644 --- a/dapps/src/tests/validation.rs +++ b/dapps/src/tests/validation.rs @@ -33,7 +33,7 @@ fn should_reject_invalid_host() { ); // then - assert_eq!(response.status, "HTTP/1.1 403 Forbidden".to_owned()); + response.assert_status("HTTP/1.1 403 Forbidden"); assert!(response.body.contains("Provided Host header is not whitelisted."), response.body); } @@ -54,7 +54,7 @@ fn should_allow_valid_host() { ); // then - assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + response.assert_status("HTTP/1.1 200 OK"); } #[test] @@ -74,7 +74,7 @@ fn should_serve_dapps_domains() { ); // then - assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + response.assert_status("HTTP/1.1 200 OK"); } #[test] @@ -95,5 +95,5 @@ fn should_allow_parity_utils_even_on_invalid_domain() { ); // then - assert_eq!(response.status, "HTTP/1.1 200 OK".to_owned()); + response.assert_status("HTTP/1.1 200 OK"); } diff --git a/dapps/src/url.rs b/dapps/src/url.rs deleted file mode 100644 index 23dbfb4fcc3043380def50f963a81a49277d98bf..0000000000000000000000000000000000000000 --- a/dapps/src/url.rs +++ /dev/null @@ -1,150 +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/HTTPS URL type. Based on URL type from Iron library. - -use url_lib::{self}; -pub use url_lib::Host; - -/// HTTP/HTTPS URL type for Iron. -#[derive(PartialEq, Eq, Clone, Debug)] -pub struct Url { - /// Raw url of url - pub raw: url_lib::Url, - - /// The host field of the URL, probably a domain. - pub host: Host, - - /// The connection port. - pub port: u16, - - /// The URL path, the resource to be accessed. - /// - /// A *non-empty* vector encoding the parts of the URL path. - /// Empty entries of `""` correspond to trailing slashes. - pub path: Vec, - - /// The URL query. - pub query: Option, - - /// The URL username field, from the userinfo section of the URL. - /// - /// `None` if the `@` character was not part of the input OR - /// if a blank username was provided. - /// Otherwise, a non-empty string. - pub username: Option, - - /// The URL password field, from the userinfo section of the URL. - /// - /// `None` if the `@` character was not part of the input OR - /// if a blank password was provided. - /// Otherwise, a non-empty string. - pub password: Option, -} - -impl Url { - /// Create a URL from a string. - /// - /// The input must be a valid URL with a special scheme for this to succeed. - /// - /// HTTP and HTTPS are special schemes. - /// - /// See: http://url.spec.whatwg.org/#special-scheme - pub fn parse(input: &str) -> Result { - // Parse the string using rust-url, then convert. - match url_lib::Url::parse(input) { - Ok(raw_url) => Url::from_generic_url(raw_url), - Err(e) => Err(format!("{}", e)) - } - } - - /// Create a `Url` from a `rust-url` `Url`. - pub fn from_generic_url(raw_url: url_lib::Url) -> Result { - // Map empty usernames to None. - let username = match raw_url.username() { - "" => None, - username => Some(username.to_owned()) - }; - - // Map empty passwords to None. - let password = match raw_url.password() { - Some(password) if !password.is_empty() => Some(password.to_owned()), - _ => None, - }; - - let port = raw_url.port_or_known_default().ok_or_else(|| format!("Unknown port for scheme: `{}`", raw_url.scheme()))?; - let host = raw_url.host().ok_or_else(|| "Valid host, because only data:, mailto: protocols does not have host.".to_owned())?.to_owned(); - let path = raw_url.path_segments().ok_or_else(|| "Valid path segments. In HTTP we won't get cannot-be-a-base URLs".to_owned())? - .map(|part| part.to_owned()).collect(); - let query = raw_url.query().map(|x| x.to_owned()); - - Ok(Url { - port: port, - host: host, - path: path, - query: query, - raw: raw_url, - username: username, - password: password, - }) - } -} - -#[cfg(test)] -mod test { - use super::Url; - - #[test] - fn test_default_port() { - assert_eq!(Url::parse("http://example.com/wow").unwrap().port, 80u16); - assert_eq!(Url::parse("https://example.com/wow").unwrap().port, 443u16); - } - - #[test] - fn test_explicit_port() { - assert_eq!(Url::parse("http://localhost:3097").unwrap().port, 3097u16); - } - - #[test] - fn test_empty_username() { - assert!(Url::parse("http://@example.com").unwrap().username.is_none()); - assert!(Url::parse("http://:password@example.com").unwrap().username.is_none()); - } - - #[test] - fn test_not_empty_username() { - let user = Url::parse("http://john:pass@example.com").unwrap().username; - assert_eq!(user.unwrap(), "john"); - - let user = Url::parse("http://john:@example.com").unwrap().username; - assert_eq!(user.unwrap(), "john"); - } - - #[test] - fn test_empty_password() { - assert!(Url::parse("http://michael@example.com").unwrap().password.is_none()); - assert!(Url::parse("http://:@example.com").unwrap().password.is_none()); - } - - #[test] - fn test_not_empty_password() { - let pass = Url::parse("http://michael:pass@example.com").unwrap().password; - assert_eq!(pass.unwrap(), "pass"); - - let pass = Url::parse("http://:pass@example.com").unwrap().password; - assert_eq!(pass.unwrap(), "pass"); - } -} diff --git a/dapps/src/web.rs b/dapps/src/web.rs index 5222f51b5ba1b22d4ab5a46a7602cfc2c637a1e1..86c0ac28d6c8d01bae482f60e2df36bfa69a3942 100644 --- a/dapps/src/web.rs +++ b/dapps/src/web.rs @@ -17,119 +17,55 @@ //! Serving web-based content (proxying) use std::sync::Arc; -use fetch::{self, Fetch}; -use parity_reactor::Remote; use base32; -use hyper::{self, server, net, Next, Encoder, Decoder}; -use hyper::status::StatusCode; +use fetch::{self, Fetch}; +use hyper::{mime, StatusCode}; use apps; -use endpoint::{Endpoint, Handler, EndpointPath}; +use endpoint::{Endpoint, EndpointPath, Request, Response}; +use futures::future; +use futures_cpupool::CpuPool; use handlers::{ ContentFetcherHandler, ContentHandler, ContentValidator, ValidatorResponse, - StreamingHandler, extract_url, + StreamingHandler, }; -use url::Url; use {Embeddable, WebProxyTokens}; pub struct Web { embeddable_on: Embeddable, web_proxy_tokens: Arc, - remote: Remote, fetch: F, + pool: CpuPool, } impl Web { pub fn boxed( embeddable_on: Embeddable, web_proxy_tokens: Arc, - remote: Remote, fetch: F, + pool: CpuPool, ) -> Box { Box::new(Web { embeddable_on, web_proxy_tokens, - remote, fetch, + pool, }) } -} - -impl Endpoint for Web { - fn to_async_handler(&self, path: EndpointPath, control: hyper::Control) -> Box { - Box::new(WebHandler { - control: control, - state: State::Initial, - path: path, - remote: self.remote.clone(), - fetch: self.fetch.clone(), - web_proxy_tokens: self.web_proxy_tokens.clone(), - embeddable_on: self.embeddable_on.clone(), - }) - } -} - -struct WebInstaller { - embeddable_on: Embeddable, - referer: String, -} - -impl ContentValidator for WebInstaller { - type Error = String; - - fn validate_and_install(&self, response: fetch::Response) -> Result { - let status = StatusCode::from_u16(response.status().to_u16()); - let is_html = response.is_html(); - let mime = response.content_type().unwrap_or(mime!(Text/Html)); - let mut handler = StreamingHandler::new( - response, - status, - mime, - self.embeddable_on.clone(), - ); - if is_html { - handler.set_initial_content(&format!( - r#""#, - apps::UTILS_PATH, - apps::URL_REFERER, - apps::WEB_PATH, - &self.referer, - )); - } - Ok(ValidatorResponse::Streaming(handler)) - } -} - -enum State { - Initial, - Error(ContentHandler), - Fetching(ContentFetcherHandler), -} - -struct WebHandler { - control: hyper::Control, - state: State, - path: EndpointPath, - remote: Remote, - fetch: F, - web_proxy_tokens: Arc, - embeddable_on: Embeddable, -} -impl WebHandler { - fn extract_target_url(&self, url: Option) -> Result> { - let token_and_url = self.path.app_params.get(0) + fn extract_target_url(&self, path: &EndpointPath) -> Result { + let token_and_url = path.app_params.get(0) .map(|encoded| encoded.replace('.', "")) .and_then(|encoded| base32::decode(base32::Alphabet::Crockford, &encoded.to_uppercase())) .and_then(|data| String::from_utf8(data).ok()) - .ok_or_else(|| State::Error(ContentHandler::error( + .ok_or_else(|| ContentHandler::error( StatusCode::BadRequest, "Invalid parameter", "Couldn't parse given parameter:", - self.path.app_params.get(0).map(String::as_str), + path.app_params.get(0).map(String::as_str), self.embeddable_on.clone() - )))?; + ))?; let mut token_it = token_and_url.split('+'); let token = token_it.next(); @@ -139,9 +75,9 @@ impl WebHandler { let domain = match token.and_then(|token| self.web_proxy_tokens.domain(token)) { Some(domain) => domain, _ => { - return Err(State::Error(ContentHandler::error( + return Err(ContentHandler::error( StatusCode::BadRequest, "Invalid Access Token", "Invalid or old web proxy access token supplied.", Some("Try refreshing the page."), self.embeddable_on.clone() - ))); + )); } }; @@ -149,95 +85,87 @@ impl WebHandler { let mut target_url = match target_url { Some(url) if url.starts_with("http://") || url.starts_with("https://") => url.to_owned(), _ => { - return Err(State::Error(ContentHandler::error( + return Err(ContentHandler::error( StatusCode::BadRequest, "Invalid Protocol", "Invalid protocol used.", None, self.embeddable_on.clone() - ))); + )); } }; if !target_url.starts_with(&*domain) { - return Err(State::Error(ContentHandler::error( + return Err(ContentHandler::error( StatusCode::BadRequest, "Invalid Domain", "Dapp attempted to access invalid domain.", Some(&target_url), self.embeddable_on.clone(), - ))); + )); } if !target_url.ends_with("/") { target_url = format!("{}/", target_url); } - // TODO [ToDr] Should just use `path.app_params` - let (path, query) = match (&url, self.path.using_dapps_domains) { - (&Some(ref url), true) => (&url.path[..], &url.query), - (&Some(ref url), false) => (&url.path[2..], &url.query), - _ => { - return Err(State::Error(ContentHandler::error( - StatusCode::BadRequest, "Invalid URL", "Couldn't parse URL", None, self.embeddable_on.clone() - ))); - } - }; - - let query = match *query { - Some(ref query) => format!("?{}", query), - None => "".into(), - }; + // Skip the token + let query = path.query.as_ref().map_or_else(String::new, |query| format!("?{}", query)); + let path = path.app_params[1..].join("/"); - Ok(format!("{}{}{}", target_url, path.join("/"), query)) + Ok(format!("{}{}{}", target_url, path, query)) } } -impl server::Handler for WebHandler { - fn on_request(&mut self, request: server::Request) -> Next { - let url = extract_url(&request); +impl Endpoint for Web { + fn respond(&self, path: EndpointPath, req: Request) -> Response { // First extract the URL (reject invalid URLs) - let target_url = match self.extract_target_url(url) { + let target_url = match self.extract_target_url(&path) { Ok(url) => url, - Err(error) => { - self.state = error; - return Next::write(); + Err(response) => { + return Box::new(future::ok(response.into())); } }; - let mut handler = ContentFetcherHandler::new( - target_url, - self.path.clone(), - self.control.clone(), + let token = path.app_params.get(0) + .expect("`target_url` is valid; app_params is not empty;qed") + .to_owned(); + + Box::new(ContentFetcherHandler::new( + req.method(), + &target_url, + path, WebInstaller { embeddable_on: self.embeddable_on.clone(), - referer: self.path.app_params.get(0) - .expect("`target_url` is valid; app_params is not empty;qed") - .to_owned(), + token, }, self.embeddable_on.clone(), - self.remote.clone(), self.fetch.clone(), - ); - let res = handler.on_request(request); - self.state = State::Fetching(handler); - - res + self.pool.clone(), + )) } +} - fn on_request_readable(&mut self, decoder: &mut Decoder) -> Next { - match self.state { - State::Initial => Next::end(), - State::Error(ref mut handler) => handler.on_request_readable(decoder), - State::Fetching(ref mut handler) => handler.on_request_readable(decoder), - } - } +struct WebInstaller { + embeddable_on: Embeddable, + token: String, +} - fn on_response(&mut self, res: &mut server::Response) -> Next { - match self.state { - State::Initial => Next::end(), - State::Error(ref mut handler) => handler.on_response(res), - State::Fetching(ref mut handler) => handler.on_response(res), - } - } +impl ContentValidator for WebInstaller { + type Error = String; - fn on_response_writable(&mut self, encoder: &mut Encoder) -> Next { - match self.state { - State::Initial => Next::end(), - State::Error(ref mut handler) => handler.on_response_writable(encoder), - State::Fetching(ref mut handler) => handler.on_response_writable(encoder), + fn validate_and_install(self, response: fetch::Response) -> Result { + let status = response.status(); + let is_html = response.is_html(); + let mime = response.content_type().unwrap_or(mime::TEXT_HTML); + let mut handler = StreamingHandler::new( + fetch::BodyReader::new(response), + status, + mime, + self.embeddable_on, + ); + if is_html { + handler.set_initial_content(&format!( + r#""#, + apps::UTILS_PATH, + apps::URL_REFERER, + apps::WEB_PATH, + &self.token, + )); } + Ok(ValidatorResponse::Streaming(handler)) } } + diff --git a/dapps/ui/Cargo.toml b/dapps/ui/Cargo.toml index 41763b14dc96876e260b369ca8b5fca4b511d7fd..e7f409b1c1cdadefd7abc1e1d2984a4c9c44df23 100644 --- a/dapps/ui/Cargo.toml +++ b/dapps/ui/Cargo.toml @@ -3,17 +3,18 @@ description = "Ethcore Parity UI" homepage = "http://parity.io" license = "GPL-3.0" name = "parity-ui" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] [build-dependencies] -rustc_version = "0.1" +rustc_version = "0.2" [dependencies] -parity-ui-dev = { path = "../../js", optional = true } -# This is managed by the js/scripts/release.sh script on CI - keep it in a single line -parity-ui-precompiled = { git = "https://github.com/paritytech/js-precompiled.git", optional = true, branch = "master" } +parity-ui-dev = { git = "https://github.com/parity-js/shell.git", rev = "eecaadcb9e421bce31e91680d14a20bbd38f92a2", optional = true } +parity-ui-old-dev = { git = "https://github.com/parity-js/dapp-wallet.git", rev = "65deb02e7c007a0fd8aab0c089c93e3fd1de6f87", optional = true } +parity-ui-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-shell.git", rev="bd25b41cd642c6b822d820dded3aa601a29aa079", optional = true } +parity-ui-old-precompiled = { git = "https://github.com/js-dist-paritytech/parity-master-1-10-wallet.git", rev="4b6f112412716cd05123d32eeb7fda448288a6c6", optional = true } [features] -no-precompiled-js = ["parity-ui-dev"] -use-precompiled-js = ["parity-ui-precompiled"] +no-precompiled-js = ["parity-ui-dev", "parity-ui-old-dev"] +use-precompiled-js = ["parity-ui-precompiled", "parity-ui-old-precompiled"] diff --git a/dapps/ui/src/lib.rs b/dapps/ui/src/lib.rs index 931fd06beea804fade8392f6ad7a426b714e1fe8..aa1c86736668a09d325f1f91462c171a959ce265 100644 --- a/dapps/ui/src/lib.rs +++ b/dapps/ui/src/lib.rs @@ -29,5 +29,18 @@ mod inner { pub use self::parity_ui_precompiled::*; } +#[cfg(feature = "parity-ui-old-dev")] +pub mod old { + extern crate parity_ui_old_dev; + + pub use self::parity_ui_old_dev::*; +} + +#[cfg(feature = "parity-ui-old-precompiled")] +pub mod old { + extern crate parity_ui_old_precompiled; + + pub use self::parity_ui_old_precompiled::*; +} pub use self::inner::*; diff --git a/devtools/Cargo.toml b/devtools/Cargo.toml index faae037311342ec788d29c74bafb2ca203cfb3bf..d5e275a3adbcc8e857006883f3c68244ff48945f 100644 --- a/devtools/Cargo.toml +++ b/devtools/Cargo.toml @@ -3,14 +3,5 @@ description = "Ethcore development/test/build tools" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-devtools" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] - -[dependencies] -rand = "0.3" - -[features] - -[lib] -path = "src/lib.rs" -test = true diff --git a/devtools/src/http_client.rs b/devtools/src/http_client.rs index 078c33721c1a076b1cbfbb089507283e3dd35a42..ab234105929077c3d777e2b5ac37a733a2bfbe2c 100644 --- a/devtools/src/http_client.rs +++ b/devtools/src/http_client.rs @@ -16,7 +16,7 @@ use std::thread; use std::time::Duration; -use std::io::{Read, Write}; +use std::io::{self, Read, Write}; use std::str::{self, Lines}; use std::net::{TcpStream, SocketAddr}; @@ -83,9 +83,18 @@ pub fn request(address: &SocketAddr, request: &str) -> Response { req.set_read_timeout(Some(Duration::from_secs(2))).unwrap(); req.write_all(request.as_bytes()).unwrap(); - let mut response = String::new(); - let _ = req.read_to_string(&mut response); + let mut response = Vec::new(); + loop { + let mut chunk = [0; 32 *1024]; + match req.read(&mut chunk) { + Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break, + Err(err) => panic!("Unable to read response: {:?}", err), + Ok(0) => break, + Ok(read) => response.extend_from_slice(&chunk[..read]), + } + } + let response = String::from_utf8_lossy(&response).into_owned(); let mut lines = response.lines(); let status = lines.next().expect("Expected a response").to_owned(); let headers_raw = read_block(&mut lines, false); diff --git a/devtools/src/lib.rs b/devtools/src/lib.rs index 419f0d6428b12594068da2c1ec8ff127a04af4b3..efaf4b9351acb9e04e65e4eabcb68f9310925789 100644 --- a/devtools/src/lib.rs +++ b/devtools/src/lib.rs @@ -16,14 +16,4 @@ //! dev-tools - -extern crate rand; - -mod random_path; -mod test_socket; -mod stop_guard; pub mod http_client; - -pub use random_path::*; -pub use test_socket::*; -pub use stop_guard::*; diff --git a/devtools/src/random_path.rs b/devtools/src/random_path.rs deleted file mode 100644 index 9c399115b228531ce9210c8f8e07a979121416e1..0000000000000000000000000000000000000000 --- a/devtools/src/random_path.rs +++ /dev/null @@ -1,148 +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 . - -//! Random path - -use std::path::*; -use std::fs; -use std::env; -use std::ops::{Deref, DerefMut}; -use rand::random; - -pub struct RandomTempPath { - path: PathBuf, - pub panic_on_drop_failure: bool, -} - -pub fn random_filename() -> String { - random_str(8) -} - -pub fn random_str(len: usize) -> String { - (0..len).map(|_| ((random::() * 26.0) as u8 + 97) as char).collect() -} - -impl RandomTempPath { - pub fn new() -> RandomTempPath { - let mut dir = env::temp_dir(); - dir.push(random_filename()); - RandomTempPath { - path: dir.clone(), - panic_on_drop_failure: true, - } - } - - pub fn create_dir() -> RandomTempPath { - let mut dir = env::temp_dir(); - dir.push(random_filename()); - fs::create_dir_all(dir.as_path()).unwrap(); - RandomTempPath { - path: dir.clone(), - panic_on_drop_failure: true, - } - } - - pub fn as_path(&self) -> &PathBuf { - &self.path - } - - pub fn as_str(&self) -> &str { - self.path.to_str().unwrap() - } - - pub fn new_in(&self, name: &str) -> String { - let mut path = self.path.clone(); - path.push(name); - path.to_str().unwrap().to_owned() - } -} - -impl AsRef for RandomTempPath { - fn as_ref(&self) -> &Path { - self.as_path() - } -} -impl Deref for RandomTempPath { - type Target = Path; - fn deref(&self) -> &Self::Target { - self.as_path() - } -} - -impl Drop for RandomTempPath { - fn drop(&mut self) { - if let Err(_) = fs::remove_dir_all(&self) { - if let Err(e) = fs::remove_file(&self) { - if self.panic_on_drop_failure { - panic!("Failed to remove temp directory. Here's what prevented this from happening: ({})", e); - } - } - } - } -} - -pub struct GuardedTempResult { - pub result: Option, - pub _temp: RandomTempPath, -} - -impl GuardedTempResult { - pub fn reference(&self) -> &T { - self.result.as_ref().unwrap() - } - - pub fn reference_mut(&mut self) -> &mut T { - self.result.as_mut().unwrap() - } - - pub fn take(&mut self) -> T { - self.result.take().unwrap() - } -} - -impl Deref for GuardedTempResult { - type Target = T; - - fn deref(&self) -> &T { self.result.as_ref().unwrap() } -} - -impl DerefMut for GuardedTempResult { - fn deref_mut(&mut self) -> &mut T { self.result.as_mut().unwrap() } -} - -#[test] -fn creates_dir() { - let temp = RandomTempPath::create_dir(); - assert!(fs::metadata(temp.as_path()).unwrap().is_dir()); -} - -#[test] -fn destroys_dir() { - let path_buf = { - let temp = RandomTempPath::create_dir(); - assert!(fs::metadata(temp.as_path()).unwrap().is_dir()); - let path_buf = temp.as_path().to_path_buf(); - path_buf - }; - - assert!(fs::metadata(&path_buf).is_err()); -} - -#[test] -fn provides_random() { - let temp = RandomTempPath::create_dir(); - assert!(temp.as_path().to_str().is_some()); -} diff --git a/devtools/src/test_socket.rs b/devtools/src/test_socket.rs deleted file mode 100644 index b5b0cefd3d9fcf96f4a3875a145f82bfbf8091d8..0000000000000000000000000000000000000000 --- a/devtools/src/test_socket.rs +++ /dev/null @@ -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 . - -use std::io::*; -use std::cmp; - -pub struct TestSocket { - pub read_buffer: Vec, - pub write_buffer: Vec, - pub cursor: usize, - pub buf_size: usize, -} - -impl Default for TestSocket { - fn default() -> Self { - TestSocket::new() - } -} - -impl TestSocket { - pub fn new() -> Self { - TestSocket { - read_buffer: vec![], - write_buffer: vec![], - cursor: 0, - buf_size: 0, - } - } - - pub fn new_buf(buf_size: usize) -> TestSocket { - TestSocket { - read_buffer: vec![], - write_buffer: vec![], - cursor: 0, - buf_size: buf_size, - } - } - - pub fn new_ready(data: Vec) -> TestSocket { - TestSocket { - read_buffer: data, - write_buffer: vec![], - cursor: 0, - buf_size: 0, - } - } -} - -impl Read for TestSocket { - fn read(&mut self, buf: &mut [u8]) -> Result { - let end_position = cmp::min(self.read_buffer.len(), self.cursor+buf.len()); - if self.cursor > end_position { return Ok(0) } - let len = cmp::max(end_position - self.cursor, 0); - match len { - 0 => Ok(0), - _ => { - for i in self.cursor..end_position { - buf[i-self.cursor] = self.read_buffer[i]; - } - self.cursor = end_position; - Ok(len) - } - } - } -} - -impl Write for TestSocket { - fn write(&mut self, buf: &[u8]) -> Result { - if self.buf_size == 0 || buf.len() < self.buf_size { - self.write_buffer.extend(buf.iter().cloned()); - Ok(buf.len()) - } - else { - self.write_buffer.extend(buf.iter().take(self.buf_size).cloned()); - Ok(self.buf_size) - } - } - - fn flush(&mut self) -> Result<()> { - unimplemented!(); - } -} diff --git a/docs/CHANGELOG-0.9.md b/docs/CHANGELOG-0.9.md new file mode 100644 index 0000000000000000000000000000000000000000..be61dd27242bba620fcd1b322113411dc0236f57 --- /dev/null +++ b/docs/CHANGELOG-0.9.md @@ -0,0 +1,228 @@ +Note: Parity 0.9 reached End-of-Life on 2016-05-02 (EOL). + +## Parity [beta-0.9.1](https://github.com/paritytech/parity/releases/tag/beta-0.9.1) (2016-02-16) + +Homestead transition block changed to 1100000. + +- Beta patch to 0.9.1 [#445](https://github.com/paritytech/parity/pull/445) +- Delay homestead transition [#430](https://github.com/paritytech/parity/pull/430) +- (BETA) https link in the installer (?) [#392](https://github.com/paritytech/parity/pull/392) +- beta: Check for handshake expiration before attempting replace [#377](https://github.com/paritytech/parity/pull/377) + +## Parity [beta-0.9](https://github.com/paritytech/parity/releases/tag/beta-0.9) (2016-02-08) + +First Parity Beta 0.9 released. + +- Panic on missing counters; Client cleanup [#368](https://github.com/paritytech/parity/pull/368) +- Update README for new PPAs. [#369](https://github.com/paritytech/parity/pull/369) +- block_queue::clear should be more thorough [#365](https://github.com/paritytech/parity/pull/365) +- Fixed an issue with forked counters [#363](https://github.com/paritytech/parity/pull/363) +- Install parity [#362](https://github.com/paritytech/parity/pull/362) +- DB directory versioning [#358](https://github.com/paritytech/parity/pull/358) +- Raise FD limit for MacOS [#357](https://github.com/paritytech/parity/pull/357) +- Travis slack integration. [#356](https://github.com/paritytech/parity/pull/356) +- SignedTransaction structure [#350](https://github.com/paritytech/parity/pull/350) +- License [#354](https://github.com/paritytech/parity/pull/354) +- Performance optimizations [#353](https://github.com/paritytech/parity/pull/353) +- Gitter in README. [#355](https://github.com/paritytech/parity/pull/355) +- test efforts, receipt requests [#352](https://github.com/paritytech/parity/pull/352) +- sync tests setup & local module coverage [#348](https://github.com/paritytech/parity/pull/348) +- install parity script [#347](https://github.com/paritytech/parity/pull/347) +- evmjit homestead merge [#342](https://github.com/paritytech/parity/pull/342) +- Fixed sync stalling on fork [#343](https://github.com/paritytech/parity/pull/343) +- Remerge 264 [#334](https://github.com/paritytech/parity/pull/334) +- Ethsync tests bfix [#339](https://github.com/paritytech/parity/pull/339) +- Fix default options. [#335](https://github.com/paritytech/parity/pull/335) +- sync queue limit hotfix [#338](https://github.com/paritytech/parity/pull/338) +- Network tests, separate local coverage for utils [#333](https://github.com/paritytech/parity/pull/333) +- fix parity version so netstats can parse it [#332](https://github.com/paritytech/parity/pull/332) +- reveal surprise [#331](https://github.com/paritytech/parity/pull/331) +- Revert removal of `new_code`. [#330](https://github.com/paritytech/parity/pull/330) +- Network mod tests first part [#329](https://github.com/paritytech/parity/pull/329) +- Look ma no `dead_code` [#323](https://github.com/paritytech/parity/pull/323) +- Fixing JIT, Updating hook to run `ethcore` tests. [#326](https://github.com/paritytech/parity/pull/326) +- Final docs [#327](https://github.com/paritytech/parity/pull/327) +- update install-deps.sh [#316](https://github.com/paritytech/parity/pull/316) +- Finish all my docs. Fix previous test compilation. [#320](https://github.com/paritytech/parity/pull/320) +- Additional evm tests (extops, call, jumps) and some docs [#317](https://github.com/paritytech/parity/pull/317) +- More documentation. [#318](https://github.com/paritytech/parity/pull/318) +- Additional documentation. [#315](https://github.com/paritytech/parity/pull/315) +- unused functions cleanup [#310](https://github.com/paritytech/parity/pull/310) +- update ethcore.github.io documentation automatically [#311](https://github.com/paritytech/parity/pull/311) +- Another try with travis ci credentials [#314](https://github.com/paritytech/parity/pull/314) +- Document some stuff. [#309](https://github.com/paritytech/parity/pull/309) +- Check block parent on import; Peer timeouts [#303](https://github.com/paritytech/parity/pull/303) +- Increasing coverage for evm. [#306](https://github.com/paritytech/parity/pull/306) +- ethcore docs [#301](https://github.com/paritytech/parity/pull/301) +- Replacing secure token for deployment [#305](https://github.com/paritytech/parity/pull/305) +- doc.sh [#299](https://github.com/paritytech/parity/pull/299) +- Building beta-* and stable-* tags [#302](https://github.com/paritytech/parity/pull/302) +- Deploying artifacts for tags (release/beta) [#300](https://github.com/paritytech/parity/pull/300) +- cov.sh to show coverage locally [#298](https://github.com/paritytech/parity/pull/298) +- benchmark fixes [#297](https://github.com/paritytech/parity/pull/297) +- Include JSONRPC CLI options. [#296](https://github.com/paritytech/parity/pull/296) +- travis.yml fixes [#293](https://github.com/paritytech/parity/pull/293) +- Improve version string. [#295](https://github.com/paritytech/parity/pull/295) +- Fixed block queue test [#294](https://github.com/paritytech/parity/pull/294) +- Util docs [#292](https://github.com/paritytech/parity/pull/292) +- fixed building docs [#289](https://github.com/paritytech/parity/pull/289) +- update travis to build PRs only against master [#290](https://github.com/paritytech/parity/pull/290) +- Coverage effort [#272](https://github.com/paritytech/parity/pull/272) +- updated docker containers [#288](https://github.com/paritytech/parity/pull/288) +- rpc module fixes [#287](https://github.com/paritytech/parity/pull/287) +- Test for Receipt RLP. [#282](https://github.com/paritytech/parity/pull/282) +- Building from source guide [#284](https://github.com/paritytech/parity/pull/284) +- Fixed neted empty list RLP encoding [#283](https://github.com/paritytech/parity/pull/283) +- Fix CALLDATACOPY (and bonus CODECOPY, too!). [#279](https://github.com/paritytech/parity/pull/279) +- added travis && coveralls badge to README.md [#280](https://github.com/paritytech/parity/pull/280) +- coveralls coverage [#277](https://github.com/paritytech/parity/pull/277) +- Travis [in progress] [#257](https://github.com/paritytech/parity/pull/257) +- Travis on reorganized repo [#276](https://github.com/paritytech/parity/pull/276) +- umbrella project [#275](https://github.com/paritytech/parity/pull/275) +- Ethash disk cache [#273](https://github.com/paritytech/parity/pull/273) +- Parity executable name and version [#274](https://github.com/paritytech/parity/pull/274) +- Dockerfile [#195](https://github.com/paritytech/parity/pull/195) +- Garbage collection test fix [#267](https://github.com/paritytech/parity/pull/267) +- Fix stCallCreateCallCodeTest, add more tests [#271](https://github.com/paritytech/parity/pull/271) +- Moved sync out of ethcore crate; Added block validation [#265](https://github.com/paritytech/parity/pull/265) +- RLP encoder refactoring [#252](https://github.com/paritytech/parity/pull/252) +- Chain sync tests and minor refactoring [#264](https://github.com/paritytech/parity/pull/264) +- Common log init function [#263](https://github.com/paritytech/parity/pull/263) +- changed max vm depth from 128 to 64, change homestead block to 1_000_000 [#262](https://github.com/paritytech/parity/pull/262) +- fixed blockchain tests crash on log init [#261](https://github.com/paritytech/parity/pull/261) +- Blockchain tests and some helpers for guarding temp directory [#256](https://github.com/paritytech/parity/pull/256) +- Fix logging and random tests. [#260](https://github.com/paritytech/parity/pull/260) +- Fix difficulty calculation algo. [#259](https://github.com/paritytech/parity/pull/259) +- fix submodule version [#258](https://github.com/paritytech/parity/pull/258) +- temp dir spawn refactoring [#246](https://github.com/paritytech/parity/pull/246) +- fixed tests submodule branch [#254](https://github.com/paritytech/parity/pull/254) +- rpc net methods returns real peer count && protocol version [#253](https://github.com/paritytech/parity/pull/253) +- Add homestead & random tests. [#245](https://github.com/paritytech/parity/pull/245) +- Fixing suicide with self-refund to be consistent with CPP. [#247](https://github.com/paritytech/parity/pull/247) +- stubs for rpc methods [#251](https://github.com/paritytech/parity/pull/251) +- clippy, missing docs, renaming etc. [#244](https://github.com/paritytech/parity/pull/244) +- impl missing methods in tests [#243](https://github.com/paritytech/parity/pull/243) +- General tests and some helpers [#239](https://github.com/paritytech/parity/pull/239) +- Note additional tests are fixed, fix doc test. [#242](https://github.com/paritytech/parity/pull/242) +- jsonrpc http server [#193](https://github.com/paritytech/parity/pull/193) +- Ethash nonce is H64 not a u64 [#240](https://github.com/paritytech/parity/pull/240) +- Fix import for bcMultiChainTest [#236](https://github.com/paritytech/parity/pull/236) +- Client basic tests [#232](https://github.com/paritytech/parity/pull/232) +- Fix ensure_db_good() and flush_queue(), block refactoring, check block format, be strict. [#231](https://github.com/paritytech/parity/pull/231) +- Rlp [#207](https://github.com/paritytech/parity/pull/207) +- Schedule documentation [#219](https://github.com/paritytech/parity/pull/219) +- U256<->H256 Conversion [#206](https://github.com/paritytech/parity/pull/206) +- Spawning new thread when we are reaching stack limit [#217](https://github.com/paritytech/parity/pull/217) +- Blockchain tests [#211](https://github.com/paritytech/parity/pull/211) +- fixed failing sync test [#218](https://github.com/paritytech/parity/pull/218) +- Removing println [#216](https://github.com/paritytech/parity/pull/216) +- Cleaning readme [#212](https://github.com/paritytech/parity/pull/212) +- Fixing delegatecall [#196](https://github.com/paritytech/parity/pull/196) +- Autogenerate the Args from the docopt macro. [#205](https://github.com/paritytech/parity/pull/205) +- Networking fixes [#202](https://github.com/paritytech/parity/pull/202) +- Argument parsing from CLI [#204](https://github.com/paritytech/parity/pull/204) +- Removed wildcard from clippy version [#203](https://github.com/paritytech/parity/pull/203) +- Fixed tests and tweaked sync progress report [#201](https://github.com/paritytech/parity/pull/201) +- Heavy tests [#199](https://github.com/paritytech/parity/pull/199) +- Mutithreaded IO [#198](https://github.com/paritytech/parity/pull/198) +- Populating last_hashes [#197](https://github.com/paritytech/parity/pull/197) +- Fixing clippy stuff [#170](https://github.com/paritytech/parity/pull/170) +- basic .travis.yml [#194](https://github.com/paritytech/parity/pull/194) +- Generating coverage reports. [#190](https://github.com/paritytech/parity/pull/190) +- Adding doc requests comments [#192](https://github.com/paritytech/parity/pull/192) +- moved src/bin/client.rs -> src/bin/client/main.rs [#185](https://github.com/paritytech/parity/pull/185) +- removed overflowing_shr [#188](https://github.com/paritytech/parity/pull/188) +- fixed wrapping ops on latest nightly [#187](https://github.com/paritytech/parity/pull/187) +- Pruned state DB [#176](https://github.com/paritytech/parity/pull/176) +- Memory management for cache [#180](https://github.com/paritytech/parity/pull/180) +- Implement signs having low-s. [#183](https://github.com/paritytech/parity/pull/183) +- Introduce sha3 crate and use it in ethash [#178](https://github.com/paritytech/parity/pull/178) +- Multithreaded block queue [#173](https://github.com/paritytech/parity/pull/173) +- Iterator for NibbleSlice and TrieDB. [#171](https://github.com/paritytech/parity/pull/171) +- Handling all possible overflows [#145](https://github.com/paritytech/parity/pull/145) +- Global secp256k1 context [#164](https://github.com/paritytech/parity/pull/164) +- Ethash [#152](https://github.com/paritytech/parity/pull/152) +- Move util into here [#153](https://github.com/paritytech/parity/pull/153) +- EVM Interpreter [#103](https://github.com/paritytech/parity/pull/103) +- Homestead transition support, maybe. [#141](https://github.com/paritytech/parity/pull/141) +- externalities refactor [#131](https://github.com/paritytech/parity/pull/131) +- More open files. [#140](https://github.com/paritytech/parity/pull/140) +- Single array for logs output. [#133](https://github.com/paritytech/parity/pull/133) +- Client app event handler [#132](https://github.com/paritytech/parity/pull/132) +- Various consensus fixes. [#130](https://github.com/paritytech/parity/pull/130) +- callcode builtins tests pass [#127](https://github.com/paritytech/parity/pull/127) +- Client state syncing [#119](https://github.com/paritytech/parity/pull/119) +- Split externalities from executive. [#126](https://github.com/paritytech/parity/pull/126) +- executive error on not enoguh base gas [#124](https://github.com/paritytech/parity/pull/124) +- Gav [#125](https://github.com/paritytech/parity/pull/125) +- builtin sets excepted to true [#123](https://github.com/paritytech/parity/pull/123) +- More state tests. [#122](https://github.com/paritytech/parity/pull/122) +- updated to rocksdb wrapper version 0.3 [#121](https://github.com/paritytech/parity/pull/121) +- out_of_gas -> excepted [#120](https://github.com/paritytech/parity/pull/120) +- Parametrizing evm::Factory [#111](https://github.com/paritytech/parity/pull/111) +- stLogs tests passing [#118](https://github.com/paritytech/parity/pull/118) +- Fix executive. [#117](https://github.com/paritytech/parity/pull/117) +- Fixes for marek's shooting from the hip. [#116](https://github.com/paritytech/parity/pull/116) +- Executive revert fix [#115](https://github.com/paritytech/parity/pull/115) +- Fix storage/account and add butress test. [#114](https://github.com/paritytech/parity/pull/114) +- Refactored Pod & Diff types into separate files, JSON infrastructure revamp. [#113](https://github.com/paritytech/parity/pull/113) +- Fix storage stuff and introduce per-item dirty-tracking. [#112](https://github.com/paritytech/parity/pull/112) +- Check logs in state tests. [#109](https://github.com/paritytech/parity/pull/109) +- executive gas calculation fixes [#108](https://github.com/paritytech/parity/pull/108) +- proper gas calculation in executive [#107](https://github.com/paritytech/parity/pull/107) +- Fixing MaxDepth param for executive [#105](https://github.com/paritytech/parity/pull/105) +- Fix determination of state roots. [#106](https://github.com/paritytech/parity/pull/106) +- transact substracts tx_gas [#104](https://github.com/paritytech/parity/pull/104) +- Pretty-print and fix for state. [#102](https://github.com/paritytech/parity/pull/102) +- Tier step price. [#101](https://github.com/paritytech/parity/pull/101) +- Refactor Diff datastructures. [#100](https://github.com/paritytech/parity/pull/100) +- externalities use u256 instead of u64 for gas calculation [#99](https://github.com/paritytech/parity/pull/99) +- Executive tests [#97](https://github.com/paritytech/parity/pull/97) +- State conensus tests now print mismatching diff on fail. [#98](https://github.com/paritytech/parity/pull/98) +- State testing framework. First test is failing. [#96](https://github.com/paritytech/parity/pull/96) +- executive tests [#95](https://github.com/paritytech/parity/pull/95) +- Use U512s for ether cost calculation, complete transaction API [#94](https://github.com/paritytech/parity/pull/94) +- Utils for consensus test decoding and better layout. [#93](https://github.com/paritytech/parity/pull/93) +- executive fixes + tests [#89](https://github.com/paritytech/parity/pull/89) +- All transaction tests pass. Nicer testing framework. [#92](https://github.com/paritytech/parity/pull/92) +- Block verification tests; BlockProvider blockchain trait for testing [#88](https://github.com/paritytech/parity/pull/88) +- State::exists, docs and tests. [#87](https://github.com/paritytech/parity/pull/87) +- Add tests module, add two more transaction tests. [#86](https://github.com/paritytech/parity/pull/86) +- bring back removed tests, removed build warnings [#82](https://github.com/paritytech/parity/pull/82) +- Nicer transaction validation API. Nicer OutOfBounds API in general. [#85](https://github.com/paritytech/parity/pull/85) +- Transaction fixes and consensus tests (all passing) [#84](https://github.com/paritytech/parity/pull/84) +- fixed getting block info in evmjit + tests [#81](https://github.com/paritytech/parity/pull/81) +- evm tests cleanup [#80](https://github.com/paritytech/parity/pull/80) +- renamed VmFactory -> Factory [#77](https://github.com/paritytech/parity/pull/77) +- fixed rust-evmjit description of improper_ctypes usage [#76](https://github.com/paritytech/parity/pull/76) +- jit feature enabled by default [#75](https://github.com/paritytech/parity/pull/75) +- evm [#52](https://github.com/paritytech/parity/pull/52) +- state clone [#74](https://github.com/paritytech/parity/pull/74) +- Block Verification (no tests yet) [#72](https://github.com/paritytech/parity/pull/72) +- Improvements to LogEntry and Transaction [#73](https://github.com/paritytech/parity/pull/73) +- Use getter in header in preparation for a Header trait; additional testing in enact_block(). [#64](https://github.com/paritytech/parity/pull/64) +- BlockChain sync and Client app [#55](https://github.com/paritytech/parity/pull/55) +- Block enactment (including test) [#63](https://github.com/paritytech/parity/pull/63) +- Block complete. Needs tests. [#62](https://github.com/paritytech/parity/pull/62) +- More on OpenBlock::close; State::kill_account added [#61](https://github.com/paritytech/parity/pull/61) +- Remove genesis module, add more chain specs and separate out ethereum-specific stuff [#60](https://github.com/paritytech/parity/pull/60) +- State::new_contract, camelCase engine params, missing param [#59](https://github.com/paritytech/parity/pull/59) +- Use reorganisation [#58](https://github.com/paritytech/parity/pull/58) +- Initial Ethash/Block skeleton implementations. [#57](https://github.com/paritytech/parity/pull/57) +- Spec with tested Morden genesis decoder and builtins. [#54](https://github.com/paritytech/parity/pull/54) +- Move all chain parameters into `engine_params` [#50](https://github.com/paritytech/parity/pull/50) +- jit ffi improvements [please review] [#51](https://github.com/paritytech/parity/pull/51) +- blockchain [please review] [#34](https://github.com/paritytech/parity/pull/34) +- Move information from networkparams.rs into spec.rs [#48](https://github.com/paritytech/parity/pull/48) +- Move bulking out in Engine/Params. [#47](https://github.com/paritytech/parity/pull/47) +- Removed need for mutation in State. [#46](https://github.com/paritytech/parity/pull/46) +- State::code and State::storage_at + tests. [#45](https://github.com/paritytech/parity/pull/45) +- State functions for balance and nonce operations [#44](https://github.com/paritytech/parity/pull/44) +- Account::storage_at, Account::ensure_cached and tests. [#43](https://github.com/paritytech/parity/pull/43) +- Additional tests. [#42](https://github.com/paritytech/parity/pull/42) +- seal todo done [#41](https://github.com/paritytech/parity/pull/41) +- missing rustc_serialize crate && rlp `as_list` function [#40](https://github.com/paritytech/parity/pull/40) +- More methods in Account, documentation and tests. [#39](https://github.com/paritytech/parity/pull/39) +- Minor reworking of Account. [#38](https://github.com/paritytech/parity/pull/38) +- Add Account and State classes. [#37](https://github.com/paritytech/parity/pull/37) +- Revert regressions [#36](https://github.com/paritytech/parity/pull/36) diff --git a/docs/CHANGELOG-1.0.md b/docs/CHANGELOG-1.0.md new file mode 100644 index 0000000000000000000000000000000000000000..58d3101f5a7f9059281a66eb3feb9afe8c4a676f --- /dev/null +++ b/docs/CHANGELOG-1.0.md @@ -0,0 +1,317 @@ +Note: Parity 1.0 reached End-of-Life on 2016-06-24 (EOL). + +## Parity [v1.0.2](https://github.com/paritytech/parity/releases/tag/v1.0.2) (2016-04-11) + +Parity 1.0.2 release improves Json RPC compatibility and fixes a number of stability issues. + +- Flush password prompt [#1031](https://github.com/paritytech/parity/pull/1031) +- [beta] dependencies update [#949](https://github.com/paritytech/parity/pull/949) +- Master to beta v1.0.2 [#922](https://github.com/paritytech/parity/pull/922) +- Master to beta 1.0.2 [#908](https://github.com/paritytech/parity/pull/908) + +## Parity [v1.0.1](https://github.com/paritytech/parity/releases/tag/v1.0.1) (2016-03-28) + +Parity 1.0.1 update fixes a number of issues with Json RPC, transaction propagation and syncing. + +- Imporved sync error handling [#905](https://github.com/paritytech/parity/pull/905) +- Publish locally-made transactions to peers. [#851](https://github.com/paritytech/parity/pull/851) +- Merge fixes from master to beta [#845](https://github.com/paritytech/parity/pull/845) +- Full sync restart on bad block [#844](https://github.com/paritytech/parity/pull/844) +- Make BlockNumber optional, fix eth_call [#828](https://github.com/paritytech/parity/pull/828) +- Web3sha3 beta [#826](https://github.com/paritytech/parity/pull/826) +- Use network id for the web3_net_version return. [#821](https://github.com/paritytech/parity/pull/821) +- Fix mining from spinning [#806](https://github.com/paritytech/parity/pull/806) +- Merge master to beta [#796](https://github.com/paritytech/parity/pull/796) + +## Parity [v1.0.0](https://github.com/paritytech/parity/releases/tag/v1.0.0) (2016-03-24) + +Parity 1.0.0 release adds the following features: + +- Standard JsonRPC interface. +- Full Homestead compatibility. +- Transaction management. +- Mining with external miner. +- Account management. +- Geth key chain compatibility. +- Additional command line options. +- State trie pruning. +- Cache and queue footprint. +- Network discovery & NAT traversal. +- Custom chain specification files. + +Note that in this release the state database is in archive (full) mode by default. Run with one of the `--pruning` options to enable pruning. + +- First part of multi-mining support [#804](https://github.com/paritytech/parity/pull/804) +- Fixing future-current transactions clash [#802](https://github.com/paritytech/parity/pull/802) +- Increase threads to num_cpus & fix author reporting [#800](https://github.com/paritytech/parity/pull/800) +- another batch of rpc improvements [#798](https://github.com/paritytech/parity/pull/798) +- Avoid tracing DELEGATECALL and CALLCODE. Plus tests for it. [#794](https://github.com/paritytech/parity/pull/794) +- complete getting started steps for OS X [#793](https://github.com/paritytech/parity/pull/793) +- Auto detect available port (with fixed test) [#788](https://github.com/paritytech/parity/pull/788) +- eth_getTransactionReceipt [#792](https://github.com/paritytech/parity/pull/792) +- Comprehensive tests for tracing transactions [#791](https://github.com/paritytech/parity/pull/791) +- Disable preparing work package if miners don't ask for it. [#771](https://github.com/paritytech/parity/pull/771) +- Listen on all interfaces for JSONRPC by default. [#786](https://github.com/paritytech/parity/pull/786) +- eth_call [#783](https://github.com/paritytech/parity/pull/783) +- Revert "Auto detect available port" [#789](https://github.com/paritytech/parity/pull/789) +- added output to execution result [#777](https://github.com/paritytech/parity/pull/777) +- Auto detect available port [#782](https://github.com/paritytech/parity/pull/782) +- Allow 0x prefix for --author. [#785](https://github.com/paritytech/parity/pull/785) +- updated dependencies, moved rpctest to its own submodule [#784](https://github.com/paritytech/parity/pull/784) +- use ethjson module to load chain json tests [#778](https://github.com/paritytech/parity/pull/778) +- Tracing implemented. [#772](https://github.com/paritytech/parity/pull/772) +- test ethjson module on travis [#780](https://github.com/paritytech/parity/pull/780) +- batch of rpc fixes [#775](https://github.com/paritytech/parity/pull/775) +- rpctest executable [#757](https://github.com/paritytech/parity/pull/757) +- Refactoring error transaction_queue error handling and `update_sealing` method. [#753](https://github.com/paritytech/parity/pull/753) +- Avoid importing transactions with gas above 1.1*block_gas_limit to transaction queue [#760](https://github.com/paritytech/parity/pull/760) +- Removing transactions that failed to be pushed to block. [#752](https://github.com/paritytech/parity/pull/752) +- Updating clippy [#766](https://github.com/paritytech/parity/pull/766) +- Attempting to add all transactions to mined block [#754](https://github.com/paritytech/parity/pull/754) +- Prettier version w/o git dir; Use rustc compile time version [#761](https://github.com/paritytech/parity/pull/761) +- Stop adding transactions to queue while not fully synced [#751](https://github.com/paritytech/parity/pull/751) +- Verify sender's balance before importing transaction to queue [#746](https://github.com/paritytech/parity/pull/746) +- Returning number of transactions pending in block not queue [#750](https://github.com/paritytech/parity/pull/750) +- Speeding up build [#733](https://github.com/paritytech/parity/pull/733) +- adding check for a sync when giving work to miner [#742](https://github.com/paritytech/parity/pull/742) +- json deserialization module [#745](https://github.com/paritytech/parity/pull/745) +- Update install-parity.sh [#749](https://github.com/paritytech/parity/pull/749) +- Restart sync on getting old unknown header [#747](https://github.com/paritytech/parity/pull/747) +- Missing return for #737 [#744](https://github.com/paritytech/parity/pull/744) +- Enact block with uncles test [#741](https://github.com/paritytech/parity/pull/741) +- Fix outdated libc version on dependency [#740](https://github.com/paritytech/parity/pull/740) +- Fixing possible race in transaction queue [#735](https://github.com/paritytech/parity/pull/735) +- Sync fixed again [#737](https://github.com/paritytech/parity/pull/737) +- Don't change best block until extras is committed. [#734](https://github.com/paritytech/parity/pull/734) +- stable only until travis speedup [#736](https://github.com/paritytech/parity/pull/736) +- Optimizing uint operations (architecture independent) [#629](https://github.com/paritytech/parity/pull/629) +- Add RLP, not a data item. [#725](https://github.com/paritytech/parity/pull/725) +- PV63 receipts response [#687](https://github.com/paritytech/parity/pull/687) +- another batch of rpc tests [#723](https://github.com/paritytech/parity/pull/723) +- dockerfiles update [#726](https://github.com/paritytech/parity/pull/726) +- Lock reports to avoid out of order badness. [#721](https://github.com/paritytech/parity/pull/721) +- Fixed handshake leak [#722](https://github.com/paritytech/parity/pull/722) +- Allow configuration of target gas limit. [#719](https://github.com/paritytech/parity/pull/719) +- Version 1.1 in master [#714](https://github.com/paritytech/parity/pull/714) +- Silence UDP warnings [#720](https://github.com/paritytech/parity/pull/720) +- Rpc personal tests [#715](https://github.com/paritytech/parity/pull/715) +- Fixing warnings [#704](https://github.com/paritytech/parity/pull/704) +- docopts cleanups [#713](https://github.com/paritytech/parity/pull/713) +- Removed rocksdb build dependency [#717](https://github.com/paritytech/parity/pull/717) +- Fixed splitting Neighbours packet [#710](https://github.com/paritytech/parity/pull/710) +- management of account expiration & memory [#701](https://github.com/paritytech/parity/pull/701) +- Remove EarlyMerge from user docs. [#708](https://github.com/paritytech/parity/pull/708) +- Fixes and traces for refcountdb. [#705](https://github.com/paritytech/parity/pull/705) +- Check for NULL_RLP in AccountDB [#706](https://github.com/paritytech/parity/pull/706) +- ethminer as crate [#700](https://github.com/paritytech/parity/pull/700) +- Old ref-counted DB code [#692](https://github.com/paritytech/parity/pull/692) +- next batch of rpc tests and fixes [#699](https://github.com/paritytech/parity/pull/699) +- implemented eth_geStorageAt rpc method, added more tests for rpc [#695](https://github.com/paritytech/parity/pull/695) +- Fix JournalDB era marker [#690](https://github.com/paritytech/parity/pull/690) +- More sync fixes [#685](https://github.com/paritytech/parity/pull/685) +- mark some key tests as heavy [#694](https://github.com/paritytech/parity/pull/694) +- Limit incoming connections [#693](https://github.com/paritytech/parity/pull/693) +- Updating clippy [#688](https://github.com/paritytech/parity/pull/688) +- eth_accounts, eth_getBalance rpc functions && tests [#691](https://github.com/paritytech/parity/pull/691) +- state query for archive jdb [#683](https://github.com/paritytech/parity/pull/683) +- Fix for option 1 of JournalDB [#658](https://github.com/paritytech/parity/pull/658) +- Rename into something that is a little more descriptive. [#689](https://github.com/paritytech/parity/pull/689) +- JournalDB with in-memory overlay (option2) [#634](https://github.com/paritytech/parity/pull/634) +- additional (failing) SecretStore test [#682](https://github.com/paritytech/parity/pull/682) +- Updating clippy & fixing warnings. [#670](https://github.com/paritytech/parity/pull/670) +- rpc web3 tests [#681](https://github.com/paritytech/parity/pull/681) +- Making personal json-rpc configurable via cli [#677](https://github.com/paritytech/parity/pull/677) +- RPC Pending Transactions Filter [#661](https://github.com/paritytech/parity/pull/661) +- Rearrange journaldb infrastructure to make more extensible [#678](https://github.com/paritytech/parity/pull/678) +- JournalDB -> Box, and it's a trait. [#673](https://github.com/paritytech/parity/pull/673) +- fix warning for transaction_queue.add usage [#676](https://github.com/paritytech/parity/pull/676) +- Adding std::mem back (only for asm) [#680](https://github.com/paritytech/parity/pull/680) +- update readme to exclude beta step (stable is ok) [#679](https://github.com/paritytech/parity/pull/679) +- fixed U256 and transaction request deserialization [#675](https://github.com/paritytech/parity/pull/675) +- More geth compatibility. [#666](https://github.com/paritytech/parity/pull/666) +- Removing running clippy by default on nightly. [#671](https://github.com/paritytech/parity/pull/671) +- rpc net submodule tests [#667](https://github.com/paritytech/parity/pull/667) +- Client module overhaul [#665](https://github.com/paritytech/parity/pull/665) +- Rpc transaction signing [#587](https://github.com/paritytech/parity/pull/587) +- Transaction queue exposed via JSON rpc. [#652](https://github.com/paritytech/parity/pull/652) +- Remove unneeded locking [#499](https://github.com/paritytech/parity/pull/499) +- extend sync status interface to sync provider [#664](https://github.com/paritytech/parity/pull/664) +- --archive is default. --pruning is option. [#663](https://github.com/paritytech/parity/pull/663) +- jsonrpc uses client and sync interfaces [#641](https://github.com/paritytech/parity/pull/641) +- Expose transaction insertion in sync lib [#609](https://github.com/paritytech/parity/pull/609) +- Removing get prefix from poll_info [#660](https://github.com/paritytech/parity/pull/660) +- Tx queue update height bug [#657](https://github.com/paritytech/parity/pull/657) +- Tx_queue_docs -> To master [#651](https://github.com/paritytech/parity/pull/651) +- blockchain import_route [#645](https://github.com/paritytech/parity/pull/645) +- Stop workers before stopping event loop [#655](https://github.com/paritytech/parity/pull/655) +- Validate sender before importing to queue [#650](https://github.com/paritytech/parity/pull/650) +- Gas price threshold for transactions [#640](https://github.com/paritytech/parity/pull/640) +- `dev` feature enabled when compiling without `--release` [#627](https://github.com/paritytech/parity/pull/627) +- Don't call mark_as_bad needlessly [#648](https://github.com/paritytech/parity/pull/648) +- Fixed sync handling large forks [#647](https://github.com/paritytech/parity/pull/647) +- Additional documentation for transaction queue [#631](https://github.com/paritytech/parity/pull/631) +- Transaction Queue Integration [#607](https://github.com/paritytech/parity/pull/607) +- Keys cli [#639](https://github.com/paritytech/parity/pull/639) +- fix build warning [#643](https://github.com/paritytech/parity/pull/643) +- updated jsonrpc-core and http-server libs [#642](https://github.com/paritytech/parity/pull/642) +- jsonrpc panics gracefully shutdown client [#638](https://github.com/paritytech/parity/pull/638) +- Fixing CLI parameters [#633](https://github.com/paritytech/parity/pull/633) +- Normal CLI options with geth. [#628](https://github.com/paritytech/parity/pull/628) +- Do not remove the peer immediatelly on send error [#626](https://github.com/paritytech/parity/pull/626) +- Jsonrpc block behind [#622](https://github.com/paritytech/parity/pull/622) +- Remove println!s. [#624](https://github.com/paritytech/parity/pull/624) +- JournalDB option 1 fix [#613](https://github.com/paritytech/parity/pull/613) +- Network tracing cleanup [#611](https://github.com/paritytech/parity/pull/611) +- Revert "Transaction Queue integration" [#602](https://github.com/paritytech/parity/pull/602) +- fix benches compilation [#601](https://github.com/paritytech/parity/pull/601) +- Transaction Queue integration [#595](https://github.com/paritytech/parity/pull/595) +- verifier trait improvements [#597](https://github.com/paritytech/parity/pull/597) +- build on rust stable [#600](https://github.com/paritytech/parity/pull/600) +- Geth import silent if no geth [#599](https://github.com/paritytech/parity/pull/599) +- Additional journaldb logging and assert [#593](https://github.com/paritytech/parity/pull/593) +- Uncle inclusion in block authoring. [#578](https://github.com/paritytech/parity/pull/578) +- Fixed potential deadlock on startup [#592](https://github.com/paritytech/parity/pull/592) +- Fixing an overflow panic [#591](https://github.com/paritytech/parity/pull/591) +- Fixed one more case of sync stalling [#590](https://github.com/paritytech/parity/pull/590) +- JournalDB can now operate in "archive" mode [#589](https://github.com/paritytech/parity/pull/589) +- Secret store integration with client [#586](https://github.com/paritytech/parity/pull/586) +- fix build on nightly rust [#588](https://github.com/paritytech/parity/pull/588) +- deserialization for uint generic [#585](https://github.com/paritytech/parity/pull/585) +- TransactionsQueue implementation [#559](https://github.com/paritytech/parity/pull/559) +- JSON-RPC personal service (follows #582) [#583](https://github.com/paritytech/parity/pull/583) +- making key directory thread-safe [#582](https://github.com/paritytech/parity/pull/582) +- verifier trait [#581](https://github.com/paritytech/parity/pull/581) +- shrink_to_fit after removing hashes. [#580](https://github.com/paritytech/parity/pull/580) +- support for rpc polling [#504](https://github.com/paritytech/parity/pull/504) +- limit serde codegen only to rpc types submodule [#569](https://github.com/paritytech/parity/pull/569) +- fork test for Issue test/568 [#573](https://github.com/paritytech/parity/pull/573) +- Fixing clippy warnings = small refactoring of `request_blocks` [#560](https://github.com/paritytech/parity/pull/560) +- Improved journaldb logging [#571](https://github.com/paritytech/parity/pull/571) +- Additional check to ancient enactments. [#570](https://github.com/paritytech/parity/pull/570) +- chainfilter shouldnt exclude to_block from results [#564](https://github.com/paritytech/parity/pull/564) +- Fix coverage test run [#567](https://github.com/paritytech/parity/pull/567) +- Mining [#547](https://github.com/paritytech/parity/pull/547) +- fix uint warnings [#565](https://github.com/paritytech/parity/pull/565) +- Finished blockchain generator. [#562](https://github.com/paritytech/parity/pull/562) +- fixed broken master [#563](https://github.com/paritytech/parity/pull/563) +- uint to separate crate [#544](https://github.com/paritytech/parity/pull/544) +- improved test chain generator [#554](https://github.com/paritytech/parity/pull/554) +- Fixing spelling in propagade->propagate [#558](https://github.com/paritytech/parity/pull/558) +- Changing RefCell to Cell in transaction. [#557](https://github.com/paritytech/parity/pull/557) +- Fix for morden consensus. [#556](https://github.com/paritytech/parity/pull/556) +- blockchain generator [#550](https://github.com/paritytech/parity/pull/550) +- Sparse Table Implementation (Row, Col) -> Val [#545](https://github.com/paritytech/parity/pull/545) +- fixup install script [#548](https://github.com/paritytech/parity/pull/548) +- Fixing clippy warnings [#546](https://github.com/paritytech/parity/pull/546) +- ignore out directory [#543](https://github.com/paritytech/parity/pull/543) +- u256 full multiplication [#539](https://github.com/paritytech/parity/pull/539) +- Fix panic when downloading stales, update homestead transition [#537](https://github.com/paritytech/parity/pull/537) +- changing x64 asm config [#534](https://github.com/paritytech/parity/pull/534) +- uncomment state transition tests [#533](https://github.com/paritytech/parity/pull/533) +- jsonrpc uses weak pointers to client [#532](https://github.com/paritytech/parity/pull/532) +- Morden switch to Homestead rules at #494,000. [#531](https://github.com/paritytech/parity/pull/531) +- Blockchain module cleanup [#524](https://github.com/paritytech/parity/pull/524) +- Multiplication issue + very exhaustive tests for it [#528](https://github.com/paritytech/parity/pull/528) +- EIP-8 [#498](https://github.com/paritytech/parity/pull/498) +- Make "random" trie tests fully deterministic. [#527](https://github.com/paritytech/parity/pull/527) +- udpated serde to version 0.7.0 [#526](https://github.com/paritytech/parity/pull/526) +- Better memory management [#516](https://github.com/paritytech/parity/pull/516) +- Typo [#523](https://github.com/paritytech/parity/pull/523) +- U512 add/sub optimize [#521](https://github.com/paritytech/parity/pull/521) +- Account management + geth keystore import (no utility crate added) [#509](https://github.com/paritytech/parity/pull/509) +- Delayed UPnP initialization [#505](https://github.com/paritytech/parity/pull/505) +- Fixing marking blocks as bad & SyncMessage bugs + small client refactoring. [#503](https://github.com/paritytech/parity/pull/503) +- optimization of U256 [#515](https://github.com/paritytech/parity/pull/515) +- Removed rocksdb from build scripts and instructions [#520](https://github.com/paritytech/parity/pull/520) +- RocksDB abstraction layer + Hash index for state DB [#464](https://github.com/paritytech/parity/pull/464) +- bloomfilter [#418](https://github.com/paritytech/parity/pull/418) +- Fixed a race condition when connecting peer disconnects immediately [#519](https://github.com/paritytech/parity/pull/519) +- ignore intellij idea project files as well [#518](https://github.com/paritytech/parity/pull/518) +- updated version of unicase [#517](https://github.com/paritytech/parity/pull/517) +- jsonrpc security, cors headers, fixed #359 [#493](https://github.com/paritytech/parity/pull/493) +- Rust implementations to replace data tables (#161) [#482](https://github.com/paritytech/parity/pull/482) +- fix issue with starting requested block number was not included itself [#512](https://github.com/paritytech/parity/pull/512) +- fixed travis --org GH_TOKEN [#510](https://github.com/paritytech/parity/pull/510) +- Improved log format [#506](https://github.com/paritytech/parity/pull/506) +- Log address on failed connection attempt [#502](https://github.com/paritytech/parity/pull/502) +- Bumping clippy and fixing warnings. [#501](https://github.com/paritytech/parity/pull/501) +- Bumping versions. Fixes #496 [#500](https://github.com/paritytech/parity/pull/500) +- Manage final user-input errors. [#494](https://github.com/paritytech/parity/pull/494) +- Remove unneeded code, fix minor potential issue with length. [#495](https://github.com/paritytech/parity/pull/495) +- Remove "unknown" from version string. [#488](https://github.com/paritytech/parity/pull/488) +- Include git commit date & hash. [#486](https://github.com/paritytech/parity/pull/486) +- Use proper version string. [#485](https://github.com/paritytech/parity/pull/485) +- Networking fixes [#480](https://github.com/paritytech/parity/pull/480) +- Fix potential deadlock on node table update [#484](https://github.com/paritytech/parity/pull/484) +- Squash more warnings [#481](https://github.com/paritytech/parity/pull/481) +- dev/test/build tools to separate crate [#477](https://github.com/paritytech/parity/pull/477) +- Back to original slab crate [#479](https://github.com/paritytech/parity/pull/479) +- Better user errors. [#476](https://github.com/paritytech/parity/pull/476) +- UDP Discovery [#440](https://github.com/paritytech/parity/pull/440) +- update readme with rust override [#475](https://github.com/paritytech/parity/pull/475) +- fixed warnings on rust beta [#474](https://github.com/paritytech/parity/pull/474) +- Secret store (part2 - encrypted key/value svc) [#449](https://github.com/paritytech/parity/pull/449) +- Kill bad test. [#473](https://github.com/paritytech/parity/pull/473) +- Make clippy an optional dependency [#422](https://github.com/paritytech/parity/pull/422) +- parity compiling fine [#469](https://github.com/paritytech/parity/pull/469) +- compiling ethcore on beta [#468](https://github.com/paritytech/parity/pull/468) +- Utils compiling in beta [#467](https://github.com/paritytech/parity/pull/467) +- Get rid of lru_cache dependency [#466](https://github.com/paritytech/parity/pull/466) +- Add daemonization. [#459](https://github.com/paritytech/parity/pull/459) +- Master upgrade [#448](https://github.com/paritytech/parity/pull/448) +- Remove contributing stuff now that we have CLA bot. [#447](https://github.com/paritytech/parity/pull/447) +- Add Morden bootnode. [#446](https://github.com/paritytech/parity/pull/446) +- beta fixes to master [#441](https://github.com/paritytech/parity/pull/441) +- Secret store (part1 - key management) [#423](https://github.com/paritytech/parity/pull/423) +- Use 1100000 as the homestead transition, fix build instructions. [#438](https://github.com/paritytech/parity/pull/438) +- More sync and propagation fixes [#420](https://github.com/paritytech/parity/pull/420) +- back to cargo crates [#436](https://github.com/paritytech/parity/pull/436) +- Fixing clippy warnings [#435](https://github.com/paritytech/parity/pull/435) +- preserving root cargo lock [#434](https://github.com/paritytech/parity/pull/434) +- Nightly fix [#432](https://github.com/paritytech/parity/pull/432) +- nightly fixes [#431](https://github.com/paritytech/parity/pull/431) +- Delay Homestead transition from 1,000,000. [#429](https://github.com/paritytech/parity/pull/429) +- Nightly fix effort (still should fail) [#428](https://github.com/paritytech/parity/pull/428) +- clippy version update, docopt-macro moving to fork [#425](https://github.com/paritytech/parity/pull/425) +- Network/Sync fixes and optimizations [#416](https://github.com/paritytech/parity/pull/416) +- Use latest era instead of end era as journal marker [#414](https://github.com/paritytech/parity/pull/414) +- api changes [#402](https://github.com/paritytech/parity/pull/402) +- Option for no init nodes. [#408](https://github.com/paritytech/parity/pull/408) +- Fixed block_bodies not returning a list [#406](https://github.com/paritytech/parity/pull/406) +- Fix test. [#405](https://github.com/paritytech/parity/pull/405) +- Allow path to be configured. [#404](https://github.com/paritytech/parity/pull/404) +- Upnp [#400](https://github.com/paritytech/parity/pull/400) +- eth_syncing, fixed #397 [#398](https://github.com/paritytech/parity/pull/398) +- Using modified version of ctrlc that catches SIGTERM [#399](https://github.com/paritytech/parity/pull/399) +- Catching panics. [#396](https://github.com/paritytech/parity/pull/396) +- jsonrpc [#391](https://github.com/paritytech/parity/pull/391) +- Externalities tests (still clumsy) [#394](https://github.com/paritytech/parity/pull/394) +- excluding test code itself from coverage [#395](https://github.com/paritytech/parity/pull/395) +- Additional tweaks to options. [#390](https://github.com/paritytech/parity/pull/390) +- --chain option for setting which network to go on. [#388](https://github.com/paritytech/parity/pull/388) +- Ethash unit tests final [#387](https://github.com/paritytech/parity/pull/387) +- jsonrpc [#374](https://github.com/paritytech/parity/pull/374) +- Editorconfig file. [#384](https://github.com/paritytech/parity/pull/384) +- Coverage effort [in progress] [#382](https://github.com/paritytech/parity/pull/382) +- making root kcov runner simular to the one running on CI [#380](https://github.com/paritytech/parity/pull/380) +- add gcc as a dependency to dockerfiles [#381](https://github.com/paritytech/parity/pull/381) +- Check for handshake expiration before attempting connection replace [#375](https://github.com/paritytech/parity/pull/375) +- Blocks propagation [#364](https://github.com/paritytech/parity/pull/364) +- Network params. [#376](https://github.com/paritytech/parity/pull/376) +- Add parity-node-zero to bootnodes. [#373](https://github.com/paritytech/parity/pull/373) +- kcov uses travis_job_id instead of coveralls token [#370](https://github.com/paritytech/parity/pull/370) +- Add parity-node-zero.ethcore.io to boot nodes. [#371](https://github.com/paritytech/parity/pull/371) + +## Parity [v1.0.0-rc1](https://github.com/paritytech/parity/releases/tag/v1.0.0-rc1) (2016-03-15) + +First Parity 1.0.0 release candidate. + +- Version 1.0 in beta [#712](https://github.com/paritytech/parity/pull/712) +- Fix test for beta [#617](https://github.com/paritytech/parity/pull/617) +- JournalDB fix option 1 for beta [#614](https://github.com/paritytech/parity/pull/614) +- Failing test. [#606](https://github.com/paritytech/parity/pull/606) +- Fix transition points [#604](https://github.com/paritytech/parity/pull/604) +- (BETA) Update README.md [#549](https://github.com/paritytech/parity/pull/549) +- (BETA) instructions for beta release channel [#456](https://github.com/paritytech/parity/pull/456) +- (BETA) fix nightly - remerge [#454](https://github.com/paritytech/parity/pull/454) +- (BETA) fixing nightly version for beta [#452](https://github.com/paritytech/parity/pull/452) diff --git a/docs/CHANGELOG-1.1.md b/docs/CHANGELOG-1.1.md new file mode 100644 index 0000000000000000000000000000000000000000..6c40ad8234e1b1f3535ff1d24fd44552d6e3e54f --- /dev/null +++ b/docs/CHANGELOG-1.1.md @@ -0,0 +1,154 @@ +Note: Parity 1.1 reached End-of-Life on 2016-08-12 (EOL). + +## Parity [v1.1.0](https://github.com/paritytech/parity/releases/tag/v1.1.0) (2016-05-02) + +Parity 1.1.0 introduces: + +- Transaction tracing. Parity now optionally indexes & stores message-call/"internal transaction" information and provides additional RPC for querying. +- Web interface for logs, status & JSON RPC. +- Improved JSON RPC compatibility. +- Reduced memory footprint. +- Optimized EVM interpreter performance. + +Full Changes: + +- Exposing default extra data via ethcore RPC [#1032](https://github.com/paritytech/parity/pull/1032) +- Net etiquette [#1028](https://github.com/paritytech/parity/pull/1028) +- Bumping clippy & fixing warnings [#1024](https://github.com/paritytech/parity/pull/1024) +- Tracedb interface && cli [#997](https://github.com/paritytech/parity/pull/997) +- Switching to geth-attach supporting version of rpc core and server [#1022](https://github.com/paritytech/parity/pull/1022) +- Fixing status page displaying homestead [#1020](https://github.com/paritytech/parity/pull/1020) +- Core tracedb functionality. [#996](https://github.com/paritytech/parity/pull/996) +- RPC method for supported modules [#1019](https://github.com/paritytech/parity/pull/1019) +- Updating status page [#1015](https://github.com/paritytech/parity/pull/1015) +- Disabling wallet [#1017](https://github.com/paritytech/parity/pull/1017) +- More detailed fatal error reporting [#1016](https://github.com/paritytech/parity/pull/1016) +- Support 'pending' block in RPC [#1007](https://github.com/paritytech/parity/pull/1007) +- Enable pending block when there is local transaction pending. [#1005](https://github.com/paritytech/parity/pull/1005) +- updating key files permissions on save [#1010](https://github.com/paritytech/parity/pull/1010) +- IPC JSON RPC (for external interface) [#1009](https://github.com/paritytech/parity/pull/1009) +- Fixing Firefox authorization issues [#1013](https://github.com/paritytech/parity/pull/1013) +- cargo update [#1012](https://github.com/paritytech/parity/pull/1012) +- Switching to rust-url@1.0.0 [#1011](https://github.com/paritytech/parity/pull/1011) +- Exception handling in RPC & WebApps [#988](https://github.com/paritytech/parity/pull/988) +- Fixed uint deserialization from hex [#1008](https://github.com/paritytech/parity/pull/1008) +- Tweak timeout and packet size to handle slow networks better [#1004](https://github.com/paritytech/parity/pull/1004) +- db key is generic and can be made smaller [#1006](https://github.com/paritytech/parity/pull/1006) +- IPC with new serialization [#998](https://github.com/paritytech/parity/pull/998) +- make jsonrpc api engine agnostic [#1001](https://github.com/paritytech/parity/pull/1001) +- updated cargo.lock [#1002](https://github.com/paritytech/parity/pull/1002) +- updated parity dependencies [#993](https://github.com/paritytech/parity/pull/993) +- Auto (with codegen) binary serializer [#980](https://github.com/paritytech/parity/pull/980) +- Fixing transaction queue last_nonces update [#995](https://github.com/paritytech/parity/pull/995) +- import route contains ommited blocks [#994](https://github.com/paritytech/parity/pull/994) +- fixed encoding 0u8 [#992](https://github.com/paritytech/parity/pull/992) +- Use latest netstats [#989](https://github.com/paritytech/parity/pull/989) +- RPC shared external miner [#984](https://github.com/paritytech/parity/pull/984) +- Additional RPC methods for settings [#983](https://github.com/paritytech/parity/pull/983) +- Fixing transaction_queue deadlock [#985](https://github.com/paritytech/parity/pull/985) +- Refactoring of `parity/main.rs` [#981](https://github.com/paritytech/parity/pull/981) +- Fixing clippy warnings. [#982](https://github.com/paritytech/parity/pull/982) +- Bumping status page [#977](https://github.com/paritytech/parity/pull/977) +- querying extras separated to its own module [#972](https://github.com/paritytech/parity/pull/972) +- Exposing application logs via RPC. [#976](https://github.com/paritytech/parity/pull/976) +- Addressing binary serialization for db types [#966](https://github.com/paritytech/parity/pull/966) +- removed redundant unwraps [#935](https://github.com/paritytech/parity/pull/935) +- fixed transaction queue merge conflict [#975](https://github.com/paritytech/parity/pull/975) +- Configurable limit for transaction queue (CLI & Ethcore-RPC) [#974](https://github.com/paritytech/parity/pull/974) +- Enforce limit caused `last_nonce` to return incorrect values. [#973](https://github.com/paritytech/parity/pull/973) +- Even more detailed errors for transaction queue [#969](https://github.com/paritytech/parity/pull/969) +- temporary fix of panic in blockchain garbage collection [#970](https://github.com/paritytech/parity/pull/970) +- IPC codegen - some minor fixes & enhancements [#967](https://github.com/paritytech/parity/pull/967) +- Additional logging for transactions [#968](https://github.com/paritytech/parity/pull/968) +- refactored blockchain extras keys building [#963](https://github.com/paritytech/parity/pull/963) +- Using hyper-mio branch in webapps. [#957](https://github.com/paritytech/parity/pull/957) +- Remove nanomsg from build-dependencies [#965](https://github.com/paritytech/parity/pull/965) +- Fix build for --target=armv7-unknown-linux-gnueabihf [#964](https://github.com/paritytech/parity/pull/964) +- IPC RPC codegen extra feature [#962](https://github.com/paritytech/parity/pull/962) +- IPC RPC codegen for generic implementation [#961](https://github.com/paritytech/parity/pull/961) +- using db_path directory when upgrading [#960](https://github.com/paritytech/parity/pull/960) +- IPC hypervisor [#958](https://github.com/paritytech/parity/pull/958) +- Removing a transaction from queue now removes all from this sender with lower nonces. [#950](https://github.com/paritytech/parity/pull/950) +- bump status page version 0.1.7 [#955](https://github.com/paritytech/parity/pull/955) +- Changing cors header to be optional [#956](https://github.com/paritytech/parity/pull/956) +- Update ARM Dockerfile [#959](https://github.com/paritytech/parity/pull/959) +- Sensible gas limits for eth_sendTransaction [#953](https://github.com/paritytech/parity/pull/953) +- Fix upgrade script and make parity run when no .parity dir. [#954](https://github.com/paritytech/parity/pull/954) +- Tracing and docs for --pruning=auto. [#952](https://github.com/paritytech/parity/pull/952) +- IPC serialization for custom parameters [#946](https://github.com/paritytech/parity/pull/946) +- default filter from block should be Latest, not Earliest [#948](https://github.com/paritytech/parity/pull/948) +- README.md: removes sudo from multirust installation [#943](https://github.com/paritytech/parity/pull/943) +- Disable long lines formatting + ethash example. [#939](https://github.com/paritytech/parity/pull/939) +- Ethcore-specific RPC methods for altering miner parameters. [#934](https://github.com/paritytech/parity/pull/934) +- Use ethcore nanomsg bindings [#941](https://github.com/paritytech/parity/pull/941) +- Update IPC codegen to latest syntax libs [#938](https://github.com/paritytech/parity/pull/938) +- IPC documentation [#937](https://github.com/paritytech/parity/pull/937) +- Bumping clippy and fixing warnings. [#936](https://github.com/paritytech/parity/pull/936) +- Pruning auto [#927](https://github.com/paritytech/parity/pull/927) +- IPC persistent client link [#933](https://github.com/paritytech/parity/pull/933) +- IPC persistent client link [#930](https://github.com/paritytech/parity/pull/930) +- IPC handshake (negotiating protocol/api version) [#928](https://github.com/paritytech/parity/pull/928) +- Upgrade logic between versions [#914](https://github.com/paritytech/parity/pull/914) +- executive tracing cleanup [#903](https://github.com/paritytech/parity/pull/903) +- Ethcore-specific RPC methods [#923](https://github.com/paritytech/parity/pull/923) +- Parameter to allow user to force the sealing mechanism [#918](https://github.com/paritytech/parity/pull/918) +- updated dependencies [#921](https://github.com/paritytech/parity/pull/921) +- Fixed send transaction deadlock [#920](https://github.com/paritytech/parity/pull/920) +- --unlock is comma-delimited. [#916](https://github.com/paritytech/parity/pull/916) +- fixed eth_getLogs [#915](https://github.com/paritytech/parity/pull/915) +- create provided custom dir for keys if none [#912](https://github.com/paritytech/parity/pull/912) +- spec loading cleanup [#858](https://github.com/paritytech/parity/pull/858) +- WebApps HTTP Basic Auth Support [#906](https://github.com/paritytech/parity/pull/906) +- Removing match on constant [#888](https://github.com/paritytech/parity/pull/888) +- Update auth.rs [#907](https://github.com/paritytech/parity/pull/907) +- Enabling webapps compilation by default [#904](https://github.com/paritytech/parity/pull/904) +- fixed #895 [#898](https://github.com/paritytech/parity/pull/898) +- Support for compile-time included WebApplications. [#899](https://github.com/paritytech/parity/pull/899) +- Propagate transaction queue [#894](https://github.com/paritytech/parity/pull/894) +- Use new json RPC server [#901](https://github.com/paritytech/parity/pull/901) +- Gracefully dying when trying to enable RPC and app is compiled without it. [#900](https://github.com/paritytech/parity/pull/900) +- Additional logging and friendlier error messages [#893](https://github.com/paritytech/parity/pull/893) +- Avoid signalling readiness when app is about to be closed. [#897](https://github.com/paritytech/parity/pull/897) +- fixed #875 and added tests for eth_sendTransaction [#890](https://github.com/paritytech/parity/pull/890) +- passing key path to all invocations [#891](https://github.com/paritytech/parity/pull/891) +- Fixed eth_call nonce and gas handling [#892](https://github.com/paritytech/parity/pull/892) +- ipc rpc with nano transport (simple duplex) [#886](https://github.com/paritytech/parity/pull/886) +- Bumping clippy and fixing warnings [#889](https://github.com/paritytech/parity/pull/889) +- More descriptive expectations to transaction queue consistency. [#878](https://github.com/paritytech/parity/pull/878) +- uint bug - replace add with or [#879](https://github.com/paritytech/parity/pull/879) +- Fixing typo in bigint [#877](https://github.com/paritytech/parity/pull/877) +- update misleading cli help msg for author [#874](https://github.com/paritytech/parity/pull/874) +- Find geth data store cross-platform. [#871](https://github.com/paritytech/parity/pull/871) +- Import geth 1.4.0 keys [#872](https://github.com/paritytech/parity/pull/872) +- Syntax helpers for IPC RPC (part 2) [#854](https://github.com/paritytech/parity/pull/854) +- Fixed bootnode URL and error message [#870](https://github.com/paritytech/parity/pull/870) +- replace popcnt with mov (861) [#867](https://github.com/paritytech/parity/pull/867) +- weekly dependencies update [#865](https://github.com/paritytech/parity/pull/865) +- Remove unused mut [#866](https://github.com/paritytech/parity/pull/866) +- fixed #855 [#864](https://github.com/paritytech/parity/pull/864) +- simplified trace from functions, removed clippy warnings [#862](https://github.com/paritytech/parity/pull/862) +- Update deprecated HashDB methods in docs. [#857](https://github.com/paritytech/parity/pull/857) +- refactored loading transaction json tests [#853](https://github.com/paritytech/parity/pull/853) +- reorganised price info lookup [#852](https://github.com/paritytech/parity/pull/852) +- Publish locally-made transactions to peers. [#850](https://github.com/paritytech/parity/pull/850) +- Add generalbeck's token [#847](https://github.com/paritytech/parity/pull/847) +- Fix response for mining. [#846](https://github.com/paritytech/parity/pull/846) +- USD-based pricing of gas. [#843](https://github.com/paritytech/parity/pull/843) +- Parity can accept older work packages [#811](https://github.com/paritytech/parity/pull/811) +- Caching for computing seed hashes (#541) [#841](https://github.com/paritytech/parity/pull/841) +- checking transaction queue for pending transaction [#838](https://github.com/paritytech/parity/pull/838) +- refactored loading of state tests [#817](https://github.com/paritytech/parity/pull/817) +- tests for deserialization of transaction from issue #835 [#837](https://github.com/paritytech/parity/pull/837) +- unlocks with no expiration [on top of 833] [#834](https://github.com/paritytech/parity/pull/834) +- Unlock accounts on CLI. [#833](https://github.com/paritytech/parity/pull/833) +- Make BlockNumber optional, fix eth_call [#829](https://github.com/paritytech/parity/pull/829) +- Test socket to common test code (ethcore-devtools) [#831](https://github.com/paritytech/parity/pull/831) +- Use network id for the web3_net_version return. [#822](https://github.com/paritytech/parity/pull/822) +- json-rpc web3_sha3 [#824](https://github.com/paritytech/parity/pull/824) +- remove some unused files [#819](https://github.com/paritytech/parity/pull/819) +- debug symbols for master/beta [#818](https://github.com/paritytech/parity/pull/818) +- Syntax helpers for IPC RPC [#809](https://github.com/paritytech/parity/pull/809) +- refactored loading of execution tests [#803](https://github.com/paritytech/parity/pull/803) +- Rustfmt.toml [#805](https://github.com/paritytech/parity/pull/805) +- install-partiy runs brew reinstall parity on osx [#810](https://github.com/paritytech/parity/pull/810) +- Fix mining from spinning [#807](https://github.com/paritytech/parity/pull/807) diff --git a/docs/CHANGELOG-1.2.md b/docs/CHANGELOG-1.2.md new file mode 100644 index 0000000000000000000000000000000000000000..4a9bfecd0714af2086b70f62e8e636c6eb511e09 --- /dev/null +++ b/docs/CHANGELOG-1.2.md @@ -0,0 +1,376 @@ +Note: Parity 1.2 reached End-of-Life on 2016-11-07 (EOL). + +## Parity [v1.2.4](https://github.com/paritytech/parity/releases/tag/v1.2.4) (2016-08-09) + +Parity 1.2.4 Is a maintenance release that fixes a [few](https://github.com/paritytech/parity/pull/1888/commits) issues related to mining and peer synchronization. +This release is marked as stable. + +- Backports for beta [#1888](https://github.com/paritytech/parity/pull/1888) +- BETA: fixed trace_transaction crash when block contained suicide [#1782](https://github.com/paritytech/parity/pull/1782) + +## Parity [v1.2.3](https://github.com/paritytech/parity/releases/tag/v1.2.3) (2016-07-31) + +Parity 1.2.3 is a patch release that addresses network stability issues for both Ethereum HF and Ethereum classic chains and brings a few changes to the transaction tracing API. + +#### Tracing API changes +- Added tracing for `CALLCODE`, `DELEGATECALL` and `SUICIDE` +- `trace_call` returns traces in flat format +- Added 2 new methods: `trace_rawTransaction` and `trace_replayTransaction` + +Note that to continue using tracing features in this version you need to re-sync the blockchain. This can be done by using `parity export $HOME/ethereum-chain-backup.rlp` , deleting the database usually located at `~/.parity/906a34e69aec8c0d` followed by `parity import $HOME/ethereum-chain-backup.rlp`. + +- [beta] Updating UI [#1778](https://github.com/paritytech/parity/pull/1778) +- tracing backport [#1770](https://github.com/paritytech/parity/pull/1770) +- Backport commits to beta [#1763](https://github.com/paritytech/parity/pull/1763) +- Deadlock on incoming connection (#1672) [#1675](https://github.com/paritytech/parity/pull/1675) +- [BETA] Removed DAO soft fork traces [#1640](https://github.com/paritytech/parity/pull/1640) + + +## Parity [v1.2.2](https://github.com/paritytech/parity/releases/tag/v1.2.2) (2016-07-16) + +#### New +- DAO hard-fork. + +DAO hard-fork implementation conforms to the [specification](https://blog.slock.it/hard-fork-specification-24b889e70703) and is enabled by default. + +#### Changed +- `--reseal-on-txs` defaults to `own`. +- DAO soft-fork support has been removed along with related command line options. + +#### Resolved issues +- `--db-cache-size` consuming too much memory. + `eth_getWork` RPC response additionally includes the block number. +- Skipping transactions with invalid nonces when pushing to block. +- Update sealing just once when externally importing many blocks (#1541). +- Transaction tracing skipping simple transactions (#1606). +- Other small fixes and improvements. + +Full changelog + +- DAO hard-fork (#1483) [#1636](https://github.com/paritytech/parity/pull/1636) +- Backports for beta [#1628](https://github.com/paritytech/parity/pull/1628) +- don't batch best block for branches (#1623) [#1626](https://github.com/paritytech/parity/pull/1626) +- Merge bugfixes from master to beta [#1605](https://github.com/paritytech/parity/pull/1605) +- (BETA) using block options cache instead of general cache for rocksdb [#1613](https://github.com/paritytech/parity/pull/1613) +- Backport sealing fixes to beta [#1583](https://github.com/paritytech/parity/pull/1583) +- v1.2.2 in beta [#1581](https://github.com/paritytech/parity/pull/1581) +- Skipping transactions with invalid nonces when pushing to block. (#1545) [#1547](https://github.com/paritytech/parity/pull/1547) + + +## Parity [v1.2.1](https://github.com/paritytech/parity/releases/tag/v1.2.1) (2016-07-01) + +#### New +- Options for more precise mining tuning (see below). +- Informative notification when block mined. +- HTTP signal on new work-package. +- Optimised database insertion for self-mined blocks. +- Short-circuit for local transaction gas-price approval. +- A number of issues related to mining have been fixed. + +##### Mining options +- `--author` is now required for mining. +- `--reseal-on-txs` Specify which transactions should force the node to reseal a block. By default parity updates the seal on incoming transactions to reduce transaction latency. Set this option to `none` to force updates on new blocks only. +- `--reseal-min-period` Can be used to control how often a new pending block is generated if `none` is not selected on prior option. +- `--work-queue-size` Controls how many pending blocks to keep in memory. +- `--relay-set` Can be used to enable more strict transaction verification. +- `--remove-solved` Move solved blocks from the work package queue instead of cloning them. This gives a slightly faster import speed, but means that extra solutions submitted for the same work package will go unused. +- `--notify-work` Accepts a list of URLs that will receive a POST request when new work package is available. The body of the POST message is JSON encoded and has the same format as `eth_getWork` RPC response. + +##### RPC + +`eth_getWork` RPC response additionally includes the block number. + +##### DAO soft-fork + +DAO soft-fork control options have been replaced by the single `--fork` option which disables the soft-fork by default. + +#### Changes + +- v1.2.1 in beta [#1492](https://github.com/paritytech/parity/pull/1492) +- (BETA) add artifacts [#1420](https://github.com/paritytech/parity/pull/1420) + +## Parity [v1.2.0: "Security"](https://github.com/paritytech/parity/releases/tag/v1.2.0) (2016-06-24) + +[Blog post](https://blog.parity.io/announcing-parity-1-2/) + +#### New + +- Transaction signing UI. +- IPC/RPC module. +- Optimised mining support. +- Windows build. +- DAO soft-fork support. + +##### Transaction signing UI + +This is a new framework for signing transactions. It fulfills three requirements: +- You should never have to type your passwords into a Dapp. +- No Javascript code should ever hold a secret. +- No transaction should ever be signed without the consent of the user. + +The feature is enabled through the `--signer` flag. When enabled, the user must ensure at least one "Signer UI" is set-up for managing transaction confirmation. There are two such UIs available; one through a Google Chrome Extension, separately installable and the second through a special web page hosted locally. Set-up must be done once for each such UI, through copying and pasting a token from the output console of Parity into the UI. Specific instructions are given in the UI. + +From this point on, no transaction may ever be signed by Parity except through one of these allowed Signer UIs, and no password should ever be entered anywhere else. + +##### IPC/RPC module and Mist/Geth compatibility + +Should be started with `--geth` to ensure Mist compatibility. + +##### Optimised mining support + +Numerous improvements and optimisations have been added to our mining implementation. A large "active queue" ensures that late-included transactions are included in the mined block without sacrificing older results from latent-reported `ethminer` results. + +##### Windows build + +We're happy to announce full Windows support with 1.2! + +##### Soft-fork + +This release includes support for the proposed [DAO soft-fork](https://docs.google.com/document/d/10RktunzjKNfp6Y8Cu4EhR5V9IqxEZq42LU126EYhWY4/pub). Upon upgrade, all mining nodes can vote for or against the soft fork (this is done through altering the block gas limit; a gas limit of at most 4M results in the soft-fork being triggered). + +By default, nodes vote "for" the DAO soft-fork (and try to reduce the gas limit to 3.1M). To vote against the soft-fork (keeping it at 4.7M), run with `--dont-help-rescue-dao`. Not upgrading is not recommended; if the majority votes with a soft-fork, an upgrade will be necessary to mine on the correct chain. + +#### Changed +- Fast pruning method is now default for a fresh sync. +- Web UI renamed to Dapps UI. +- JSONRPC and Dapps UI enabled by default. +- CLI options ending `-off` renamed to GNU-consistent prefix `--no-`. +- Dynamic gas-pricing (data feed and statistical techniques used to determine optimum gas prices). + +Full changes: + +- Signer enabled by default for UI [#1417](https://github.com/paritytech/parity/pull/1417) +- Remove experimental pruning options. [#1415](https://github.com/paritytech/parity/pull/1415) +- Fixing interface and port for parity ui [#1414](https://github.com/paritytech/parity/pull/1414) +- Configurable gas limit cap. [#1405](https://github.com/paritytech/parity/pull/1405) +- Bumping TopBar, Minimal SignerUI and wallet [#1413](https://github.com/paritytech/parity/pull/1413) +- Sync: Update highest block for progress reporting [#1411](https://github.com/paritytech/parity/pull/1411) +- Tweaked CLI options for the release [#1407](https://github.com/paritytech/parity/pull/1407) +- Further rocksdb tuning [#1409](https://github.com/paritytech/parity/pull/1409) +- Fixing jit compilation [#1406](https://github.com/paritytech/parity/pull/1406) +- Bump clippy [#1403](https://github.com/paritytech/parity/pull/1403) +- Shortcut SF condition when canon known [#1401](https://github.com/paritytech/parity/pull/1401) +- Additional assertions for internal state of queue [#1402](https://github.com/paritytech/parity/pull/1402) +- Replace deprecated hashdb trait names [#1394](https://github.com/paritytech/parity/pull/1394) +- rpc api by default for ipc [#1400](https://github.com/paritytech/parity/pull/1400) +- Ensure judging the SF trigger by relative branch [#1399](https://github.com/paritytech/parity/pull/1399) +- Signer with unlocked account working as expected. [#1398](https://github.com/paritytech/parity/pull/1398) +- Make --signer default. [#1392](https://github.com/paritytech/parity/pull/1392) +- Presale wallet [#1376](https://github.com/paritytech/parity/pull/1376) +- Removing signer connection limit [#1396](https://github.com/paritytech/parity/pull/1396) +- Optional gas price in transactions come from statistics [#1388](https://github.com/paritytech/parity/pull/1388) +- Update README.md with cargo install [ci-skip] [#1389](https://github.com/paritytech/parity/pull/1389) +- Fixing possible overflow during multiplication [#1381](https://github.com/paritytech/parity/pull/1381) +- Update SF to latest spec [#1386](https://github.com/paritytech/parity/pull/1386) +- Sync optimization [#1385](https://github.com/paritytech/parity/pull/1385) +- Fixing order of if statements to avoid overflows. [#1384](https://github.com/paritytech/parity/pull/1384) +- New topbar & signer UI [#1383](https://github.com/paritytech/parity/pull/1383) +- Install trigger for DAO-rescue soft-fork. [#1329](https://github.com/paritytech/parity/pull/1329) +- Rocksdb flush/compact limit [#1375](https://github.com/paritytech/parity/pull/1375) +- CentOS Dockerfile [#1377](https://github.com/paritytech/parity/pull/1377) +- RPC method to return number of unconfirmed transactions... [#1371](https://github.com/paritytech/parity/pull/1371) +- bump jsonrpc-http-server [#1369](https://github.com/paritytech/parity/pull/1369) +- Fix lock order when updating sealing [#1364](https://github.com/paritytech/parity/pull/1364) +- Update sealing on new transactions [#1365](https://github.com/paritytech/parity/pull/1365) +- Fixed panic on aborted connection [#1370](https://github.com/paritytech/parity/pull/1370) +- importing presale wallet [#1368](https://github.com/paritytech/parity/pull/1368) +- Set default database file size large enough [#1363](https://github.com/paritytech/parity/pull/1363) +- Reserved peers rpc API [#1360](https://github.com/paritytech/parity/pull/1360) +- Fixing replacing transaction with lower gas_price result. [#1343](https://github.com/paritytech/parity/pull/1343) +- fixed migration of empty pruning dir [#1362](https://github.com/paritytech/parity/pull/1362) +- Transaction processing queue [#1335](https://github.com/paritytech/parity/pull/1335) +- Fixing last nonce values in case transaction is replaced [#1359](https://github.com/paritytech/parity/pull/1359) +- docopt is an optional dependency of ethkey and ethstore [#1358](https://github.com/paritytech/parity/pull/1358) +- Fixing clippy warnings [#1354](https://github.com/paritytech/parity/pull/1354) +- Reduce locking when syncing [#1357](https://github.com/paritytech/parity/pull/1357) +- removed unnecessary logs [#1356](https://github.com/paritytech/parity/pull/1356) +- Updating parity-dapps [#1353](https://github.com/paritytech/parity/pull/1353) +- moved keystore tests files from util to ethstore [#1352](https://github.com/paritytech/parity/pull/1352) +- removed redundant bigint deps [#1351](https://github.com/paritytech/parity/pull/1351) +- Reopen "reserved peers and reserved-only flag" [#1350](https://github.com/paritytech/parity/pull/1350) +- Configurable rocksdb cache size [#1348](https://github.com/paritytech/parity/pull/1348) +- Fixing future order and errors when reaching limit. [#1346](https://github.com/paritytech/parity/pull/1346) +- Removing priority on local transactions [#1342](https://github.com/paritytech/parity/pull/1342) +- Revert "Reserved peers, reserved-only flag" [#1349](https://github.com/paritytech/parity/pull/1349) +- Sync attack defense: Deactivate peers on invalid block bodies [#1345](https://github.com/paritytech/parity/pull/1345) +- Reserved peers, reserved-only flag [#1347](https://github.com/paritytech/parity/pull/1347) +- CI for ethkey and ethstore [#1341](https://github.com/paritytech/parity/pull/1341) +- Fixed empty block body composition [#1340](https://github.com/paritytech/parity/pull/1340) +- Provide a signer UI token by default. [#1334](https://github.com/paritytech/parity/pull/1334) +- docker uses rustup, fixes #1337 [#1344](https://github.com/paritytech/parity/pull/1344) +- Fixed network service dispose [#1339](https://github.com/paritytech/parity/pull/1339) +- Sync: Cache last sync round block parents [#1331](https://github.com/paritytech/parity/pull/1331) +- secret store separated from util [#1304](https://github.com/paritytech/parity/pull/1304) +- --geth prevent getTransactionReceipt from using pending. [#1325](https://github.com/paritytech/parity/pull/1325) +- Fixing locks order in miner. [#1328](https://github.com/paritytech/parity/pull/1328) +- Update default gas limit, rename field [#1324](https://github.com/paritytech/parity/pull/1324) +- Use constants for DatabaseConfig [#1318](https://github.com/paritytech/parity/pull/1318) +- Fixing clippy warnings [#1321](https://github.com/paritytech/parity/pull/1321) +- Bumping topbar. Fixing ws server closing when suspending [#1312](https://github.com/paritytech/parity/pull/1312) +- Syncing fix [#1320](https://github.com/paritytech/parity/pull/1320) +- Filling-in optional fields of TransactionRequest... [#1305](https://github.com/paritytech/parity/pull/1305) +- Removing MakerOTC and DAO dapps [#1319](https://github.com/paritytech/parity/pull/1319) +- Disabling ethcore_set* APIs by default (+ Status page update) [#1315](https://github.com/paritytech/parity/pull/1315) +- fixed #1180 [#1282](https://github.com/paritytech/parity/pull/1282) +- Network start/stop [#1313](https://github.com/paritytech/parity/pull/1313) +- Additional logging for own transactions in queue [#1311](https://github.com/paritytech/parity/pull/1311) +- DAO Rescue soft fork [#1309](https://github.com/paritytech/parity/pull/1309) +- Appveyor config for windows build+installer [#1302](https://github.com/paritytech/parity/pull/1302) +- Key load avoid warning [#1303](https://github.com/paritytech/parity/pull/1303) +- More meaningful errors when sending transaction [#1290](https://github.com/paritytech/parity/pull/1290) +- Gas price statistics. [#1291](https://github.com/paritytech/parity/pull/1291) +- Fix read-ahead bug. [#1298](https://github.com/paritytech/parity/pull/1298) +- firewall rules for windows installer [#1297](https://github.com/paritytech/parity/pull/1297) +- x64 program files path for installer [#1296](https://github.com/paritytech/parity/pull/1296) +- Fixed loosing peers on incoming connections. [#1293](https://github.com/paritytech/parity/pull/1293) +- fixed #1261, overflow when calculating work [#1283](https://github.com/paritytech/parity/pull/1283) +- snappy and minor block compression [#1286](https://github.com/paritytech/parity/pull/1286) +- clarify build instructions [#1287](https://github.com/paritytech/parity/pull/1287) +- fixed #1255 [#1280](https://github.com/paritytech/parity/pull/1280) +- bump rust-crypto [#1289](https://github.com/paritytech/parity/pull/1289) +- Security audit issues fixed [#1279](https://github.com/paritytech/parity/pull/1279) +- Fixing origin/host validation [#1273](https://github.com/paritytech/parity/pull/1273) +- windows installer + parity start ui cli option [#1284](https://github.com/paritytech/parity/pull/1284) +- ipc lib version bump [#1285](https://github.com/paritytech/parity/pull/1285) +- Syncing improvements [#1274](https://github.com/paritytech/parity/pull/1274) +- removed redundant if condition [#1270](https://github.com/paritytech/parity/pull/1270) +- Naive chunk creation, snapshotting [#1263](https://github.com/paritytech/parity/pull/1263) +- Fixing generating new token while another parity instance is running. [#1272](https://github.com/paritytech/parity/pull/1272) +- README: rustup and windows instructions [#1266](https://github.com/paritytech/parity/pull/1266) +- Windows build [#1253](https://github.com/paritytech/parity/pull/1253) +- removed try_seal from MiningBlockChainClient [#1262](https://github.com/paritytech/parity/pull/1262) +- simplified block opening [#1232](https://github.com/paritytech/parity/pull/1232) +- Clippy bump [#1259](https://github.com/paritytech/parity/pull/1259) +- Fixing uint ASM macros compilation [#1258](https://github.com/paritytech/parity/pull/1258) +- Signer port returned from RPC + Topbar showing count of unconfirmed transactions. [#1252](https://github.com/paritytech/parity/pull/1252) +- codegen - avoid unwraps leading to compilation crash [#1250](https://github.com/paritytech/parity/pull/1250) +- Dapps bump [#1257](https://github.com/paritytech/parity/pull/1257) +- Windows named pipes [#1254](https://github.com/paritytech/parity/pull/1254) +- remove unsafety from util/hash.rs and util/bigint/uint.rs [#1236](https://github.com/paritytech/parity/pull/1236) +- Fixing CORS settings for special values: * & null. [#1247](https://github.com/paritytech/parity/pull/1247) +- JSONRPC test strings avoid using \ char [#1246](https://github.com/paritytech/parity/pull/1246) +- Tests for JSON serialisation of statediff/vmtrace [#1241](https://github.com/paritytech/parity/pull/1241) +- Bumping Dapps & TopBar to newest version. [#1245](https://github.com/paritytech/parity/pull/1245) +- keys import [#1240](https://github.com/paritytech/parity/pull/1240) +- Splitting RPC Apis into more fine-grained sets [#1234](https://github.com/paritytech/parity/pull/1234) +- Refactor triedb constructors to error on invalid state root [#1230](https://github.com/paritytech/parity/pull/1230) +- Signer RPC method to check if signer is enabled [#1238](https://github.com/paritytech/parity/pull/1238) +- Fixing signer behaviour when confirming transaction with wrong password. [#1237](https://github.com/paritytech/parity/pull/1237) +- SystemUIs authorization [#1233](https://github.com/paritytech/parity/pull/1233) +- IPC path for tesetnet with --geth compatibility [#1231](https://github.com/paritytech/parity/pull/1231) +- Transaction tracing for eth_call [#1210](https://github.com/paritytech/parity/pull/1210) +- Removing compilation warnings [#1227](https://github.com/paritytech/parity/pull/1227) +- Allowing connections only from chrome-extension and self-hosted client [#1226](https://github.com/paritytech/parity/pull/1226) +- Clippy bump & fixing warnings [#1219](https://github.com/paritytech/parity/pull/1219) +- Bumping serde & syntex [#1216](https://github.com/paritytech/parity/pull/1216) +- Minimal Signer UI (System UI) exposed over websockets. [#1211](https://github.com/paritytech/parity/pull/1211) +- Switch RPC namespace form ethcore_ to trace_ [#1208](https://github.com/paritytech/parity/pull/1208) +- Verify the state root exists before creating a State [#1217](https://github.com/paritytech/parity/pull/1217) +- Integrate state diffing into the ethcore JSONRPC [#1206](https://github.com/paritytech/parity/pull/1206) +- Updating topbar to latest version [#1220](https://github.com/paritytech/parity/pull/1220) +- Loading local Dapps from FS. [#1214](https://github.com/paritytech/parity/pull/1214) +- Ipc serialization & protocol fixes [#1188](https://github.com/paritytech/parity/pull/1188) +- Have Ext::ret take self by value [#1187](https://github.com/paritytech/parity/pull/1187) +- Simple WebSockets notification about new request [#1202](https://github.com/paritytech/parity/pull/1202) +- Removing leftovers of ethminer [#1207](https://github.com/paritytech/parity/pull/1207) +- fixed #1204 [#1205](https://github.com/paritytech/parity/pull/1205) +- VM tracing and JSON RPC endpoint for it. [#1169](https://github.com/paritytech/parity/pull/1169) +- devtools helpers extended [#1186](https://github.com/paritytech/parity/pull/1186) +- Networking refactoring [#1172](https://github.com/paritytech/parity/pull/1172) +- Client & Miner refactoring [#1195](https://github.com/paritytech/parity/pull/1195) +- update readme [#1201](https://github.com/paritytech/parity/pull/1201) +- Simple signing queue, confirmation APIs exposed in signer WebSockets. [#1182](https://github.com/paritytech/parity/pull/1182) +- Using ordered hashmap to keep the order of dapps on home screen [#1199](https://github.com/paritytech/parity/pull/1199) +- Disabling `ethcore` by default, adding x-frame-options header to dapps. [#1197](https://github.com/paritytech/parity/pull/1197) +- transaction count verifier tests [#1196](https://github.com/paritytech/parity/pull/1196) +- expunge x! and xx! from the codebase [#1192](https://github.com/paritytech/parity/pull/1192) +- Database service upgrade (from the ipc branch) [#1185](https://github.com/paritytech/parity/pull/1185) +- stop eth_syncing from returning true forever [#1181](https://github.com/paritytech/parity/pull/1181) +- Sync fixes and tweaks [#1164](https://github.com/paritytech/parity/pull/1164) +- Exposing RPC over Signer WebSockets [#1167](https://github.com/paritytech/parity/pull/1167) +- implement missing rpc methods and tests [#1171](https://github.com/paritytech/parity/pull/1171) +- json ipc server version bump [#1170](https://github.com/paritytech/parity/pull/1170) +- Updated dependencies for windows build [#1173](https://github.com/paritytech/parity/pull/1173) +- Framework for improved RPC unit tests [#1141](https://github.com/paritytech/parity/pull/1141) +- remove all possible unsafe code in crypto [#1168](https://github.com/paritytech/parity/pull/1168) +- Base for Signer Websockets server [#1158](https://github.com/paritytech/parity/pull/1158) +- Write queue to speed-up db ipc [#1160](https://github.com/paritytech/parity/pull/1160) +- Fixing few clippy warnings [#1163](https://github.com/paritytech/parity/pull/1163) +- Change eth_signAndSendTransaction to personal_SignAndSendTransaction [#1154](https://github.com/paritytech/parity/pull/1154) +- Support "earliest" and specific block parameters in RPC where possible [#1149](https://github.com/paritytech/parity/pull/1149) +- migration fixes [#1155](https://github.com/paritytech/parity/pull/1155) +- Empty trusted signer crate with it's general purpose described. [#1150](https://github.com/paritytech/parity/pull/1150) +- More bootnodes for morden. [#1153](https://github.com/paritytech/parity/pull/1153) +- move existing rpc tests into mocked module [#1151](https://github.com/paritytech/parity/pull/1151) +- Bloomchain [#1014](https://github.com/paritytech/parity/pull/1014) +- Renaming dapps repos. Updating dapps [#1142](https://github.com/paritytech/parity/pull/1142) +- fixed pending transactions [#1147](https://github.com/paritytech/parity/pull/1147) +- Basic benches to provide metrics for ipc optimizations [#1145](https://github.com/paritytech/parity/pull/1145) +- Fixing clippy warnings [#1148](https://github.com/paritytech/parity/pull/1148) +- correct signature of SecTrieDB::raw_mut [#1143](https://github.com/paritytech/parity/pull/1143) +- Merge to master and start hypervisor for import/export [#1138](https://github.com/paritytech/parity/pull/1138) +- Bumping clippy. Fixing warnings [#1139](https://github.com/paritytech/parity/pull/1139) +- Display progress when importing [#1136](https://github.com/paritytech/parity/pull/1136) +- foundation of simple db migration [#1128](https://github.com/paritytech/parity/pull/1128) +- Fixpending [#1074](https://github.com/paritytech/parity/pull/1074) +- Sync: Propagate uncles and fix status reporting [#1134](https://github.com/paritytech/parity/pull/1134) +- Coloured, padding logging. [#1133](https://github.com/paritytech/parity/pull/1133) +- Importing [#1132](https://github.com/paritytech/parity/pull/1132) +- Have `die_with_error` use `fmt::Display` rather than Debug [#1116](https://github.com/paritytech/parity/pull/1116) +- Exporting [#1129](https://github.com/paritytech/parity/pull/1129) +- Sign and send transaction [#1124](https://github.com/paritytech/parity/pull/1124) +- Fixing unused imports warnings [#1125](https://github.com/paritytech/parity/pull/1125) +- Adding info messages on mined blocks [#1127](https://github.com/paritytech/parity/pull/1127) +- Fix styling - don't mix spaces with tabs!!! [#1123](https://github.com/paritytech/parity/pull/1123) +- Fix is_syncing so it's false as long as the update is trivial. [#1122](https://github.com/paritytech/parity/pull/1122) +- Relock unlocked accounts after first use [#1120](https://github.com/paritytech/parity/pull/1120) +- Avoid importing keys into wrong place. [#1119](https://github.com/paritytech/parity/pull/1119) +- Implement receipt's gasUsed field [#1118](https://github.com/paritytech/parity/pull/1118) +- New dapps & query parameter handling [#1113](https://github.com/paritytech/parity/pull/1113) +- pretty print trace error [#1098](https://github.com/paritytech/parity/pull/1098) +- New syncing strategy [#1095](https://github.com/paritytech/parity/pull/1095) +- ethcore-db crate [#1097](https://github.com/paritytech/parity/pull/1097) +- Fix the default for pruning. [#1107](https://github.com/paritytech/parity/pull/1107) +- Make Id/ID and db/Db/DB usage consistent [#1105](https://github.com/paritytech/parity/pull/1105) +- Miner holds it's own copy of spec/engine [#1091](https://github.com/paritytech/parity/pull/1091) +- Apps listing API & Home webapp. [#1101](https://github.com/paritytech/parity/pull/1101) +- CLI option for using JITEVM [#1103](https://github.com/paritytech/parity/pull/1103) +- Fix up the seal fields in RPC output [#1096](https://github.com/paritytech/parity/pull/1096) +- Fixing some warnings [#1102](https://github.com/paritytech/parity/pull/1102) +- fixed incorrect decoding of header seal_fields. added tests. #1090 [#1094](https://github.com/paritytech/parity/pull/1094) +- Bumping Clippy [#1093](https://github.com/paritytech/parity/pull/1093) +- Injectable topbar support. [#1092](https://github.com/paritytech/parity/pull/1092) +- New syncing part 1: Block collection [#1088](https://github.com/paritytech/parity/pull/1088) +- Moving all Client public API types to separate mod & binary serialization codegen for that mod [#1051](https://github.com/paritytech/parity/pull/1051) +- Subdomains support in content server (webapps server). [#1082](https://github.com/paritytech/parity/pull/1082) +- Fix uncle getter [#1087](https://github.com/paritytech/parity/pull/1087) +- Provide fallback for usd-per-eth option when offline. [#1085](https://github.com/paritytech/parity/pull/1085) +- path centralized [#1083](https://github.com/paritytech/parity/pull/1083) +- Limiting result of the execution to execution-specific errors [#1071](https://github.com/paritytech/parity/pull/1071) +- Configurable keys security [#1080](https://github.com/paritytech/parity/pull/1080) +- comma delimeting multiple cors headers [#1078](https://github.com/paritytech/parity/pull/1078) +- Update error message [#1081](https://github.com/paritytech/parity/pull/1081) +- Updating dapp-wallet [#1076](https://github.com/paritytech/parity/pull/1076) +- Fixed connecting to local nodes on startup [#1070](https://github.com/paritytech/parity/pull/1070) +- Validate signature in Tx queue [#1068](https://github.com/paritytech/parity/pull/1068) +- moving deps to ethcore/hyper and bumping jsonrpc-http-server version [#1067](https://github.com/paritytech/parity/pull/1067) +- Updating status page. Bringing back wallet [#1064](https://github.com/paritytech/parity/pull/1064) +- Fix --geth IPC for MacOS. [#1062](https://github.com/paritytech/parity/pull/1062) +- Fixing formatter for defaultExtraData [#1060](https://github.com/paritytech/parity/pull/1060) +- --geth IPC compatibility [#1059](https://github.com/paritytech/parity/pull/1059) +- Moving dependencies to ethcore & uniforming syntax libs through all crates [#1050](https://github.com/paritytech/parity/pull/1050) +- update hyper branch mio [#1054](https://github.com/paritytech/parity/pull/1054) +- IPC lib update [#1047](https://github.com/paritytech/parity/pull/1047) +- Updating hyper-mio revision [#1048](https://github.com/paritytech/parity/pull/1048) +- Bump ipc-lib version [#1046](https://github.com/paritytech/parity/pull/1046) +- Tidy up CLI options and make JSONRPC & webapps on by default. [#1045](https://github.com/paritytech/parity/pull/1045) +- Fixing clippy warnings [#1044](https://github.com/paritytech/parity/pull/1044) +- Fixing RPC modules compatibility [#1041](https://github.com/paritytech/parity/pull/1041) +- Fixing hyper-mio revision [#1043](https://github.com/paritytech/parity/pull/1043) +- Updating locations of webapp stuff [#1040](https://github.com/paritytech/parity/pull/1040) +- JSON-RPC over IPC [#1039](https://github.com/paritytech/parity/pull/1039) +- Update nix/mio for ARM [#1036](https://github.com/paritytech/parity/pull/1036) +- Basic Authority [#991](https://github.com/paritytech/parity/pull/991) +- Prioritizing of local transaction [#1023](https://github.com/paritytech/parity/pull/1023) +- Version 1.2 [#1030](https://github.com/paritytech/parity/pull/1030) +- Bumping status page [#1033](https://github.com/paritytech/parity/pull/1033) diff --git a/docs/CHANGELOG-1.3.md b/docs/CHANGELOG-1.3.md new file mode 100644 index 0000000000000000000000000000000000000000..d380eaccc2a32eb36540d45a3380a749f4225573 --- /dev/null +++ b/docs/CHANGELOG-1.3.md @@ -0,0 +1,502 @@ +Note: Parity 1.3 reached End-of-Life on 2017-01-19 (EOL). + +## Parity [v1.3.15](https://github.com/paritytech/parity/releases/tag/v1.3.15) (2016-12-10) + +This patch release fixes an issue with syncing on the Ropsten test network. + +- Backporting to stable [#3793](https://github.com/paritytech/parity/pull/3793) + +## Parity [v1.3.14](https://github.com/paritytech/parity/releases/tag/v1.3.14) (2016-11-25) + +Parity 1.3.14 fixes a few stability issues and adds support for the Ropsten testnet. + +- Backporting to stable [#3616](https://github.com/paritytech/parity/pull/3616) + +## Parity [v1.3.13](https://github.com/paritytech/parity/releases/tag/v1.3.13) (2016-11-18) + +This release fixes an issue with EIP-155 transactions being allowed into the transaction pool. + +- [stable] Check tx signatures before adding to the queue. [#3521](https://github.com/paritytech/parity/pull/3521) +- Fix Stable Docker Build [#3479](https://github.com/paritytech/parity/pull/3479) + +## Parity [v1.3.12](https://github.com/paritytech/parity/releases/tag/v1.3.12) (2016-11-16) + +This stable release enables EIP-155/160/161/170 hardfork at block 2675000 (1885000 for test network). + +- [stable] EIP-170 [#3462](https://github.com/paritytech/parity/pull/3462) +- #3035 Backport to stable [#3441](https://github.com/paritytech/parity/pull/3441) + +## Parity [v1.3.11](https://github.com/paritytech/parity/releases/tag/v1.3.11) (2016-11-11) + +This is a maintenance release for the stable series to delay the EIP-155/160/161 hard fork transition. **Update from 1.3.10 is mandatory**. It also deprecates and disables the old Parity UI. + +- [stable] Disable HF and UI [#3372](https://github.com/paritytech/parity/pull/3372) +- [stable] EIP-155 update with Vitalik's new test vectors (#3166) [#3190](https://github.com/paritytech/parity/pull/3190) +- Backport EIP-150 to stable [#2672](https://github.com/paritytech/parity/pull/2672) +- Create gitlab-ci.yml for stable [#2517](https://github.com/paritytech/parity/pull/2517) + +## Parity [v1.3.10](https://github.com/paritytech/parity/releases/tag/v1.3.10) (2016-11-04) + +The latest 1.3 series release, now considered stable. + +This includes several additional optimisations and fixes together with provisional support for the upcoming hard fork for EIP155/160/161. + +- Stable branch reset to 1.3.10 [#3156](https://github.com/paritytech/parity/pull/3156) +- Backporting to beta [#3149](https://github.com/paritytech/parity/pull/3149) +- apply post-consolidation migrations after consolidating (BETA) [#3048](https://github.com/paritytech/parity/pull/3048) +- [beta] Fix the brainwallet functionality. (#2994) [#3005](https://github.com/paritytech/parity/pull/3005) +- Bumping json-ipc-server [#2989](https://github.com/paritytech/parity/pull/2989) +- Backports for 1.3.10 [#2987](https://github.com/paritytech/parity/pull/2987) + +## Parity [v1.3.9](https://github.com/paritytech/parity/releases/tag/v1.3.9) (2016-10-21) + +This release enables EIP-150 hard fork for Ethereum Classic chain and resolves a few stability and performance issues, such as: +- Interrupted syncing on the test network. +- Block import delays caused by a large number of incoming transactions. A full re-sync is recommended for performance improvement to take effect. + +Full changes: +- [beta] Resolve morden fork [#2776](https://github.com/paritytech/parity/pull/2776) +- Fixing botched merge [#2767](https://github.com/paritytech/parity/pull/2767) +- Backports for beta [#2764](https://github.com/paritytech/parity/pull/2764) +- Introduce EIP150 hardfork block for ETC [#2736](https://github.com/paritytech/parity/pull/2736) +- [beta] fix issues with no test dir present (#2659) [#2724](https://github.com/paritytech/parity/pull/2724) +- [beta] Bumping jsonrpc-http-server [#2715](https://github.com/paritytech/parity/pull/2715) +- [beta] Fix migration system, better errors [#2661](https://github.com/paritytech/parity/pull/2661) + +## Parity [v1.3.8](https://github.com/paritytech/parity/releases/tag/v1.3.8) (2016-10-15) + +Parity 1.3.8 is our EIP150 hard-fork compliant release. + +Running this will enact a mild change of the protocol at block number 2,463,000 which should occur on Tuesday 18th October 2016 at approximately 12:20 London time (BST). This change alters the gas prices for a number of operations, mainly centring around i/o intensive Merkle trie lookups (`BALANCE`, `EXTCODESIZE` &c.) and state-trie polluters (`SUICIDE`, `CREATE` and `CALL`). These operations were heavily underpriced, an oversight which lead to the recent degradation of network service. The full details of the alteration are specified in [EIP-150](https://github.com/ethereum/EIPs/issues/150). + +Additionally several issues have been fixed including: +- a transaction queue limitation leading to dropped transactions; +- a synchronisation issue leading to stalls when syncing; + +And some small features including database performance improvements and additional logging. + +#### Upgrading private chain specification files. + +All the chain specification files now have EIP-150 rules enabled by default. To continue using the chain add the `eip150Transition` key under `Engine/ethash/params` and set it to a future transition block as shown in [this example](https://github.com/paritytech/parity/blob/85eeb3ea6e5e21ad8e5644241edf82eb8069f536/ethcore/res/ethereum/morden.json#L13). + +The key related to homestead transition has been renamed from `frontierCompatibilityModeLimit` to `homesteadTransition`. + +#### Full changes + +- [beta] EIP150.1c [#2599](https://github.com/paritytech/parity/pull/2599) +- Remove count limit for local transactions [#2634](https://github.com/paritytech/parity/pull/2634) +- Tweak DB and mining defaults [#2598](https://github.com/paritytech/parity/pull/2598) +- Revert "Bloom upgrade in beta" [#2635](https://github.com/paritytech/parity/pull/2635) +- Bloom upgrade in beta [#2609](https://github.com/paritytech/parity/pull/2609) +- Backports to beta [#2628](https://github.com/paritytech/parity/pull/2628) + +## Parity [v1.3.7](https://github.com/paritytech/parity/releases/tag/v1.3.7) (2016-10-12) + +This release contains fixes to reduce memory usage under the DoS attack and improve transaction relay. + +- Configurable history size in beta [#2587](https://github.com/paritytech/parity/pull/2587) +- Backports to beta [#2592](https://github.com/paritytech/parity/pull/2592) + + +## Parity [v1.3.6](https://github.com/paritytech/parity/releases/tag/v1.3.6) (2016-10-11) + +Parity 1.3.6 is another hotfix release to address transaction spam and deal with stability issues. With this release transaction pool gas limit no longer applies to local transactions. Full list of changes is available here: + +- Backports to beta v1.3.6 [#2571](https://github.com/paritytech/parity/pull/2571) +- Use global state cache when mining [#2529](https://github.com/paritytech/parity/pull/2529) +- Transaction queue limited by gas [#2528](https://github.com/paritytech/parity/pull/2528) + +## Parity [v1.3.5](https://github.com/paritytech/parity/releases/tag/v1.3.5) (2016-10-08) + +1.3.5 is a hotfix release for the transaction propagation issue. Transaction pool limit is now calculated based on the block gas limit. + +- Update appveyor rustc [beta] [#2521](https://github.com/paritytech/parity/pull/2521) +- Increase size of transaction queue by default [#2519](https://github.com/paritytech/parity/pull/2519) + +## Parity [v1.3.4](https://github.com/paritytech/parity/releases/tag/v1.3.4) (2016-10-07) + +Parity 1.3.4 release contains more optimizations to internal caching as well as stability improvements. + +It also introduces an ability for miners to choose a transaction ordering strategy: + + --tx-queue-strategy S Prioritization strategy used to order transactions + in the queue. S may be: + gas - Prioritize txs with low gas limit; + gas_price - Prioritize txs with high gas price; + gas_factor - Prioritize txs using gas price + and gas limit ratio [default: gas_factor]. + +- Backport to beta [#2518](https://github.com/paritytech/parity/pull/2518) +- [beta] Fixing RPC Filter conversion to EthFilter [#2501](https://github.com/paritytech/parity/pull/2501) +- [beta] Using pending block only if is not old [#2515](https://github.com/paritytech/parity/pull/2515) +- Backports into beta [#2512](https://github.com/paritytech/parity/pull/2512) +- CLI to specify queue ordering strategy [#2494](https://github.com/paritytech/parity/pull/2494) +- Fix ethstore opening all key files in the directory at once (BETA) [#2472](https://github.com/paritytech/parity/pull/2472) +- Beta backports [#2465](https://github.com/paritytech/parity/pull/2465) +- IPC-library dependency fork & bump for beta [#2455](https://github.com/paritytech/parity/pull/2455) + +## Parity [v1.3.3](https://github.com/paritytech/parity/releases/tag/v1.3.3) (2016-10-04) + +1.3.3 is another hotfix release for the DoS attack + +- Jumptable cache [#2435](https://github.com/paritytech/parity/pull/2435) +- fix broken beta compilation (backport to beta) [#2414](https://github.com/paritytech/parity/pull/2414) +- Run inplace upgrades after version update [#2411](https://github.com/paritytech/parity/pull/2411) + +## Parity [v1.3.2](https://github.com/paritytech/parity/releases/tag/v1.3.2) (2016-09-29) + +This is a hotfix release to address stability and performance issues uncovered during the network DoS attack. Full list of changes is available [here](https://github.com/paritytech/parity/compare/v1.3.1...v1.3.2) + +- Beta Backports [#2396](https://github.com/paritytech/parity/pull/2396) +- Fixing penalization in future [#2493](https://github.com/paritytech/parity/pull/2493) +- A quick fix for missing tree route blocks [#2400](https://github.com/paritytech/parity/pull/2400) +- Cache the fork block header after snapshot restoration [#2391](https://github.com/paritytech/parity/pull/2391) +- correct sync memory usage calculation (BETA) [#2386](https://github.com/paritytech/parity/pull/2386) +- Accounts bloom [#2357](https://github.com/paritytech/parity/pull/2357) +- Disable colors when generating signer token. [#2379](https://github.com/paritytech/parity/pull/2379) +- Fixing jit feature compilation [#2376](https://github.com/paritytech/parity/pull/2376) +- Clear state cache on sealed block import [#2377](https://github.com/paritytech/parity/pull/2377) +- DIV optimization (beta) [#2353](https://github.com/paritytech/parity/pull/2353) +- Canonical state cache [#2308](https://github.com/paritytech/parity/pull/2308) +- Reorder transaction_by_hash to favour canon search [#2331](https://github.com/paritytech/parity/pull/2331) +- Lenient bytes deserialization [#2340](https://github.com/paritytech/parity/pull/2340) +- Penalize transactions with gas above gas limit [#2271](https://github.com/paritytech/parity/pull/2271) +- Peek transaction queue via RPC [#2270](https://github.com/paritytech/parity/pull/2270) +- Handle RLP to string UTF-8 decoding errors (#2217) [#2226](https://github.com/paritytech/parity/pull/2226) +- Fixing compilation without default features [beta] [#2207](https://github.com/paritytech/parity/pull/2207) +- Avoid cloning clean stuff [beta backport] [#2173](https://github.com/paritytech/parity/pull/2173) +- v1.3.2 in beta [#2200](https://github.com/paritytech/parity/pull/2200) + +## Parity [v1.3.1](https://github.com/paritytech/parity/releases/tag/v1.3.1) (2016-09-11) + +1.3.1 includes many [bugfixes](https://github.com/paritytech/parity/commit/2a82fa0a47b00bedfec520a2fdd3cc31aa4ccd8c). Critical ones: +- **Chain reorganisation fix** Transaction receipts / traces were sometimes linked with incorrect block hash. Fixed in https://github.com/paritytech/parity/commit/a9587f8965a32c84973c35ce1c8d51d07044143f +- **Trace overflow fix** Overflow which occurred during tracing. Fixed in https://github.com/paritytech/parity/pull/1979 + +- Backports to beta [#2068](https://github.com/paritytech/parity/pull/2068) +- Fixing serde overflow error (#1977) [#2030](https://github.com/paritytech/parity/pull/2030) +- Simplified db pruning detection in beta [#1924](https://github.com/paritytech/parity/pull/1924) +- Backports to beta [#1919](https://github.com/paritytech/parity/pull/1919) + +## Parity [v1.3.0: "Acuity"](https://github.com/paritytech/parity/releases/tag/v1.3.0) (2016-08-12) + +As well as many bug fixes, 1.3.0 includes a number of important improvements including: +- **Optimisations** Heavily optimised block/transaction processing core - up to 2x faster than 1.2 series. +- **Database compression** Databases take as much as 30% less storage than before. +- **State snapshotting** An installation synchronised from scratch in 1-2 minutes can be made after downloading the 140MB state snapshot. See [the wiki](https://github.com/paritytech/parity/wiki/Getting-Synced) for more information. +- **Process isolation** The networking/chain-synchronisation is now a fully independent process. + +Incremental improvements include: +- Additional [RPCs](https://github.com/paritytech/parity/wiki/JSONRPC) for transaction tracing, state diffing, VM tracing, asynchronous transaction posting, accounts metadata and message signing. +- Improved logging, including for chain reorganisations. +- Added a `--fast-and-loose` option for additional speed-ups which can compromise integrity on a dirty shutdown. +- Column families to ensure maximal inter-database integrity. +- Key naming includes date/time of creation. +- Various improvements to networking robustness and performance. +- Solidity compilation supported through RPC if `solc` is available. +- Various improvements to the miner including [HTTP push work notification](https://github.com/ethcoreparitytech/parity/wiki/Mining#starting-it). + +Full changes: +- Bumping Parity UI [#1920](https://github.com/paritytech/parity/pull/1920) +- Adding entrypoints to docker images [#1909](https://github.com/paritytech/parity/pull/1909) +- Save nodes removed from backing_overlay until commit [#1917](https://github.com/paritytech/parity/pull/1917) +- RPC for importing geth keys [#1916](https://github.com/paritytech/parity/pull/1916) +- Peers RPC + UI displaying active/connected/max peers [#1915](https://github.com/paritytech/parity/pull/1915) +- RPC for deriving address from phrase. [#1912](https://github.com/paritytech/parity/pull/1912) +- adjust polling & connection timeouts for ipc [#1910](https://github.com/paritytech/parity/pull/1910) +- Don't return deleted nodes that are not yet flushed [#1908](https://github.com/paritytech/parity/pull/1908) +- Wallet rpcs [#1898](https://github.com/paritytech/parity/pull/1898) +- Fix binary serialization bug [#1907](https://github.com/paritytech/parity/pull/1907) +- fixed #1889, .DS_Store is no longer treated as key file [#1892](https://github.com/paritytech/parity/pull/1892) +- Purging .derefs, fixing clippy warnings. [#1890](https://github.com/paritytech/parity/pull/1890) +- RocksDB version bump [#1904](https://github.com/paritytech/parity/pull/1904) +- Fix ipc compilation and add ipc feature to test targets [#1902](https://github.com/paritytech/parity/pull/1902) +- Autocreating geth dir if none and geth mode on [#1896](https://github.com/paritytech/parity/pull/1896) +- v1.4.0 in master [#1886](https://github.com/paritytech/parity/pull/1886) +- Adding more details to miner log [#1891](https://github.com/paritytech/parity/pull/1891) +- moved hash.rs to bigint library [#1827](https://github.com/paritytech/parity/pull/1827) +- fixed cache_manager lock order [#1877](https://github.com/paritytech/parity/pull/1877) +- Fixing miner deadlock [#1885](https://github.com/paritytech/parity/pull/1885) +- Updating WS + Increasing token validity [#1882](https://github.com/paritytech/parity/pull/1882) +- take snapshot at specified block and slightly better informants [#1873](https://github.com/paritytech/parity/pull/1873) +- RPC errors & logs [#1845](https://github.com/paritytech/parity/pull/1845) +- Reduce max open files [#1876](https://github.com/paritytech/parity/pull/1876) +- Send new block hashes to all peers [#1875](https://github.com/paritytech/parity/pull/1875) +- Use UntrustedRlp for block verification [#1872](https://github.com/paritytech/parity/pull/1872) +- Update cache usage on commiting block info [#1871](https://github.com/paritytech/parity/pull/1871) +- Validating conversion U256->usize when doing gas calculation (for 32bits) [#1870](https://github.com/paritytech/parity/pull/1870) +- Sync to peers with confirmed fork block only [#1863](https://github.com/paritytech/parity/pull/1863) +- miner and client take spec reference [#1853](https://github.com/paritytech/parity/pull/1853) +- Unlock account with timeout for geth compatibility [#1854](https://github.com/paritytech/parity/pull/1854) +- Fixed reported max height and transaction propagation [#1852](https://github.com/paritytech/parity/pull/1852) +- Snapshot creation and restoration [#1679](https://github.com/paritytech/parity/pull/1679) +- fix deprecated typo [#1850](https://github.com/paritytech/parity/pull/1850) +- Split IO and network crates [#1828](https://github.com/paritytech/parity/pull/1828) +- updated classic JSON spec with classic bootnodes, fixes #1842 [#1847](https://github.com/paritytech/parity/pull/1847) +- protect unsafety in plainhasher; get more unique hashes [#1841](https://github.com/paritytech/parity/pull/1841) +- use mutex in dbtransaction [#1843](https://github.com/paritytech/parity/pull/1843) +- Fix state not using "account_starting_nonce" [#1830](https://github.com/paritytech/parity/pull/1830) +- Supporting blockid in eth_call and trace_call/trace_raw [#1837](https://github.com/paritytech/parity/pull/1837) +- eth_checkTransaction renamed to eth_checkRequest [#1817](https://github.com/paritytech/parity/pull/1817) +- Bump json-ipc-server again [#1839](https://github.com/paritytech/parity/pull/1839) +- Fixing another deadlock in trace db [#1833](https://github.com/paritytech/parity/pull/1833) +- Fix up the VM trace. [#1829](https://github.com/paritytech/parity/pull/1829) +- fixed parsing export params, fixes #1826 [#1834](https://github.com/paritytech/parity/pull/1834) +- More performance optimizations [#1814](https://github.com/paritytech/parity/pull/1814) +- Bumping clippy & fixing warnings [#1823](https://github.com/paritytech/parity/pull/1823) +- removed unused code from util and unnecessary dependency of FixedHash [#1824](https://github.com/paritytech/parity/pull/1824) +- Remove (almost all) panickers from trie module [#1776](https://github.com/paritytech/parity/pull/1776) +- Fixing account naming [#1810](https://github.com/paritytech/parity/pull/1810) +- JournalDB inject [#1806](https://github.com/paritytech/parity/pull/1806) +- No block number in get work while in geth-compat mode. [#1821](https://github.com/paritytech/parity/pull/1821) +- Import wallet fix [#1820](https://github.com/paritytech/parity/pull/1820) +- Supporting eth_sign in Signer [#1787](https://github.com/paritytech/parity/pull/1787) +- Fixing cache update after chain reorg [#1816](https://github.com/paritytech/parity/pull/1816) +- Development mode for Signer UI [#1788](https://github.com/paritytech/parity/pull/1788) +- Miner tweaks [#1797](https://github.com/paritytech/parity/pull/1797) +- Util & ipc clenup [#1807](https://github.com/paritytech/parity/pull/1807) +- Fixing unlock parsing [#1802](https://github.com/paritytech/parity/pull/1802) +- fixed importing presale wallet with encseed longer than 96 bytes [#1801](https://github.com/paritytech/parity/pull/1801) +- DRYing build scripts [#1795](https://github.com/paritytech/parity/pull/1795) +- Allow code from spec json [#1790](https://github.com/paritytech/parity/pull/1790) +- nano-tests (ipc transport) to the CI [#1793](https://github.com/paritytech/parity/pull/1793) +- Commit best block after closing transaction [#1791](https://github.com/paritytech/parity/pull/1791) +- Place thread name in the log output [#1792](https://github.com/paritytech/parity/pull/1792) +- Fix ipc tests and bring to CI [#1789](https://github.com/paritytech/parity/pull/1789) +- dynamic keys pickup [#1779](https://github.com/paritytech/parity/pull/1779) +- ipc version bump [#1783](https://github.com/paritytech/parity/pull/1783) +- Prevent deadlock on trace GC [#1780](https://github.com/paritytech/parity/pull/1780) +- fixed trace_transaction crash when block contained suicide [#1781](https://github.com/paritytech/parity/pull/1781) +- Fix block body migration [#1777](https://github.com/paritytech/parity/pull/1777) +- cache manager and clearing tracing cache [#1769](https://github.com/paritytech/parity/pull/1769) +- Return storage as H256 from RPC. [#1774](https://github.com/paritytech/parity/pull/1774) +- Instant sealing engine [#1767](https://github.com/paritytech/parity/pull/1767) +- fix state unsafety with a mostly-guaranteed handle [#1755](https://github.com/paritytech/parity/pull/1755) +- Gas for mem optimization [#1768](https://github.com/paritytech/parity/pull/1768) +- Min and Max peers setting [#1771](https://github.com/paritytech/parity/pull/1771) +- Disable WAL [#1765](https://github.com/paritytech/parity/pull/1765) +- Add new line when printing start strings [#1766](https://github.com/paritytech/parity/pull/1766) +- Log tweak [#1764](https://github.com/paritytech/parity/pull/1764) +- Remove update_sealing call on importing own block [#1762](https://github.com/paritytech/parity/pull/1762) +- Single DB [#1741](https://github.com/paritytech/parity/pull/1741) +- Tweak format of log so it's not so verbose. [#1758](https://github.com/paritytech/parity/pull/1758) +- Combine mining queue and enabled into single locked datum [#1749](https://github.com/paritytech/parity/pull/1749) +- Collect consensus/null engines into a single module [#1754](https://github.com/paritytech/parity/pull/1754) +- Fix failing deserialization test [#1756](https://github.com/paritytech/parity/pull/1756) +- Stackoverflow fix [#1742](https://github.com/paritytech/parity/pull/1742) +- compaction profile used during migration, fixes #1750 [#1751](https://github.com/paritytech/parity/pull/1751) +- Splitting documentation into separate build job [#1752](https://github.com/paritytech/parity/pull/1752) +- handle keys deserialization errors, fixes #1592 [#1701](https://github.com/paritytech/parity/pull/1701) +- add gitlab-ci yaml [#1753](https://github.com/paritytech/parity/pull/1753) +- Better handling of multiple migrations [#1747](https://github.com/paritytech/parity/pull/1747) +- Disconnect peers on a fork [#1738](https://github.com/paritytech/parity/pull/1738) +- Add RPC & client call to replay a transaction. [#1734](https://github.com/paritytech/parity/pull/1734) +- another version bump for jsonrpc-ipc [#1744](https://github.com/paritytech/parity/pull/1744) +- Trace other types of calls [#1727](https://github.com/paritytech/parity/pull/1727) +- Fixing compilation on latest nightly [#1736](https://github.com/paritytech/parity/pull/1736) +- Blocks and snapshot compression [#1687](https://github.com/paritytech/parity/pull/1687) +- bump json-ipc-server version [#1739](https://github.com/paritytech/parity/pull/1739) +- Use std::sync::Condvar [#1732](https://github.com/paritytech/parity/pull/1732) +- Bump json-ipc-server version [#1733](https://github.com/paritytech/parity/pull/1733) +- bump json-ipc-server version [#1731](https://github.com/paritytech/parity/pull/1731) +- Fixing some clippy warnings [#1728](https://github.com/paritytech/parity/pull/1728) +- Bumping Parity UI [#1682](https://github.com/paritytech/parity/pull/1682) +- Various improvements to tracing & diagnostics. [#1707](https://github.com/paritytech/parity/pull/1707) +- Fixed reading chunked EIP8 handshake [#1712](https://github.com/paritytech/parity/pull/1712) +- Fix for importing blocks from a pipe file [#1724](https://github.com/paritytech/parity/pull/1724) +- Proper errors for binary serializer [#1714](https://github.com/paritytech/parity/pull/1714) +- Use a transaction for writing blocks [#1718](https://github.com/paritytech/parity/pull/1718) +- Exclude generated code from coverage [#1720](https://github.com/paritytech/parity/pull/1720) +- Use single binary for ipc modules [#1710](https://github.com/paritytech/parity/pull/1710) +- Log a chain-reorg. [#1715](https://github.com/paritytech/parity/pull/1715) +- Restore new block informant message [#1716](https://github.com/paritytech/parity/pull/1716) +- Parallel block body download [#1659](https://github.com/paritytech/parity/pull/1659) +- Rotate blockchain cache [#1709](https://github.com/paritytech/parity/pull/1709) +- Fix broken internal names. [#1711](https://github.com/paritytech/parity/pull/1711) +- cli overhaul [#1600](https://github.com/paritytech/parity/pull/1600) +- Key files include timestamp in name. [#1700](https://github.com/paritytech/parity/pull/1700) +- Fixing warnings [#1705](https://github.com/paritytech/parity/pull/1705) +- Ethereum classic [#1706](https://github.com/paritytech/parity/pull/1706) +- Docker Arguments [#1703](https://github.com/paritytech/parity/pull/1703) +- Informant tidyup. [#1699](https://github.com/paritytech/parity/pull/1699) +- Name and meta in accounts [#1695](https://github.com/paritytech/parity/pull/1695) +- Stackoverflow #1686 [#1698](https://github.com/paritytech/parity/pull/1698) +- filtering transactions toAddress includes contract creation [#1697](https://github.com/paritytech/parity/pull/1697) +- Prevent syncing to ancient blocks [#1693](https://github.com/paritytech/parity/pull/1693) +- Enable WAL and disable DB repair [#1696](https://github.com/paritytech/parity/pull/1696) +- Returning error when transaction is rejected (for consistency) [#1667](https://github.com/paritytech/parity/pull/1667) +- Disabling signer when in geth-compatibility mode [#1676](https://github.com/paritytech/parity/pull/1676) +- Suicides tracing [#1688](https://github.com/paritytech/parity/pull/1688) +- small cleanup of substate.rs [#1685](https://github.com/paritytech/parity/pull/1685) +- resolve #411: remove install scripts [#1684](https://github.com/paritytech/parity/pull/1684) +- IPC (feature-gated) [#1654](https://github.com/paritytech/parity/pull/1654) +- Bumping JSONRPC-http-server [#1678](https://github.com/paritytech/parity/pull/1678) +- Fixing hash deserialisation [#1674](https://github.com/paritytech/parity/pull/1674) +- Ping discovery nodes gradually [#1671](https://github.com/paritytech/parity/pull/1671) +- Fixing the deadlock on incoming connection [#1672](https://github.com/paritytech/parity/pull/1672) +- Fixing errors returned by sendTransaction* method family [#1665](https://github.com/paritytech/parity/pull/1665) +- Moved syncing log out of the client [#1670](https://github.com/paritytech/parity/pull/1670) +- Host validation (again) [#1666](https://github.com/paritytech/parity/pull/1666) +- Update install-deps.sh [ci skip] [#1664](https://github.com/paritytech/parity/pull/1664) +- fix typos [#1644](https://github.com/paritytech/parity/pull/1644) +- Size for blocks [#1668](https://github.com/paritytech/parity/pull/1668) +- Revert "Validating Host headers in RPC requests" [#1663](https://github.com/paritytech/parity/pull/1663) +- Validating Host headers in RPC requests [#1658](https://github.com/paritytech/parity/pull/1658) +- fixed failing master [#1662](https://github.com/paritytech/parity/pull/1662) +- Fixing clippy warnings [#1660](https://github.com/paritytech/parity/pull/1660) +- Don't ping all nodes on start [#1656](https://github.com/paritytech/parity/pull/1656) +- More performance optimizations [#1649](https://github.com/paritytech/parity/pull/1649) +- Removing unused client code [#1645](https://github.com/paritytech/parity/pull/1645) +- Asynchronous transactions (polling based for now). [#1652](https://github.com/paritytech/parity/pull/1652) +- Sync stand-alone binary and feature-gated dependencies refactoring [#1637](https://github.com/paritytech/parity/pull/1637) +- Re-enabling Parity UI [#1627](https://github.com/paritytech/parity/pull/1627) +- Blockchain repair on missing state root [#1646](https://github.com/paritytech/parity/pull/1646) +- Multi-mode logging. [#1643](https://github.com/paritytech/parity/pull/1643) +- Pro paths [#1650](https://github.com/paritytech/parity/pull/1650) +- Performance optimizations [#1642](https://github.com/paritytech/parity/pull/1642) +- Removed DAO soft fork traces [#1639](https://github.com/paritytech/parity/pull/1639) +- Compiler version update for windows [#1638](https://github.com/paritytech/parity/pull/1638) +- Delete values immediately from DB overlay [#1631](https://github.com/paritytech/parity/pull/1631) +- DAO hard-fork [#1483](https://github.com/paritytech/parity/pull/1483) +- fix network_start regression [#1629](https://github.com/paritytech/parity/pull/1629) +- Die if the DB is newer than the one supported. [#1630](https://github.com/paritytech/parity/pull/1630) +- Cleanup of colour code. Use is_a_tty. [#1621](https://github.com/paritytech/parity/pull/1621) +- don't batch best block for branches [#1623](https://github.com/paritytech/parity/pull/1623) +- In-memory trie operations [#1408](https://github.com/paritytech/parity/pull/1408) +- Fix "pending" parameter on RPC block requests [#1602](https://github.com/paritytech/parity/pull/1602) +- Allow RPC to use solc to compile solidity [#1607](https://github.com/paritytech/parity/pull/1607) +- IPC RPC deriving for traits [#1599](https://github.com/paritytech/parity/pull/1599) +- Utilize cached kcov if exists [#1619](https://github.com/paritytech/parity/pull/1619) +- Fixing no-ui feature [#1618](https://github.com/paritytech/parity/pull/1618) +- Couple of rocksdb optimizations [#1614](https://github.com/paritytech/parity/pull/1614) +- Miner tests [#1597](https://github.com/paritytech/parity/pull/1597) +- Sync IPC interface [#1584](https://github.com/paritytech/parity/pull/1584) +- Make sure reserved peers are in the node table [#1616](https://github.com/paritytech/parity/pull/1616) +- Fix bloomchain on blockchain repair [#1610](https://github.com/paritytech/parity/pull/1610) +- fixed broken tracing [#1615](https://github.com/paritytech/parity/pull/1615) +- fix benchmark compilation [#1612](https://github.com/paritytech/parity/pull/1612) +- Updating jsonrpc-http-server [#1611](https://github.com/paritytech/parity/pull/1611) +- replace synchronization primitives with those from parking_lot [#1593](https://github.com/paritytech/parity/pull/1593) +- ui compilation feature [#1604](https://github.com/paritytech/parity/pull/1604) +- is_zero() and pow() optimisations for uint [#1608](https://github.com/paritytech/parity/pull/1608) +- Optimizing & Cleaning the build [#1591](https://github.com/paritytech/parity/pull/1591) +- Fix logging [#1590](https://github.com/paritytech/parity/pull/1590) +- remove unnecessary mutex in logging [#1601](https://github.com/paritytech/parity/pull/1601) +- Using streamlined parity-ui repository [#1566](https://github.com/paritytech/parity/pull/1566) +- Optimizing InstructionInfo access. [#1595](https://github.com/paritytech/parity/pull/1595) +- V7 Migration progress indicator [#1594](https://github.com/paritytech/parity/pull/1594) +- bring snapshotting work into master [#1577](https://github.com/paritytech/parity/pull/1577) +- Bump clippy [#1587](https://github.com/paritytech/parity/pull/1587) +- refactoring of handshake messages serialization in ipc [#1586](https://github.com/paritytech/parity/pull/1586) +- expunge &Vec pattern [#1579](https://github.com/paritytech/parity/pull/1579) +- EVM gas for memory tiny optimization [#1578](https://github.com/paritytech/parity/pull/1578) +- cleaned up parity/signer [#1551](https://github.com/paritytech/parity/pull/1551) +- Major sync <-> client interactions refactoring [#1572](https://github.com/paritytech/parity/pull/1572) +- failing test with overlayrecent pruning [#1567](https://github.com/paritytech/parity/pull/1567) +- Enable state queries for OverlayRecent DB [#1575](https://github.com/paritytech/parity/pull/1575) +- have AccountDB use address hash for uniqueness [#1533](https://github.com/paritytech/parity/pull/1533) +- Very basic EVM binary. [#1574](https://github.com/paritytech/parity/pull/1574) +- Some obvious evm & uint optimizations [#1576](https://github.com/paritytech/parity/pull/1576) +- Fixing clippy warnings [#1568](https://github.com/paritytech/parity/pull/1568) +- Miner's gas price gets updated dynamically [#1570](https://github.com/paritytech/parity/pull/1570) +- bringing hypervisor as a crate in ipc dir [#1565](https://github.com/paritytech/parity/pull/1565) +- Init public interface with IO message [#1573](https://github.com/paritytech/parity/pull/1573) +- Uncommenting simple Miner tests [#1571](https://github.com/paritytech/parity/pull/1571) +- Kill lock unwraps [#1558](https://github.com/paritytech/parity/pull/1558) +- Fixing deadlock in miner [#1569](https://github.com/paritytech/parity/pull/1569) +- Idealpeers in log [#1563](https://github.com/paritytech/parity/pull/1563) +- Simple style fix. [#1561](https://github.com/paritytech/parity/pull/1561) +- Enum variants serialisation test&fix [#1559](https://github.com/paritytech/parity/pull/1559) +- Supporting /api/ping for dapps server [#1543](https://github.com/paritytech/parity/pull/1543) +- Client IPC Interface [#1493](https://github.com/paritytech/parity/pull/1493) +- Kill timers when removing IO handler [#1554](https://github.com/paritytech/parity/pull/1554) +- Fix and add info messages [#1552](https://github.com/paritytech/parity/pull/1552) +- Fix indent of #1541 [#1555](https://github.com/paritytech/parity/pull/1555) +- Update sealing just once when externally importing many blocks [#1541](https://github.com/paritytech/parity/pull/1541) +- Remove soft-fork stuff. [#1548](https://github.com/paritytech/parity/pull/1548) +- fix codegen warning [#1550](https://github.com/paritytech/parity/pull/1550) +- Extend migration framework [#1546](https://github.com/paritytech/parity/pull/1546) +- Refactoring dapps to support API endpoints. [#1542](https://github.com/paritytech/parity/pull/1542) +- serde is no longer util dependency [#1534](https://github.com/paritytech/parity/pull/1534) +- mention wiki in README [#1549](https://github.com/paritytech/parity/pull/1549) +- Skipping transactions with invalid nonces when pushing to block. [#1545](https://github.com/paritytech/parity/pull/1545) +- Silent running operating modes [#1477](https://github.com/paritytech/parity/pull/1477) +- util cleanup [#1474](https://github.com/paritytech/parity/pull/1474) +- Calculating gas using usize (if supplied gaslimit fits in usize) [#1518](https://github.com/paritytech/parity/pull/1518) +- add owning NibbleVec [#1536](https://github.com/paritytech/parity/pull/1536) +- Attempt to fix blochchain/extras DBs sync [#1538](https://github.com/paritytech/parity/pull/1538) +- Client API refactoring - limiting errors to crate-level error types [#1525](https://github.com/paritytech/parity/pull/1525) +- IPC codegen enhancement - allow void methods [#1540](https://github.com/paritytech/parity/pull/1540) +- Fixing serving nested files for dapps. [#1539](https://github.com/paritytech/parity/pull/1539) +- Fixed public address config [#1537](https://github.com/paritytech/parity/pull/1537) +- Fixing compilation&clippy warnings [#1531](https://github.com/paritytech/parity/pull/1531) +- creating ethereum dir while in geth mode [#1530](https://github.com/paritytech/parity/pull/1530) +- Bumping clippy [#1532](https://github.com/paritytech/parity/pull/1532) +- Make signer default as long as --unlock isn't used. [#1524](https://github.com/paritytech/parity/pull/1524) +- add client timeout when requesting usd price for gas [#1526](https://github.com/paritytech/parity/pull/1526) +- Fix gitter-url link in README.md [#1528](https://github.com/paritytech/parity/pull/1528) +- Fix error message. [#1527](https://github.com/paritytech/parity/pull/1527) +- BTreeMap binary serialization [#1489](https://github.com/paritytech/parity/pull/1489) +- Save block reference in the queue on notification [#1501](https://github.com/paritytech/parity/pull/1501) +- bigint tests to run on CI [#1522](https://github.com/paritytech/parity/pull/1522) +- Client api cleaning - uncles are returned as rlp [#1516](https://github.com/paritytech/parity/pull/1516) +- Fatdb integration with CLI [#1464](https://github.com/paritytech/parity/pull/1464) +- Optimizing/simplifying shr [#1517](https://github.com/paritytech/parity/pull/1517) +- change IPC codegen to allow attributes [#1500](https://github.com/paritytech/parity/pull/1500) +- Fix warnings [#1514](https://github.com/paritytech/parity/pull/1514) +- FatDB [#1452](https://github.com/paritytech/parity/pull/1452) +- Fix the reseal mechanism. [#1513](https://github.com/paritytech/parity/pull/1513) +- Update Dockerfile ubuntu-aarch64 [#1509](https://github.com/paritytech/parity/pull/1509) +- Update Ubuntu-arm Dockerfile [#1510](https://github.com/paritytech/parity/pull/1510) +- Update Ubuntu-jit Dockerfile [#1511](https://github.com/paritytech/parity/pull/1511) +- Update Ubuntu Dockerfile [#1512](https://github.com/paritytech/parity/pull/1512) +- Update CentOS Dockerfile [#1508](https://github.com/paritytech/parity/pull/1508) +- bump status page v0.5.1 [#1502](https://github.com/paritytech/parity/pull/1502) +- Update CentOS Dockerfile [#1507](https://github.com/paritytech/parity/pull/1507) +- Update Dockerfile ubuntu-aarch64 [#1506](https://github.com/paritytech/parity/pull/1506) +- Update Ubuntu-arm Dockerfile [#1505](https://github.com/paritytech/parity/pull/1505) +- Update Ubuntu-jit Dockerfile [#1504](https://github.com/paritytech/parity/pull/1504) +- Update Ubuntu Dockerfile [#1503](https://github.com/paritytech/parity/pull/1503) +- Optionally clone block behind work-package [#1497](https://github.com/paritytech/parity/pull/1497) +- Fix no colour on windows. [#1498](https://github.com/paritytech/parity/pull/1498) +- Workaround for hyper panic [#1495](https://github.com/paritytech/parity/pull/1495) +- Colourful notification on mine [#1488](https://github.com/paritytech/parity/pull/1488) +- Quick fix for max open files error [#1494](https://github.com/paritytech/parity/pull/1494) +- Work notification over HTTP [#1491](https://github.com/paritytech/parity/pull/1491) +- Sealed block importing and propagation optimization [#1478](https://github.com/paritytech/parity/pull/1478) +- vm factory to mining client [#1487](https://github.com/paritytech/parity/pull/1487) +- topbar dialog fix [#1479](https://github.com/paritytech/parity/pull/1479) +- Minor additions to allow resetting of code. [#1482](https://github.com/paritytech/parity/pull/1482) +- Introduce options for fine-grained management of work queue. [#1484](https://github.com/paritytech/parity/pull/1484) +- Snapshot state restoration [#1308](https://github.com/paritytech/parity/pull/1308) +- Merge master into pv64 branch [#1486](https://github.com/paritytech/parity/pull/1486) +- Ensure we don't reject our own transactions for gasprice. [#1485](https://github.com/paritytech/parity/pull/1485) +- Signing parity executable & windows installer in appveyor [#1481](https://github.com/paritytech/parity/pull/1481) +- Rearrange fork CLI options. [#1476](https://github.com/paritytech/parity/pull/1476) +- give appveyor some breath [#1475](https://github.com/paritytech/parity/pull/1475) +- Ensure we always get the latest work when mining on submitted. [#1469](https://github.com/paritytech/parity/pull/1469) +- Tests for views [#1471](https://github.com/paritytech/parity/pull/1471) +- json ipc version bump [#1470](https://github.com/paritytech/parity/pull/1470) +- verifier is no longer a template type of client [#1467](https://github.com/paritytech/parity/pull/1467) +- Allow configuration of when to reseal blocks. [#1460](https://github.com/paritytech/parity/pull/1460) +- removed unsafe code [#1466](https://github.com/paritytech/parity/pull/1466) +- WS bump + Adding default for value [#1465](https://github.com/paritytech/parity/pull/1465) +- Attempt DB repair if corrupted [#1461](https://github.com/paritytech/parity/pull/1461) +- Database configuration extended [#1454](https://github.com/paritytech/parity/pull/1454) +- Updating WS-RS server [#1459](https://github.com/paritytech/parity/pull/1459) +- Reduced IO messages; removed panics on IO notifications [#1457](https://github.com/paritytech/parity/pull/1457) +- Handle errors when starting parity --signer [#1451](https://github.com/paritytech/parity/pull/1451) +- Fixed losing queued blocks on error [#1453](https://github.com/paritytech/parity/pull/1453) +- Updated to latest hyper with patched mio [#1450](https://github.com/paritytech/parity/pull/1450) +- Retweak BASE and MULTIPLIER in rocksdb config. [#1445](https://github.com/paritytech/parity/pull/1445) +- Removing Miner::default. [#1410](https://github.com/paritytech/parity/pull/1410) +- Don't mine without --author [#1436](https://github.com/paritytech/parity/pull/1436) +- Revert the rescuedao extradata. [#1437](https://github.com/paritytech/parity/pull/1437) +- More conservative settings for rocksdb. [#1440](https://github.com/paritytech/parity/pull/1440) +- v1.3.0 in master [#1421](https://github.com/paritytech/parity/pull/1421) +- Update Ubuntu-arm Dockerfile [#1429](https://github.com/paritytech/parity/pull/1429) +- Create Dockerfile ubuntu-aarch64 [#1430](https://github.com/paritytech/parity/pull/1430) +- Update CentOS Dockerfile [#1424](https://github.com/paritytech/parity/pull/1424) +- Update Ubuntu Dockerfile [#1426](https://github.com/paritytech/parity/pull/1426) +- Update Ubuntu-jit Dockerfile [#1427](https://github.com/paritytech/parity/pull/1427) +- Update SF blocknumber to 1800000. [#1418](https://github.com/paritytech/parity/pull/1418) diff --git a/docs/CHANGELOG-1.4.md b/docs/CHANGELOG-1.4.md new file mode 100644 index 0000000000000000000000000000000000000000..7595c10a7ef7b9b95723c256179518d2080ecbc0 --- /dev/null +++ b/docs/CHANGELOG-1.4.md @@ -0,0 +1,746 @@ +Note: Parity 1.4 reached End-of-Life on 2017-03-13 (EOL). + +## Parity [v1.4.12](https://github.com/paritytech/parity/releases/tag/v1.4.12) (2017-02-22) + +This stable release fixes an issue with block uncle validation. Parity now allows uncle headers to have timestamp set to arbitrary future value. + +- Stable Backporting ([#4633](https://github.com/paritytech/parity/pull/4633)) [#4642](https://github.com/paritytech/parity/pull/4642) + - Tweak some checks. + - Fixed build and added a difficulty test + - Bump to v1.4.12 +- Add missing maxCodeSize [#4585](https://github.com/paritytech/parity/pull/4585) + +## Parity [v1.4.11](https://github.com/paritytech/parity/releases/tag/v1.4.11) (2017-02-17) + +This release corrects the Ropsten chain specification file. + +- Bump to v1.4.11 [#4587](https://github.com/paritytech/parity/pull/4587) +- Fixing etherscan price parsing ([#4202](https://github.com/paritytech/parity/pull/4202)) [#4209](https://github.com/paritytech/parity/pull/4209) + - Fixing etherscan price parsing + - Handling all errors +- Removed pdbs +- Add missing maxCodeSize [#4585](https://github.com/paritytech/parity/pull/4585) + +## Parity [v1.4.10](https://github.com/paritytech/parity/releases/tag/v1.4.10) (2017-01-18) + +Parity 1.4.10 is a first stable release of 1.4.x series. It includes a few minor networking fixes. + +- Gas_limit for blocks, mined by Parity will be divisible by 37 (#4154) [#4179](https://github.com/paritytech/parity/pull/4179) + - gas_limit for new blocks will divide evenly by 13 + - increased PARITY_GAS_LIMIT_DETERMINANT to 37 + - separate method for marking mined block + - debug_asserts(gas_limit within protocol range) + - round_block_gas_limit method is now static + - made round_block_gas_limit free-function + - multiplier->multiple +- Backporing to 1.4.10-stable [#4110](https://github.com/paritytech/parity/pull/4110) + - Bump to v1.4.10 + - No reorg limit for ancient blocks + - Update registration after every write + +## Parity [v1.4.9](https://github.com/paritytech/parity/releases/tag/v1.4.9) (2017-01-09) + +This fixes an issue introduced in 1.4.8 that causes Parity to panic on propagating transactions in some cases. + +- v1.4.9 in beta [#4097](https://github.com/paritytech/parity/pull/4097) + - Bump to v1.4.9 + - Disable armv6 build +- beta Fix queue deadlock [#4095](https://github.com/paritytech/parity/pull/4095) +- Fix rebroadcast panic beta [#4085](https://github.com/paritytech/parity/pull/4085) + - fix compile + - fix backport + - clean up old method + - remove unnecessary reference + - simplify + - Fixing 'simplify' + +## Parity [v1.4.8](https://github.com/paritytech/parity/releases/tag/v1.4.8) (2017-01-06) + +Ethereum Classic Hard Fork ready release containing various bugfixes: + +- Fix for excessive transactions propagation +- Fix for inconsistent `logIndex` in transaction receipts + +See [full list of changes](https://github.com/paritytech/parity/compare/v1.4.7...v1.4.8): + +- Beta backports [#4067](https://github.com/paritytech/parity/pull/4067) +- Re-broadcast transactions to few random peers on each new block. (#4054) [#4061](https://github.com/paritytech/parity/pull/4061) +- Tolerate errors in user_defaults [#4060](https://github.com/paritytech/parity/pull/4060) +- ETC Config change backport [#4056](https://github.com/paritytech/parity/pull/4056) +- [beta] Avoid re-broadcasting transactions on each block [#4047](https://github.com/paritytech/parity/pull/4047) +- Beta Backports [#4012](https://github.com/paritytech/parity/pull/4012) + +## Parity [v1.4.7](https://github.com/paritytech/parity/releases/tag/v1.4.7) (2016-12-27) + +This maintenance release fixes an issue with sync falling behind occasionally. + +- Backporting to beta [#3980](https://github.com/paritytech/parity/pull/3980) +- [beta] enforce gas limit falls within engine bounds [#3816](https://github.com/paritytech/parity/pull/3816) + + +## Parity [v1.4.6](https://github.com/paritytech/parity/releases/tag/v1.4.6) (2016-12-05) + +This patch release fixes an issue with syncing on the Ropsten test network. + +- Backporting to beta [#3718](https://github.com/paritytech/parity/pull/3718) +- [beta] scrollable contract deploy & execute modals [#3656](https://github.com/paritytech/parity/pull/3656) + +## Parity [v1.4.5](https://github.com/paritytech/parity/releases/tag/v1.4.5) (2016-11-26) + +1.4.5 release fixes a number of issues, notably: +- High CPU usage when idle. +- Key recovery phrases generated on windows now can be imported. + +#### Configuration changes +- `--usd-per-tx` is now set to 0.0025 by default. + +#### New features +- Support for Ropsten test network is introduced with `--chain=ropsten` or `--testnet`. Morden network is still available via `--chain=morden` + +#### Full changes +- [beta] Pin package versions for React [#3628](https://github.com/paritytech/parity/pull/3628) +- Backporting to beta [#3623](https://github.com/paritytech/parity/pull/3623) +- [beta] Ropsten chain for UI [#3622](https://github.com/paritytech/parity/pull/3622) + +## Parity [v1.4.4](https://github.com/paritytech/parity/releases/tag/v1.4.4) (2016-11-18) + +This is a maintenance release that fixes an issue with EIP-155 transactions being added to the transaction pool. It also improves syncing stability and resolved a number of UI issues. +Full changelog is available [here.](https://github.com/paritytech/parity/commit/3e0d033eaf789cfdf517f4a97effc500f1f9263b) + +- [beta] apps typo fix [#3533](https://github.com/paritytech/parity/pull/3533) +- Backporting to beta [#3525](https://github.com/paritytech/parity/pull/3525) + +## Parity [v1.4.3](https://github.com/paritytech/parity/releases/tag/v1.4.3) (2016-11-16) + +This release includes memory footprint optimization as well as a few fixes in the UI. +EIP-155/160/161/170 hardfork is enabled at block 2675000 (1885000 for test network). +Full changelog is available [here.](https://github.com/paritytech/parity/compare/v1.4.2...v1.4.3) + +- [beta] EIP-170 [#3464](https://github.com/paritytech/parity/pull/3464) +- Backports to beta [#3465](https://github.com/paritytech/parity/pull/3465) +- Backport: additional fields on transaction and receipt [#3463](https://github.com/paritytech/parity/pull/3463) +- v1.4.3 in beta [#3424](https://github.com/paritytech/parity/pull/3424) + +## Parity [v1.4.2](https://github.com/paritytech/parity/releases/tag/v1.4.2) (2016-11-10) + +This release fixes a few additional issues: +- Parity now correctly handles external `--dapps-interface` and `--ui-interface` in the UI. +- Crash in `eth_getUncle*` has been fixed. +- macOS installer now includes an uninstall script. +- Security token input UI has been fixed. +- Correct display for tokens with minimum decimals. + +And some additional minor changes. Full changelog is [available](https://github.com/paritytech/parity/compare/v1.4.1...v1.4.2) +- Backporting to beta [#3344](https://github.com/paritytech/parity/pull/3344) +- Backporting to beta [#3324](https://github.com/paritytech/parity/pull/3324) + +## Parity [v1.4.1](https://github.com/paritytech/parity/releases/tag/v1.4.1) (2016-11-09) + +This is a hotfix release to address a couple of issues with 1.4.0: + +- UI token is requested instead of being supplied automatically. +- Running with `--geth` results in an error. + +- Backporting to beta [#3293](https://github.com/paritytech/parity/pull/3293) + +## Parity [v1.4.0](https://github.com/paritytech/parity/releases/tag/v1.4.0) (2016-11-07) + +First beta release of the 1.4 series. + +This includes the new Parity Wallet and Warp-Sync synchronisation as well as several optimisations and fixes. + +- Add secure flag back [#3246](https://github.com/paritytech/parity/pull/3246) +- [BETA] verify chunk hashes in cli restore [#3242](https://github.com/paritytech/parity/pull/3242) +- Backporting to beta [#3239](https://github.com/paritytech/parity/pull/3239) +- UI fixes backporting [#3234](https://github.com/paritytech/parity/pull/3234) +- Backporting to beta [#3229](https://github.com/paritytech/parity/pull/3229) +- Beta branch cleanup [#3226](https://github.com/paritytech/parity/pull/3226) +- [beta] Set passive mode for first run only (#3214) [#3216](https://github.com/paritytech/parity/pull/3216) +- Mode configuration backported to beta [#3213](https://github.com/paritytech/parity/pull/3213) +- Backporting [#3198](https://github.com/paritytech/parity/pull/3198) +- [beta] EIP-155 update with Vitalik's new test vectors (#3166) [#3189](https://github.com/paritytech/parity/pull/3189) +- Backporting to beta [#3176](https://github.com/paritytech/parity/pull/3176) +- parity-ui-precompiled pinned to beta [#3168](https://github.com/paritytech/parity/pull/3168) +- EIP-155 update with Vitalik's new test vectors [#3166](https://github.com/paritytech/parity/pull/3166) +- Push precompiled for beta/stable, npm only master [#3163](https://github.com/paritytech/parity/pull/3163) +- Back to real root after npm publish [#3178](https://github.com/paritytech/parity/pull/3178) +- Remove extra cd js [#3177](https://github.com/paritytech/parity/pull/3177) +- Fixes Gas price selection bug [#3175](https://github.com/paritytech/parity/pull/3175) +- Exposing state root and logsBloom in RPC receipts [#3174](https://github.com/paritytech/parity/pull/3174) +- Exposing v,r,s from transaction signature in RPC [#3172](https://github.com/paritytech/parity/pull/3172) +- Enabling personal RPC over IPC by default [#3165](https://github.com/paritytech/parity/pull/3165) +- Gitlab CI badge [#3164](https://github.com/paritytech/parity/pull/3164) +- Dependencies in README [#3162](https://github.com/paritytech/parity/pull/3162) +- Make the footer a bit less ugly. [#3160](https://github.com/paritytech/parity/pull/3160) +- Linux build case sensitivity fix [#3161](https://github.com/paritytech/parity/pull/3161) +- abbreviated enode, `CopyToClipboard` component [#3131](https://github.com/paritytech/parity/pull/3131) +- EIPs 155, 160, 161 [#2976](https://github.com/paritytech/parity/pull/2976) +- beta reset to 1.4.0 [#3157](https://github.com/paritytech/parity/pull/3157) +- Fix histogram [#3150](https://github.com/paritytech/parity/pull/3150) +- Remove network label from TabBar [#3142](https://github.com/paritytech/parity/pull/3142) +- Speed up unresponsive Contract events & Account transactions [#3145](https://github.com/paritytech/parity/pull/3145) +- Better windows shortcut [#3147](https://github.com/paritytech/parity/pull/3147) +- Redirect content to the same address as requested [#3133](https://github.com/paritytech/parity/pull/3133) +- Fixed peer ping timeout [#3137](https://github.com/paritytech/parity/pull/3137) +- Fix for windows build [#3125](https://github.com/paritytech/parity/pull/3125) +- Fix AddessInput icon position [#3132](https://github.com/paritytech/parity/pull/3132) +- Fixed not scrollable accounts in tokenreg dapp [#3128](https://github.com/paritytech/parity/pull/3128) +- Returning cache headers for network content [#3123](https://github.com/paritytech/parity/pull/3123) +- Optimise contract events display [#3120](https://github.com/paritytech/parity/pull/3120) +- Add basic validation for contract execute values [#3118](https://github.com/paritytech/parity/pull/3118) +- Dapps errors embeddable on signer [#3115](https://github.com/paritytech/parity/pull/3115) +- Use enode RPC in UI [#3108](https://github.com/paritytech/parity/pull/3108) +- Windows tray app [#3103](https://github.com/paritytech/parity/pull/3103) +- Displaying CLI errors on stderr [#3116](https://github.com/paritytech/parity/pull/3116) +- new InputAddressSelect component [#3071](https://github.com/paritytech/parity/pull/3071) +- Bump mio [#3117](https://github.com/paritytech/parity/pull/3117) +- Minor typo fixed. [#3110](https://github.com/paritytech/parity/pull/3110) +- Sort by ETH balance and contract by date [#3107](https://github.com/paritytech/parity/pull/3107) +- Add RPC enode lookup [#3096](https://github.com/paritytech/parity/pull/3096) +- Initializing logger for each command [#3090](https://github.com/paritytech/parity/pull/3090) +- Allow registration of content bundles in GitHubHint [#3094](https://github.com/paritytech/parity/pull/3094) +- Add read-only inputs to UI plus Copy to Clipboard buttons [#3095](https://github.com/paritytech/parity/pull/3095) +- Allow boolean dropdowns for contract deploy [#3077](https://github.com/paritytech/parity/pull/3077) +- Add mac installer files [#2995](https://github.com/paritytech/parity/pull/2995) +- Fixing dapps sorting [#3086](https://github.com/paritytech/parity/pull/3086) +- Add a Gitter chat badge to README.md [#3092](https://github.com/paritytech/parity/pull/3092) +- Fixes webpack HTML loader [#3089](https://github.com/paritytech/parity/pull/3089) +- Redirecting /home to new UI [#3084](https://github.com/paritytech/parity/pull/3084) +- Allow GitHubHint content owner to update url [#3083](https://github.com/paritytech/parity/pull/3083) +- Remove token assets (moved to ethcore/dapps-assets) [#3082](https://github.com/paritytech/parity/pull/3082) +- Goodbye Gavcoin, Hello Gavcoin [#3080](https://github.com/paritytech/parity/pull/3080) +- Load network dapps [#3078](https://github.com/paritytech/parity/pull/3078) +- Swap account phrase input to normal (non-multiline) [#3060](https://github.com/paritytech/parity/pull/3060) +- Fix minor typo in informant [#3056](https://github.com/paritytech/parity/pull/3056) +- Warp sync status display [#3045](https://github.com/paritytech/parity/pull/3045) +- Enhance address input [#3065](https://github.com/paritytech/parity/pull/3065) +- Go to Accounts Page if Tooltips are displayed [#3063](https://github.com/paritytech/parity/pull/3063) +- Change contract Execute bool values & query bool value display [#3024](https://github.com/paritytech/parity/pull/3024) +- Update Parity logo [#3036](https://github.com/paritytech/parity/pull/3036) +- settings: replace background patterns (inline) [#3047](https://github.com/paritytech/parity/pull/3047) +- Multiple line description for dapps [#3058](https://github.com/paritytech/parity/pull/3058) +- Fix status log order [#3062](https://github.com/paritytech/parity/pull/3062) +- Graphical gas price selection [#2898](https://github.com/paritytech/parity/pull/2898) +- [Registry dApp] Actions not available before selecting accounts [#3032](https://github.com/paritytech/parity/pull/3032) +- apply post-consolidation migrations after consolidating [#3020](https://github.com/paritytech/parity/pull/3020) +- fix chain badge padding [#3046](https://github.com/paritytech/parity/pull/3046) +- Don't delete Tags input on blur (eg. tab) [#3044](https://github.com/paritytech/parity/pull/3044) +- Fixing last hashes for ethcall [#3043](https://github.com/paritytech/parity/pull/3043) +- Remove signer icons [#3039](https://github.com/paritytech/parity/pull/3039) +- execute periodic snapshot in new thread [#3029](https://github.com/paritytech/parity/pull/3029) +- fix background of embedded signer [#3026](https://github.com/paritytech/parity/pull/3026) +- registry dapp: fix reducer [#3028](https://github.com/paritytech/parity/pull/3028) +- Replace Execute by Query in contract button [#3031](https://github.com/paritytech/parity/pull/3031) +- Fixing GavCoin dApp overflow issues [#3030](https://github.com/paritytech/parity/pull/3030) +- execute contract function: validate address [#3013](https://github.com/paritytech/parity/pull/3013) +- Align tag inputs with other input boxes [#2965](https://github.com/paritytech/parity/pull/2965) +- Sweep panickers from IO and network [#3018](https://github.com/paritytech/parity/pull/3018) +- Terms & Conditions [#3019](https://github.com/paritytech/parity/pull/3019) +- open column families after reparing db corruption [#3017](https://github.com/paritytech/parity/pull/3017) +- Snapshot sync and block gap info in `eth_syncing` [#2948](https://github.com/paritytech/parity/pull/2948) +- personal_ RPCs to AutoArgs [#3000](https://github.com/paritytech/parity/pull/3000) +- RPCs for mode change [#3002](https://github.com/paritytech/parity/pull/3002) +- Fix a test sensitive to slow execution. [#3014](https://github.com/paritytech/parity/pull/3014) +- Fixes search filtering issues [#3011](https://github.com/paritytech/parity/pull/3011) +- Restart sync if no more peers with snapshots [#3007](https://github.com/paritytech/parity/pull/3007) +- Allow empty/non-existant input arrays for ABIs in contract view [#3001](https://github.com/paritytech/parity/pull/3001) +- Allow operation when no registry is available [#2980](https://github.com/paritytech/parity/pull/2980) +- Make JS lint & test run on Travis [#2894](https://github.com/paritytech/parity/pull/2894) +- Update account dropdowns [#2959](https://github.com/paritytech/parity/pull/2959) +- Modify gas price statistics [#2947](https://github.com/paritytech/parity/pull/2947) +- Fixes pending/mined transactions in registry dApp [#3004](https://github.com/paritytech/parity/pull/3004) +- Prevent connecting to self [#2997](https://github.com/paritytech/parity/pull/2997) +- Disable verbose in gitlab CI [#2999](https://github.com/paritytech/parity/pull/2999) +- Allow warnings in gitlab [#2998](https://github.com/paritytech/parity/pull/2998) +- Fix the brainwallet functionality. [#2994](https://github.com/paritytech/parity/pull/2994) +- Provided gas description update [#2993](https://github.com/paritytech/parity/pull/2993) +- Print messages to stderr [#2991](https://github.com/paritytech/parity/pull/2991) +- Networking and syncing tweaks [#2990](https://github.com/paritytech/parity/pull/2990) +- Allow build warnings [#2985](https://github.com/paritytech/parity/pull/2985) +- Display network status for finished Signer requests [#2983](https://github.com/paritytech/parity/pull/2983) +- Fixed rejecting transactions [#2984](https://github.com/paritytech/parity/pull/2984) +- mio version bump [#2982](https://github.com/paritytech/parity/pull/2982) +- Publish parity.js to npmjs registry [#2978](https://github.com/paritytech/parity/pull/2978) +- Import raw private key [#2945](https://github.com/paritytech/parity/pull/2945) +- refactor etherscan.io links [#2896](https://github.com/paritytech/parity/pull/2896) +- Use separate lock for code cache [#2977](https://github.com/paritytech/parity/pull/2977) +- Add favicon [#2974](https://github.com/paritytech/parity/pull/2974) +- Align password change dialog with create dialog ordering [#2970](https://github.com/paritytech/parity/pull/2970) +- WS bump [#2973](https://github.com/paritytech/parity/pull/2973) +- Discovery performance optimization [#2972](https://github.com/paritytech/parity/pull/2972) +- Pass gas & gasPrice to token transfers [#2964](https://github.com/paritytech/parity/pull/2964) +- Updating ws-rs [#2962](https://github.com/paritytech/parity/pull/2962) +- Run cargo with verbose flag when testing [#2943](https://github.com/paritytech/parity/pull/2943) +- Fixing clippy warnings take two [#2961](https://github.com/paritytech/parity/pull/2961) +- Snapshot sync improvements [#2960](https://github.com/paritytech/parity/pull/2960) +- Gavcoin event display updates [#2956](https://github.com/paritytech/parity/pull/2956) +- Eslint fixes [#2957](https://github.com/paritytech/parity/pull/2957) +- Add import of raw private key RPCs [#2942](https://github.com/paritytech/parity/pull/2942) +- Bring in styling queues from original Gavcoin [#2936](https://github.com/paritytech/parity/pull/2936) +- Validating minimal required gas for a transaction [#2937](https://github.com/paritytech/parity/pull/2937) +- Even more snapshot validity checks [#2935](https://github.com/paritytech/parity/pull/2935) +- Shared code cache [#2921](https://github.com/paritytech/parity/pull/2921) +- Updating bootnodes for ETC [#2938](https://github.com/paritytech/parity/pull/2938) +- More bootnodes [#2926](https://github.com/paritytech/parity/pull/2926) +- Revert hash updates until testable [#2925](https://github.com/paritytech/parity/pull/2925) +- Release.sh verbose output [#2924](https://github.com/paritytech/parity/pull/2924) +- additional release.sh debugging info [#2922](https://github.com/paritytech/parity/pull/2922) +- Pass the js-precompiled commit hash to cargo update [#2920](https://github.com/paritytech/parity/pull/2920) +- Next nonce RPC [#2917](https://github.com/paritytech/parity/pull/2917) +- Get rid of duplicated code in EVM [#2915](https://github.com/paritytech/parity/pull/2915) +- Transaction Queue banning [#2524](https://github.com/paritytech/parity/pull/2524) +- Revert to gas price ordering [#2919](https://github.com/paritytech/parity/pull/2919) +- Personal split [#2879](https://github.com/paritytech/parity/pull/2879) +- Fixing config values for pruning_history [#2918](https://github.com/paritytech/parity/pull/2918) +- Apply pending block details on commit [#2254](https://github.com/paritytech/parity/pull/2254) +- Fixed GetNodeData output [#2892](https://github.com/paritytech/parity/pull/2892) +- New sync protocol ID [#2912](https://github.com/paritytech/parity/pull/2912) +- Clippy bump [#2877](https://github.com/paritytech/parity/pull/2877) +- iconomi token images [#2906](https://github.com/paritytech/parity/pull/2906) +- Fixes too long description and Token balance value in Dapps/Accounts [#2902](https://github.com/paritytech/parity/pull/2902) +- Add missing images for local dapps [#2890](https://github.com/paritytech/parity/pull/2890) +- Fix Webpack, again [#2895](https://github.com/paritytech/parity/pull/2895) +- Enable suicide json test [#2893](https://github.com/paritytech/parity/pull/2893) +- More snapshot fixes and optimizations [#2883](https://github.com/paritytech/parity/pull/2883) +- Fixes CI JS precompiled build [#2886](https://github.com/paritytech/parity/pull/2886) +- Fix empty tags modification [#2884](https://github.com/paritytech/parity/pull/2884) +- Fix up informant. [#2865](https://github.com/paritytech/parity/pull/2865) +- Get rid of MemoryDB denote [#2881](https://github.com/paritytech/parity/pull/2881) +- Add inject to "bundle everything" list [#2871](https://github.com/paritytech/parity/pull/2871) +- Fixes signer and MUI errors throwing [#2876](https://github.com/paritytech/parity/pull/2876) +- Fix failing tests after log parsing updates [#2878](https://github.com/paritytech/parity/pull/2878) +- Sweep some more panics [#2848](https://github.com/paritytech/parity/pull/2848) +- Make GitLab js-precompiled really update Cargo.toml in main repo [#2869](https://github.com/paritytech/parity/pull/2869) +- IPC version bump [#2870](https://github.com/paritytech/parity/pull/2870) +- Snapshot sync fixes and optimizations [#2863](https://github.com/paritytech/parity/pull/2863) +- Add Check and Change Password for an Account [#2861](https://github.com/paritytech/parity/pull/2861) +- Output git fetch/push to log files [#2862](https://github.com/paritytech/parity/pull/2862) +- Align contract event log l&f with transactions [#2812](https://github.com/paritytech/parity/pull/2812) +- Nicer port in use errors [#2859](https://github.com/paritytech/parity/pull/2859) +- Remove personal_* calls from dapps [#2860](https://github.com/paritytech/parity/pull/2860) +- Token sorting, zero-ETH transfer & token decimals [#2805](https://github.com/paritytech/parity/pull/2805) +- Don't fail badly when no transactions in last 100 blocks. [#2856](https://github.com/paritytech/parity/pull/2856) +- Fixing home.parity address for new signer [#2851](https://github.com/paritytech/parity/pull/2851) +- Enabling UI build back [#2853](https://github.com/paritytech/parity/pull/2853) +- Remove eventName in unsubscribe API arguments [#2844](https://github.com/paritytech/parity/pull/2844) +- Don't return empty names as clickable titles [#2809](https://github.com/paritytech/parity/pull/2809) +- Auto-bump js-precompiled on release [#2828](https://github.com/paritytech/parity/pull/2828) +- Remove ethcore::common re-export module [#2792](https://github.com/paritytech/parity/pull/2792) +- Prevent database corruption on OOM [#2832](https://github.com/paritytech/parity/pull/2832) +- Download/Export Addressbook [#2847](https://github.com/paritytech/parity/pull/2847) +- Snapshot and blockchain stability improvements [#2843](https://github.com/paritytech/parity/pull/2843) +- Extended network options [#2845](https://github.com/paritytech/parity/pull/2845) +- fix failing master test build [#2846](https://github.com/paritytech/parity/pull/2846) +- Local dapps embeddable on signer port [#2815](https://github.com/paritytech/parity/pull/2815) +- Trigger accounts/contracts search on search input change [#2838](https://github.com/paritytech/parity/pull/2838) +- Move snapshot sync to a subprotocol [#2820](https://github.com/paritytech/parity/pull/2820) +- fix node log being reversed [#2839](https://github.com/paritytech/parity/pull/2839) +- Fixes currency symbol font size in Shapeshift modal [#2840](https://github.com/paritytech/parity/pull/2840) +- Disable personal APIs by default for security reasons [#2834](https://github.com/paritytech/parity/pull/2834) +- Clear cached content [#2833](https://github.com/paritytech/parity/pull/2833) +- Add ethcore_[dapps|signer]Port APIs [#2821](https://github.com/paritytech/parity/pull/2821) +- CLI option to skip seal check when importing [#2842](https://github.com/paritytech/parity/pull/2842) +- Fix case error in Dapps import [#2837](https://github.com/paritytech/parity/pull/2837) +- Double click on address in account detail view should select it [#2841](https://github.com/paritytech/parity/pull/2841) +- Bump js-precompiled to 20161022-223915 UTC [#2826](https://github.com/paritytech/parity/pull/2826) +- Adjust paths to handle CORS changes [#2816](https://github.com/paritytech/parity/pull/2816) +- RPC for dapps port and signer port [#2819](https://github.com/paritytech/parity/pull/2819) +- Update build to working version on pre-compiled repo [#2825](https://github.com/paritytech/parity/pull/2825) +- Adjust network name badge colours (darker) [#2823](https://github.com/paritytech/parity/pull/2823) +- Removing submodule in favour of rust crate [#2756](https://github.com/paritytech/parity/pull/2756) +- Return old-ish content even when syncing [#2757](https://github.com/paritytech/parity/pull/2757) +- fix Signer UI [#2750](https://github.com/paritytech/parity/pull/2750) +- USG, GBP, Euro & Yuan updates [#2818](https://github.com/paritytech/parity/pull/2818) +- Make locally installed apps available again (Fixes #2771) [#2808](https://github.com/paritytech/parity/pull/2808) +- Additional RPCs for password management [#2779](https://github.com/paritytech/parity/pull/2779) +- flush DB changes on drop [#2795](https://github.com/paritytech/parity/pull/2795) +- rename State::snapshot to checkpoint to avoid confusion [#2796](https://github.com/paritytech/parity/pull/2796) +- Missing changes required to make new UI work [#2793](https://github.com/paritytech/parity/pull/2793) +- Cleanup method decoding (Fixes #2811) [#2810](https://github.com/paritytech/parity/pull/2810) +- Use trace API for decentralized transaction list [#2784](https://github.com/paritytech/parity/pull/2784) +- Automatic compaction selection on Linux [#2785](https://github.com/paritytech/parity/pull/2785) +- Update token images [#2804](https://github.com/paritytech/parity/pull/2804) +- Hackergold token images [#2801](https://github.com/paritytech/parity/pull/2801) +- Additional token images [#2800](https://github.com/paritytech/parity/pull/2800) +- Additional token images [#2798](https://github.com/paritytech/parity/pull/2798) +- Resolve morden fork [#2773](https://github.com/paritytech/parity/pull/2773) +- Using SipHashes from crates.io [#2778](https://github.com/paritytech/parity/pull/2778) +- Fixed issues on Searchable Addresses [#2790](https://github.com/paritytech/parity/pull/2790) +- Currency icons [#2788](https://github.com/paritytech/parity/pull/2788) +- Update token images [#2783](https://github.com/paritytech/parity/pull/2783) +- Fix warning in master [#2775](https://github.com/paritytech/parity/pull/2775) +- Add empty account existence test from beta. [#2769](https://github.com/paritytech/parity/pull/2769) +- Update name of basiccoin manager [#2768](https://github.com/paritytech/parity/pull/2768) +- sweep most unwraps from ethcore crate, dapps crate [#2762](https://github.com/paritytech/parity/pull/2762) +- Check queue to determine major importing [#2763](https://github.com/paritytech/parity/pull/2763) +- Trace filtering fix [#2760](https://github.com/paritytech/parity/pull/2760) +- Update js precompiled to 20161020-141636 [#2761](https://github.com/paritytech/parity/pull/2761) +- Incrementally calculate verification queue heap size [#2749](https://github.com/paritytech/parity/pull/2749) +- Don't add empty accounts to bloom [#2753](https://github.com/paritytech/parity/pull/2753) +- fix contract deployments not showing up [#2759](https://github.com/paritytech/parity/pull/2759) +- Fixes a positioning issue in Address Selection component [#2754](https://github.com/paritytech/parity/pull/2754) +- fix linting issues [#2758](https://github.com/paritytech/parity/pull/2758) +- Making Trie.iter non-recursive [#2733](https://github.com/paritytech/parity/pull/2733) +- Block import optimization [#2748](https://github.com/paritytech/parity/pull/2748) +- Update js-precompiled to 20161020-110858 [#2752](https://github.com/paritytech/parity/pull/2752) +- Fixing small files fetching [#2742](https://github.com/paritytech/parity/pull/2742) +- Fixing stalled sync [#2747](https://github.com/paritytech/parity/pull/2747) +- refactor signer components [#2691](https://github.com/paritytech/parity/pull/2691) +- Png images with backgrounds (original svg) [#2740](https://github.com/paritytech/parity/pull/2740) +- Make address selection searchable [#2739](https://github.com/paritytech/parity/pull/2739) +- very basic dapp add/remove interface [#2721](https://github.com/paritytech/parity/pull/2721) +- Frontport commits from beta to master [#2743](https://github.com/paritytech/parity/pull/2743) +- Implements Trace API Formatter [#2732](https://github.com/paritytech/parity/pull/2732) +- bump parking_lot to 0.3.x series [#2702](https://github.com/paritytech/parity/pull/2702) +- Unify major syncing detection [#2699](https://github.com/paritytech/parity/pull/2699) +- Fixes gas/gasPrice change not reflected in transaction modal [#2735](https://github.com/paritytech/parity/pull/2735) +- Fixing build UI stuff along with Rust [#2726](https://github.com/paritytech/parity/pull/2726) +- Fixed Snackbar not showing and/or behind transactions (#2730) [#2731](https://github.com/paritytech/parity/pull/2731) +- Updating json tests to latest develop commit [#2728](https://github.com/paritytech/parity/pull/2728) +- dapps: show errors [#2727](https://github.com/paritytech/parity/pull/2727) +- node logs: break lines [#2722](https://github.com/paritytech/parity/pull/2722) +- Bumping JSON-RPC http server [#2714](https://github.com/paritytech/parity/pull/2714) +- Add ability to copy address to the clipboard [#2716](https://github.com/paritytech/parity/pull/2716) +- Sort tags when displaying ; use AND for search results [#2720](https://github.com/paritytech/parity/pull/2720) +- allow-same-origin for iframe [#2711](https://github.com/paritytech/parity/pull/2711) +- Update Registry address (mainnet) [#2713](https://github.com/paritytech/parity/pull/2713) +- Allow tags for Accounts, Addresses and Contracts [#2712](https://github.com/paritytech/parity/pull/2712) +- Correct parameters for eth_sign [#2703](https://github.com/paritytech/parity/pull/2703) +- Bump js-precompiled to 20161018-161705 [#2698](https://github.com/paritytech/parity/pull/2698) +- Add inject.js (for web3 exposed) [#2692](https://github.com/paritytech/parity/pull/2692) +- Remove obsolete dapps and update security headers [#2694](https://github.com/paritytech/parity/pull/2694) +- Snapshot sync part 2 [#2098](https://github.com/paritytech/parity/pull/2098) +- Fix issues with no ethereum test dir present (2382) [#2659](https://github.com/paritytech/parity/pull/2659) +- Apply UI PRs after master merge [#2690](https://github.com/paritytech/parity/pull/2690) +- Fix importing traces for non-canon blocks [#2683](https://github.com/paritytech/parity/pull/2683) +- Fixing random test failures [#2577](https://github.com/paritytech/parity/pull/2577) +- Disable IPC in default build for 1.4 [#2657](https://github.com/paritytech/parity/pull/2657) +- use pruning history in CLI snapshots [#2658](https://github.com/paritytech/parity/pull/2658) +- Fixing --no-default-features again and evmbin [#2670](https://github.com/paritytech/parity/pull/2670) +- Settings > Proxy for proxy.pac setup instructions [#2678](https://github.com/paritytech/parity/pull/2678) +- Re-instate transaitions to allow updating busy indicator [#2682](https://github.com/paritytech/parity/pull/2682) +- signer: remove reject counter [#2685](https://github.com/paritytech/parity/pull/2685) +- Initial new UI source code import [#2607](https://github.com/paritytech/parity/pull/2607) +- Additional dapp logo images [#2677](https://github.com/paritytech/parity/pull/2677) +- Redirect from :8080 to :8180 [#2676](https://github.com/paritytech/parity/pull/2676) +- script to update js-precompiled [#2673](https://github.com/paritytech/parity/pull/2673) +- Styling in FF is not 100% [#2669](https://github.com/paritytech/parity/pull/2669) +- Don't allow gavcoin transfer with no balances [#2667](https://github.com/paritytech/parity/pull/2667) +- fix signer rejections [#2666](https://github.com/paritytech/parity/pull/2666) +- better text on unique background pattern [#2664](https://github.com/paritytech/parity/pull/2664) +- Adjust z-index for error overlay [#2662](https://github.com/paritytech/parity/pull/2662) +- Fix address selection for contract deployment [#2660](https://github.com/paritytech/parity/pull/2660) +- Add additional contract images [#2655](https://github.com/paritytech/parity/pull/2655) +- Update /api/* to point to :8080/api/* (first generation interface) [#2612](https://github.com/paritytech/parity/pull/2612) +- Initial import of new UI (compiled JS code) [#2220](https://github.com/paritytech/parity/pull/2220) +- Fixing evmbin compilation [#2652](https://github.com/paritytech/parity/pull/2652) +- Fix up ETC EIP-150 transition to 2,500,000. [#2636](https://github.com/paritytech/parity/pull/2636) +- Fixing compilation without default features [#2638](https://github.com/paritytech/parity/pull/2638) +- [frontport] CLI to specify queue ordering strategy (#2494) [#2623](https://github.com/paritytech/parity/pull/2623) +- Support for decryption in Signer [#2421](https://github.com/paritytech/parity/pull/2421) +- EIP150.1c [#2591](https://github.com/paritytech/parity/pull/2591) +- Release merge with origin with ours strategy [#2631](https://github.com/paritytech/parity/pull/2631) +- Adjust build output directories [#2630](https://github.com/paritytech/parity/pull/2630) +- cater for txhash returning null/empty object [#2629](https://github.com/paritytech/parity/pull/2629) +- snapshot: single byte for empty accounts [#2625](https://github.com/paritytech/parity/pull/2625) +- Configurable history size in master [#2606](https://github.com/paritytech/parity/pull/2606) +- Database performance tweaks [#2619](https://github.com/paritytech/parity/pull/2619) +- Enable suicide json test [#2626](https://github.com/paritytech/parity/pull/2626) +- Split journaldb commit into two functions: journal_under and mark_canonical [#2329](https://github.com/paritytech/parity/pull/2329) +- Fixed tx queue limit for local transactions [#2616](https://github.com/paritytech/parity/pull/2616) +- Additional logs when transactions is removed from queue [#2617](https://github.com/paritytech/parity/pull/2617) +- mitigate refcell conflict in state diffing [#2601](https://github.com/paritytech/parity/pull/2601) +- Fix tests [#2611](https://github.com/paritytech/parity/pull/2611) +- small styling updates [#2610](https://github.com/paritytech/parity/pull/2610) +- Remove web3 from Signer, bring in parity.js API [#2604](https://github.com/paritytech/parity/pull/2604) +- Mostly configurable canonical cache size [#2516](https://github.com/paritytech/parity/pull/2516) +- Added peers details to ethcore_netPeers RPC [#2580](https://github.com/paritytech/parity/pull/2580) +- Display account password hint when available [#2596](https://github.com/paritytech/parity/pull/2596) +- Fix gas estimation on transfer when data supplied [#2593](https://github.com/paritytech/parity/pull/2593) +- remove unused npm packages [#2590](https://github.com/paritytech/parity/pull/2590) +- Bundle fonts as part of the build process [#2588](https://github.com/paritytech/parity/pull/2588) +- Contract constructor params [#2586](https://github.com/paritytech/parity/pull/2586) +- Update json test suite [#2574](https://github.com/paritytech/parity/pull/2574) +- Filter apps that has been replaced for the local list [#2583](https://github.com/paritytech/parity/pull/2583) +- Display local apps listed by Parity [#2581](https://github.com/paritytech/parity/pull/2581) +- Network-specific nodes file [#2569](https://github.com/paritytech/parity/pull/2569) +- Dont close when block is known to be invalid [#2572](https://github.com/paritytech/parity/pull/2572) +- deny compiler warnings in CI [#2570](https://github.com/paritytech/parity/pull/2570) +- adjust alignment of queries [#2573](https://github.com/paritytech/parity/pull/2573) +- update ethcore-bigint crate to 0.1.1 [#2562](https://github.com/paritytech/parity/pull/2562) +- Registry dapp uses setAddress to actually set addresses now [#2568](https://github.com/paritytech/parity/pull/2568) +- Add the new EIP150 test. [#2563](https://github.com/paritytech/parity/pull/2563) +- fix failing tests [#2567](https://github.com/paritytech/parity/pull/2567) +- ΞTH -> ETH [#2566](https://github.com/paritytech/parity/pull/2566) +- Ensure polling is only done when connected [#2565](https://github.com/paritytech/parity/pull/2565) +- Fixed race condition in trace import [#2555](https://github.com/paritytech/parity/pull/2555) +- Disable misbehaving peers while seeking for best block [#2537](https://github.com/paritytech/parity/pull/2537) +- TX queue gas limit config and allow local transactions over the gas limit [#2553](https://github.com/paritytech/parity/pull/2553) +- standard component for address -> name mappings (consistent use everywhere) [#2557](https://github.com/paritytech/parity/pull/2557) +- Remove unwrap from client module [#2554](https://github.com/paritytech/parity/pull/2554) +- Removing panickers from sync module [#2551](https://github.com/paritytech/parity/pull/2551) +- Address images (tokens, dapps) as registered via contentHash (when available) [#2526](https://github.com/paritytech/parity/pull/2526) +- TokenReg set & get images working [#2540](https://github.com/paritytech/parity/pull/2540) +- adjust app_id where /api/content/ is called, fixes #2541 [#2543](https://github.com/paritytech/parity/pull/2543) +- connection dialog now shows up in dapps as well, closes #2538 [#2550](https://github.com/paritytech/parity/pull/2550) +- display account uuid (where available), closes #2546 [#2549](https://github.com/paritytech/parity/pull/2549) +- create accounts via recovery phrase [#2545](https://github.com/paritytech/parity/pull/2545) +- Build ethcore/js-precompiled on GitLab [#2522](https://github.com/paritytech/parity/pull/2522) +- Return errors from eth_call RPC [#2498](https://github.com/paritytech/parity/pull/2498) +- registry dapp: manage records [#2323](https://github.com/paritytech/parity/pull/2323) +- Print backtrace on panic [#2535](https://github.com/paritytech/parity/pull/2535) +- GitHubHint dapp [#2531](https://github.com/paritytech/parity/pull/2531) +- Backports to master [#2530](https://github.com/paritytech/parity/pull/2530) +- Handle reorganizations in the state cache [#2490](https://github.com/paritytech/parity/pull/2490) +- Hypervisor: terminate hanging modules [#2513](https://github.com/paritytech/parity/pull/2513) +- signer & node connection prompts/indicators [#2504](https://github.com/paritytech/parity/pull/2504) +- Using pending block only if is not old [#2514](https://github.com/paritytech/parity/pull/2514) +- More caching optimizations [#2505](https://github.com/paritytech/parity/pull/2505) +- Fixed possible panic in the networking [#2495](https://github.com/paritytech/parity/pull/2495) +- Trim password from file [#2503](https://github.com/paritytech/parity/pull/2503) +- Fixing RPC Filter conversion to EthFilter [#2500](https://github.com/paritytech/parity/pull/2500) +- Fixing error message for transactions [#2496](https://github.com/paritytech/parity/pull/2496) +- Adjustable stack size for EVM [#2483](https://github.com/paritytech/parity/pull/2483) +- [master] Fixing penalization in future [#2499](https://github.com/paritytech/parity/pull/2499) +- Preserve cache on reverting the snapshot [#2488](https://github.com/paritytech/parity/pull/2488) +- RocksDB version bump [#2492](https://github.com/paritytech/parity/pull/2492) +- Increase default size of transaction queue [#2489](https://github.com/paritytech/parity/pull/2489) +- basiccoin v1 available [#2491](https://github.com/paritytech/parity/pull/2491) +- Small EVM optimization [#2487](https://github.com/paritytech/parity/pull/2487) +- Track dirty accounts in the state [#2461](https://github.com/paritytech/parity/pull/2461) +- fix signature lookup address [#2480](https://github.com/paritytech/parity/pull/2480) +- update registrar test with generic non-empty test [#2476](https://github.com/paritytech/parity/pull/2476) +- Derive IPC interface only when ipc feature is on [#2463](https://github.com/paritytech/parity/pull/2463) +- Fix ethstore opening all key files in the directory at once [#2471](https://github.com/paritytech/parity/pull/2471) +- contract api event log fixes [#2469](https://github.com/paritytech/parity/pull/2469) +- basiccoin base functionality in-place [#2468](https://github.com/paritytech/parity/pull/2468) +- Merge IPC codegen attributes into one [#2460](https://github.com/paritytech/parity/pull/2460) +- Close after importing keys from geth [#2464](https://github.com/paritytech/parity/pull/2464) +- Port a couple more RPC APIs to the new auto args [#2325](https://github.com/paritytech/parity/pull/2325) +- update rustc for appveyor to 1.12.0 [#2423](https://github.com/paritytech/parity/pull/2423) +- dapp basiccoin send operations [#2456](https://github.com/paritytech/parity/pull/2456) +- Better EVM informant & Slow transactions warning [#2436](https://github.com/paritytech/parity/pull/2436) +- Fixing Signer token RPC API [#2437](https://github.com/paritytech/parity/pull/2437) +- Fixed FatDB check [#2443](https://github.com/paritytech/parity/pull/2443) +- dapp basiccoin structure [#2444](https://github.com/paritytech/parity/pull/2444) +- Accounts bloom in master [#2426](https://github.com/paritytech/parity/pull/2426) +- Polishing Actually enable fat db pr (#1974) [#2048](https://github.com/paritytech/parity/pull/2048) +- Jumptable cache [#2427](https://github.com/paritytech/parity/pull/2427) +- signaturereg registered, remove hardcoding [#2431](https://github.com/paritytech/parity/pull/2431) +- tokenreg dapp fixes for non-null returns [#2430](https://github.com/paritytech/parity/pull/2430) +- update ABI json to latest deployed versions [#2428](https://github.com/paritytech/parity/pull/2428) +- update Morden registry address [#2417](https://github.com/paritytech/parity/pull/2417) +- Make migration api more friendly [#2420](https://github.com/paritytech/parity/pull/2420) +- Journaling bloom filter crate in util [#2395](https://github.com/paritytech/parity/pull/2395) +- move abis from js/json to contracts/abi [#2418](https://github.com/paritytech/parity/pull/2418) +- Fixing logs-receipt matching [#2403](https://github.com/paritytech/parity/pull/2403) +- fix broken beta compilation [#2405](https://github.com/paritytech/parity/pull/2405) +- registry dapp: transfer names [#2335](https://github.com/paritytech/parity/pull/2335) +- manage firstRun better [#2398](https://github.com/paritytech/parity/pull/2398) +- render contract deployment address [#2397](https://github.com/paritytech/parity/pull/2397) +- Transaction Queue fix [#2392](https://github.com/paritytech/parity/pull/2392) +- contracts abi types & execute value [#2394](https://github.com/paritytech/parity/pull/2394) +- update styling with ParityBar overlay [#2390](https://github.com/paritytech/parity/pull/2390) +- application Signer popup window [#2388](https://github.com/paritytech/parity/pull/2388) +- Fixing Delegate Call in JIT [#2378](https://github.com/paritytech/parity/pull/2378) +- Prioritizing re-imported transactions [#2372](https://github.com/paritytech/parity/pull/2372) +- Revert #2172, pretty much. [#2387](https://github.com/paritytech/parity/pull/2387) +- correct sync memory usage calculation [#2385](https://github.com/paritytech/parity/pull/2385) +- fix migration system for post-consolidation migrations, better errors [#2334](https://github.com/paritytech/parity/pull/2334) +- Fix the traceAddress field in transaction traces. [#2373](https://github.com/paritytech/parity/pull/2373) +- Gavcoin utilises the popup box [#2381](https://github.com/paritytech/parity/pull/2381) +- registry dapp: support dropping names [#2328](https://github.com/paritytech/parity/pull/2328) +- settings view, set background & store views [#2380](https://github.com/paritytech/parity/pull/2380) +- Removing extras data from retracted blocks. [#2375](https://github.com/paritytech/parity/pull/2375) +- fixed #2263, geth keys with ciphertext shorter than 32 bytes [#2318](https://github.com/paritytech/parity/pull/2318) +- Expanse compatibility [#2369](https://github.com/paritytech/parity/pull/2369) +- Allow queries of constant functions on contracts [#2360](https://github.com/paritytech/parity/pull/2360) +- Auto Open/Close the Signer window on new transaction request [#2362](https://github.com/paritytech/parity/pull/2362) +- Specify column cache sizes explicitly; default fallback of 2MB [#2358](https://github.com/paritytech/parity/pull/2358) +- Canonical state cache (master) [#2311](https://github.com/paritytech/parity/pull/2311) +- method signature lookups, parameter decoding & management [#2313](https://github.com/paritytech/parity/pull/2313) +- make block queue into a more generic verification queue and fix block heap size calculation [#2095](https://github.com/paritytech/parity/pull/2095) +- Hash Content RPC method [#2355](https://github.com/paritytech/parity/pull/2355) +- registry dapp: show reserved events by default [#2359](https://github.com/paritytech/parity/pull/2359) +- Display timestamp in Signer requests details [#2324](https://github.com/paritytech/parity/pull/2324) +- Reorder transaction_by_hash to favour canon search [#2332](https://github.com/paritytech/parity/pull/2332) +- Optimize DIV for some common divisors [#2327](https://github.com/paritytech/parity/pull/2327) +- Return error when deserializing invalid hex [#2339](https://github.com/paritytech/parity/pull/2339) +- Changed http:// to https:// on some links [#2349](https://github.com/paritytech/parity/pull/2349) +- user defaults [#2014](https://github.com/paritytech/parity/pull/2014) +- Fixing jit feature compilation [#2310](https://github.com/paritytech/parity/pull/2310) +- Tx Queue improvements [#2292](https://github.com/paritytech/parity/pull/2292) +- Removing PropTypes on build [#2322](https://github.com/paritytech/parity/pull/2322) +- Lenient bytes deserialization [#2036](https://github.com/paritytech/parity/pull/2036) +- reverse call data decoding given transaction data & method [#2312](https://github.com/paritytech/parity/pull/2312) +- add missing gpl headers to gavcoin dapp [#2317](https://github.com/paritytech/parity/pull/2317) +- contract Events, Functions & Queries sub-components as well as Event log visual updates [#2306](https://github.com/paritytech/parity/pull/2306) +- webpack config updates (really include babel-polyfill, rename npm steps) [#2305](https://github.com/paritytech/parity/pull/2305) +- remove unneeded Form from Account header [#2302](https://github.com/paritytech/parity/pull/2302) +- edit of metadata across accounts, addresses & contracts [#2300](https://github.com/paritytech/parity/pull/2300) +- Adjust all modals for consistency & css DRY-ness [#2301](https://github.com/paritytech/parity/pull/2301) +- update container spacing [#2296](https://github.com/paritytech/parity/pull/2296) +- local cache of generated background (no allocation on each re-render) [#2298](https://github.com/paritytech/parity/pull/2298) +- fix failing tests [#2290](https://github.com/paritytech/parity/pull/2290) +- Respecting standards for tokenreg dapp [#2287](https://github.com/paritytech/parity/pull/2287) +- Separate RPC serialization from implementation [#2072](https://github.com/paritytech/parity/pull/2072) +- Webpack optimisations - Using DLL [#2264](https://github.com/paritytech/parity/pull/2264) +- header background, theme adjustments (not that harsh) [#2273](https://github.com/paritytech/parity/pull/2273) +- contract view (developer-centric) [#2259](https://github.com/paritytech/parity/pull/2259) +- Add hash as CLI function [#1995](https://github.com/paritytech/parity/pull/1995) +- registry: fix mined events showing as pending [#2267](https://github.com/paritytech/parity/pull/2267) +- Dapp - Tokereg ; Query Tokens from TLA or Address [#2266](https://github.com/paritytech/parity/pull/2266) +- Fixes to the Token Registration dApp [#2250](https://github.com/paritytech/parity/pull/2250) +- remove abi *.json duplication, provide a single version of the truth [#2253](https://github.com/paritytech/parity/pull/2253) +- Separate path for ext code size [#2251](https://github.com/paritytech/parity/pull/2251) +- Snapshot format changes [#2234](https://github.com/paritytech/parity/pull/2234) +- Serving content at /api/content/ [#2248](https://github.com/paritytech/parity/pull/2248) +- Fails when deserializing non-hex uints [#2247](https://github.com/paritytech/parity/pull/2247) +- registry dapp: add GPL headers [#2252](https://github.com/paritytech/parity/pull/2252) +- registry dapp: user-friendly lookup [#2229](https://github.com/paritytech/parity/pull/2229) +- registry dapp: show DataChanged events [#2242](https://github.com/paritytech/parity/pull/2242) +- fixups for deploys [#2249](https://github.com/paritytech/parity/pull/2249) +- Fixing output of eth_call and Bytes deserialization [#2230](https://github.com/paritytech/parity/pull/2230) +- Encryption, decryption and public key RPCs. [#1946](https://github.com/paritytech/parity/pull/1946) +- limit number of event logs returned [#2231](https://github.com/paritytech/parity/pull/2231) +- babel-polyfill [#2239](https://github.com/paritytech/parity/pull/2239) +- procedurally generate background based on signer key [#2233](https://github.com/paritytech/parity/pull/2233) +- UI fixes [#2238](https://github.com/paritytech/parity/pull/2238) +- expose isConnected() from transport [#2225](https://github.com/paritytech/parity/pull/2225) +- registry dapp: rename event log [#2227](https://github.com/paritytech/parity/pull/2227) +- registry dapp: show pending events [#2223](https://github.com/paritytech/parity/pull/2223) +- Handle RLP to string UTF-8 decoding errors [#2217](https://github.com/paritytech/parity/pull/2217) +- Use WebSocket transport for all built-in calls [#2216](https://github.com/paritytech/parity/pull/2216) +- Remove panickers from trie iterators [#2209](https://github.com/paritytech/parity/pull/2209) +- Limit for logs filter. [#2180](https://github.com/paritytech/parity/pull/2180) +- Various state copy optimizations [#2172](https://github.com/paritytech/parity/pull/2172) +- New signer token RPC & Initial signer connection without token. [#2096](https://github.com/paritytech/parity/pull/2096) +- signer ui fixes [#2219](https://github.com/paritytech/parity/pull/2219) +- contract deploy ui [#2212](https://github.com/paritytech/parity/pull/2212) +- registry dapp: fix propTypes [#2218](https://github.com/paritytech/parity/pull/2218) +- registry: fix IdentityIcon in events log [#2206](https://github.com/paritytech/parity/pull/2206) +- Fixing evm-debug [#2161](https://github.com/paritytech/parity/pull/2161) +- Fix syncing with pv63 peers [#2204](https://github.com/paritytech/parity/pull/2204) +- registry: show shortened hashes [#2205](https://github.com/paritytech/parity/pull/2205) +- registry dapp: remove owner [#2203](https://github.com/paritytech/parity/pull/2203) +- webpack proxy updates for /api* [#2175](https://github.com/paritytech/parity/pull/2175) +- simplify personal event publishing, fix delete refresh issues [#2183](https://github.com/paritytech/parity/pull/2183) +- fix global & initial states [#2160](https://github.com/paritytech/parity/pull/2160) +- Allow selection & saving of available views [#2131](https://github.com/paritytech/parity/pull/2131) +- global/contract events with promisy subscribe/unsubscribe [#2136](https://github.com/paritytech/parity/pull/2136) +- Token Registry dApp [#2178](https://github.com/paritytech/parity/pull/2178) +- re-usable bytesToHex exposed in api.util [#2174](https://github.com/paritytech/parity/pull/2174) +- Webpack optimisations [#2179](https://github.com/paritytech/parity/pull/2179) +- cleanup on contract event subscriptions [#2104](https://github.com/paritytech/parity/pull/2104) +- move utility functions to api.util [#2105](https://github.com/paritytech/parity/pull/2105) +- registry dapp [#2077](https://github.com/paritytech/parity/pull/2077) +- mui/FlatButton to ui/Button [#2129](https://github.com/paritytech/parity/pull/2129) +- address delete functionality [#2128](https://github.com/paritytech/parity/pull/2128) +- contract deployment updates [#2106](https://github.com/paritytech/parity/pull/2106) +- contract events, indexed string fix [#2108](https://github.com/paritytech/parity/pull/2108) +- Bumping jsonrpc-core & jsonrpc-http-server [#2162](https://github.com/paritytech/parity/pull/2162) +- gitlab testing & build processes [#2090](https://github.com/paritytech/parity/pull/2090) +- Misc small UI fixes (recently broken) [#2101](https://github.com/paritytech/parity/pull/2101) +- Bump clippy & Fix warnings [#2109](https://github.com/paritytech/parity/pull/2109) +- Import command summary [#2102](https://github.com/paritytech/parity/pull/2102) +- check for existence of deprecated ethash file before attempting delete [#2103](https://github.com/paritytech/parity/pull/2103) +- shapeshift Promise API library [#2088](https://github.com/paritytech/parity/pull/2088) +- fund account via ShapeShift [#2099](https://github.com/paritytech/parity/pull/2099) +- Get bigint on crates.io [#2078](https://github.com/paritytech/parity/pull/2078) +- Enable sealing if Engine provides internal sealing given author [#2084](https://github.com/paritytech/parity/pull/2084) +- Config files [#2070](https://github.com/paritytech/parity/pull/2070) +- re-add lodash plugin to babel config [#2092](https://github.com/paritytech/parity/pull/2092) +- Remove old cache data [#2081](https://github.com/paritytech/parity/pull/2081) +- Logs limit & log_index bug [#2073](https://github.com/paritytech/parity/pull/2073) +- flatten store, muiTheme & api providers [#2087](https://github.com/paritytech/parity/pull/2087) +- add babel es2016 & es2017 presets [#2083](https://github.com/paritytech/parity/pull/2083) +- remove all '/index' imports in API [#2089](https://github.com/paritytech/parity/pull/2089) +- add missing GPL headers to all files [#2086](https://github.com/paritytech/parity/pull/2086) +- readme cleanups [#2085](https://github.com/paritytech/parity/pull/2085) +- gavcoin global import of parity api [#2082](https://github.com/paritytech/parity/pull/2082) +- Fixing removal from gas price when moving future->current [#2076](https://github.com/paritytech/parity/pull/2076) +- Split internal sealing from work preparation [#2071](https://github.com/paritytech/parity/pull/2071) +- ensure the target folder doesn't exist before renaming [#2074](https://github.com/paritytech/parity/pull/2074) +- Get rid of 'Dapp is being downloaded' page [#2055](https://github.com/paritytech/parity/pull/2055) +- fix failing master build: update tests to new init_restore signature. [#2069](https://github.com/paritytech/parity/pull/2069) +- Local snapshot restore [#2058](https://github.com/paritytech/parity/pull/2058) +- import: keep informant going until finished [#2065](https://github.com/paritytech/parity/pull/2065) +- Add a few tests for the snapshot service [#2059](https://github.com/paritytech/parity/pull/2059) +- IPC tweaks [#2046](https://github.com/paritytech/parity/pull/2046) +- Update arm* Docker [#2064](https://github.com/paritytech/parity/pull/2064) +- Fetching any content-addressed content [#2050](https://github.com/paritytech/parity/pull/2050) +- Use proper database configuration in snapshots. [#2052](https://github.com/paritytech/parity/pull/2052) +- periodic snapshot tweaks [#2054](https://github.com/paritytech/parity/pull/2054) +- ethkey-cli [#2057](https://github.com/paritytech/parity/pull/2057) +- Forward ethstore-cli feature [#2056](https://github.com/paritytech/parity/pull/2056) +- handling invalid spec jsons properly, additional tests, closes #1840 [#2049](https://github.com/paritytech/parity/pull/2049) +- Periodic snapshots [#2044](https://github.com/paritytech/parity/pull/2044) +- Snapshot sync [#2047](https://github.com/paritytech/parity/pull/2047) +- Nice error pages for Dapps & Signer [#2033](https://github.com/paritytech/parity/pull/2033) +- Add a few small snapshot tests [#2038](https://github.com/paritytech/parity/pull/2038) +- facelift for traces, added errors [#2042](https://github.com/paritytech/parity/pull/2042) +- Fetching content from HTTPS using `rustls` [#2024](https://github.com/paritytech/parity/pull/2024) +- Skipping log when there are no transactions were sent [#2045](https://github.com/paritytech/parity/pull/2045) +- rlp as separate crate [#2034](https://github.com/paritytech/parity/pull/2034) +- Fixing uint serialization [#2037](https://github.com/paritytech/parity/pull/2037) +- Fixing new transactions propagation [#2039](https://github.com/paritytech/parity/pull/2039) +- Propagating transactions to peers on timer. [#2035](https://github.com/paritytech/parity/pull/2035) +- Remove Populatable and BytesConvertable traits [#2019](https://github.com/paritytech/parity/pull/2019) +- fixed #1933 [#1979](https://github.com/paritytech/parity/pull/1979) +- Synchronization tweaks for IPC services [#2028](https://github.com/paritytech/parity/pull/2028) +- Asynchronous RPC support [#2017](https://github.com/paritytech/parity/pull/2017) +- Disable ArchiveDB counter check [#2016](https://github.com/paritytech/parity/pull/2016) +- always process trie death row on commit, add more tracing [#2025](https://github.com/paritytech/parity/pull/2025) +- fixed transaction addresses mapping, fixes #1971 [#2026](https://github.com/paritytech/parity/pull/2026) +- Adding tests for dapps server. [#2021](https://github.com/paritytech/parity/pull/2021) +- builtin trait refactoring [#2018](https://github.com/paritytech/parity/pull/2018) +- Start parity with systemd [#1967](https://github.com/paritytech/parity/pull/1967) +- Control service for IPC [#2013](https://github.com/paritytech/parity/pull/2013) +- LRU cache for dapps [#2006](https://github.com/paritytech/parity/pull/2006) +- CLI for valid hosts for dapps server [#2005](https://github.com/paritytech/parity/pull/2005) +- Make the block header struct's internals private [#2000](https://github.com/paritytech/parity/pull/2000) +- Take control of recovered snapshots, start restoration asynchronously [#2010](https://github.com/paritytech/parity/pull/2010) +- remove internal locking from DBTransaction [#2003](https://github.com/paritytech/parity/pull/2003) +- Snapshot optimizations [#1991](https://github.com/paritytech/parity/pull/1991) +- Revert removing ecies [#2009](https://github.com/paritytech/parity/pull/2009) +- small blooms optimization [#1998](https://github.com/paritytech/parity/pull/1998) +- protection from adding empty traces && assertion in traces db [#1994](https://github.com/paritytech/parity/pull/1994) +- Stratum IPC service [#1959](https://github.com/paritytech/parity/pull/1959) +- Signature cleanup [#1921](https://github.com/paritytech/parity/pull/1921) +- Fixed discovery skipping some nodes [#1996](https://github.com/paritytech/parity/pull/1996) +- Trie query recording and AccountDB factory for no mangling [#1944](https://github.com/paritytech/parity/pull/1944) +- Validating sha3 of a dapp bundle [#1993](https://github.com/paritytech/parity/pull/1993) +- Improve eth_getWork timeout test rpc_get_work_should_timeout [#1992](https://github.com/paritytech/parity/pull/1992) +- Resolving URLs from contract [#1964](https://github.com/paritytech/parity/pull/1964) +- Add timeout for eth_getWork call [#1975](https://github.com/paritytech/parity/pull/1975) +- CLI for Signer interface [#1980](https://github.com/paritytech/parity/pull/1980) +- IPC timeout multiplied [#1990](https://github.com/paritytech/parity/pull/1990) +- Use relative path for IPC sockets [#1983](https://github.com/paritytech/parity/pull/1983) +- Market-orientated transaction pricing [#1963](https://github.com/paritytech/parity/pull/1963) +- Bump clippy [#1982](https://github.com/paritytech/parity/pull/1982) +- Fixing mutual recursive types serialization [#1977](https://github.com/paritytech/parity/pull/1977) +- Fix open on FreeBSD [#1984](https://github.com/paritytech/parity/pull/1984) +- Upgrade hyper dependency to 0.9 [#1973](https://github.com/paritytech/parity/pull/1973) +- Create network-specific nodes files [#1970](https://github.com/paritytech/parity/pull/1970) +- Getting rid of syntex [#1965](https://github.com/paritytech/parity/pull/1965) +- Remove binary specification from hypervisor [#1960](https://github.com/paritytech/parity/pull/1960) +- Stratum protocol general [#1954](https://github.com/paritytech/parity/pull/1954) +- keep track of first block in blockchain [#1937](https://github.com/paritytech/parity/pull/1937) +- introduce ethcore/state module [#1953](https://github.com/paritytech/parity/pull/1953) +- Apply settings to column families [#1956](https://github.com/paritytech/parity/pull/1956) +- move column family constants into db module [#1955](https://github.com/paritytech/parity/pull/1955) +- ECIES without MAC [#1948](https://github.com/paritytech/parity/pull/1948) +- Fix canny warnings [#1951](https://github.com/paritytech/parity/pull/1951) +- Fetchable dapps [#1949](https://github.com/paritytech/parity/pull/1949) +- remove impossible panickers related to infallible db transaction [#1947](https://github.com/paritytech/parity/pull/1947) +- Minor optimizations [#1943](https://github.com/paritytech/parity/pull/1943) +- remove randomness from bigint benches, fix warnings [#1945](https://github.com/paritytech/parity/pull/1945) +- Fix several RPCs [#1926](https://github.com/paritytech/parity/pull/1926) +- Bump clippy, fix warnings [#1939](https://github.com/paritytech/parity/pull/1939) +- DB WAL size limit [#1935](https://github.com/paritytech/parity/pull/1935) +- Use explicit global namespaces in codegen [#1928](https://github.com/paritytech/parity/pull/1928) +- Fix build on master [#1934](https://github.com/paritytech/parity/pull/1934) +- IPC on by default [#1927](https://github.com/paritytech/parity/pull/1927) +- fix util benches compilation [#1931](https://github.com/paritytech/parity/pull/1931) +- Update gitlab-ci [#1929](https://github.com/paritytech/parity/pull/1929) +- ethkey and ethstore use hash structures from bigint [#1851](https://github.com/paritytech/parity/pull/1851) diff --git a/docs/CHANGELOG-1.5.md b/docs/CHANGELOG-1.5.md new file mode 100644 index 0000000000000000000000000000000000000000..fe9f72375ee26f850214041401b0896783ad76af --- /dev/null +++ b/docs/CHANGELOG-1.5.md @@ -0,0 +1,1017 @@ +Note: Parity 1.5 reached End-of-Life on 2017-07-28 (EOL). + +## Parity [v1.5.12](https://github.com/paritytech/parity/releases/tag/v1.5.12) (2017-03-27) + +Stable release that adds support for a new warp sync snapshot format. + +- Stable Backports [#5297](https://github.com/paritytech/parity/pull/5297) + - Bump to v1.5.12 + - Fine grained snapshot chunking + +## Parity [v1.5.11](https://github.com/paritytech/parity/releases/tag/v1.5.11) (2017-03-14) + +Parity 1.5.11 Includes a patch for a more comprehensive block verification. + +- Bump to v1.5.11 +- Additional kovan params +- Recalculate receipt roots in close_and_lock +- Bump to v1.5.10 + +## Parity [v1.5.9](https://github.com/paritytech/parity/releases/tag/v1.5.9) (2017-03-11) + +First stable release of 1.5.x series. This release enables EIP-161 transaction replay protection for PoA networks. + +- Bump to v1.5.9 +- Fix auto-updater stable [#4869](https://github.com/paritytech/parity/pull/4869) +- Fixing windows build script +- Bump js-precompiled 20170308-152339 +- Force js update +- Stable Engine backports [#4807](https://github.com/paritytech/parity/pull/4807) + - Calibrate before rejection + - Change flag name + - Add eip155 + - Fix build + - Make network_id default +- Switch js branch to stable +- Bump to v1.5.8 + +## Parity [v1.5.7](https://github.com/paritytech/parity/releases/tag/v1.5.7) (2017-03-07) + +This release resolves a single issue with failing auto-updates. + +- Update ETC bootnodes [#4794](https://github.com/paritytech/parity/pull/4794) +- Bump to v1.5.7 +- Sane updater [#4658](https://github.com/paritytech/parity/pull/4658) + - Disable if files can't be moved. + - Make updater avoid downloading earlier versions. + +## Parity [v1.5.6](https://github.com/paritytech/parity/releases/tag/v1.5.6) (2017-03-06) + +This release among various stability fixes adds support for a new [Kovan](https://github.com/kovan-testnet/proposal) testnet. + +See [full list of changes.](https://github.com/paritytech/parity/compare/v1.5.4...v1.5.6): + +- Beta Update comments and reg ABI [#4788](https://github.com/paritytech/parity/pull/4788) + - Update comments. + - Fix up new ABI. +- Bump to v1.5.6 in beta [#4786](https://github.com/paritytech/parity/pull/4786) +- Beta Optimize signature for fallback function. ([#4780](https://github.com/paritytech/parity/pull/4780)) [#4784](https://github.com/paritytech/parity/pull/4784) +- Beta Add registrar fields ([#4716](https://github.com/paritytech/parity/pull/4716)) [#4781](https://github.com/paritytech/parity/pull/4781) +- Beta Etherscan links ([#4772](https://github.com/paritytech/parity/pull/4772)) [#4778](https://github.com/paritytech/parity/pull/4778) + - Etherscan links [#4772](https://github.com/paritytech/parity/pull/4772) + - Use netVersion to determine external links + - Update additional isTest references + - Port tests + - Update address links + - Signer accountlink isTest +- Beta Fix invalid props [#4767](https://github.com/paritytech/parity/pull/4767) +- Backporting to beta [#4741](https://github.com/paritytech/parity/pull/4741) + - New chains [#4720](https://github.com/paritytech/parity/pull/4720) + - Add Kovan chain. + - Fix up --testnet. + - Fix tests. + - Fix to UglifyJS 2.8.2 to fix app build issues [#4723](https://github.com/paritytech/parity/pull/4723) + - Update classic bootnodes, ref #4717 [#4735](https://github.com/paritytech/parity/pull/4735) + - Allow failure docker beta + - Adjust pruning history default to 64 [#4709](https://github.com/paritytech/parity/pull/4709) + - Backporting from master + - Update docker-build.sh + - Update gitlab.ci + - Fix docker hub build + - Update gitlab + - Docker beta-release->latest + - Add registry. + - Add info on forks. + - Fixed spec file + - Support both V1 & V2 DataChanged events in registry [#4734](https://github.com/paritytech/parity/pull/4734) + - Add info on forks. + - Add new registry ABI + - Import registry2 & fix exports + - Select ABI based on code hash + - Render new event types (owner not available) + - New registry. + - Rename old chain. + - Fix test. + - Another fix. + - Finish rename. + - Fixed fonts URLs [#4579](https://github.com/paritytech/parity/pull/4579) + - Fix Token Reg Dapp issues in Firefox [#4489](https://github.com/paritytech/parity/pull/4489) + - Fix overflow issues in Firefox [#4348](https://github.com/paritytech/parity/issues/4348) + - Fix wrong Promise inferance + - Revert "Add new Componennt for Token Images [#4496](https://github.com/paritytech/parity/issues/4496)" + - Add new Componennt for Token Images [#4496](https://github.com/paritytech/parity/issues/4496) + - Add StackEventListener [#4745](https://github.com/paritytech/parity/pull/4745) + - Update testnet detection [#4746](https://github.com/paritytech/parity/pull/4746) + - Fix Account Selection in Signer [#4744](https://github.com/paritytech/parity/pull/4744) + - Can pass FormattedMessage to Input (eg. Status // RPC Enabled) + - Simple fixed-width fix for Accoutn Selection in Parity Signer +- Beta backports [#4763](https://github.com/paritytech/parity/pull/4763) + - Https://mkr-market -> https://oasisdex.com [#4701](https://github.com/paritytech/parity/pull/4701) + - Wallet s/delete/forget/ [#4741](https://github.com/paritytech/parity/pull/4741) +- Update classic bootnodes [#4735](https://github.com/paritytech/parity/pull/4735) +- Engine backports [#4718](https://github.com/paritytech/parity/pull/4718) + - Custom dev presets + - Add registrar field + - Use constructor for dev registrar + - Fix test +- Beta Adjust pruning history default to 64 [#4709](https://github.com/paritytech/parity/pull/4709) +- Bump to v1.5.5 + +## Parity [v1.5.4](https://github.com/paritytech/parity/releases/tag/v1.5.4) (2017-02-23) + +A couple of issue fixed in this release: + +- Parity now allows uncles headers to have timestamp set to arbitrary future value. +- Importing keys from geth is now working again. + +Changes: + +- Beta Fix Geth account import [#4643](https://github.com/paritytech/parity/pull/4643) + - Fix Geth import - actually pass addresses through + - Fix geth accounts not displayed + - Port saving of returned addresses (master MobX, beta state) + - Log result -> importGethAccounts +- Beta Backporting ([#4633](https://github.com/paritytech/parity/pull/4633)) [#4640](https://github.com/paritytech/parity/pull/4640) + - Tweak some checks. + - Fixed build and added a difficulty test + - Bump to v1.5.4 + +## Parity [v1.5.3](https://github.com/paritytech/parity/releases/tag/v1.5.3) (2017-02-20) + +This is a maintenance release that fixes a number of stability issues. Notably this resolves an issue where Parity would allow a pre EIP-155 transaction into the sealed block. + +See [full list of changes](https://github.com/paritytech/parity/compare/v1.5.2...v1.5.3): + +- Bump to v1.5.3 [#4611](https://github.com/paritytech/parity/pull/4611) +- Handle invalid ABI retrieved from address_book gracefully ([#4606](https://github.com/paritytech/parity/pull/4606)) [#4610](https://github.com/paritytech/parity/pull/4610) + - Handle invalid ABI gracefully + - Also include failed abi in log +- Backporting to beta [#4602](https://github.com/paritytech/parity/pull/4602) + - Static link for snappy + - added 3 warpnodes for ropsten ([#4289](https://github.com/paritytech/parity/pull/4289)) + - Fixed indentation +- Validate transaction before adding to the queue [#4600](https://github.com/paritytech/parity/pull/4600) +- Beta backports [#4569](https://github.com/paritytech/parity/pull/4569) + - Fixing evmbin compilation and added standard build. ([#4561](https://github.com/paritytech/parity/pull/4561)) + - Alias for personal_sendTransaction ([#4554](https://github.com/paritytech/parity/pull/4554)) + - Fix console dapp ([#4544](https://github.com/paritytech/parity/pull/4544)) + - Fixing linting issues. Better support for console as secure app + - Fixing linting issues + - Fix no data sent in TxQueue dapp ([#4502](https://github.com/paritytech/parity/pull/4502)) + - Fix wrong PropType req for Embedded Signer + - Fix wrong data for tx #4499 +- Explicitly set seconds to 0 from selector ([#4559](https://github.com/paritytech/parity/pull/4559)) [#4571](https://github.com/paritytech/parity/pull/4571) + - Explicitly set seconds/milli to 0 + - Use condition time & block setters consistently + - Fix failing test + - test for 0 ms & sec + - It cannot hurt, clone date before setting + - Prettier date test constants (OCD) +- Remove invalid expectation [#4542](https://github.com/paritytech/parity/pull/4542) +- Skip OOG check for simple transfers [#4558](https://github.com/paritytech/parity/pull/4558) [#4560](https://github.com/paritytech/parity/pull/4560) + - Skip OOG check for simple transfers [#4558](https://github.com/paritytech/parity/pull/4558) + - Fix failing test + +## Parity [v1.5.2](https://github.com/paritytech/parity/releases/tag/v1.5.2) (2017-02-08) + +This release brings a few stability fixes along with a feature that allows queuing transactions that are activated and send out on selected date or block number. +- Debian packages have been updated to require `libssl1.0.0` for better compatibility. +- eth_sign (and parity_postSign) used to return concatenated r ++ s ++ v with v being 0 or 1. it now agrees with geth as v ++ r ++ s with v being 27 or 28. + +Parity Wallet +- Accounts & ShapeShift integration now displays QR code for scanning from mobile wallets +- Dapp integration now allows for the selection of available accounts and the setting of the default account +- Transaction creation now allows for the selection of future blocks or timestamps after which the transaction is released + +Parity Extension +- First release of the Parity Extension, allowing for Parity integration from web-based dapps + +See [full list of changes](https://github.com/paritytech/parity/compare/v1.5.0...v1.5.2): +- Work with string numbers in contract (Fixes #4472) ([#4478](https://github.com/paritytech/parity/pull/4478)) [#4480](https://github.com/paritytech/parity/pull/4480) +- Eth_sign improvements backport [#4473](https://github.com/paritytech/parity/pull/4473) + - Fix postsign ([#4347](https://github.com/paritytech/parity/pull/4347)) + - Fix whitespace. + - Fix post sign. + - Fix message. + - Fix tests. + - Rest of the problems. + - All hail the linter and its omniscience. + - ...and its divine omniscience. + - Grumbles and wording. + - Make signing compatible with geth. ([#4468](https://github.com/paritytech/parity/pull/4468)) +- Sort gas price corpus when hitting genesis [#4471](https://github.com/paritytech/parity/pull/4471) +- Wallet dev chain fix [#4466](https://github.com/paritytech/parity/pull/4466) +- Fixing histogram again [#4464](https://github.com/paritytech/parity/pull/4464) +- Beta backports [#4462](https://github.com/paritytech/parity/pull/4462) + - Support HTML5-routed dapps ([#4173](https://github.com/paritytech/parity/pull/4173)) + - Fix compilation on latest nightly + - Updating precompiled +- Fix Portal scrolling getting stuck [#4456](https://github.com/paritytech/parity/pull/4456) + - Fix Portal scrolling getting stuck + - DappCard container flex + - Container height to 100% +- Fix AccountCard stretch to 100% [#4451](https://github.com/paritytech/parity/pull/4451) +- Fix wrong output format of peers ([#4270](https://github.com/paritytech/parity/pull/4270)) [#4442](https://github.com/paritytech/parity/pull/4442) + - Fix wrong output format of peers + - Add outPeer tests +- Opening extension page without inline installation [#4441](https://github.com/paritytech/parity/pull/4441) + - Open popup without attempting inline + - Cater for all .web3.site addresses +- Fix svg extension image webpack inlining [#4437](https://github.com/paritytech/parity/pull/4437) +- Backporting to beta [#4434](https://github.com/paritytech/parity/pull/4434) + - Bump to v1.5.2 + - Fix eth_sign/parity_postSign ([#4432](https://github.com/paritytech/parity/pull/4432)) + - Fix dispatch for signing. + - Remove console log + - Fix signing & tests. +- Returning default account as coinbase [#4431](https://github.com/paritytech/parity/pull/4431) + - Returning first address as coinbase + - Allowing sender alteration in signer + - Adding default account RPC +- UI updates for 1.5.1 [#4429](https://github.com/paritytech/parity/pull/4429) + - S/Delete Contract/Forget Contract/ ([#4237](https://github.com/paritytech/parity/pull/4237)) + - Adjust the location of the signer snippet ([#4155](https://github.com/paritytech/parity/pull/4155)) + - Additional building-block UI components ([#4239](https://github.com/paritytech/parity/pull/4239)) + - Currency WIP + - Expand tests + - Pass className + - Add QrCode + - Export new components in ~/ui + - S/this.props.netSymbol/netSymbol/ + - Fix import case + - Ui/SectionList component ([#4292](https://github.com/paritytech/parity/pull/4292)) + - Array chunking utility + - Add SectionList component + - Add TODOs to indicate possible future work + - Add missing overlay style (as used in dapps at present) + - Add a Playground for the UI Components ([#4301](https://github.com/paritytech/parity/pull/4301)) + - Playground // WIP + - Linting + - Add Examples with code + - CSS Linting + - Linting + - Add Connected Currency Symbol + - 2015-2017 + - Added `renderSymbol` tests + - PR grumbles + - Add Eth and Btc QRCode examples + - 2015-2017 + - Add tests for playground + - Fixing tests + - Split Dapp icon into ui/DappIcon ([#4308](https://github.com/paritytech/parity/pull/4308)) + - Add QrCode & Copy to ShapeShift ([#4322](https://github.com/paritytech/parity/pull/4322)) + - Extract CopyIcon to ~/ui/Icons + - Add copy & QrCode address + - Default size 4 + - Add bitcoin: link + - Use protocol links applicable to coin exchanged + - Remove .only + - Display QrCode for accounts, addresses & contracts ([#4329](https://github.com/paritytech/parity/pull/4329)) + - Allow Portal to be used as top-level modal ([#4338](https://github.com/paritytech/parity/pull/4338)) + - Portal + - Allow Portal to be used in as both top-level and popover + - Modal/popover variable naming + - Export Portal in ~/ui + - Properly handle optional onKeyDown + - Add simple Playground Example + - Add proper event listener to Portal ([#4359](https://github.com/paritytech/parity/pull/4359)) + - Display AccountCard name via IdentityName ([#4235](https://github.com/paritytech/parity/pull/4235)) + - Fix signing ([#4363](https://github.com/paritytech/parity/pull/4363)) + - Dapp Account Selection & Defaults ([#4355](https://github.com/paritytech/parity/pull/4355)) + - Add parity_defaultAccount RPC (with subscription) ([#4383](https://github.com/paritytech/parity/pull/4383)) + - Default Account selector in Signer overlay ([#4375](https://github.com/paritytech/parity/pull/4375)) + - Typo, fixes #4271 ([#4391](https://github.com/paritytech/parity/pull/4391)) + - Fix ParityBar account selection overflows ([#4405](https://github.com/paritytech/parity/pull/4405)) + - Available Dapp selection alignment with Permissions (Portal) ([#4374](https://github.com/paritytech/parity/pull/4374)) + - Registry dapp: make lookup use lower case ([#4409](https://github.com/paritytech/parity/pull/4409)) + - Dapps use defaultAccount instead of own selectors ([#4386](https://github.com/paritytech/parity/pull/4386)) + - Poll for defaultAccount to update dapp & overlay subscriptions ([#4417](https://github.com/paritytech/parity/pull/4417)) + - Poll for defaultAccount (Fixes #4413) + - Fix nextTimeout on catch + - Store timers + - Re-enable default updates on change detection + - Add block & timestamp conditions to Signer ([#4411](https://github.com/paritytech/parity/pull/4411)) + - Extension installation overlay ([#4423](https://github.com/paritytech/parity/pull/4423)) + - Extension installation overlay + - Pr gumbles + - Spelling + - Update Chrome URL + - Fix for non-included jsonrpc + - Extend Portal component (as per Modal) [#4392](https://github.com/paritytech/parity/pull/4392) +- Transaction timestamp condition [#4427](https://github.com/paritytech/parity/pull/4427) +- Fixing embedded bar not closing in chrome extension [#4421](https://github.com/paritytech/parity/pull/4421) +- Backporting to beta [#4418](https://github.com/paritytech/parity/pull/4418) + - Bump to 1.5.1 + - Disable notifications ([#4243](https://github.com/paritytech/parity/pull/4243)) + - Fix wrong token handling ([#4254](https://github.com/paritytech/parity/pull/4254)) + - Fixing wrong token displayed + - Linting + - Revert filtering out + - Revert the revert + - Don't panic on uknown git commit hash ([#4231](https://github.com/paritytech/parity/pull/4231)) + - Additional logs for own transactions ([#4278](https://github.com/paritytech/parity/pull/4278)) + - Integration with zgp whitelist contract ([#4215](https://github.com/paritytech/parity/pull/4215)) + - Zgp-transactions checker + - Polishing + - Rename + refactor + - Refuse-service-transactions cl option + - Fixed tests compilation + - Renaming signAndSendTransaction to sendTransaction ([#4351](https://github.com/paritytech/parity/pull/4351)) + - Fixed deadlock in external_url ([#4354](https://github.com/paritytech/parity/pull/4354)) + - Fixing web3 in console ([#4382](https://github.com/paritytech/parity/pull/4382)) + - Fixing estimate gas in case histogram is not available ([#4387](https://github.com/paritytech/parity/pull/4387)) + - Restarting fetch client every now and then ([#4399](https://github.com/paritytech/parity/pull/4399)) +- Embeddable ParityBar ([#4222](https://github.com/paritytech/parity/pull/4222)) [#4287](https://github.com/paritytech/parity/pull/4287) + - Embeddable ParityBar + - Replacing storage with store + - Fixing references. + - Addressing style issues + - Supporting parity background + +## Parity [v1.5.0: "Nativity"](https://github.com/paritytech/parity/releases/tag/v1.5.0) (2017-01-19) + +Major feature release including _Tendermint_ consensus engine, _Multisig wallet_ support, _badge/certification_ UI integration and _automatic updates_. + +Directories: + +- New XDG-informed Parity data directory structure. Base dir (`--base-path` or `-d`) that defaulted to `$HOME/.parity` is changed to: + - `/Users/You/AppData/Roaming/Parity/Ethereum` on Windows + - `/Users/you/Library/Application Support/io.parity.ethereum` on MacOS + - `/home/you/.local/share/parity` on Linux/Unix +- Keys are now stored in chain-specific directories . On first run of 1.5, all keys will be moved into the key's directory of the chain you run. You'll need to move the wallet files between directories manually if you wish to split them between testnet/mainnet. +- `--db-path` option now controls the path just for the databases, not for keys (`--keys-path`) or dapps (`--dapps-path`). + +Basics: + +- Version tracking, consensus-protection, hypervised auto-updating: + - Parity will ensure syncing is paused if its version cannot support an upcoming hard-fork (disable with `--no-consensus`). + - Parity will automatically download the latest version and may be updated through Parity Wallet (disable with `--no-download`) + - Parity can automatically update and seamlessly restart to later versions in the same release track (enable with `--auto-update=all` or `--auto-update=critical`). + - Parity hypervisor will automatically run the latest version (disable with `--force-direct`). +- Fat database; to enable, sync the chain with the option `--fat-db`. + - Accounts and storage entries can be enumerated. + - Chain state can be exported to JSON for analysis with `parity export state`. +- CLI and config options renamed: all variants of `--signer` are renamed to `--ui`. +- Log files are appended by default rather than truncated (useful for daemon deployments). + +Parity Wallet: + +- Multisig wallet support: "New Wallet" button in the "Accounts" section allows you to create a new multisig wallet or import an existing one. +- Solidity compiler: "Develop Contract" button in the "Contracts" section allows you to write, edit, compile and deploy contracts. +- SMS & e-mail verification: Accounts can now be certified as verified using Parity's SMS and e-Mail verification/registration oracle. +- Badge/certification integration: The `BadgeReg` contract can be used to deploy additional certifications. +- Local transaction propagation tracking: "TxQueue Viewer" in the "Applications" section allows you to track and resubmit previously sent transactions. +- Contract executions can now have gas and gas-price configured. +- Signer can now alter the gas and gas-price of transactions at password-entry. +- The deprecated Chrome "Signer" extension is now incompatible. + +[Proof of Authority](https://github.com/paritytech/parity/wiki/Proof-of-Authority-Chains): + +- Authority Round consensus engine: `engine: authorityRound {...}`; this is a high-performance Proof-of-Authority consensus engine. It is not BFT under normal circumstances (however the `--force-sealing` flag can be used to ensure consensus even with Byzantine nodes). +- Tendermint Engine: `engine: tendermint {...}`; this is an experimental Proof-of-Authority consensus engine. BFT up to one third of the authorities and falling back to delayed finalization chain ordering (50% fault tolerant). +- Generic seal JSON spec includes engine-specific types (`seal: { generic: { rlp: "0x..." } }` becomes `seal: { authority_round { step: 0, signature: "0x..." } }`. +- To set a node as authority either `--engine-signer ADDRESS` should be used with `--password` or `parity_setEngineSigner(address, password)` RPC should be called. Unlocking the account permanently or using `--author` is now unnecessary. +- Set of authorities can now be specified using a [list or a contract](https://github.com/paritytech/parity/wiki/Consensus-Engines#validator-engines). + +Chains: + +- Dev chain: `--chain=dev`; instant seal engine (no mining needed). Great for development work. +- Ropsten chain (`--chain=ropsten` or `--chain=testnet`) configures for Ropsten, the new test net. +- Morden chain (`--chain=morden`) changed to "Classic" rules and stays as the Ethereum Classic test net. + +RPCs/APIs: + +- All JSON-RPC interfaces have strict JSON deserialization - no extra fields are allowed. +- `eth_sign` RPC now hashes given data instead of getting the hash. +- `signer_confirmRequestWithToken`: additional RPC for signing transactions with a rotating token, alleviating the need for keeping an account password in memory. +- `eth_signTransaction` now conforms to the specification, `eth_submitTransaction` is introduced. + +Full changes: + +- Backporting to beta [#4211](https://github.com/paritytech/parity/pull/4211) + - JsonRPC bump for IPC fix + - Fixing etherscan price parsing ([#4202](https://github.com/paritytech/parity/pull/4202)) + - Handling all errors + - Fixed --base-path on windows ([#4193](https://github.com/paritytech/parity/pull/4193)) + - Add support for optional args with default text + - Fixing minimal transaction queue price ([#4204](https://github.com/paritytech/parity/pull/4204)) + - Fixing tests + - verification: add mainnet BadgeReg ids ([#4190](https://github.com/paritytech/parity/pull/4190)) + - verification: fetch contracts by name + - verification: better wording + - typo + - reregistered badges + - Console now has admin ([#4220](https://github.com/paritytech/parity/pull/4220)) + - Fixes [#4210](https://github.com/paritytech/parity/pull/4210) + - Non-secure for DappReg ([#4216](https://github.com/paritytech/parity/pull/4216)) +- Backporting to beta [#4203](https://github.com/paritytech/parity/pull/4203) + - Minor typo to ensure it updates only when synced. ([#4188](https://github.com/paritytech/parity/pull/4188)) + - Updater fixes ([#4196](https://github.com/paritytech/parity/pull/4196)) + - Minor typo to ensure it updates only when synced. + - Fix deadlock. + - Skip unneeded arg in making list. + - Allow auto-restart even when not running an update. + - Fix trace. + - Update update info on each loop. + - Fix build. + - Shutdown all sockets + - Remove superfluous use. + - Poll for upgrades as part of global status (long) ([#4197](https://github.com/paritytech/parity/pull/4197)) + - Fix path + - Prevent duplicate incoming connections ([#4180](https://github.com/paritytech/parity/pull/4180)) +- Gas_limit for blocks, mined by Parity will be divisible by 37 ([#4154](https://github.com/paritytech/parity/pull/4154)) [#4176](https://github.com/paritytech/parity/pull/4176) + - gas_limit for new blocks will divide evenly by 13 + - increased PARITY_GAS_LIMIT_DETERMINANT to 37 + - separate method for marking mined block + - debug_asserts(gas_limit within protocol range) + - round_block_gas_limit method is now static + - made round_block_gas_limit free-function + - multiplier->multiple +- Backporting to beta [#4175](https://github.com/paritytech/parity/pull/4175) + - verification: check if server is running ([#4140](https://github.com/paritytech/parity/pull/4140)) + - verification: check if server is running + - See also ethcore/email-verification#67c6466 and ethcore/sms-verification#a585e42. + - verification: show in the UI if server is running + - verification: code style ✨, more i18n + - fix i18n key + - Optimized hash lookups ([#4144](https://github.com/paritytech/parity/pull/4144)) + - Optimize hash comparison + - Use libc + - Ropsten fork detection ([#4163](https://github.com/paritytech/parity/pull/4163)) + - Stop flickering + added loader in AddressSelector ([#4149](https://github.com/paritytech/parity/pull/4149)) + - Stop UI flickering + added loader to AddressSelector [#4103](https://github.com/paritytech/parity/pull/4103) + - PR Grumbles + - Add a password strength component ([#4153](https://github.com/paritytech/parity/pull/4153)) + - Added new PasswordStrength Component + - Added tests + - PR Grumbles + - icarus -> update, increase web timeout. ([#4165](https://github.com/paritytech/parity/pull/4165)) + - Fix estimate gas + - Fix token images // Error in Contract Queries ([#4169](https://github.com/paritytech/parity/pull/4169)) + - Fix dapps not loading ([#4170](https://github.com/paritytech/parity/pull/4170)) + - Add secure to dappsreg + - Remove trailing slash // fix dapps +- Bumping hyper [#4168](https://github.com/paritytech/parity/pull/4168) + - Bumping hyper + - Bumping again +- Backporting to beta [#4158](https://github.com/paritytech/parity/pull/4158) + - Remove onSubmit of current (no auto-change on password edit) ([#4151](https://github.com/paritytech/parity/pull/4151)) + - Remove onSubmit from current password + - Remove onSubmit from hint + - Pull in console dapp as builtin ([#4145](https://github.com/paritytech/parity/pull/4145)) + - Copy static dapps from static (no build) + - Console sources + - Add console to builtins + - Remove console assets + - Disable eslint on console.js + - Enable eslint after disable + - Webpack copy +- Backporting to beta [#4152](https://github.com/paritytech/parity/pull/4152) + - Fix broken transfer total balance ([#4127](https://github.com/paritytech/parity/pull/4127)) + - Add proper label to method decoding inputs ([#4136](https://github.com/paritytech/parity/pull/4136)) + - Another minor estimation fix ([#4133](https://github.com/paritytech/parity/pull/4133)) + - Return 0 instead of error with out of gas on estimate_gas + - Fix stuff up. + - Another estimate gas fix. + - Alter balance to maximum possible rather than GP=0. + - Only increase to amount strictly necessary. + - Get rid of unsafe code in ethkey, propagate incorrect Secret errors. ([#4119](https://github.com/paritytech/parity/pull/4119)) + - Implementing secret + - Fixing tests + - Refactor VoteCollector ([#4101](https://github.com/paritytech/parity/pull/4101)) + - dir + - simple validator list + - stub validator contract + - make the engine hold Weak instead of IoChannel + - validator set factory + - register weak client with ValidatorContract + - check chain security + - add address array to generator + - register provider contract + - update validator set on notify + - add validator contract spec + - simple list test + - split update and contract test + - contract change + - use client in tendermint + - fix deadlock + - step duration in params + - adapt tendermint tests + - add storage fields to test spec + - constructor spec + - execute under wrong address + - create under correct address + - revert + - validator contract constructor + - move genesis block lookup + - add removal ability to contract + - validator contract adding validators + - fix basic authority + - validator changing test + - more docs + - update sync tests + - remove env_logger + - another env_logger + - cameltoe + - hold EngineClient instead of Client + - return error on misbehaviour + - nicer return + - sprinkle docs + - Reenable mainnet update server. ([#4137](https://github.com/paritytech/parity/pull/4137)) + - basic tests for subscribeToEvents ([#4115](https://github.com/paritytech/parity/pull/4115)) + - subscribeToEvent fixtures ✅ + - subscribeToEvent tests ✅ + - temporarily skip failing test ([#4138](https://github.com/paritytech/parity/pull/4138)) + - Improvements and optimisations to estimate_gas ([#4142](https://github.com/paritytech/parity/pull/4142)) + - Return 0 instead of error with out of gas on estimate_gas + - Fix stuff up. + - Another estimate gas fix. + - Alter balance to maximum possible rather than GP=0. + - Only increase to amount strictly necessary. + - Improvements and optimisations to estimate_gas. + - Introduce proper error type + - Avoid building costly traces + - Fix tests. + - Actually fix testsActually fix tests + - Use estimateGas error (as per updated implementation) ([#4131](https://github.com/paritytech/parity/pull/4131)) + - EXCEPTION_ERROR as per #4142 + - Better error log reporting & handling ([#4128](https://github.com/paritytech/parity/pull/4128)) + - Don't pop-up notifications after network switch ([#4076](https://github.com/paritytech/parity/pull/4076)) + - Better notifications + - Don't pollute with notifs if switched networks + - Better connection close/open events / No more notifs on change network + - PR Grumbles + - Add close and open events to HTTP // Add tests + - Fix tests + - WIP Signer Fix + - Fix Signer // Better reconnection handling + - PR Grumbles + - PR Grumbles + - Fixes wrong fetching of balances + Notifications + - Secure API WIP + - Updated Secure API Connection + Status + - Linting + - Updated Secure API Logic + - Proper handling of token updates // Fixing poping notifications + - PR Grumbles + - Fixing tests + - Trim spaces from InputAddress ([#4126](https://github.com/paritytech/parity/pull/4126)) + - Trim spaces for addresses + - onSubmit has only value, not event + - onSubmit (again) + - Length check on trimmed value + - Remove bindActionCreators({}, dispatch) (empty) ([#4135](https://github.com/paritytech/parity/pull/4135)) +- Backporting to beta [#4118](https://github.com/paritytech/parity/pull/4118) + - Ignore get_price_info test by default. ([#4112](https://github.com/paritytech/parity/pull/4112)) + - Auto-detect hex encoded bytes in sha3 ([#4108](https://github.com/paritytech/parity/pull/4108)) + - Using types/isHex + - Removing unused imports + - Use binary chop to estimate gas accurately ([#4100](https://github.com/paritytech/parity/pull/4100)) + - Initial sketch. + - Building. + - Fix a few things. + - Fix issue, add tracing. + - Address grumbles + - Raise upper limit if needed + - Fix test. + - Fixing decoding API with signatures in names ([#4125](https://github.com/paritytech/parity/pull/4125)) + - Fix call/estimate_gas ([#4121](https://github.com/paritytech/parity/pull/4121)) + - Return 0 instead of error with out of gas on estimate_gas + - Fix stuff up. +- Current release: 1.3 -> 1.4 [#4183](https://github.com/paritytech/parity/pull/4183) +- Fix rebroadcast panic [#4084](https://github.com/paritytech/parity/pull/4084) +- Use shallow-only rendering in all tests [#4087](https://github.com/paritytech/parity/pull/4087) +- Sending transactions in chunks [#4089](https://github.com/paritytech/parity/pull/4089) +- Move to new auto-update server. [#4091](https://github.com/paritytech/parity/pull/4091) +- Fixing compilation without dapps. [#4088](https://github.com/paritytech/parity/pull/4088) +- Fix balances update [#4077](https://github.com/paritytech/parity/pull/4077) +- Key derivation in Worker [#4071](https://github.com/paritytech/parity/pull/4071) +- Display contract block creation [#4069](https://github.com/paritytech/parity/pull/4069) +- Improving logs for transactions sync and disable re-broadcasting while syncing [#4065](https://github.com/paritytech/parity/pull/4065) +- Passwords are valid by default [#4075](https://github.com/paritytech/parity/pull/4075) +- Show Origin label to events table [#4073](https://github.com/paritytech/parity/pull/4073) +- Fix tags not working [#4070](https://github.com/paritytech/parity/pull/4070) +- Zero-alloc trie lookups [#3998](https://github.com/paritytech/parity/pull/3998) +- Opening local dapp [#4041](https://github.com/paritytech/parity/pull/4041) +- Bringing back `js-sha3` to fix in-browser signing [#4063](https://github.com/paritytech/parity/pull/4063) +- Fix wrong transaction input for contract deployments [#4052](https://github.com/paritytech/parity/pull/4052) +- Re-broadcast transactions to few random peers on each new block. [#4054](https://github.com/paritytech/parity/pull/4054) +- Removing old transactions from the queue [#4046](https://github.com/paritytech/parity/pull/4046) +- Add block rewards to more Engines [#4055](https://github.com/paritytech/parity/pull/4055) +- Return old trie values on insert and remove [#4053](https://github.com/paritytech/parity/pull/4053) +- Let users open urls from dapps view [#4042](https://github.com/paritytech/parity/pull/4042) +- Util/validation update [#4051](https://github.com/paritytech/parity/pull/4051) +- Convert ShapeShift modal to store [#4035](https://github.com/paritytech/parity/pull/4035) +- Using local path on Windows [#4017](https://github.com/paritytech/parity/pull/4017) +- Fixing minGasLimit > ceil limit mining issue [#4018](https://github.com/paritytech/parity/pull/4018) +- Naive light client synchronization [#3892](https://github.com/paritytech/parity/pull/3892) +- Starting on homestead shows reload snackbar [#4043](https://github.com/paritytech/parity/pull/4043) +- Show contract parameters in MethodDecoding [#4024](https://github.com/paritytech/parity/pull/4024) +- UI component updates [#4010](https://github.com/paritytech/parity/pull/4010) +- Account view updates [#4008](https://github.com/paritytech/parity/pull/4008) +- Better error messages for PoA chains [#4034](https://github.com/paritytech/parity/pull/4034) +- Make some spec fields optional [#4019](https://github.com/paritytech/parity/pull/4019) +- Basic account type [#4021](https://github.com/paritytech/parity/pull/4021) +- Fix wallet in main net [#4038](https://github.com/paritytech/parity/pull/4038) +- Removing orphaned Cargo.toml [#4032](https://github.com/paritytech/parity/pull/4032) +- Address selector: support reverse lookup [#4033](https://github.com/paritytech/parity/pull/4033) +- Only fetch App when necessary [#4023](https://github.com/paritytech/parity/pull/4023) +- Connection UI cleanups & tests for prior PR [#4020](https://github.com/paritytech/parity/pull/4020) +- Unsubscribe error on ShapeShift modal close [#4005](https://github.com/paritytech/parity/pull/4005) +- Add ownership checks the Registry dApp [#4001](https://github.com/paritytech/parity/pull/4001) +- Refresh balances of contacts & contracts when syncing [#4022](https://github.com/paritytech/parity/pull/4022) +- Show message on new chain [#4016](https://github.com/paritytech/parity/pull/4016) +- Use TypedInputs in Contracts view [#4015](https://github.com/paritytech/parity/pull/4015) +- Fix focus on Modal [#4014](https://github.com/paritytech/parity/pull/4014) +- Fix newError noops when not bound to dispacher [#4013](https://github.com/paritytech/parity/pull/4013) +- Parse testnet chain as ropsten [#4004](https://github.com/paritytech/parity/pull/4004) +- Work on Portal Style [#4003](https://github.com/paritytech/parity/pull/4003) +- Make Wallet first-class citizens [#3990](https://github.com/paritytech/parity/pull/3990) +- Don't slice non-existent tags [#4000](https://github.com/paritytech/parity/pull/4000) +- Update dev dependencies and make Webpack less verbose [#3997](https://github.com/paritytech/parity/pull/3997) +- Correct log index in transaction receipt [#3995](https://github.com/paritytech/parity/pull/3995) +- Add Email and Registry lookups to Address Selector [#3992](https://github.com/paritytech/parity/pull/3992) +- Remove node journal: dead code [#3994](https://github.com/paritytech/parity/pull/3994) +- Cleanup AddContract with store [#3981](https://github.com/paritytech/parity/pull/3981) +- Store for EditPassword Modal [#3979](https://github.com/paritytech/parity/pull/3979) +- Additional fetch tests [#3983](https://github.com/paritytech/parity/pull/3983) +- Owning views of blockchain data [#3982](https://github.com/paritytech/parity/pull/3982) +- Make test network generic over peer type [#3974](https://github.com/paritytech/parity/pull/3974) +- Fetch tests (first batch) [#3977](https://github.com/paritytech/parity/pull/3977) +- Fetch certifiers only when needed [#3978](https://github.com/paritytech/parity/pull/3978) +- Visible accounts for dapps (default whitelist) [#3898](https://github.com/paritytech/parity/pull/3898) +- Remove some old (unused/duplicate) files [#3975](https://github.com/paritytech/parity/pull/3975) +- Port `try` macro to new `?` operator. [#3962](https://github.com/paritytech/parity/pull/3962) +- Small UI fixes [#3966](https://github.com/paritytech/parity/pull/3966) +- Fix wrong use of Icons [#3973](https://github.com/paritytech/parity/pull/3973) +- Updating dependencies [#3968](https://github.com/paritytech/parity/pull/3968) +- Web Based Dapps [#3956](https://github.com/paritytech/parity/pull/3956) +- Contract query: render false as false [#3971](https://github.com/paritytech/parity/pull/3971) +- Email verification: add Terms of Service [#3970](https://github.com/paritytech/parity/pull/3970) +- Fix method decoding [#3967](https://github.com/paritytech/parity/pull/3967) +- Store for EditMeta modal [#3959](https://github.com/paritytech/parity/pull/3959) +- Registry dapp: cleanup, support reverse entries [#3933](https://github.com/paritytech/parity/pull/3933) +- New Address Selector Component [#3829](https://github.com/paritytech/parity/pull/3829) +- Limiting accounts returned by parity_accountInfo [#3931](https://github.com/paritytech/parity/pull/3931) +- Unknown block error for RPC [#3965](https://github.com/paritytech/parity/pull/3965) +- Remove unused fields in informant [#3963](https://github.com/paritytech/parity/pull/3963) +- Allow contract constructors in chain spec [#3932](https://github.com/paritytech/parity/pull/3932) +- Sync reorg up to history size [#3874](https://github.com/paritytech/parity/pull/3874) +- Rising the limit for fetch [#3964](https://github.com/paritytech/parity/pull/3964) +- Bring integer arithmetic up to crates.io [#3943](https://github.com/paritytech/parity/pull/3943) +- Eslint rule for block curlies [#3955](https://github.com/paritytech/parity/pull/3955) +- Gas exception warnings on deployment [#3938](https://github.com/paritytech/parity/pull/3938) +- Move verification store into modal [#3951](https://github.com/paritytech/parity/pull/3951) +- Allow setting of minBlock on sending [#3921](https://github.com/paritytech/parity/pull/3921) +- Allow empty address [#3961](https://github.com/paritytech/parity/pull/3961) +- Fix default import [#3960](https://github.com/paritytech/parity/pull/3960) +- Display 0x00..00 as null [#3950](https://github.com/paritytech/parity/pull/3950) +- Global Fetch Service [#3915](https://github.com/paritytech/parity/pull/3915) +- Update babel-loader for WebPack 2.2-rc [#3953](https://github.com/paritytech/parity/pull/3953) +- Fix Webpack build [#3946](https://github.com/paritytech/parity/pull/3946) +- Fix manual input token [#3945](https://github.com/paritytech/parity/pull/3945) +- Update Webpack [#3952](https://github.com/paritytech/parity/pull/3952) +- Add missing Ethcore -> Parity headers [#3948](https://github.com/paritytech/parity/pull/3948) +- Code example: do start before register_protocol [#3947](https://github.com/paritytech/parity/pull/3947) +- Set CHAIN_ID for Classic [#3934](https://github.com/paritytech/parity/pull/3934) +- Fixed compile error. [#3940](https://github.com/paritytech/parity/pull/3940) +- Fix dapps not loading [#3935](https://github.com/paritytech/parity/pull/3935) +- Fix Secure API hangs [#3927](https://github.com/paritytech/parity/pull/3927) +- Parity_chainStatus RPC for block gap info [#3899](https://github.com/paritytech/parity/pull/3899) +- Custom attribute for binary serialization [#3922](https://github.com/paritytech/parity/pull/3922) +- Split intermediate stage into two. [#3926](https://github.com/paritytech/parity/pull/3926) +- Move release-registering to intermediate stage. [#3920](https://github.com/paritytech/parity/pull/3920) +- Blocktime format rounding [#3894](https://github.com/paritytech/parity/pull/3894) +- Ignore dapps_policy.json [#3919](https://github.com/paritytech/parity/pull/3919) +- Fixing Contract Development [#3912](https://github.com/paritytech/parity/pull/3912) +- Use rhash for non-native CI platforms and submit build. [#3911](https://github.com/paritytech/parity/pull/3911) +- Remove -Zorbit=off from rustflags on windows [#3907](https://github.com/paritytech/parity/pull/3907) +- Fixed upgrading keys on the first run [#3904](https://github.com/paritytech/parity/pull/3904) +- Fix deadlock in queue drop [#3903](https://github.com/paritytech/parity/pull/3903) +- Require only simpler methods on Provider [#3897](https://github.com/paritytech/parity/pull/3897) +- Fix grammar ("you try" -> "you tried" + article) [#3902](https://github.com/paritytech/parity/pull/3902) +- Remove light server capability temporarily [#3872](https://github.com/paritytech/parity/pull/3872) +- Allow retry for future blocks [#3896](https://github.com/paritytech/parity/pull/3896) +- Consistent engine and seal names [#3895](https://github.com/paritytech/parity/pull/3895) +- Update email certification ABI [#3893](https://github.com/paritytech/parity/pull/3893) +- Remove existence & length checks on passwords & phrases [#3854](https://github.com/paritytech/parity/pull/3854) +- Refresh certifications automatically [#3878](https://github.com/paritytech/parity/pull/3878) +- Fix Wallet Settings Modal [#3856](https://github.com/paritytech/parity/pull/3856) +- Fix difficulty adjustment. [#3884](https://github.com/paritytech/parity/pull/3884) +- Final fixups for updater [#3883](https://github.com/paritytech/parity/pull/3883) +- Attempt to fix windows CI. [#3882](https://github.com/paritytech/parity/pull/3882) +- Fixing racy test [#3881](https://github.com/paritytech/parity/pull/3881) +- Fix updater permissions [#3880](https://github.com/paritytech/parity/pull/3880) +- Delayed transactions [#3865](https://github.com/paritytech/parity/pull/3865) +- Don't log auth token [#3853](https://github.com/paritytech/parity/pull/3853) +- Loading default config from default path [#3875](https://github.com/paritytech/parity/pull/3875) +- New paths [#3877](https://github.com/paritytech/parity/pull/3877) +- Update tests, gitlabci [#3876](https://github.com/paritytech/parity/pull/3876) +- Base directory option [#3868](https://github.com/paritytech/parity/pull/3868) +- Auto-updating [#3505](https://github.com/paritytech/parity/pull/3505) +- Fix naming collision [#3873](https://github.com/paritytech/parity/pull/3873) +- Get rid of unecessary redirection while fetching content [#3858](https://github.com/paritytech/parity/pull/3858) +- Fix verification stores [#3864](https://github.com/paritytech/parity/pull/3864) +- Store subscriptionId, align with main subscription model [#3863](https://github.com/paritytech/parity/pull/3863) +- Additional RPCs for dapps accounts management [#3792](https://github.com/paritytech/parity/pull/3792) +- Add Ws Json rpc client and command line utils (take 2) [#3830](https://github.com/paritytech/parity/pull/3830) +- Fix typo in method call (broken contract interface) [#3862](https://github.com/paritytech/parity/pull/3862) +- Fix flaky test [#3860](https://github.com/paritytech/parity/pull/3860) +- Converting traces API to AutoArgs [#3844](https://github.com/paritytech/parity/pull/3844) +- Get certifications from BadgeReg, show them in accounts overview [#3768](https://github.com/paritytech/parity/pull/3768) +- New directory structure [#3828](https://github.com/paritytech/parity/pull/3828) +- First run: skip account creation if they already have accounts [#3827](https://github.com/paritytech/parity/pull/3827) +- Tendermint seal [#3857](https://github.com/paritytech/parity/pull/3857) +- Tendermint Engine [#3759](https://github.com/paritytech/parity/pull/3759) +- Expand lint to catch css issues [#3852](https://github.com/paritytech/parity/pull/3852) +- Inject exports both partiy & web3 [#3851](https://github.com/paritytech/parity/pull/3851) +- Let Webpack talk again [#3848](https://github.com/paritytech/parity/pull/3848) +- AuthorityRound seal and simplify Generic seal Spec [#3843](https://github.com/paritytech/parity/pull/3843) +- Signing transactions with rotating token [#3691](https://github.com/paritytech/parity/pull/3691) +- Bump dev chain [#3835](https://github.com/paritytech/parity/pull/3835) +- Spelling [#3839](https://github.com/paritytech/parity/pull/3839) +- Email verification [#3766](https://github.com/paritytech/parity/pull/3766) +- Network configuration for Ethereum Classic [#3812](https://github.com/paritytech/parity/pull/3812) +- Using jsonrpc-macros [#3831](https://github.com/paritytech/parity/pull/3831) +- Fixed bool dropdown in contract execution [#3823](https://github.com/paritytech/parity/pull/3823) +- Avoid broadcasting transactions to peers that send them [#3796](https://github.com/paritytech/parity/pull/3796) +- Eth_sign RPC now hashes given data instead of getting the hash [#3800](https://github.com/paritytech/parity/pull/3800) +- Add store for MethodDecoding [#3821](https://github.com/paritytech/parity/pull/3821) +- Add store for AddAddress [#3819](https://github.com/paritytech/parity/pull/3819) +- Fix React-Router in i18n locale change [#3815](https://github.com/paritytech/parity/pull/3815) +- Cache fetched Dapps [#3804](https://github.com/paritytech/parity/pull/3804) +- Authors & homepage => Parity [#3818](https://github.com/paritytech/parity/pull/3818) +- Rename Ethcore -> Parity Technologies [#3817](https://github.com/paritytech/parity/pull/3817) +- Allow editing of gasPrice & gas in Signer [#3777](https://github.com/paritytech/parity/pull/3777) +- I18n string dictionaries [#3532](https://github.com/paritytech/parity/pull/3532) +- Fix padding in App [#3813](https://github.com/paritytech/parity/pull/3813) +- Light server improvements and protocol adjustments [#3801](https://github.com/paritytech/parity/pull/3801) +- Tolerate errors in user_defaults [#3810](https://github.com/paritytech/parity/pull/3810) +- Block: enforce gas limit falls within engine bounds [#3809](https://github.com/paritytech/parity/pull/3809) +- Target Babel to latest Chrome Versions in dev [#3806](https://github.com/paritytech/parity/pull/3806) +- Lowercase npm packages [#3807](https://github.com/paritytech/parity/pull/3807) +- Extended publishing of libraries to npm [#3786](https://github.com/paritytech/parity/pull/3786) +- Several Fixes to the UI [#3799](https://github.com/paritytech/parity/pull/3799) +- Remove "s [#3805](https://github.com/paritytech/parity/pull/3805) +- Extract CSS to file in production builds [#3783](https://github.com/paritytech/parity/pull/3783) +- Notify user on transaction received [#3782](https://github.com/paritytech/parity/pull/3782) +- Removing all old entries from transaction queue [#3772](https://github.com/paritytech/parity/pull/3772) +- Status page updates [#3774](https://github.com/paritytech/parity/pull/3774) +- Allow modifications of gas when confirming in signer [#3798](https://github.com/paritytech/parity/pull/3798) +- Network connectivity fixes [#3794](https://github.com/paritytech/parity/pull/3794) +- Make *ID names consistent with std Rust (Id) [#3781](https://github.com/paritytech/parity/pull/3781) +- Update CI builds [#3780](https://github.com/paritytech/parity/pull/3780) +- Update AuthorityRound tests to new spec [#3790](https://github.com/paritytech/parity/pull/3790) +- Fixes to the Wallet UI [#3787](https://github.com/paritytech/parity/pull/3787) +- Add support for wallets without getOwner() interface [#3779](https://github.com/paritytech/parity/pull/3779) +- Update Material-UI [#3785](https://github.com/paritytech/parity/pull/3785) +- Fixes error in Transfer modal [#3788](https://github.com/paritytech/parity/pull/3788) +- LES Part 3: Event handlers and handling responses [#3755](https://github.com/paritytech/parity/pull/3755) +- Basic UI rendering tests [#3743](https://github.com/paritytech/parity/pull/3743) +- Network: process packets only after connection handler finishes [#3776](https://github.com/paritytech/parity/pull/3776) +- AuthorityRound network simulation test [#3778](https://github.com/paritytech/parity/pull/3778) +- GasPrice selection for contract execution [#3770](https://github.com/paritytech/parity/pull/3770) +- Reject existing transactions [#3762](https://github.com/paritytech/parity/pull/3762) +- Allow autoRemove from api.subscribe based on callback return values [#3752](https://github.com/paritytech/parity/pull/3752) +- Replace misplaced & with && in gitlab-ci.yml [#3753](https://github.com/paritytech/parity/pull/3753) +- Lower gas usage for creating a Multisig Wallet [#3773](https://github.com/paritytech/parity/pull/3773) +- Added IO service explicit stop [#3761](https://github.com/paritytech/parity/pull/3761) +- Be lenient around invalid owners map [#3764](https://github.com/paritytech/parity/pull/3764) +- GasEditor component [#3750](https://github.com/paritytech/parity/pull/3750) +- Cleanups [#3742](https://github.com/paritytech/parity/pull/3742) +- Update babel, fix CI build due to breaking changes [#3754](https://github.com/paritytech/parity/pull/3754) +- Small fixes to contract [#3751](https://github.com/paritytech/parity/pull/3751) +- Make engine hold AccountProvider [#3725](https://github.com/paritytech/parity/pull/3725) +- Properly delete addresses/contracts in addressbook [#3739](https://github.com/paritytech/parity/pull/3739) +- Display Wallet Owners Icons in Accounts list [#3741](https://github.com/paritytech/parity/pull/3741) +- Edit Multisig Wallet settings [#3740](https://github.com/paritytech/parity/pull/3740) +- Replace build directory completely [#3748](https://github.com/paritytech/parity/pull/3748) +- Add existing release files before merge [#3747](https://github.com/paritytech/parity/pull/3747) +- Release script back to using fetch/merge [#3746](https://github.com/paritytech/parity/pull/3746) +- Update with -X only for merge [#3745](https://github.com/paritytech/parity/pull/3745) +- Give accounts precedence over address_book entries [#3732](https://github.com/paritytech/parity/pull/3732) +- Enable Panic=abort [#3423](https://github.com/paritytech/parity/pull/3423) +- Cleanups on js-precompiled [#3738](https://github.com/paritytech/parity/pull/3738) +- Add parity_removeAddress RPC [#3735](https://github.com/paritytech/parity/pull/3735) +- Fix up the transaction JSON serialisation for RPC. [#3633](https://github.com/paritytech/parity/pull/3633) +- Queue: CLI for auto-scaling and num verifiers [#3709](https://github.com/paritytech/parity/pull/3709) +- Add functionalities to multi-sig wallet [#3729](https://github.com/paritytech/parity/pull/3729) +- PropTypes as function call [#3731](https://github.com/paritytech/parity/pull/3731) +- Unify proptypes in util/proptypes.js [#3728](https://github.com/paritytech/parity/pull/3728) +- Bump jsonrpc-ipc-server to fix windows build [#3730](https://github.com/paritytech/parity/pull/3730) +- LES Part 2 [#3527](https://github.com/paritytech/parity/pull/3527) +- First draft of the MultiSig Wallet [#3700](https://github.com/paritytech/parity/pull/3700) +- Engine block ordering [#3719](https://github.com/paritytech/parity/pull/3719) +- Use fdlimit utility crate from crates.io [#3716](https://github.com/paritytech/parity/pull/3716) +- Move decoding for contract deployment logic earlier [#3714](https://github.com/paritytech/parity/pull/3714) +- Possible fix for queue drop deadlock [#3702](https://github.com/paritytech/parity/pull/3702) +- Encode networkid as a u64. [#3713](https://github.com/paritytech/parity/pull/3713) +- Use valid RLP in generic genesis seal spec [#3717](https://github.com/paritytech/parity/pull/3717) +- Update JS dependencies [#3710](https://github.com/paritytech/parity/pull/3710) +- Use Webpack Aliases [#3711](https://github.com/paritytech/parity/pull/3711) +- Dapps-specific accounts [#3627](https://github.com/paritytech/parity/pull/3627) +- Signer method parameter decoding & destination info [#3671](https://github.com/paritytech/parity/pull/3671) +- Remove invalid slice test [#3712](https://github.com/paritytech/parity/pull/3712) +- React library update [#3704](https://github.com/paritytech/parity/pull/3704) +- New Loading Component for the UI [#3707](https://github.com/paritytech/parity/pull/3707) +- Refactoring Transfer Modal [#3705](https://github.com/paritytech/parity/pull/3705) +- Fix extra scrollbars in dapps [#3706](https://github.com/paritytech/parity/pull/3706) +- Indent state tests [#3431](https://github.com/paritytech/parity/pull/3431) +- Filter null transactions for display (not available on node) [#3698](https://github.com/paritytech/parity/pull/3698) +- Move recovery phrase print button [#3697](https://github.com/paritytech/parity/pull/3697) +- Fix padding bottom needed after fixed status [#3701](https://github.com/paritytech/parity/pull/3701) +- Don't share the snapshot while downloading old blocks [#3695](https://github.com/paritytech/parity/pull/3695) +- Button to print recovery phrase [#3694](https://github.com/paritytech/parity/pull/3694) +- Fix status bar to bottom of the screen [#3692](https://github.com/paritytech/parity/pull/3692) +- Splitting serialization of signTransaction and sendTransaction confirmation requests [#3642](https://github.com/paritytech/parity/pull/3642) +- Implement basic badges/certifications/flair [#3665](https://github.com/paritytech/parity/pull/3665) +- Simplify Container title rendering [#3680](https://github.com/paritytech/parity/pull/3680) +- Update loading splash to fit in with l&f [#3685](https://github.com/paritytech/parity/pull/3685) +- Safari UI fixes [#3678](https://github.com/paritytech/parity/pull/3678) +- Remove strict mode for DappReg (work-around for package upgrade) [#3681](https://github.com/paritytech/parity/pull/3681) +- Bumping clippy [#3654](https://github.com/paritytech/parity/pull/3654) +- Return of the Fat DB [#3636](https://github.com/paritytech/parity/pull/3636) +- Invalidate blocks from future [#3652](https://github.com/paritytech/parity/pull/3652) +- Make Modal always scrollable [#3667](https://github.com/paritytech/parity/pull/3667) +- Display local/completed transactions [#3630](https://github.com/paritytech/parity/pull/3630) +- Added build-essential dep to dockerfiles [#3666](https://github.com/paritytech/parity/pull/3666) +- Strict config parsing (uknown keys are rejected) [#3663](https://github.com/paritytech/parity/pull/3663) +- Strict deserialization [#3662](https://github.com/paritytech/parity/pull/3662) +- Disable peer if no common block found [#3655](https://github.com/paritytech/parity/pull/3655) +- Show snackbar on password change [#3661](https://github.com/paritytech/parity/pull/3661) +- Bring back PV62 support [#3660](https://github.com/paritytech/parity/pull/3660) +- Unlock expecting quantity [#3659](https://github.com/paritytech/parity/pull/3659) +- Update Webpack => v2 [#3643](https://github.com/paritytech/parity/pull/3643) +- Update SMS verification [#3579](https://github.com/paritytech/parity/pull/3579) +- Simplify tx confirmations display [#3559](https://github.com/paritytech/parity/pull/3559) +- Fixes overflow in Signer tx data [#3657](https://github.com/paritytech/parity/pull/3657) +- Fixed tab bar not updating [#3653](https://github.com/paritytech/parity/pull/3653) +- Set default min tx price to $0.0025 [#3617](https://github.com/paritytech/parity/pull/3617) +- Use accountsInfo instead of eth_accounts for first check [#3618](https://github.com/paritytech/parity/pull/3618) +- Fix Copy to Clipboard Snackbar [#3619](https://github.com/paritytech/parity/pull/3619) +- Manually add \r to Windows phrases pre 1.4.5 [#3615](https://github.com/paritytech/parity/pull/3615) +- Signer layouts to flexbox [#3600](https://github.com/paritytech/parity/pull/3600) +- Fixing wrong tokens type in Redux store [#3621](https://github.com/paritytech/parity/pull/3621) +- Add dappreg link to apps list [#3568](https://github.com/paritytech/parity/pull/3568) +- Smarter balance fetching [#3605](https://github.com/paritytech/parity/pull/3605) +- Dapp iframe allow forms, allow target=_blank [#3597](https://github.com/paritytech/parity/pull/3597) +- Align copy button to input field [#3604](https://github.com/paritytech/parity/pull/3604) +- Appending logs by default [#3609](https://github.com/paritytech/parity/pull/3609) +- Update test, fix number. [#3612](https://github.com/paritytech/parity/pull/3612) +- Fixing phrases generated on windows [#3614](https://github.com/paritytech/parity/pull/3614) +- Check for network ID for live/test matching [#3602](https://github.com/paritytech/parity/pull/3602) +- Always insert traces for genesis. [#3603](https://github.com/paritytech/parity/pull/3603) +- Real deleting accounts [#3540](https://github.com/paritytech/parity/pull/3540) +- Trim whitespace from input recovery phrase [#3599](https://github.com/paritytech/parity/pull/3599) +- Fix local tx requests [#3589](https://github.com/paritytech/parity/pull/3589) +- Fix CPU usage when idle [#3592](https://github.com/paritytech/parity/pull/3592) +- Don't fetch balances on every new block if syncing [#3591](https://github.com/paritytech/parity/pull/3591) +- Work around WS in UI [#3587](https://github.com/paritytech/parity/pull/3587) +- CLI option to disable ancient block downloading [#3573](https://github.com/paritytech/parity/pull/3573) +- Move Signer balance queries to store for component-wide re-use [#3531](https://github.com/paritytech/parity/pull/3531) +- Fix wrong method name in `contract.js` [#3580](https://github.com/paritytech/parity/pull/3580) +- Smarter Tokens fetching [#3546](https://github.com/paritytech/parity/pull/3546) +- Fix panic on importing own invalid transaction [#3550](https://github.com/paritytech/parity/pull/3550) +- Use an adaptive number of threads in the verification queue [#2445](https://github.com/paritytech/parity/pull/2445) +- Faster UI - React Tweaks [#3555](https://github.com/paritytech/parity/pull/3555) +- Send value & contract execute gas limit warnings [#3512](https://github.com/paritytech/parity/pull/3512) +- Add TxQueue visibility specifier (not added between merges) [#3566](https://github.com/paritytech/parity/pull/3566) +- DappRegistry [#3405](https://github.com/paritytech/parity/pull/3405) +- Import account message [#3552](https://github.com/paritytech/parity/pull/3552) +- --testnet set to ropsten [#3551](https://github.com/paritytech/parity/pull/3551) +- Fix flaky test [#3547](https://github.com/paritytech/parity/pull/3547) +- Sms verification code style [#3564](https://github.com/paritytech/parity/pull/3564) +- [Registry] Clear input and working buttons [#3563](https://github.com/paritytech/parity/pull/3563) +- Fix peers not displaying [#3561](https://github.com/paritytech/parity/pull/3561) +- New registry contract address for ropsten [#3549](https://github.com/paritytech/parity/pull/3549) +- Use contract Registry fee, not a hard-coded value [#3554](https://github.com/paritytech/parity/pull/3554) +- Don't query chain in Signer, use Redux isTest [#3524](https://github.com/paritytech/parity/pull/3524) +- Moving fetching of hash-addressed dapps/content to separate crate. [#3543](https://github.com/paritytech/parity/pull/3543) +- Ropsten network [#3539](https://github.com/paritytech/parity/pull/3539) +- Add simple one-line installer to README.md [#3534](https://github.com/paritytech/parity/pull/3534) +- Propagations & local transactions tracking [#3491](https://github.com/paritytech/parity/pull/3491) +- Correct format of eth_signTransaction [#3503](https://github.com/paritytech/parity/pull/3503) +- ABI can be empty and auto-fill contract name [#3518](https://github.com/paritytech/parity/pull/3518) +- Fix versions for NPM [#3516](https://github.com/paritytech/parity/pull/3516) +- Better GHH event display & tracking [#3498](https://github.com/paritytech/parity/pull/3498) +- Dapp section & visibility changes [#3438](https://github.com/paritytech/parity/pull/3438) +- Fix parity.js badly built [#3526](https://github.com/paritytech/parity/pull/3526) +- Updated the european warp bootnode addresses [#3528](https://github.com/paritytech/parity/pull/3528) +- Limit sync reorg to 20 blocks [#3519](https://github.com/paritytech/parity/pull/3519) +- Revert "Limit sync reorganization to 20 blocks" [#3517](https://github.com/paritytech/parity/pull/3517) +- Check transaction signature when adding to the queue [#3508](https://github.com/paritytech/parity/pull/3508) +- Limit sync reorganization to 20 blocks [#3509](https://github.com/paritytech/parity/pull/3509) +- Keep track of block gasLimit [#3506](https://github.com/paritytech/parity/pull/3506) +- Smarter Status Polling [#3504](https://github.com/paritytech/parity/pull/3504) +- Handle solc combined output [#3496](https://github.com/paritytech/parity/pull/3496) +- Wallet names shouldn't use UUID [#3481](https://github.com/paritytech/parity/pull/3481) +- Make parity.js usable by Node and Browser [#3475](https://github.com/paritytech/parity/pull/3475) +- Sms verification modal [#3336](https://github.com/paritytech/parity/pull/3336) +- Sudo -c is not supported on Mac [#3488](https://github.com/paritytech/parity/pull/3488) +- Add trace_{call, rawTransaction, replayTransaction} [#3492](https://github.com/paritytech/parity/pull/3492) +- Check for possible panics in scrypt key derivation [#3490](https://github.com/paritytech/parity/pull/3490) +- Sync traffic optimization [#3477](https://github.com/paritytech/parity/pull/3477) +- Wallet files shouldn't give away the address [#3378](https://github.com/paritytech/parity/pull/3378) +- Fixing tests, fixing refreshing precompiled [#3483](https://github.com/paritytech/parity/pull/3483) +- Better Errors Snackbar in UI [#3478](https://github.com/paritytech/parity/pull/3478) +- Handle Signer Rejection [#3476](https://github.com/paritytech/parity/pull/3476) +- Enhanced MethodDecoding in Transactions list [#3454](https://github.com/paritytech/parity/pull/3454) +- Signer new-token generates a link and opens browser [#3379](https://github.com/paritytech/parity/pull/3379) +- Make tokenreg dapp fast again [#3474](https://github.com/paritytech/parity/pull/3474) +- Build fix [#3470](https://github.com/paritytech/parity/pull/3470) +- Display deployed Basic token addresses [#3447](https://github.com/paritytech/parity/pull/3447) +- Export accounts as JSON or CSV [#2866](https://github.com/paritytech/parity/pull/2866) +- Set HF2 block number [#3466](https://github.com/paritytech/parity/pull/3466) +- Better word list for secret phrase generation [#3461](https://github.com/paritytech/parity/pull/3461) +- Drop spec when no longer useful [#3460](https://github.com/paritytech/parity/pull/3460) +- Add fallback check in ABI validation [#3459](https://github.com/paritytech/parity/pull/3459) +- Save sort order in LocalStorage [#3457](https://github.com/paritytech/parity/pull/3457) +- Adds onPaste event to Inputs [#3456](https://github.com/paritytech/parity/pull/3456) +- Update signer to take care of text overflows [#3450](https://github.com/paritytech/parity/pull/3450) +- Authority round consensus engine [#3426](https://github.com/paritytech/parity/pull/3426) +- Fix transfer token decimal calculation [#3445](https://github.com/paritytech/parity/pull/3445) +- Restrict max code size for EIP-150 and after. [#3363](https://github.com/paritytech/parity/pull/3363) +- Contract queries should display IdentityIcons [#3453](https://github.com/paritytech/parity/pull/3453) +- Use Babel in vendor when needed [#3451](https://github.com/paritytech/parity/pull/3451) +- Use signature of functions instead of names [#3448](https://github.com/paritytech/parity/pull/3448) +- Handle contract constructor inputs [#3430](https://github.com/paritytech/parity/pull/3430) +- Use Contract owner for unregistering Token [#3446](https://github.com/paritytech/parity/pull/3446) +- Create directories only if feature is enabled [#3442](https://github.com/paritytech/parity/pull/3442) +- Import AddresBook from exported JSON [#3433](https://github.com/paritytech/parity/pull/3433) +- Scrollable accounts in autocomplete [#3427](https://github.com/paritytech/parity/pull/3427) +- Bump ws-rs [#3428](https://github.com/paritytech/parity/pull/3428) +- Swap TokenReg dapp from base to decimals [#3425](https://github.com/paritytech/parity/pull/3425) +- Change beta builds to stable on Travis [#3421](https://github.com/paritytech/parity/pull/3421) +- Refactor copy to clipboard functionality [#3420](https://github.com/paritytech/parity/pull/3420) +- Dev chain [#3385](https://github.com/paritytech/parity/pull/3385) +- Fetch known code from the database during restoration [#3377](https://github.com/paritytech/parity/pull/3377) +- Fixing benches [#3422](https://github.com/paritytech/parity/pull/3422) +- Fix chainspec storage field. [#3406](https://github.com/paritytech/parity/pull/3406) +- Abort snapshot restoration faster [#3356](https://github.com/paritytech/parity/pull/3356) +- Remove addresses, display non-refundable warning on registries [#3403](https://github.com/paritytech/parity/pull/3403) +- Don't auto-unsubscribe when subscriber callback throws [#3401](https://github.com/paritytech/parity/pull/3401) +- Fix dapp account selection [#3399](https://github.com/paritytech/parity/pull/3399) +- Fix travis build: remove unused import [#3381](https://github.com/paritytech/parity/pull/3381) +- Optimize memory footprint [#3376](https://github.com/paritytech/parity/pull/3376) +- Fixing parsing passwords from file [#3367](https://github.com/paritytech/parity/pull/3367) +- Remove some unwraps from parity/helpers [#3364](https://github.com/paritytech/parity/pull/3364) +- Load external, builtin & local apps in parallel [#3340](https://github.com/paritytech/parity/pull/3340) +- Solidity Compiler in UI [#3279](https://github.com/paritytech/parity/pull/3279) +- Determine real-time HTTP connected status [#3335](https://github.com/paritytech/parity/pull/3335) +- Clarify error message about disabled Signer [#3359](https://github.com/paritytech/parity/pull/3359) +- Cater for home.parity hostname in dappsUrl [#3341](https://github.com/paritytech/parity/pull/3341) +- Make sure Token is ECR20 [#3347](https://github.com/paritytech/parity/pull/3347) +- [TokenReg dApp] Fixed Unregister for Contract Owner only [#3346](https://github.com/paritytech/parity/pull/3346) +- LES Part 1 [#3322](https://github.com/paritytech/parity/pull/3322) +- Make transactions load [#3348](https://github.com/paritytech/parity/pull/3348) +- Manual bump package.json [#3345](https://github.com/paritytech/parity/pull/3345) +- Windows app and installer fixes [#3338](https://github.com/paritytech/parity/pull/3338) +- Fix JS API test [#3342](https://github.com/paritytech/parity/pull/3342) +- Git pre-push checks for UI [#3072](https://github.com/paritytech/parity/pull/3072) +- Disarm the HF and add more bootnodes [#3323](https://github.com/paritytech/parity/pull/3323) +- Default contract type on UI [#3310](https://github.com/paritytech/parity/pull/3310) +- In-browser signing support [#3231](https://github.com/paritytech/parity/pull/3231) +- Handle redirects from /api/content on manifest.json gracefully [#3315](https://github.com/paritytech/parity/pull/3315) +- Dapps interface RPC [#3311](https://github.com/paritytech/parity/pull/3311) +- Additional snapshot sync checks [#3318](https://github.com/paritytech/parity/pull/3318) +- Fix spurious signer tests failures [#3312](https://github.com/paritytech/parity/pull/3312) +- Fix signer token updates [#3302](https://github.com/paritytech/parity/pull/3302) +- Update account recovery phrase hint [#3316](https://github.com/paritytech/parity/pull/3316) +- New transaction tests [#3313](https://github.com/paritytech/parity/pull/3313) +- Remove 127.0.0.1 references [#3303](https://github.com/paritytech/parity/pull/3303) +- Fix for opening UI after installation on mac [#3300](https://github.com/paritytech/parity/pull/3300) +- Fixed uncle query [#3299](https://github.com/paritytech/parity/pull/3299) +- Updated blance display with max decimals [#3266](https://github.com/paritytech/parity/pull/3266) +- Refactoring Signer to auto_args + eth_signTransaction [#3261](https://github.com/paritytech/parity/pull/3261) +- Fix typo [#3298](https://github.com/paritytech/parity/pull/3298) +- Change to more common focused spelling [#3264](https://github.com/paritytech/parity/pull/3264) +- Manual bump of package.json (recovery) [#3295](https://github.com/paritytech/parity/pull/3295) +- Fix initial token generation [#3289](https://github.com/paritytech/parity/pull/3289) +- Fixed IO service shutdown [#3286](https://github.com/paritytech/parity/pull/3286) +- Autostart setting for windows tray app [#3269](https://github.com/paritytech/parity/pull/3269) +- Fixes for 1.4 [#3260](https://github.com/paritytech/parity/pull/3260) +- Build tray app for x64 [#3255](https://github.com/paritytech/parity/pull/3255) +- Add secure flag back [#3244](https://github.com/paritytech/parity/pull/3244) +- Verify chunk hashes in cli restore [#3241](https://github.com/paritytech/parity/pull/3241) +- Load network apps manifests as contentHash (no coding) [#3235](https://github.com/paritytech/parity/pull/3235) +- Fixed some typos [#3236](https://github.com/paritytech/parity/pull/3236) +- Rename cli and config options signer->ui [#3232](https://github.com/paritytech/parity/pull/3232) +- Add store for dapps state [#3211](https://github.com/paritytech/parity/pull/3211) +- Fix first-time tagging of contracts [#3222](https://github.com/paritytech/parity/pull/3222) +- Fix /parity-utils/{web3,parity}.js webpack errors [#3221](https://github.com/paritytech/parity/pull/3221) +- Improve 'invalid raw key' error msg [#3219](https://github.com/paritytech/parity/pull/3219) +- Cleaning up polluted namespaces [#3143](https://github.com/paritytech/parity/pull/3143) +- Set passive mode for first run only [#3214](https://github.com/paritytech/parity/pull/3214) +- Parity configuration settings, i.e. mode [#3212](https://github.com/paritytech/parity/pull/3212) +- Ethash unsafety cleanup [#3210](https://github.com/paritytech/parity/pull/3210) +- Mode improvements for UI [#3109](https://github.com/paritytech/parity/pull/3109) +- Delay bomb for Classic (ECIP-1010) [#3179](https://github.com/paritytech/parity/pull/3179) +- Use ethcore_dappsPort when constructing URLs [#3139](https://github.com/paritytech/parity/pull/3139) +- Add copy address button to Contract deploy [#3199](https://github.com/paritytech/parity/pull/3199) +- Expose Parity api as window.secureApi [#3207](https://github.com/paritytech/parity/pull/3207) +- Add error for sendRawTransaction and estimateGas [#3194](https://github.com/paritytech/parity/pull/3194) +- Exposing engine extra info in block RPC [#3169](https://github.com/paritytech/parity/pull/3169) +- V1.5 [#3195](https://github.com/paritytech/parity/pull/3195) +- Remove dapp logos (GHH points to dapp-assets) [#3192](https://github.com/paritytech/parity/pull/3192) +- Fixing possible race in ethcore_hashContent [#3191](https://github.com/paritytech/parity/pull/3191) +- Bump package.json version (1.5 is master) [#3193](https://github.com/paritytech/parity/pull/3193) diff --git a/docs/CHANGELOG-1.6.md b/docs/CHANGELOG-1.6.md new file mode 100644 index 0000000000000000000000000000000000000000..f31d6f4ee748a7df48713fa05718345d3465ccd4 --- /dev/null +++ b/docs/CHANGELOG-1.6.md @@ -0,0 +1,616 @@ +Note: Parity 1.6 reached End-of-Life on 2017-10-15 (EOL). + +## Parity [v1.6.10](https://github.com/paritytech/parity/releases/tag/v1.6.10) (2017-07-25) + +This is a hotfix release for the stable channel addressing the recent [multi-signature wallet vulnerability](https://blog.parity.io/security-alert-high-2/). Note, upgrading is not mandatory, and all future multi-sig wallets created by any version of Parity are secure. + +All Changes: + +- Backports for stable [#6116](https://github.com/paritytech/parity/pull/6116) + - Remove chunk to restore from pending set only upon successful import [#6112](https://github.com/paritytech/parity/pull/6112) + - Blacklist bad snapshot manifest hashes upon failure [#5874](https://github.com/paritytech/parity/pull/5874) + - Bump snap version and tweak importing detection logic [#6079](https://github.com/paritytech/parity/pull/6079) (modified to work) +- Fix docker build for stable [#6118](https://github.com/paritytech/parity/pull/6118) +- Update wallet library binaries [#6108](https://github.com/paritytech/parity/pull/6108) +- Backported wallet fix [#6104](https://github.com/paritytech/parity/pull/6104) + - Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102)) + - Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103)) +- Bump to v1.6.10 + +## Parity [v1.6.9](https://github.com/paritytech/parity/releases/tag/v1.6.9) (2017-07-16) + +This is a first stable release of 1.6 series. It contains a number of minor fixes and introduces the `--reseal-on-uncles` option for miners. + +Full list of changes: + +- Backports [#6061](https://github.com/paritytech/parity/pull/6061) + - Ethereum Classic Monetary Policy [#5741](https://github.com/paritytech/parity/pull/5741) + - Update rewards for uncle miners for ECIP1017 + - Fix an off-by-one error in ECIP1017 era calculation + - `ecip1017_era_rounds` missing from EthashParams when run in build bot + - strip out ecip1017_eras_block_reward function and add unit test + - JS precompiled set to stable +- Backports [#6060](https://github.com/paritytech/parity/pull/6060) + - --reseal-on-uncle [#5940](https://github.com/paritytech/parity/pull/5940) + - Optimized uncle check + - Additional uncle check + - Updated comment + - Bump to v1.6.9 + - CLI: Export error message and less verbose peer counter. [#5870](https://github.com/paritytech/parity/pull/5870) + - Removed numbed of active connections from informant + - Print error message when fatdb is required + - Remove peers from UI + +## Parity [v1.6.8](https://github.com/paritytech/parity/releases/tag/v1.6.8) (2017-06-08) + +This release addresses: + +- a rare condition where quickly creating a new account was generating an account not matching the recovery phrase. +- compressed RLP strings caused wrong/empty transaction receipts on Classic network. +- blacklisting the _empty phrase_ account from UI and RPC on non-development chains. See also [this blog post](https://blog.parity.io/restoring-blank-seed-phrase/). +- canceling transactions that didn't have a condition. +- the updated Expanse fork block and chain ID. + +Full changelog: + +- Backporting to beta [#5791](https://github.com/paritytech/parity/pull/5791) + - Bump to v1.6.8 + - Update expanse json with fork at block 600000 [#5351](https://github.com/paritytech/parity/pull/5351) + - Update expanse json with fork at block 600000 + - Update exp chainID to 2 + - Bumped mio [#5763](https://github.com/paritytech/parity/pull/5763) + - Fixed default UI port for mac installer [#5782](https://github.com/paritytech/parity/pull/5782) + - Blacklist empty phrase account. [#5730](https://github.com/paritytech/parity/pull/5730) + - Update Cid/multihash/ring/tinykeccak [#5785](https://github.com/paritytech/parity/pull/5785) + - Updating ring,multihash,tiny-keccak + - Updating CID in ipfs. + - Disable compression for RLP strings [#5786](https://github.com/paritytech/parity/pull/5786) +- Beta Backports [#5789](https://github.com/paritytech/parity/pull/5789) + - Fix local transactions without condition. [#5716](https://github.com/paritytech/parity/pull/5716) + - Block invalid account name creation [#5784](https://github.com/paritytech/parity/pull/5784) + - Additional non-empty phrase check (fromNew) + - Explicit canCreate check in create (not only on UI) + - BN instance check (fixes Geth imports) + - Fixup tests after better checks + - Recover from empty phrase in dev mode [#5698](https://github.com/paritytech/parity/pull/5698) + - Add dev chain to isTest + - Fix signer + - Fix no condition transactions + - Fix case: old parity + - Fix propTypes. + +## Parity [v1.6.7](https://github.com/paritytech/parity/releases/tag/v1.6.7) (2017-05-18) + +This release addresses: + +- potential usability issues with [import and recovery of existing accounts](https://blog.parity.io/restoring-blank-seed-phrase/). +- canceling scheduled transactions via RPC or UI. +- warp sync issues with the Kovan network. + +Full changelog: + +- Backporting to beta [#5657](https://github.com/paritytech/parity/pull/5657) + - Add CHANGELOG.md [#5513](https://github.com/paritytech/parity/pull/5513) + - Reorg into blocks before minimum history [#5558](https://github.com/paritytech/parity/pull/5558) + - Bump to v1.6.7 +- Cancel Transaction [#5656](https://github.com/paritytech/parity/pull/5656) + - option to disable persistent txqueue [#5544](https://github.com/paritytech/parity/pull/5544) + - Remove transaction RPC [#4949](https://github.com/paritytech/parity/pull/4949) + - Cancel tx JS [#4958](https://github.com/paritytech/parity/pull/4958) + - Updating documentation for RPCs [#5392](https://github.com/paritytech/parity/pull/5392) +- Backport Recover button [#5654](https://github.com/paritytech/parity/pull/5654) + - Backport [#5645](https://github.com/paritytech/parity/pull/5645) +- Add monotonic step to Kovan [#5630](https://github.com/paritytech/parity/pull/5630) + - Add monotonic transition to kovan [#5587](https://github.com/paritytech/parity/pull/5587) +- Fix ethsign [#5600](https://github.com/paritytech/parity/pull/5600) +- Registry backports [#5445](https://github.com/paritytech/parity/pull/5445) + - Fixes to the Registry dapp [#4984](https://github.com/paritytech/parity/pull/4984) + - Fix references to api outside of `parity.js` [#4981](https://github.com/paritytech/parity/pull/4981) + +## Parity [v1.6.6](https://github.com/paritytech/parity/releases/tag/v1.6.6) (2017-04-11) + +This release brings warp sync support for kovan network. + +- Beta Backports [#5434](https://github.com/paritytech/parity/pull/5434) + - Bump to v1.6.6 + - Strict validation transitions [#4988](https://github.com/paritytech/parity/pull/4988) + - Ability to make validation stricter + - Fix consensus + - Remove logger + - Fix eth_sign showing as wallet account [#5309](https://github.com/paritytech/parity/pull/5309) + - DefaultProps for account + - Pass signing account + - Update tests for Connect(...) + - Add new seed nodes [#5345](https://github.com/paritytech/parity/pull/5345) + - Kovan warp sync fixed +- Aura eip155 validation transition [#5363](https://github.com/paritytech/parity/pull/5363) + - Add eip155 validation + - Add transition block +- Default eip155 validation [#5350](https://github.com/paritytech/parity/pull/5350) +- Backport syntax libs update [#5316](https://github.com/paritytech/parity/pull/5316) + +## Parity [v1.6.5](https://github.com/paritytech/parity/releases/tag/v1.6.5) (2017-03-28) + +This release contains the following changes: + +- Warp sync snapshot format improvements. +- Fix for Firefox UI issues. +- Fix for restoring from a file snapshot. +- Fix for auto-updater error handling. +- Updated configuration for [Ropsten revival](https://github.com/ethereum/ropsten/blob/master/revival.md). Make sure to delete old Ropsten blockchain first with `parity db kill --chain ropsten`. After that you can sync normally with `parity --chain ropsten`. + +Full changes: + +- Beta Backports [#5299](https://github.com/paritytech/parity/pull/5299) + - Fix FireFox overflows [#5000](https://github.com/paritytech/parity/pull/5000) + - Max width for container + - Set min-width + - Switching ValidatorSet [#4961](https://github.com/paritytech/parity/pull/4961) + - Add multi validator set + - Nicer comment + - Validate in constructor + - Reporting + - Avoid clogging up tmp when updater dir has bad permissions. [#5024](https://github.com/paritytech/parity/pull/5024) + - Force earliest era set in snapshot restore [#5021](https://github.com/paritytech/parity/pull/5021) + - Bumb to v1.6.5 + - Fine grained snapshot chunking + - Ropsten revival +- Fix validator contract syncing [#4789](https://github.com/paritytech/parity/pull/4789) [#5011](https://github.com/paritytech/parity/pull/5011) + - Make validator set aware of various states + - Fix updater build + - Clean up contract call + - Failing sync test + - Adjust tests + - Nicer indent + - Revert bound divisor + +## Parity [v1.6.4](https://github.com/paritytech/parity/releases/tag/v1.6.4) (2017-03-22) + +A number of issues fixed in this release: + +- Ledger device connectivity issues for some users on Windows. +- Improved vault usability. +- Stratum mining no longer requires `--force-sealing`. +- `evm` binary has been renamed to `parity-evm` to avoid conflict with cpp-ethereum package. + +Full Changes: + +- Backporting to beta [#4995](https://github.com/paritytech/parity/pull/4995) + - Bump to v1.6.4 + - Ensure sealing work enabled if notifier registed + - Fix condition check + - Always send full chunks [#4960](https://github.com/paritytech/parity/pull/4960) + - Bump nanomsg [#4965](https://github.com/paritytech/parity/pull/4965) + - Renaming evm binary to avoid conflicts. [#4899](https://github.com/paritytech/parity/pull/4899) +- Beta UI backports [#4993](https://github.com/paritytech/parity/pull/4993) + - Update js-precompiled 20170314-121823 + - Attach hardware wallets already in addressbook [#4912](https://github.com/paritytech/parity/pull/4912) + - Attach hardware wallets already in addressbook + - Only set values changed + - Add Vaults logic to First Run [#4894](https://github.com/paritytech/parity/issues/4894) [#4914](https://github.com/paritytech/parity/pull/4914) + - Add ability to configure Secure API (for [#4885](https://github.com/paritytech/parity/issues/4885)) [#4922](https://github.com/paritytech/parity/pull/4922) + - Add z-index to small modals as well [#4923](https://github.com/paritytech/parity/pull/4923) + - Eth_sign where account === undefined [#4964](https://github.com/paritytech/parity/pull/4964) + - Update for case where account === undefined + - Update tests to not mask account === undefined + - Default account = {} where undefined (thanks [@tomusdrw](https://github.com/tomusdrw)) + - Fix Password Dialog forms style issue [#4968](https://github.com/paritytech/parity/pull/4968) + +## Parity [v1.6.3](https://github.com/paritytech/parity/releases/tag/v1.6.3) (2017-03-14) + +This release fixes issue compatibility with Safari on MacOS. + +- Safari fixes [#4902](https://github.com/paritytech/parity/pull/4902) + - Add intitial max-width to sections + - Move background z-index to -1 + +## Parity [v1.6.2](https://github.com/paritytech/parity/releases/tag/v1.6.2) (2017-03-13) + +A major release introducing a few new features: + +- Revamped UI. +- Account Vaults. +- Support for Ledger hardware wallet devices. +- Stratum protocol for PoW mining. +- A new MacOS installer. Parity for MacOS now includes a Menu Bar icon that allows controlling Parity service. +- Disk backed transaction store. Pending transactions are now saved to disk and won't get lost when Parity is restarted. +- Improved memory management. + +See the [blog post](https://blog.parity.io/announcing-parity-1-6/) for more details. + +Full Changes: + +- Fix auto-updater beta [#4868](https://github.com/paritytech/parity/pull/4868) +- Beta UI backports [#4855](https://github.com/paritytech/parity/pull/4855) + - Added React Hot Reload to dapps + TokenDeplpoy fix ([#4846](https://github.com/paritytech/parity/pull/4846)) + - Fix method decoding ([#4845](https://github.com/paritytech/parity/pull/4845)) + - Fix contract deployment method decoding in Signer + - Linting + - Fix TxViewer when no `to` (contract deployment) ([#4847](https://github.com/paritytech/parity/pull/4847)) + - Added React Hot Reload to dapps + TokenDeplpoy fix + - Fixes to the LocalTx dapp + - Don't send the nonce for mined transactions + - Don't encode empty to values for options + - Pull steps from actual available steps ([#4848](https://github.com/paritytech/parity/pull/4848)) + - Wait for the value to have changed in the input ([#4844](https://github.com/paritytech/parity/pull/4844)) + - Backport Regsirty changes from [#4589](https://github.com/paritytech/parity/pull/4589) + - Test fixes for [#4589](https://github.com/paritytech/parity/pull/4589) +- Beta Simple score [#4852](https://github.com/paritytech/parity/pull/4852) + - Simple score + - Ignore part of a test +- Backporting to beta [#4840](https://github.com/paritytech/parity/pull/4840) + - Fixes to the Registry dapp ([#4838](https://github.com/paritytech/parity/pull/4838)) + - Fix wrong ABI methods + - Fix comparison + - Bump to v1.6.1 +- Show token icons on list summary pages ([#4826](https://github.com/paritytech/parity/pull/4826)) [#4827](https://github.com/paritytech/parity/pull/4827) + - Adjust balance overlay margins (no jumps) + - Img only balances, small verifications + - Invalid tests removed + - Always wrap display (Thanks [@ngotchac](https://github.com/ngotchac)) + - Update tests to reflect reality +- Beta Engine backports [#4806](https://github.com/paritytech/parity/pull/4806) + - Calibrate before rejection + - Change flag name + - Add eip155 + - Make network_id default +- Beta UI backports [#4823](https://github.com/paritytech/parity/pull/4823) + - Better logic for contract deployments ([#4821](https://github.com/paritytech/parity/pull/4821)) +- Beta UI backports [#4818](https://github.com/paritytech/parity/pull/4818) + - Update the key ([#4817](https://github.com/paritytech/parity/pull/4817)) + - Adjust selection colours/display ([#4811](https://github.com/paritytech/parity/pull/4811)) + - Adjust selection colours to match with mui + - allow -> disable (simplify selections) + - Only use top-border + - Overlay selection line + - Slightly more muted unselected + - Restore address icon + - Fix default values for contract queries +- Beta UI backports [#4809](https://github.com/paritytech/parity/pull/4809) + - Update Wallet to new Wallet Code ([#4805](https://github.com/paritytech/parity/pull/4805)) + - Update Wallet Version + - Update Wallet Library + - Update Wallets Bytecodes + - Typo + - Separate Deploy in Contract API + - Use the new Wallet ABI // Update wallet code + - WIP .// Deploy from Wallet + - Update Wallet contract + - Contract Deployment for Wallet + - Working deployments for Single Owned Wallet contracts + - Linting + - Create a Wallet from a Wallet + - Linting + - Fix Signer transactions // Add Gas Used for transactions + - Deploy wallet contract fix + - Fix too high gas estimate for Wallet Contract Deploys + - Final piece ; deploying from Wallet owned by wallet + - Update Wallet Code + - Updated the Wallet Codes + - Fixing Wallet Deployments + - Add Support for older wallets + - Linting + - SMS Faucet ([#4774](https://github.com/paritytech/parity/pull/4774)) + - Faucet + - Remove flakey button-index testing + - Only display faucet when sms verified (mainnet) + - Simplify availability checks + - WIP + - Resuest from verified -> verified + - Update endpoint, display response text + - Error icon on errors + - Parse hash text response + - Use /api/:address endpoint + - Hash -> data + - Adjust sms-certified message + - Fix SectionList hovering issue ([#4749](https://github.com/paritytech/parity/pull/4749)) + - Fix SectionList Items hover when <3 items + - Even easier... + - Lint (new) +- Update ETC bootnodes [#4794](https://github.com/paritytech/parity/pull/4794) +- Update comments and reg ABI [#4787](https://github.com/paritytech/parity/pull/4787) +- Optimize signature for fallback function. [#4780](https://github.com/paritytech/parity/pull/4780) +- Rephrasing token generation screen. [#4777](https://github.com/paritytech/parity/pull/4777) +- Etherscan links based on netVersion identifier [#4772](https://github.com/paritytech/parity/pull/4772) +- Update README.md [#4762](https://github.com/paritytech/parity/pull/4762) +- Fix invalid props to verification code [#4766](https://github.com/paritytech/parity/pull/4766) +- Extend authority round consensus test [#4756](https://github.com/paritytech/parity/pull/4756) +- Revert last hyper "fix" [#4752](https://github.com/paritytech/parity/pull/4752) +- Vault Management UI (round 3) [#4652](https://github.com/paritytech/parity/pull/4652) +- Update SelectionList indicators [#4736](https://github.com/paritytech/parity/pull/4736) +- Update testnet detection [#4746](https://github.com/paritytech/parity/pull/4746) +- Fix Portal in Portal ESC issue [#4745](https://github.com/paritytech/parity/pull/4745) +- Update wiki [#4743](https://github.com/paritytech/parity/pull/4743) +- Account selector close operations [#4728](https://github.com/paritytech/parity/pull/4728) +- Fix Account Selection in Signer [#4744](https://github.com/paritytech/parity/pull/4744) +- Support both V1 & V2 DataChanged events in registry [#4734](https://github.com/paritytech/parity/pull/4734) +- Add info on forks. [#4733](https://github.com/paritytech/parity/pull/4733) +- Add registry addr [#4732](https://github.com/paritytech/parity/pull/4732) +- UI support for hardware wallets [#4539](https://github.com/paritytech/parity/pull/4539) +- S/delete/forget/ for wallets [#4729](https://github.com/paritytech/parity/pull/4729) +- New chains [#4720](https://github.com/paritytech/parity/pull/4720) +- Enable --warp by default [#4719](https://github.com/paritytech/parity/pull/4719) +- Update Uglify (fix to 2.8.2) to fix binary builds [#4723](https://github.com/paritytech/parity/pull/4723) +- Extract i18n strings in modals/* [#4706](https://github.com/paritytech/parity/pull/4706) +- Provide uncle size where available in RPC [#4713](https://github.com/paritytech/parity/pull/4713) +- EC math functions [#4696](https://github.com/paritytech/parity/pull/4696) +- Add registrar fields [#4716](https://github.com/paritytech/parity/pull/4716) +- Extract i18n strings in views/* [#4695](https://github.com/paritytech/parity/pull/4695) +- Removing network=disable from config files [#4715](https://github.com/paritytech/parity/pull/4715) +- Fast in-place migration for adding and removing column families [#4687](https://github.com/paritytech/parity/pull/4687) +- Display badges on summary view [#4689](https://github.com/paritytech/parity/pull/4689) +- Consistent file uploads [#4699](https://github.com/paritytech/parity/pull/4699) +- Rename https://mkr.market -> https://oasisdex.com [#4701](https://github.com/paritytech/parity/pull/4701) +- Stop copy & clickthrough from list summaries [#4700](https://github.com/paritytech/parity/pull/4700) +- Display ... for address summary overflows [#4691](https://github.com/paritytech/parity/pull/4691) +- Less agressive grayscale/opacity in SelectionList [#4688](https://github.com/paritytech/parity/pull/4688) +- Propagate trie errors upwards from State [#4655](https://github.com/paritytech/parity/pull/4655) +- Generic state backend [#4632](https://github.com/paritytech/parity/pull/4632) +- Enhance dialog layouts (round 1) [#4637](https://github.com/paritytech/parity/pull/4637) +- Vault Management UI (round 2) [#4631](https://github.com/paritytech/parity/pull/4631) +- Fix Portal broad event stopper [#4674](https://github.com/paritytech/parity/pull/4674) +- Custom dev chain presets [#4671](https://github.com/paritytech/parity/pull/4671) +- Max gas limit and min gas price [#4661](https://github.com/paritytech/parity/pull/4661) +- Align list displays with SectionList (UI consistency) [#4621](https://github.com/paritytech/parity/pull/4621) +- Add SelectionList component to DRY up [#4639](https://github.com/paritytech/parity/pull/4639) +- I18n NL linting updates [#4662](https://github.com/paritytech/parity/pull/4662) +- Misc. small UI fixes [#4657](https://github.com/paritytech/parity/pull/4657) +- More CLI settings for IPFS API [#4608](https://github.com/paritytech/parity/pull/4608) +- Fix Tendermint deadlock [#4654](https://github.com/paritytech/parity/pull/4654) +- Nl translations [#4649](https://github.com/paritytech/parity/pull/4649) +- Update transaction condition documentation [#4659](https://github.com/paritytech/parity/pull/4659) +- Bump hyper versions [#4645](https://github.com/paritytech/parity/pull/4645) +- Sane updater [#4658](https://github.com/paritytech/parity/pull/4658) +- Remainder of RPC APIs implemented for the light client [#4594](https://github.com/paritytech/parity/pull/4594) +- Preserve vault meta when changing pwd [#4650](https://github.com/paritytech/parity/pull/4650) +- Fix Geth account import [#4641](https://github.com/paritytech/parity/pull/4641) +- Tweak some checks. [#4633](https://github.com/paritytech/parity/pull/4633) +- Attempt to fix subscribeToEvents test [#4638](https://github.com/paritytech/parity/pull/4638) +- Fix selection value from RadioButtons [#4636](https://github.com/paritytech/parity/pull/4636) +- Convert all remaining Modals to use Portal (UI consistency) [#4625](https://github.com/paritytech/parity/pull/4625) +- Default account selection update [#4609](https://github.com/paritytech/parity/pull/4609) +- Display ETH balance in overlay account selector [#4588](https://github.com/paritytech/parity/pull/4588) +- Fixed minor grammar mistake in readme [#4627](https://github.com/paritytech/parity/pull/4627) +- Extract newly available i18n strings [#4623](https://github.com/paritytech/parity/pull/4623) +- Save pending local transactions in the database [#4566](https://github.com/paritytech/parity/pull/4566) +- Bump CID version to allow compilation on all platforms [#4614](https://github.com/paritytech/parity/pull/4614) +- Vault Management UI (first round) [#4446](https://github.com/paritytech/parity/pull/4446) +- Let Engine decide if it seals internally [#4613](https://github.com/paritytech/parity/pull/4613) +- Show only known accounts/wallets/addresses on Home [#4612](https://github.com/paritytech/parity/pull/4612) +- Proper default accounts RPCs [#4580](https://github.com/paritytech/parity/pull/4580) +- Hash-fetch errors in case upstream returns non-200 [#4599](https://github.com/paritytech/parity/pull/4599) +- Added pending transaction info to eth_getTransactionByHash [#4570](https://github.com/paritytech/parity/pull/4570) +- Secret store - initial version [#4567](https://github.com/paritytech/parity/pull/4567) +- Handle invalid ABI retrieved from address_book gracefully [#4606](https://github.com/paritytech/parity/pull/4606) +- Optimize key directory reloads [#4583](https://github.com/paritytech/parity/pull/4583) +- Revert Double Click on Accounts to close in Signer Bar [#4590](https://github.com/paritytech/parity/pull/4590) +- IPFS MVP [#4545](https://github.com/paritytech/parity/pull/4545) +- Networking fixes [#4563](https://github.com/paritytech/parity/pull/4563) +- Remove eth_compile* RPCs [#4577](https://github.com/paritytech/parity/pull/4577) +- Ledger wallet signing fixed [#4578](https://github.com/paritytech/parity/pull/4578) +- Remove vertx from Webpack config [#4576](https://github.com/paritytech/parity/pull/4576) +- Better display of tags [#4564](https://github.com/paritytech/parity/pull/4564) +- Added vaults support to `ethstore-cli` [#4532](https://github.com/paritytech/parity/pull/4532) +- Fixed font URLs [#4579](https://github.com/paritytech/parity/pull/4579) +- Explicitly set seconds to 0 from selector [#4559](https://github.com/paritytech/parity/pull/4559) +- Fixes evmbin compilation and adding to standard build. [#4561](https://github.com/paritytech/parity/pull/4561) +- Alias for personal_sendTransaction [#4554](https://github.com/paritytech/parity/pull/4554) +- Key derivation in ethstore & rpc [#4515](https://github.com/paritytech/parity/pull/4515) +- Skip OOG check for simple transfers [#4558](https://github.com/paritytech/parity/pull/4558) +- Light Client transaction queue, initial LightDispatcher [#4501](https://github.com/paritytech/parity/pull/4501) +- Fixes BadgeReg Middleware [#4556](https://github.com/paritytech/parity/pull/4556) +- Fix pasting of value in Input fields [#4555](https://github.com/paritytech/parity/pull/4555) +- Tooltips with react-intl [#4549](https://github.com/paritytech/parity/pull/4549) +- Close on double-click for Signer Account selection [#4540](https://github.com/paritytech/parity/pull/4540) +- Signer provenance [#4477](https://github.com/paritytech/parity/pull/4477) +- Fix console dapp [#4544](https://github.com/paritytech/parity/pull/4544) +- Extract i18n string into i18n/_defaults (base of translations) [#4514](https://github.com/paritytech/parity/pull/4514) +- Fix contract queries bug [#4534](https://github.com/paritytech/parity/pull/4534) +- Fixing namespace of couple methods in console. [#4538](https://github.com/paritytech/parity/pull/4538) +- Home landing page [#4178](https://github.com/paritytech/parity/pull/4178) +- Bump JSON RPC crates versions [#4530](https://github.com/paritytech/parity/pull/4530) +- Update rust version in README [#4531](https://github.com/paritytech/parity/pull/4531) +- Lower default pruning history and memory [#4528](https://github.com/paritytech/parity/pull/4528) +- Serde 0.9 [#4508](https://github.com/paritytech/parity/pull/4508) +- Fixes to Token Deploy dapp [#4513](https://github.com/paritytech/parity/pull/4513) +- Fixed receipt decoding [#4521](https://github.com/paritytech/parity/pull/4521) +- Several fixes to the Wallet in general [#4504](https://github.com/paritytech/parity/pull/4504) +- Use the current contract name for Solidity compilation [#4510](https://github.com/paritytech/parity/pull/4510) +- Preparation for Light client RPC [#4485](https://github.com/paritytech/parity/pull/4485) +- Fix Dutch translation [#4509](https://github.com/paritytech/parity/pull/4509) +- Fixed a warning and bumped libusb-sys [#4507](https://github.com/paritytech/parity/pull/4507) +- Fix TnC overflows on small screens [#4505](https://github.com/paritytech/parity/pull/4505) +- Fix no data sent in TxQueue dapp [#4502](https://github.com/paritytech/parity/pull/4502) +- Ledger wallet support [#4486](https://github.com/paritytech/parity/pull/4486) +- Add new Componennt for Token Images [#4498](https://github.com/paritytech/parity/pull/4498) +- Fix address and accounts links [#4491](https://github.com/paritytech/parity/pull/4491) +- Fix Token Reg Dapp issues in Firefox [#4489](https://github.com/paritytech/parity/pull/4489) +- Parity.js interfaces for vaults [#4497](https://github.com/paritytech/parity/pull/4497) +- Initial Dutch translations [#4484](https://github.com/paritytech/parity/pull/4484) +- Fix key.meta.vault for root dir keys && read vault.meta without vault key [#4482](https://github.com/paritytech/parity/pull/4482) +- Arbitrary labels for extended keys (u32, H256 built-in) [#4438](https://github.com/paritytech/parity/pull/4438) +- Fix ethstore build [#4492](https://github.com/paritytech/parity/pull/4492) +- Fixed compilation of ethstore-cli [#4493](https://github.com/paritytech/parity/pull/4493) +- Build embedded Parity JS properly and separatly [#4426](https://github.com/paritytech/parity/pull/4426) +- Static link for snappy [#4487](https://github.com/paritytech/parity/pull/4487) +- Work with string numbers in contract (Fixes #4472) [#4478](https://github.com/paritytech/parity/pull/4478) +- Metadata support for vaults [#4475](https://github.com/paritytech/parity/pull/4475) +- Sort gas price corpus when hitting genesis [#4470](https://github.com/paritytech/parity/pull/4470) +- Fixing CORS headers for parity.web3.site [#4461](https://github.com/paritytech/parity/pull/4461) +- Make signing compatible with geth. [#4468](https://github.com/paritytech/parity/pull/4468) +- Handle registry not found errors [#4465](https://github.com/paritytech/parity/pull/4465) +- Fix Portal scrolling getting stuck [#4455](https://github.com/paritytech/parity/pull/4455) +- Fix AccountCard stretch to 100% [#4450](https://github.com/paritytech/parity/pull/4450) +- Include total difficulty in CHTs and hide implementation details from consumers [#4428](https://github.com/paritytech/parity/pull/4428) +- Fix RLP encoding for types recursively calling `RlpStream::append` [#4362](https://github.com/paritytech/parity/pull/4362) +- Open popup without attempting inline [#4440](https://github.com/paritytech/parity/pull/4440) +- Fixing histogram again ([#4464](https://github.com/paritytech/parity/issues/4464)) port from beta [#4467](https://github.com/paritytech/parity/pull/4467) +- Vaults RPCs [#4366](https://github.com/paritytech/parity/pull/4366) +- Ethkey - extended keys [#4377](https://github.com/paritytech/parity/pull/4377) +- Use secure websocket from HTTPS clients [#4436](https://github.com/paritytech/parity/pull/4436) +- RPC middleware: Informant & Client.keep_alive [#4384](https://github.com/paritytech/parity/pull/4384) +- Fix eth_sign/parity_postSign [#4432](https://github.com/paritytech/parity/pull/4432) +- Web view with web3.site support [#4313](https://github.com/paritytech/parity/pull/4313) +- Extend Portal component with title, buttons & steps (as per Modal) [#4392](https://github.com/paritytech/parity/pull/4392) +- Extension installation overlay [#4423](https://github.com/paritytech/parity/pull/4423) +- Add block & timestamp conditions to Signer [#4411](https://github.com/paritytech/parity/pull/4411) +- Transaction timestamp condition [#4419](https://github.com/paritytech/parity/pull/4419) +- Poll for defaultAccount to update dapp & overlay subscriptions [#4417](https://github.com/paritytech/parity/pull/4417) +- Validate dapps accounts with address book [#4407](https://github.com/paritytech/parity/pull/4407) +- Dapps use defaultAccount instead of own selectors [#4386](https://github.com/paritytech/parity/pull/4386) +- Fix lock and rename tracing [#4403](https://github.com/paritytech/parity/pull/4403) +- Restarting fetch client every now and then [#4399](https://github.com/paritytech/parity/pull/4399) +- Perform a sync between Rust and JS when generating markdown instead of in spec tests [#4408](https://github.com/paritytech/parity/pull/4408) +- Registry dapp: make lookup use lower case [#4409](https://github.com/paritytech/parity/pull/4409) +- Available Dapp selection alignment with Permissions (Portal) [#4374](https://github.com/paritytech/parity/pull/4374) +- More permissive verification process [#4317](https://github.com/paritytech/parity/pull/4317) +- Fix ParityBar account selection overflows [#4405](https://github.com/paritytech/parity/pull/4405) +- Mac binaries signing [#4397](https://github.com/paritytech/parity/pull/4397) +- Revert "remove [ci skip]" [#4398](https://github.com/paritytech/parity/pull/4398) +- Registry, s/a the owner/the owner/ [#4391](https://github.com/paritytech/parity/pull/4391) +- Fixing invalid address in docs [#4388](https://github.com/paritytech/parity/pull/4388) +- Remove [ci skip] [#4381](https://github.com/paritytech/parity/pull/4381) +- Fixing estimate gas in case histogram is not available [#4387](https://github.com/paritytech/parity/pull/4387) +- Default Account selector in Signer overlay [#4375](https://github.com/paritytech/parity/pull/4375) +- Fixing web3 in console [#4382](https://github.com/paritytech/parity/pull/4382) +- Add parity_defaultAccount RPC (with subscription) [#4383](https://github.com/paritytech/parity/pull/4383) +- Full JSON-RPC docs + sync tests. [#4335](https://github.com/paritytech/parity/pull/4335) +- Expose util as Api.util [#4372](https://github.com/paritytech/parity/pull/4372) +- Dapp Account Selection & Defaults [#4355](https://github.com/paritytech/parity/pull/4355) +- Publish @parity/jsonrpc [#4365](https://github.com/paritytech/parity/pull/4365) +- Fix signing [#4363](https://github.com/paritytech/parity/pull/4363) +- Fixing embedded bar not closing in chrome extension [#4367](https://github.com/paritytech/parity/pull/4367) +- Update AccountCard for re-use [#4350](https://github.com/paritytech/parity/pull/4350) +- Add proper event listener to Portal [#4359](https://github.com/paritytech/parity/pull/4359) +- Optional from field in Transaction Requests [#4332](https://github.com/paritytech/parity/pull/4332) +- Rust 1.14 in README [ci-skip] [#4361](https://github.com/paritytech/parity/pull/4361) +- Fix JournalDB::earliest_era on empty database [#4316](https://github.com/paritytech/parity/pull/4316) +- Fixed race condition deadlock on fetching enode URL [#4354](https://github.com/paritytech/parity/pull/4354) +- Allow Portal to be used as top-level modal [#4338](https://github.com/paritytech/parity/pull/4338) +- Fix postsign [#4347](https://github.com/paritytech/parity/pull/4347) +- Renaming signAndSendTransaction to sendTransaction [#4351](https://github.com/paritytech/parity/pull/4351) +- Add api.util.encodeMethodCall to parity.js [#4330](https://github.com/paritytech/parity/pull/4330) +- Initial commit for vaults [#4312](https://github.com/paritytech/parity/pull/4312) +- Returning default account as coinbase + allow altering sender in signer [#4323](https://github.com/paritytech/parity/pull/4323) +- Persistent tracking of dapps [#4302](https://github.com/paritytech/parity/pull/4302) +- Exposing all RPCs over dapps port as CLI option [#4346](https://github.com/paritytech/parity/pull/4346) +- New macOS App [#4345](https://github.com/paritytech/parity/pull/4345) +- Display QrCode for accounts, addresses & contracts [#4329](https://github.com/paritytech/parity/pull/4329) +- Add QrCode & Copy to ShapeShift [#4322](https://github.com/paritytech/parity/pull/4322) +- Parity.js api.parity.chainStatus should handle { blockGap: null } [#4327](https://github.com/paritytech/parity/pull/4327) +- DeleteAccount & LoadContract modal updates [#4320](https://github.com/paritytech/parity/pull/4320) +- Split Tab from TabBar [#4318](https://github.com/paritytech/parity/pull/4318) +- Contracts interface expansion [#4307](https://github.com/paritytech/parity/pull/4307) +- HistoryStore for tracking relevant routes [#4305](https://github.com/paritytech/parity/pull/4305) +- Split Dapp icon into ui/DappIcon (re-use) [#4308](https://github.com/paritytech/parity/pull/4308) +- Add a Playground for the UI Components [#4301](https://github.com/paritytech/parity/pull/4301) +- Update CreateWallet with FormattedMessage [#4298](https://github.com/paritytech/parity/pull/4298) +- Update dates for new PRs missed [#4306](https://github.com/paritytech/parity/pull/4306) +- EIP-98: Optional transaction state root [#4296](https://github.com/paritytech/parity/pull/4296) +- Fix whitespace [#4299](https://github.com/paritytech/parity/pull/4299) +- Attempt to fix console. [#4294](https://github.com/paritytech/parity/pull/4294) +- Ui/SectionList component [#4292](https://github.com/paritytech/parity/pull/4292) +- Stratum up [#4233](https://github.com/paritytech/parity/pull/4233) +- Logging transaction duration [#4297](https://github.com/paritytech/parity/pull/4297) +- Generic engine utilities [#4258](https://github.com/paritytech/parity/pull/4258) +- JSON-RPC interfaces with documentation [#4276](https://github.com/paritytech/parity/pull/4276) +- Dont decode seal fields [#4263](https://github.com/paritytech/parity/pull/4263) +- Skip misbehaving test until properly fixed [#4283](https://github.com/paritytech/parity/pull/4283) +- Additional logs for own transactions [#4278](https://github.com/paritytech/parity/pull/4278) +- Ensure write lock isn't held when calling handlers [#4285](https://github.com/paritytech/parity/pull/4285) +- Feature selector [#4074](https://github.com/paritytech/parity/pull/4074) +- AccountCreate updates [#3988](https://github.com/paritytech/parity/pull/3988) +- Extended JS interface -> Markdown generator [#4275](https://github.com/paritytech/parity/pull/4275) +- Added 3 warpnodes for ropsten [#4289](https://github.com/paritytech/parity/pull/4289) +- Ledger Communication JS toolkit [#4268](https://github.com/paritytech/parity/pull/4268) +- ValidatorSet reporting [#4208](https://github.com/paritytech/parity/pull/4208) +- Add support for api.subscribe('parity_accountsInfo') [#4273](https://github.com/paritytech/parity/pull/4273) +- Display AccountCard name via IdentityName [#4235](https://github.com/paritytech/parity/pull/4235) +- Dapp visibility save/load tests [#4150](https://github.com/paritytech/parity/pull/4150) +- Fix wrong output format of peers [#4270](https://github.com/paritytech/parity/pull/4270) +- Chain scoring [#4218](https://github.com/paritytech/parity/pull/4218) +- Rust 1.14 for windows builds [#4269](https://github.com/paritytech/parity/pull/4269) +- Eslint formatting updates [#4234](https://github.com/paritytech/parity/pull/4234) +- Embeddable ParityBar [#4222](https://github.com/paritytech/parity/pull/4222) +- Update deb-build.sh to fix libssl dependency [#4260](https://github.com/paritytech/parity/pull/4260) +- Integration with zgp whitelist contract [#4215](https://github.com/paritytech/parity/pull/4215) +- Adjust the location of the signer snippet [#4155](https://github.com/paritytech/parity/pull/4155) +- Fix wrong token handling [#4254](https://github.com/paritytech/parity/pull/4254) +- Additional building-block UI components [#4239](https://github.com/paritytech/parity/pull/4239) +- Bump package.json to 0.3.0 (1.6 track) [#4244](https://github.com/paritytech/parity/pull/4244) +- Disable incoming ETH notifications [#4243](https://github.com/paritytech/parity/pull/4243) +- Memory-based pruning history size [#4114](https://github.com/paritytech/parity/pull/4114) +- Common EngineSigner [#4189](https://github.com/paritytech/parity/pull/4189) +- Verification: don't request a code twice [#4221](https://github.com/paritytech/parity/pull/4221) +- S/Delete Contract/Forget Contract/ [#4237](https://github.com/paritytech/parity/pull/4237) +- Light protocol syncing improvements [#4212](https://github.com/paritytech/parity/pull/4212) +- LES Peer Info [#4195](https://github.com/paritytech/parity/pull/4195) +- Don't panic on uknown git commit hash [#4231](https://github.com/paritytech/parity/pull/4231) +- Cache registry reverses in local storage [#4182](https://github.com/paritytech/parity/pull/4182) +- Update version numbers in README [#4223](https://github.com/paritytech/parity/pull/4223) +- CHT calculations for full nodes [#4181](https://github.com/paritytech/parity/pull/4181) +- Use single source of info for dapp meta (build & display) [#4217](https://github.com/paritytech/parity/pull/4217) +- Non-secure API for DappReg [#4216](https://github.com/paritytech/parity/pull/4216) +- Console now has admin [#4220](https://github.com/paritytech/parity/pull/4220) +- Verification: add mainnet BadgeReg ids [#4190](https://github.com/paritytech/parity/pull/4190) +- Fixing minimal transaction queue price [#4204](https://github.com/paritytech/parity/pull/4204) +- Remove unnecessary Engine method [#4184](https://github.com/paritytech/parity/pull/4184) +- Fixed --base-path on windows [#4193](https://github.com/paritytech/parity/pull/4193) +- Fixing etherscan price parsing [#4202](https://github.com/paritytech/parity/pull/4202) +- LES: Better timeouts + Track failed requests [#4093](https://github.com/paritytech/parity/pull/4093) +- ESLint additional rules [#4186](https://github.com/paritytech/parity/pull/4186) +- JsonRPC bump for IPC fix [#4200](https://github.com/paritytech/parity/pull/4200) +- Poll for upgrades as part of global status (long) [#4197](https://github.com/paritytech/parity/pull/4197) +- Updater fixes [#4196](https://github.com/paritytech/parity/pull/4196) +- Prevent duplicate incoming connections [#4180](https://github.com/paritytech/parity/pull/4180) +- Minor typo to ensure it updates only when synced. [#4188](https://github.com/paritytech/parity/pull/4188) +- Minor refactor for clarity [#4174](https://github.com/paritytech/parity/pull/4174) +- Secret - from hash function, also validate data [#4159](https://github.com/paritytech/parity/pull/4159) +- Gas_limit for blocks, mined by Parity will be divisible by 37 [#4154](https://github.com/paritytech/parity/pull/4154) +- Support HTML5-routed dapps [#4173](https://github.com/paritytech/parity/pull/4173) +- Fix subscribeToEvents test [#4166](https://github.com/paritytech/parity/pull/4166) +- Fix dapps not loading [#4170](https://github.com/paritytech/parity/pull/4170) +- Fix broken token images [#4169](https://github.com/paritytech/parity/pull/4169) +- Bumping hyper [#4167](https://github.com/paritytech/parity/pull/4167) +- Icarus -> update, increase web timeout. [#4165](https://github.com/paritytech/parity/pull/4165) +- Add a password strength component [#4153](https://github.com/paritytech/parity/pull/4153) +- Stop flickering + added loader in AddressSelector [#4149](https://github.com/paritytech/parity/pull/4149) +- On demand LES request [#4036](https://github.com/paritytech/parity/pull/4036) +- Ropsten fork detection [#4163](https://github.com/paritytech/parity/pull/4163) +- Pull in console dapp as builtin [#4145](https://github.com/paritytech/parity/pull/4145) +- Optimized hash lookups [#4144](https://github.com/paritytech/parity/pull/4144) +- UnverifiedTransaction type [#4134](https://github.com/paritytech/parity/pull/4134) +- Verification: check if server is running [#4140](https://github.com/paritytech/parity/pull/4140) +- Remove onSubmit of current (no auto-change on password edit) [#4151](https://github.com/paritytech/parity/pull/4151) +- Trim spaces from InputAddress [#4126](https://github.com/paritytech/parity/pull/4126) +- Don't pop-up notifications after network switch [#4076](https://github.com/paritytech/parity/pull/4076) +- Use estimateGas error (as per updated implementation) [#4131](https://github.com/paritytech/parity/pull/4131) +- Improvements and optimisations to estimate_gas [#4142](https://github.com/paritytech/parity/pull/4142) +- New jsonrpc-core with futures and metadata support [#3859](https://github.com/paritytech/parity/pull/3859) +- Reenable mainnet update server. [#4137](https://github.com/paritytech/parity/pull/4137) +- Temporarily skip failing test [#4138](https://github.com/paritytech/parity/pull/4138) +- Refactor VoteCollector [#4101](https://github.com/paritytech/parity/pull/4101) +- Another minor estimation fix [#4133](https://github.com/paritytech/parity/pull/4133) +- Add proper label to method decoding inputs [#4136](https://github.com/paritytech/parity/pull/4136) +- Remove bindActionCreators({}, dispatch) (empty, unneeded) [#4135](https://github.com/paritytech/parity/pull/4135) +- Better contract error log reporting & handling [#4128](https://github.com/paritytech/parity/pull/4128) +- Fix broken Transfer : total account balance [#4127](https://github.com/paritytech/parity/pull/4127) +- Test harness for lightsync [#4109](https://github.com/paritytech/parity/pull/4109) +- Fix call/estimate_gas [#4121](https://github.com/paritytech/parity/pull/4121) +- Fixing decoding ABI with signatures in names [#4125](https://github.com/paritytech/parity/pull/4125) +- Get rid of unsafe code in ethkey, propagate incorrect Secret errors. [#4119](https://github.com/paritytech/parity/pull/4119) +- Basic tests for subscribeToEvents [#4115](https://github.com/paritytech/parity/pull/4115) +- Auto-detect hex encoded bytes in sha3 [#4108](https://github.com/paritytech/parity/pull/4108) +- Use binary chop to estimate gas accurately [#4100](https://github.com/paritytech/parity/pull/4100) +- V1.6 in master [#4113](https://github.com/paritytech/parity/pull/4113) +- Ignore get_price_info test by default. [#4112](https://github.com/paritytech/parity/pull/4112) +- Fix wrong information logging [#4106](https://github.com/paritytech/parity/pull/4106) +- Avoid comms with not-yet-active release update server. [#4111](https://github.com/paritytech/parity/pull/4111) +- Update Transfer logic + Better logging [#4098](https://github.com/paritytech/parity/pull/4098) +- Fix Signer : wrong account on reload [#4104](https://github.com/paritytech/parity/pull/4104) +- Cache registry reverses, completion in address selector [#4066](https://github.com/paritytech/parity/pull/4066) +- Validator/authority contract [#3937](https://github.com/paritytech/parity/pull/3937) +- No reorg limit for ancient blocks [#4099](https://github.com/paritytech/parity/pull/4099) +- Update registration after every write [#4102](https://github.com/paritytech/parity/pull/4102) +- Default to no auto-update. [#4092](https://github.com/paritytech/parity/pull/4092) +- Don't remove out of date local transactions [#4094](https://github.com/paritytech/parity/pull/4094) diff --git a/docs/CHANGELOG-1.7.md b/docs/CHANGELOG-1.7.md new file mode 100644 index 0000000000000000000000000000000000000000..760445845ed3d07caf42c1305c860100c830ec25 --- /dev/null +++ b/docs/CHANGELOG-1.7.md @@ -0,0 +1,832 @@ +Note: Parity 1.7 reached End-of-Life on 2018-01-25 (EOL). + +### Parity [v1.7.13](https://github.com/paritytech/parity/releases/tag/v1.7.13) (2018-01-23) + +Parity 1.7.13 is a bug-fix release to improve stability of PoA-networks. Users on Kovan or other Aura-based networks are advised to upgrade as this release fixes an issue introduced with 1.7.12 that causes Proof-of-Authority nodes to stop synchronizing the chain. + +The full list of included changes: + +- AuRa fix for 1.7.x series ([#7666](https://github.com/paritytech/parity/pull/7666)) + - Fix Temporarily Invalid blocks handling ([#7613](https://github.com/paritytech/parity/pull/7613)) + - Handle temporarily invalid blocks in sync. + - Fix tests. + - Bump rustc-serialize + - Bump version. + - Update .gitlab-ci.yml + - Fix lint + - Remove slash from gitlab ci script to fix builds + - Start build. + +### Parity [v1.7.12](https://github.com/paritytech/parity/releases/tag/v1.7.12) (2018-01-09) + +Parity 1.7.12 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Fix stable builds for rustc 1.23.0 ([#7504](https://github.com/paritytech/parity/pull/7504)) +- Missing AuRa backports ([#7499](https://github.com/paritytech/parity/pull/7499) + - Wait for future blocks in AuRa ([#7368](https://github.com/paritytech/parity/pull/7368)) + - Mark future blocks as temporarily invalid. + - Don't check max. + - Advance AuRa step as far as we can and prevent invalid blocks. ([#7451](https://github.com/paritytech/parity/pull/7451)) + - Advance AuRa step as far as we can. + - Wait for future blocks. + - Problem: AuRa's unsafeties around step duration ([#7282](https://github.com/paritytech/parity/pull/7282)) + - Fix tests. + - Detect different node, same-key signing in aura ([#7245](https://github.com/paritytech/parity/pull/7245)) + - Detect different node, same-key signing in aura + - Reduce scope of warning +- Backports ([#7496](https://github.com/paritytech/parity/pull/7496)) + - Advance AuRa step as far as we can. ([#7451](https://github.com/paritytech/parity/pull/7451)) + - Advance AuRa step as far as we can. + - Wait for future blocks. + - Fixed panic when io is not available for export block, closes [#7486](https://github.com/paritytech/parity/issue/7486) ([#7495](https://github.com/paritytech/parity/pull/7495)) + - Update Parity Mainnet Bootnodes ([#7476](https://github.com/paritytech/parity/pull/7476)) + - Replace the Azure HDD bootnodes with the new ones :) + - Bump version to 1.7.12 + +### Parity [v1.7.11](https://github.com/paritytech/parity/releases/tag/v1.7.11) (2017-12-29) + +Parity 1.7.11 changes the default behavior of JSON-RPC CORS setting, and updates bootnodes for the Kovan and Foundation networks. + +Note: The default value of `--jsonrpc-cors` option has been altered to disallow (potentially malicious) websites from accessing the low-sensitivity RPCs (viewing exposed accounts, proposing transactions for signing). Currently domains need to be whitelisted manually. To bring back previous behaviour run with `--jsonrpc-cors all` or `--jsonrpc-cors http://example.com`. + +The full list of included changes: + +- Stable Bootnodes and Warpnodes ([#7298](https://github.com/paritytech/parity/pull/7298)) + - New warp enodes ([#7287](https://github.com/paritytech/parity/pull/7287)) + - New warp enodes + - Added one more warp enode; replaced spaces with tabs + - Bump stable to 1.7.11 + - Update kovan boot nodes ([#7296](https://github.com/paritytech/parity/pull/7296)) + - Fix Cargo.lock + - Updating mainnet bootnodes. + - Update bootnodes ([#7363](https://github.com/paritytech/parity/pull/7363)) + - Updating mainnet bootnodes. + - Add additional parity-beta bootnodes. + - Restore old parity bootnodes and update foudation bootnodes +- Ethstore optimizations ([#6827](https://github.com/paritytech/parity/pull/6827)) ([#6844](https://github.com/paritytech/parity/pull/6844)) ([#7347](https://github.com/paritytech/parity/pull/7347)) +- Fix default CORS. ([#7389](https://github.com/paritytech/parity/pull/7389)) + +### 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. + +The full list of included changes: + +- Bump to v1.7.9 ([#7047](https://github.com/paritytech/parity/pull/7047)) +- Disallow built-in multi-sig deploy (only watch) ([#7017](https://github.com/paritytech/parity/pull/7017)) + +### Parity [v1.7.8](https://github.com/paritytech/parity/releases/tag/v1.7.8) (2017-10-26) + +Parity 1.7.8 fixes a critical Byzantium consensus issue. Update is highly recommended. + +The full list of included changes: + +- Refactor static context check in CREATE ([#6889](https://github.com/paritytech/parity/pull/6889)) +- Bump to v1.7.8 ([#6890](https://github.com/paritytech/parity/pull/6890)) + +## Parity [v1.7.7](https://github.com/paritytech/parity/releases/tag/v1.7.7) (2017-10-15) + +Parity 1.7.7 fixes an issue with auto-update system. Updating is recommended, but not required for Byzantium. + +The full list of included changes: + +- Fix auto-update ([#6769](https://github.com/paritytech/parity/pull/6759)) + - Bump to v1.7.7 + - Updated ethabi to fix auto-update +- Bumped fork block number for auto-update ([#6754](https://github.com/paritytech/parity/pull/6754)) + +## Parity [v1.7.6](https://github.com/paritytech/parity/releases/tag/v1.7.6) (2017-10-13) + +Parity 1.7.6 includes a critical consensus-relevant fix for the Byzantium hard-fork. Please upgrade your Ethereum client before block number `4_370_000`. + +The full list of included changes: + +- Fixed modexp gas calculation overflow ([#6746](https://github.com/paritytech/parity/pull/6746)) + - Fixed modexp gas calculation overflow ([#6741](https://github.com/paritytech/parity/pull/6741)) + - Bump to v1.7.6 + +## Parity [v1.7.5](https://github.com/paritytech/parity/releases/tag/v1.7.5) (2017-10-12) + +Parity 1.7.5 includes a critical consensus-relevant fix for the Byzantium hard-fork. Please upgrade your Ethereum client before block number `4_370_000`. + +Parity 1.7.5 is the first stable release of the 1.7 branch. With this release the support for 1.6 releases ends. Please upgrade your stable nodes to 1.7.5. + +The full list of included changes: + +- Backport stable - Fixes Badges ([#6731](https://github.com/paritytech/parity/pull/6731)) + - Fix badges not showing up ([#6730](https://github.com/paritytech/parity/pull/6730)) + - Always fetch meta data first [badges] +- Backport ([#6726](https://github.com/paritytech/parity/pull/6726)) + - Check vouch status on appId in addition to contentHash ([#6719](https://github.com/paritytech/parity/pull/6719)) + - Check vouch status on appId in addition to contentHash + - Simplify var expansion + - Merge [#6725](https://github.com/paritytech/parity/pull/6725) + - Update new token fetching + - Working Certifications Monitoring + - Update on Certification / Revoke + - Fix none-fetched tokens value display + - Fix tests + - Add updated MethodDecoding from master +- v1.7.5 stabilized +- Backport ([#6724](https://github.com/paritytech/parity/pull/6724)) + - Fixed RETURNDATA out of bounds check ([#6718](https://github.com/paritytech/parity/pull/6718)) + - Prevent going offline when restoring or taking snapshot ([#6694](https://github.com/paritytech/parity/pull/6694)) +- Bump to v1.7.5 +- Trigger beta js build & release ([#6721](https://github.com/paritytech/parity/pull/6721)) + +## Parity [v1.7.4](https://github.com/paritytech/parity/releases/tag/v1.7.4) (2017-10-11) + +Parity 1.7.4 includes a critical consensus-relevant fix for the Byzantium hard-fork. Please upgrade your Ethereum client before block number `4_370_000`. + +The full list of included changes: + +- Backport ([#6715](https://github.com/paritytech/parity/pull/6715)) + - Fix estimate gas if from is not provided. ([#6714](https://github.com/paritytech/parity/pull/6714)) + - Display vouched overlay on dapps ([#6710](https://github.com/paritytech/parity/pull/6710)) + - Add vouch overlays to dapps + - Cleanup address + - Only run where we have a contentHash +- Backporting ([#6712](https://github.com/paritytech/parity/pull/6712)) + - Bump to v1.7.4 + - Fixed potential exp len overflow ([#6686](https://github.com/paritytech/parity/pull/6686)) + - Fix warp sync blockers detection ([#6691](https://github.com/paritytech/parity/pull/6691)) +- Backport ([#6713](https://github.com/paritytech/parity/pull/6713)) + - Allow signer signing display of markdown ([#6707](https://github.com/paritytech/parity/pull/6707)) + - Fix default values for address input ([#6701](https://github.com/paritytech/parity/pull/6701)) + - Fix asciiToHex for characters < 0x10 ([#6702](https://github.com/paritytech/parity/pull/6702)) + +## Parity [v1.7.3](https://github.com/paritytech/parity/releases/tag/v1.7.3) (2017-10-09) + +Parity 1.7.3 enables the Byzantium fork for Ethereum main network on Block 4_370_000 and offers a variety of bug fixes and stability improvements. Among them: + +- Fixed network protocol version negotiation with Geth nodes v1.7.1+. +- Fixed `RETURNDATA` size for built-ins. (Built-ins in some cases overwrite only a portion of the output memory slice.) +- Multisig Wallet View now loads if multiple transactions happened within one block. +- Improved stability of snapshot-sycns (warp). +- Revised timeout and batch size constants for bigger blocks. +- Renamed RPC receipt `statusCode` field to `status`. + +The full list of included changes: + +- Backporting ([#6676](https://github.com/paritytech/parity/pull/6676)) + - Fix wallet view ([#6597](https://github.com/paritytech/parity/pull/6597)) + - Add safe fail for empty logs + - Filter transactions + - Add more logging + - Fix Wallet Creation and wallet tx list + - Remove logs + - Prevent selecting twice same wallet owner + - Fix tests + - Remove unused props + - Disallow pasting recovery phrases on first run ([#6602](https://github.com/paritytech/parity/pull/6602)) + - Fix disallowing paste of recovery phrase on first run, ref [#6581](https://github.com/paritytech/parity/issues/6581) + - Allow the leader of CATS pasting recovery phrases. + - Updated systemd files for linux ([#6592](https://github.com/paritytech/parity/pull/6592)) + - Previous version put $BASE directory in root directory. + - This version clearly explains how to run as root or as specific user. + - Additional configuration: + - send SIGHUP for clean exit, + - restart on fail. + - Tested on Ubuntu 16.04.3 LTS with 4.10.0-33-generic x86_64 kernel + - Don't expose port 80 for parity anymore ([#6633](https://github.com/paritytech/parity/pull/6633)) +- Backporting ([#6675](https://github.com/paritytech/parity/pull/6675)) + - Required validators >= num owners ([#6551](https://github.com/paritytech/parity/pull/6551)) + - Debounce sync status. ([#6572](https://github.com/paritytech/parity/pull/6572)) + - Fixed network protocol version negotiation ([#6649](https://github.com/paritytech/parity/pull/6649)) + - Renamed RPC receipt statusCode field to status ([#6650](https://github.com/paritytech/parity/pull/6650)) + - Fixed RETURNDATA size for built-ins ([#6652](https://github.com/paritytech/parity/pull/6652)) +- Byzantium fork block number ([#6661](https://github.com/paritytech/parity/pull/6661)) +- Refreshing block number on status view ([#6610](https://github.com/paritytech/parity/pull/6610)) +- Tweaked block download timeouts ([#6595](https://github.com/paritytech/parity/pull/6595)) +- Backports ([#6563](https://github.com/paritytech/parity/pull/6563)) + - Sync progress and error handling fixes ([#6560](https://github.com/paritytech/parity/pull/6560)) + - Fixed receipt serialization and RPC ([#6555](https://github.com/paritytech/parity/pull/6555)) +- Bump to v1.7.3 + +## Parity [v1.7.2](https://github.com/paritytech/parity/releases/tag/v1.7.2) (2017-09-18) + +Parity 1.7.2 is a bug-fix release to improve performance and stability. Among others, it addresses the following: + +- Byzantium fork support for the Ropsten and Foundation networks. +- Added support for the ConsenSys and Gnosis multi-signature wallets. +- Significantly increased token registry and token balance lookup performance. +- Fixed issues with the health status indicator in the wallet. +- Tweaked warp-sync to quickly catch up with chains fallen back more than 10,000 blocks. +- Fixes to the Chrome extension and macOS installer upgrades. + +The full list of included changes: + +- Fix output from eth_call. ([#6538](https://github.com/paritytech/parity/pull/6538)) +- Ropsten fork ([#6532](https://github.com/paritytech/parity/pull/6532)) +- Byzantium updates ([#6529](https://github.com/paritytech/parity/pull/6529)) + - Fix modexp bug: return 0 if base=0 ([#6424](https://github.com/paritytech/parity/pull/6424)) + - Running state test using parity-evm ([#6355](https://github.com/paritytech/parity/pull/6355)) + - Initial version of state tests. + - Refactor state to support tracing. + - Unify TransactResult. + - Add test. + - Byzantium updates ([#5855](https://github.com/paritytech/parity/pull/5855)) + - EIP-211 updates + - Benchmarks + - Blockhash instruction gas cost updated + - More benches + - EIP-684 + - EIP-649 + - EIP-658 + - Updated some tests + - Modexp fixes + - STATICCALL fixes + - Pairing fixes + - More STATICALL fixes + - Use paritytech/bn + - Fixed REVERTing of contract creation + - Fixed more tests + - Fixed more tests + - Blockchain tests + - Enable previously broken tests + - Transition test + - Updated tests + - Fixed modexp reading huge numbers + - Enabled max_code_size test + - Review fixes + - Updated pairing pricing + - Missing commas (style) + - Update test.rs + - Small improvements + - Eip161abc +- Fix extension detection ([#6452](https://github.com/paritytech/parity/pull/6452)) ([#6524](https://github.com/paritytech/parity/pull/6524)) + - Fix extension detection. + - Fix mobx quirks. + - Update submodule. +- Fix detecting hardware wallets. ([#6509](https://github.com/paritytech/parity/pull/6509)) +- Allow hardware device reads without lock. ([#6517](https://github.com/paritytech/parity/pull/6517)) +- Backports [#6497](https://github.com/paritytech/parity/pull/6497) + - Fix slow balances ([#6471](https://github.com/paritytech/parity/pull/6471)) + - Update token updates + - Update token info fetching + - Update logger + - Minor fixes to updates and notifications for balances + - Use Pubsub + - Fix timeout. + - Use pubsub for status. + - Fix signer subscription. + - Process tokens in chunks. + - Fix tokens loaded by chunks + - Dispatch tokens asap + - Fix chunks processing. + - Better filter options + - Parallel log fetching. + - Fix signer polling. + - Fix initial block query. + - Token balances updates : the right(er) way + - Better tokens info fetching + - Fixes in token data fetching + - Only fetch what's needed (tokens) + - Fix linting issues + - Update wasm-tests. + - Fixing balances fetching + - Fix requests tracking in UI + - Fix request watching + - Update the Logger + - PR Grumbles Fixes + - Eth_call returns output of contract creations ([#6420](https://github.com/paritytech/parity/pull/6420)) + - Eth_call returns output of contract creations + - Fix parameters order. + - Save outputs for light client as well. + - Don't accept transactions above block gas limit. + - Expose health status over RPC ([#6274](https://github.com/paritytech/parity/pull/6274)) + - Node-health to a separate crate. + - Initialize node_health outside of dapps. + - Expose health over RPC. + - Bring back 412 and fix JS. + - Add health to workspace and tests. + - Fix compilation without default features. + - Fix borked merge. + - Revert to generics to avoid virtual calls. + - Fix node-health tests. + - Add missing trailing comma. + - Fixing/removing failing JS tests. + - Do not activate genesis epoch in immediate transition validator contract ([#6349](https://github.com/paritytech/parity/pull/6349)) + - Fix memory tracing. + - Add test to cover that. + - Ensure balances of constructor accounts are kept + - Test balance of spec-constructed account is kept +- Fix warning spam. [#6369](https://github.com/paritytech/parity/pull/6369) +- Bump to 1.7.2 +- Fix eth_call [#6366](https://github.com/paritytech/parity/pull/6366) +- Backporting [#6352](https://github.com/paritytech/parity/pull/6352) + - Better check the created accounts before showing Startup Wizard [#6331](https://github.com/paritytech/parity/pull/6331) + - Tweaked snapshot params [#6344](https://github.com/paritytech/parity/pull/6344) +- Increase default gas limit for eth_call [#6337](https://github.com/paritytech/parity/pull/6337) + - Fix balance increase. + - Cap gas limit for dapp-originating requests. +- Backports [#6333](https://github.com/paritytech/parity/pull/6333) + - Overflow check in addition + - Unexpose methods on UI RPC. [#6295](https://github.com/paritytech/parity/pull/6295) + - Add more descriptive error when signing/decrypting using hw wallet. + - Format instant change proofs correctly + - Propagate stratum submit share error upstream [#6260](https://github.com/paritytech/parity/pull/6260) + - Updated jsonrpc [#6264](https://github.com/paritytech/parity/pull/6264) + - Using multiple NTP servers [#6173](https://github.com/paritytech/parity/pull/6173) + - Small improvements to time estimation. + - Allow multiple NTP servers to be used. + - Removing boxing. + - Update list of servers and add reference. + - Fix dapps CSP when UI is exposed externally [#6178](https://github.com/paritytech/parity/pull/6178) + - Allow embeding on any page when ui-hosts=all and fix dev_ui + - Fix cache path when using --base-path [#6212](https://github.com/paritytech/parity/pull/6212) + - Bump to v1.7.1 +- UI backports [#6332](https://github.com/paritytech/parity/pull/6332) + - Time should not contribue to overall status. [#6276](https://github.com/paritytech/parity/pull/6276) + - Add warning to web browser and fix links. [#6232](https://github.com/paritytech/parity/pull/6232) + - Extension fixes [#6284](https://github.com/paritytech/parity/pull/6284) + - Fix token symbols in extension. + - Allow connections from firefox extension. + - Add support for ConsenSys multisig wallet [#6153](https://github.com/paritytech/parity/pull/6153) + - First draft of ConsenSys wallet + - Fix transfer store // WIP Consensys Wallet + - Rename walletABI JSON file + - Fix wrong daylimit in wallet modal + - Confirm/Revoke ConsensysWallet txs + - Change of settings for the Multisig Wallet +- Update README for beta [#6270](https://github.com/paritytech/parity/pull/6270) +- Fixed macOS installer upgrade [#6221](https://github.com/paritytech/parity/pull/6221) + +## Parity [v1.7.0](https://github.com/paritytech/parity/releases/tag/v1.7.0) (2017-07-28) + +Parity 1.7.0 is a major release introducing several important features: + +- **Experimental [Light client](https://github.com/paritytech/parity/wiki/The-Parity-Light-Protocol-(PIP)) support**. Start Parity with `--light` to enable light mode. Please, note: The wallet UI integration for the light client is not included, yet. +- **Experimental web wallet**. A hosted version of Parity that keeps the keys and signs transactions using your browser storage. Try it at https://wallet.parity.io or run your own with `--public-node`. +- **WASM contract support**. Private networks can run contracts compiled into WASM bytecode. _More information and documentation to follow_. +- **DApps and RPC server merge**. DApp and RPC are now available through a single API endpoint. DApp server related settings are deprecated. +- **Export accounts from the wallet**. Backing up your keys can now simply be managed through the wallet interface. +- **PoA/Kovan validator set contract**. The PoA network validator-set management via smart contract is now supported by warp and, in the near future, light sync. +- **PubSub API**. https://github.com/paritytech/parity/wiki/JSONRPC-Parity-Pub-Sub-module +- **Signer apps for IOS and Android**. + +The full list of included changes: + +- Backports [#6163](https://github.com/paritytech/parity/pull/6163) + - Light client improvements ([#6156](https://github.com/paritytech/parity/pull/6156)) + - No seal checking + - Import command and --no-seal-check for light client + - Fix eth_call + - Tweak registry dapps lookup + - Ignore failed requests to non-server peers + - Fix connecting to wildcard addresses. ([#6167](https://github.com/paritytech/parity/pull/6167)) + - Don't display an overlay in case the time sync check fails. ([#6164](https://github.com/paritytech/parity/pull/6164)) + - Small improvements to time estimation. + - Temporarily disable NTP time check by default. +- Light client fixes ([#6148](https://github.com/paritytech/parity/pull/6148)) [#6151](https://github.com/paritytech/parity/pull/6151) + - Light client fixes + - Fix memory-lru-cache + - Clear pending reqs on disconnect +- Filter tokens logs from current block, not genesis ([#6128](https://github.com/paritytech/parity/pull/6128)) [#6141](https://github.com/paritytech/parity/pull/6141) +- Fix QR scanner returning null on confirm [#6122](https://github.com/paritytech/parity/pull/6122) +- Check QR before lowercase ([#6119](https://github.com/paritytech/parity/pull/6119)) [#6120](https://github.com/paritytech/parity/pull/6120) +- Remove chunk to restore from pending set only upon successful import [#6117](https://github.com/paritytech/parity/pull/6117) +- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094) +- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095) +- Update wallet library binaries [#6108](https://github.com/paritytech/parity/pull/6108) +- Backported wallet fix [#6105](https://github.com/paritytech/parity/pull/6105) + - Fix initialisation bug. ([#6102](https://github.com/paritytech/parity/pull/6102)) + - Update wallet library modifiers ([#6103](https://github.com/paritytech/parity/pull/6103)) +- Place RETURNDATA behind block number gate [#6095](https://github.com/paritytech/parity/pull/6095) +- Fixed node address detection on incoming connection [#6094](https://github.com/paritytech/parity/pull/6094) +- Bump snap version and tweak importing detection logic ([#6079](https://github.com/paritytech/parity/pull/6079)) [#6081](https://github.com/paritytech/parity/pull/6081) + - bump last tick just before printing info and restore sync detection + - bump kovan snapshot version + - Fixed sync tests + - Fixed rpc tests +- Acquire client report under lock in informant [#6071](https://github.com/paritytech/parity/pull/6071) +- Show busy indicator on Address forget [#6069](https://github.com/paritytech/parity/pull/6069) +- Add CSP for worker-src ([#6059](https://github.com/paritytech/parity/pull/6059)) [#6064](https://github.com/paritytech/parity/pull/6064) + - Specify worker-src seperately, add blob + - Upgrade react-qr-scan to latest version +- Set release channel to beta +- Limit transaction queue memory & limit future queue [#6038](https://github.com/paritytech/parity/pull/6038) +- Fix CI build issue [#6050](https://github.com/paritytech/parity/pull/6050) +- New contract PoA sync fixes [#5991](https://github.com/paritytech/parity/pull/5991) +- Fixed link to Multisig Contract Wallet on master [#5984](https://github.com/paritytech/parity/pull/5984) +- Ethcore crate split part 1 [#6041](https://github.com/paritytech/parity/pull/6041) +- Fix status icon [#6039](https://github.com/paritytech/parity/pull/6039) +- Errors & warnings for inappropriate RPCs [#6029](https://github.com/paritytech/parity/pull/6029) +- Add missing CSP for web3.site [#5992](https://github.com/paritytech/parity/pull/5992) +- Remove cargo install --git from README.md [#6037](https://github.com/paritytech/parity/pull/6037) +- Node Health warnings [#5951](https://github.com/paritytech/parity/pull/5951) +- RPC cpu pool [#6023](https://github.com/paritytech/parity/pull/6023) +- Use crates.io dependencies for parity-wasm [#6036](https://github.com/paritytech/parity/pull/6036) +- Add test for loading the chain specs [#6028](https://github.com/paritytech/parity/pull/6028) +- Whitelist APIs for generic Pub-Sub [#5840](https://github.com/paritytech/parity/pull/5840) +- WASM contracts MVP [#5679](https://github.com/paritytech/parity/pull/5679) +- Fix valid QR scan not advancing [#6033](https://github.com/paritytech/parity/pull/6033) +- --reseal-on-uncle [#5940](https://github.com/paritytech/parity/pull/5940) +- Support comments in reserved peers file ([#6004](https://github.com/paritytech/parity/pull/6004)) [#6012](https://github.com/paritytech/parity/pull/6012) +- Add new md tnc [#5937](https://github.com/paritytech/parity/pull/5937) +- Fix output of parity-evm in case of bad instruction [#5955](https://github.com/paritytech/parity/pull/5955) +- Don't send notifications to unsubscribed clients of PubSub [#5960](https://github.com/paritytech/parity/pull/5960) +- Proper light client informant and more verification of imported headers [#5897](https://github.com/paritytech/parity/pull/5897) +- New Kovan bootnodes [#6017](https://github.com/paritytech/parity/pull/6017) +- Use standard paths for Ethash cache [#5881](https://github.com/paritytech/parity/pull/5881) +- Defer code hash calculation. [#5959](https://github.com/paritytech/parity/pull/5959) +- Fix first run wizard. [#6000](https://github.com/paritytech/parity/pull/6000) +- migration to serde 1.0 [#5996](https://github.com/paritytech/parity/pull/5996) +- SecretStore: generating signatures [#5764](https://github.com/paritytech/parity/pull/5764) +- bigint upgraded to version 3.0 [#5986](https://github.com/paritytech/parity/pull/5986) +- config: don't allow dev chain with force sealing option [#5965](https://github.com/paritytech/parity/pull/5965) +- Update lockfile for miniz-sys and gcc [#5969](https://github.com/paritytech/parity/pull/5969) +- Clean up function naming in RPC error module [#5995](https://github.com/paritytech/parity/pull/5995) +- Fix underflow in gas calculation [#5975](https://github.com/paritytech/parity/pull/5975) +- PubSub for parity-js [#5830](https://github.com/paritytech/parity/pull/5830) +- Report whether a peer was kept from `Handler::on_connect` [#5958](https://github.com/paritytech/parity/pull/5958) +- Implement skeleton for transaction index and epoch transition proof PIP messages [#5908](https://github.com/paritytech/parity/pull/5908) +- TransactionQueue improvements [#5917](https://github.com/paritytech/parity/pull/5917) +- constant time HMAC comparison and clarify docs in ethkey [#5952](https://github.com/paritytech/parity/pull/5952) +- Avoid pre-computing jump destinations [#5954](https://github.com/paritytech/parity/pull/5954) +- Upgrade elastic array [#5949](https://github.com/paritytech/parity/pull/5949) +- PoA: Wait for transition finality before applying [#5774](https://github.com/paritytech/parity/pull/5774) +- Logs Pub-Sub [#5705](https://github.com/paritytech/parity/pull/5705) +- Add the command to install the parity snap [#5945](https://github.com/paritytech/parity/pull/5945) +- Reduce unnecessary allocations [#5944](https://github.com/paritytech/parity/pull/5944) +- Clarify confusing messages. [#5935](https://github.com/paritytech/parity/pull/5935) +- Content Security Policy [#5790](https://github.com/paritytech/parity/pull/5790) +- CLI: Export error message and less verbose peer counter. [#5870](https://github.com/paritytech/parity/pull/5870) +- network: make it more explicit about StreamToken and TimerToken [#5939](https://github.com/paritytech/parity/pull/5939) +- sync: make it more idiomatic rust [#5938](https://github.com/paritytech/parity/pull/5938) +- Prioritize accounts over address book [#5909](https://github.com/paritytech/parity/pull/5909) +- Fixing failing compilation of RPC test on master. [#5916](https://github.com/paritytech/parity/pull/5916) +- Empty local middleware, until explicitly requested [#5912](https://github.com/paritytech/parity/pull/5912) +- Cancel propagated TX [#5899](https://github.com/paritytech/parity/pull/5899) +- fix minor race condition in aura seal generation [#5910](https://github.com/paritytech/parity/pull/5910) +- Docs for Pub-Sub, optional parameter for parity_subscribe [#5833](https://github.com/paritytech/parity/pull/5833) +- Fix gas editor doubling-up on gas [#5820](https://github.com/paritytech/parity/pull/5820) +- Information about used paths added to general output block [#5904](https://github.com/paritytech/parity/pull/5904) +- Domain-locked web tokens. [#5894](https://github.com/paritytech/parity/pull/5894) +- Removed panic handlers [#5895](https://github.com/paritytech/parity/pull/5895) +- Latest changes from Rust RocksDB binding merged [#5905](https://github.com/paritytech/parity/pull/5905) +- Adjust keyethereum/secp256 aliasses [#5903](https://github.com/paritytech/parity/pull/5903) +- Keyethereum fs dependency [#5902](https://github.com/paritytech/parity/pull/5902) +- Ethereum Classic Monetary Policy [#5741](https://github.com/paritytech/parity/pull/5741) +- Initial token should allow full access. [#5873](https://github.com/paritytech/parity/pull/5873) +- Fixed account selection for Dapps on public node [#5856](https://github.com/paritytech/parity/pull/5856) +- blacklist bad snapshot manifest hashes upon failure [#5874](https://github.com/paritytech/parity/pull/5874) +- Fix wrongly called timeouts [#5838](https://github.com/paritytech/parity/pull/5838) +- ArchiveDB and other small fixes [#5867](https://github.com/paritytech/parity/pull/5867) +- convert try!() to ? [#5866](https://github.com/paritytech/parity/pull/5866) +- Make config file optional in systemd [#5847](https://github.com/paritytech/parity/pull/5847) +- EIP-116 (214), [#4833](https://github.com/paritytech/parity/issues/4833) [#4851](https://github.com/paritytech/parity/pull/4851) +- all executables are workspace members [#5865](https://github.com/paritytech/parity/pull/5865) +- minor optimizations of the modexp builtin [#5860](https://github.com/paritytech/parity/pull/5860) +- three small commits for HashDB and MemoryDB [#5766](https://github.com/paritytech/parity/pull/5766) +- use rust 1.18's retain to boost the purge performance [#5801](https://github.com/paritytech/parity/pull/5801) +- Allow IPFS server to accept POST requests [#5858](https://github.com/paritytech/parity/pull/5858) +- Dutch i18n from [#5802](https://github.com/paritytech/parity/issues/5802) for master [#5836](https://github.com/paritytech/parity/pull/5836) +- Typos in token deploy dapp ui [#5851](https://github.com/paritytech/parity/pull/5851) +- A CLI flag to allow fast transaction signing when account is unlocked. [#5778](https://github.com/paritytech/parity/pull/5778) +- Removing `additional` field from EVM instructions [#5821](https://github.com/paritytech/parity/pull/5821) +- Don't fail on wrong log decoding [#5813](https://github.com/paritytech/parity/pull/5813) +- Use randomized subscription ids for PubSub [#5756](https://github.com/paritytech/parity/pull/5756) +- Fixed mem write for empty slice [#5827](https://github.com/paritytech/parity/pull/5827) +- Fix party technologies [#5810](https://github.com/paritytech/parity/pull/5810) +- Revert "Fixed mem write for empty slice" [#5826](https://github.com/paritytech/parity/pull/5826) +- Fixed mem write for empty slice [#5825](https://github.com/paritytech/parity/pull/5825) +- Fix JS tests [#5822](https://github.com/paritytech/parity/pull/5822) +- Bump native-tls and openssl crates. [#5817](https://github.com/paritytech/parity/pull/5817) +- Public node using WASM [#5734](https://github.com/paritytech/parity/pull/5734) +- enforce block signer == author field in PoA [#5808](https://github.com/paritytech/parity/pull/5808) +- Fix stack display in evmbin. [#5733](https://github.com/paritytech/parity/pull/5733) +- Disable UI if it's not compiled in. [#5773](https://github.com/paritytech/parity/pull/5773) +- Require phrase confirmation. [#5731](https://github.com/paritytech/parity/pull/5731) +- Duration limit made optional for EthashParams [#5777](https://github.com/paritytech/parity/pull/5777) +- Update Changelog for 1.6.8 [#5798](https://github.com/paritytech/parity/pull/5798) +- Replace Ethcore comany name in T&C and some other places [#5796](https://github.com/paritytech/parity/pull/5796) +- PubSub for IPC. [#5800](https://github.com/paritytech/parity/pull/5800) +- Fix terminology distributed -> decentralized applications [#5797](https://github.com/paritytech/parity/pull/5797) +- Disable compression for RLP strings [#5786](https://github.com/paritytech/parity/pull/5786) +- update the source for the snapcraft package [#5781](https://github.com/paritytech/parity/pull/5781) +- Fixed default UI port for mac installer [#5782](https://github.com/paritytech/parity/pull/5782) +- Block invalid account name creation [#5784](https://github.com/paritytech/parity/pull/5784) +- Update Cid/multihash/ring/tinykeccak [#5785](https://github.com/paritytech/parity/pull/5785) +- use NULL_RLP, remove NULL_RLP_STATIC [#5742](https://github.com/paritytech/parity/pull/5742) +- Blacklist empty phrase account. [#5730](https://github.com/paritytech/parity/pull/5730) +- EIP-211 RETURNDATACOPY and RETURNDATASIZE [#5678](https://github.com/paritytech/parity/pull/5678) +- Bump mio [#5763](https://github.com/paritytech/parity/pull/5763) +- Fixing UI issues after UI server refactor [#5710](https://github.com/paritytech/parity/pull/5710) +- Fix WS server expose issue. [#5728](https://github.com/paritytech/parity/pull/5728) +- Fix local transactions without condition. [#5716](https://github.com/paritytech/parity/pull/5716) +- Bump parity-wordlist. [#5748](https://github.com/paritytech/parity/pull/5748) +- two small changes in evm [#5700](https://github.com/paritytech/parity/pull/5700) +- Evmbin: JSON format printing pre-state. [#5712](https://github.com/paritytech/parity/pull/5712) +- Recover from empty phrase in dev mode [#5698](https://github.com/paritytech/parity/pull/5698) +- EIP-210 BLOCKHASH changes [#5505](https://github.com/paritytech/parity/pull/5505) +- fixes typo [#5708](https://github.com/paritytech/parity/pull/5708) +- Bump rocksdb [#5707](https://github.com/paritytech/parity/pull/5707) +- Fixed --datadir option [#5697](https://github.com/paritytech/parity/pull/5697) +- rpc -> weak to arc [#5688](https://github.com/paritytech/parity/pull/5688) +- typo fix [#5699](https://github.com/paritytech/parity/pull/5699) +- Revamping parity-evmbin [#5696](https://github.com/paritytech/parity/pull/5696) +- Update dependencies and bigint api [#5685](https://github.com/paritytech/parity/pull/5685) +- UI server refactoring [#5580](https://github.com/paritytech/parity/pull/5580) +- Fix from/into electrum in ethkey [#5686](https://github.com/paritytech/parity/pull/5686) +- Add unit tests [#5668](https://github.com/paritytech/parity/pull/5668) +- Guanqun add unit tests [#5671](https://github.com/paritytech/parity/pull/5671) +- Parity-PubSub as a separate API. [#5676](https://github.com/paritytech/parity/pull/5676) +- EIP-140 REVERT opcode [#5477](https://github.com/paritytech/parity/pull/5477) +- Update CHANGELOG for 1.6.7 [#5683](https://github.com/paritytech/parity/pull/5683) +- Updated docs slightly. [#5674](https://github.com/paritytech/parity/pull/5674) +- Fix build [#5684](https://github.com/paritytech/parity/pull/5684) +- Back-references for the on-demand service [#5573](https://github.com/paritytech/parity/pull/5573) +- Dynamically adjust PIP request costs based on gathered data [#5603](https://github.com/paritytech/parity/pull/5603) +- use cargo workspace [#5601](https://github.com/paritytech/parity/pull/5601) +- Latest headers Pub-Sub [#5655](https://github.com/paritytech/parity/pull/5655) +- improved dockerfile builds [#5659](https://github.com/paritytech/parity/pull/5659) +- Adding CLI options: port shift and unsafe expose. [#5677](https://github.com/paritytech/parity/pull/5677) +- Report missing author in Aura [#5583](https://github.com/paritytech/parity/pull/5583) +- typo fix [#5669](https://github.com/paritytech/parity/pull/5669) +- Remove public middleware (temporary) [#5665](https://github.com/paritytech/parity/pull/5665) +- Remove additional polyfill [#5663](https://github.com/paritytech/parity/pull/5663) +- Importing accounts from files. [#5644](https://github.com/paritytech/parity/pull/5644) +- remove the deprecated options in rustfmt.toml [#5616](https://github.com/paritytech/parity/pull/5616) +- Update the Console dapp [#5602](https://github.com/paritytech/parity/pull/5602) +- Create an account for chain=dev [#5612](https://github.com/paritytech/parity/pull/5612) +- Use babel-runtime as opposed to babel-polyfill [#5662](https://github.com/paritytech/parity/pull/5662) +- Connection dialog timestamp info [#5554](https://github.com/paritytech/parity/pull/5554) +- use copy_from_slice instead of for loop [#5647](https://github.com/paritytech/parity/pull/5647) +- Light friendly dapps [#5634](https://github.com/paritytech/parity/pull/5634) +- Add Recover button to Accounts and warnings [#5645](https://github.com/paritytech/parity/pull/5645) +- Update eth_sign docs. [#5631](https://github.com/paritytech/parity/pull/5631) +- Proper signer Pub-Sub for pending requests. [#5594](https://github.com/paritytech/parity/pull/5594) +- Bump bigint to 1.0.5 [#5641](https://github.com/paritytech/parity/pull/5641) +- PoA warp implementation [#5488](https://github.com/paritytech/parity/pull/5488) +- Improve on-demand dispatch and add support for batch requests [#5419](https://github.com/paritytech/parity/pull/5419) +- Use default account for sending transactions [#5588](https://github.com/paritytech/parity/pull/5588) +- Add peer management to the Status tab [#5566](https://github.com/paritytech/parity/pull/5566) +- Add monotonic step transition [#5587](https://github.com/paritytech/parity/pull/5587) +- Decrypting for external accounts. [#5581](https://github.com/paritytech/parity/pull/5581) +- only enable warp sync when engine supports it [#5595](https://github.com/paritytech/parity/pull/5595) +- fix the doc of installing rust [#5586](https://github.com/paritytech/parity/pull/5586) +- Small fixes [#5584](https://github.com/paritytech/parity/pull/5584) +- SecretStore: remove session on master node [#5545](https://github.com/paritytech/parity/pull/5545) +- run-clean [#5607](https://github.com/paritytech/parity/pull/5607) +- relicense RLP to MIT/Apache2 [#5591](https://github.com/paritytech/parity/pull/5591) +- Fix eth_sign signature encoding. [#5597](https://github.com/paritytech/parity/pull/5597) +- Check pending request on Node local transactions [#5564](https://github.com/paritytech/parity/pull/5564) +- Add tooltips on ActionBar [#5562](https://github.com/paritytech/parity/pull/5562) +- Can't deploy without compiling Contract [#5593](https://github.com/paritytech/parity/pull/5593) +- Add a warning when node is syncing [#5565](https://github.com/paritytech/parity/pull/5565) +- Update registry middleware [#5585](https://github.com/paritytech/parity/pull/5585) +- Set block condition to BigNumber in MethodDecoding [#5592](https://github.com/paritytech/parity/pull/5592) +- Load the sources immediately in Contract Dev [#5575](https://github.com/paritytech/parity/pull/5575) +- Remove formal verification messages in Dev Contract [#5574](https://github.com/paritytech/parity/pull/5574) +- Fix event params decoding when no names for parameters [#5567](https://github.com/paritytech/parity/pull/5567) +- Do not convert to Dates twice [#5563](https://github.com/paritytech/parity/pull/5563) +- Fix Multisig wallet settings [#5560](https://github.com/paritytech/parity/pull/5560) +- Typo [#5547](https://github.com/paritytech/parity/pull/5547) +- Generic PubSub implementation [#5456](https://github.com/paritytech/parity/pull/5456) +- Fix CI paths. [#5570](https://github.com/paritytech/parity/pull/5570) +- reorg into blocks before minimum history [#5558](https://github.com/paritytech/parity/pull/5558) +- EIP-86 update [#5506](https://github.com/paritytech/parity/pull/5506) +- Secretstore RPCs + integration [#5439](https://github.com/paritytech/parity/pull/5439) +- Fixes Parity Bar position [#5557](https://github.com/paritytech/parity/pull/5557) +- Fixes invalid log in BadgeReg events [#5556](https://github.com/paritytech/parity/pull/5556) +- Fix issues in Contract Development view [#5555](https://github.com/paritytech/parity/pull/5555) +- Added missing methods [#5542](https://github.com/paritytech/parity/pull/5542) +- option to disable persistent txqueue [#5544](https://github.com/paritytech/parity/pull/5544) +- Bump jsonrpc [#5552](https://github.com/paritytech/parity/pull/5552) +- Retrieve block headers only for header-only info [#5480](https://github.com/paritytech/parity/pull/5480) +- add snap to CI [#5519](https://github.com/paritytech/parity/pull/5519) +- Pass additional data when reporting [#5527](https://github.com/paritytech/parity/pull/5527) +- Calculate post-constructors state root in spec at load time [#5523](https://github.com/paritytech/parity/pull/5523) +- Fix utf8 decoding [#5533](https://github.com/paritytech/parity/pull/5533) +- Add CHANGELOG.md [#5513](https://github.com/paritytech/parity/pull/5513) +- Change all occurrences of ethcore.io into parity.io [#5528](https://github.com/paritytech/parity/pull/5528) +- Memory usage optimization [#5526](https://github.com/paritytech/parity/pull/5526) +- Compose transaction RPC. [#5524](https://github.com/paritytech/parity/pull/5524) +- Support external eth_sign [#5481](https://github.com/paritytech/parity/pull/5481) +- Treat block numbers as strings, not BigNums. [#5449](https://github.com/paritytech/parity/pull/5449) +- npm cleanups [#5512](https://github.com/paritytech/parity/pull/5512) +- Export acc js [#4973](https://github.com/paritytech/parity/pull/4973) +- YARN [#5395](https://github.com/paritytech/parity/pull/5395) +- Fix linting issues [#5511](https://github.com/paritytech/parity/pull/5511) +- Chinese Translation [#5460](https://github.com/paritytech/parity/pull/5460) +- Fixing secretstore TODOs - part 2 [#5416](https://github.com/paritytech/parity/pull/5416) +- fix json format of state snapshot [#5504](https://github.com/paritytech/parity/pull/5504) +- Bump jsonrpc version [#5489](https://github.com/paritytech/parity/pull/5489) +- Groundwork for generalized warp sync [#5454](https://github.com/paritytech/parity/pull/5454) +- Add the packaging metadata to build the parity snap [#5496](https://github.com/paritytech/parity/pull/5496) +- Cancel tx JS [#4958](https://github.com/paritytech/parity/pull/4958) +- EIP-212 (bn128 curve pairing) [#5307](https://github.com/paritytech/parity/pull/5307) +- fix panickers in tree-route [#5479](https://github.com/paritytech/parity/pull/5479) +- Update links to etherscan.io [#5455](https://github.com/paritytech/parity/pull/5455) +- Refresh UI on nodeKind changes, e.g. personal -> public [#5312](https://github.com/paritytech/parity/pull/5312) +- Correct contract address for EIP-86 [#5473](https://github.com/paritytech/parity/pull/5473) +- Force two decimals for USD conversion rate [#5471](https://github.com/paritytech/parity/pull/5471) +- Refactoring of Tokens & Balances [#5372](https://github.com/paritytech/parity/pull/5372) +- Background-repeat round [#5475](https://github.com/paritytech/parity/pull/5475) +- nl i18n updated [#5461](https://github.com/paritytech/parity/pull/5461) +- Show ETH value (even 0) if ETH transfer in transaction list [#5406](https://github.com/paritytech/parity/pull/5406) +- Store the pending requests per network version [#5405](https://github.com/paritytech/parity/pull/5405) +- Use in-memory database for tests [#5451](https://github.com/paritytech/parity/pull/5451) +- WebSockets RPC server [#5425](https://github.com/paritytech/parity/pull/5425) +- Added missing docs [#5452](https://github.com/paritytech/parity/pull/5452) +- Tests and tweaks for public node middleware [#5417](https://github.com/paritytech/parity/pull/5417) +- Fix removal of hash-mismatched files. [#5440](https://github.com/paritytech/parity/pull/5440) +- parity_getBlockHeaderByNumber and LightFetch utility [#5383](https://github.com/paritytech/parity/pull/5383) +- New state tests [#5418](https://github.com/paritytech/parity/pull/5418) +- Fix buffer length for QR code gen. [#5447](https://github.com/paritytech/parity/pull/5447) +- Add raw hash signing [#5423](https://github.com/paritytech/parity/pull/5423) +- Filters and block RPCs for the light client [#5320](https://github.com/paritytech/parity/pull/5320) +- Work around mismatch for QR checksum [#5374](https://github.com/paritytech/parity/pull/5374) +- easy to use conversion from and to string for ethstore::Crypto [#5437](https://github.com/paritytech/parity/pull/5437) +- Tendermint fixes [#5415](https://github.com/paritytech/parity/pull/5415) +- Adrianbrink lightclientcache branch. [#5428](https://github.com/paritytech/parity/pull/5428) +- Add caching to HeaderChain struct [#5403](https://github.com/paritytech/parity/pull/5403) +- Add decryption to the UI (in the Signer) [#5422](https://github.com/paritytech/parity/pull/5422) +- Add CIDv0 RPC [#5414](https://github.com/paritytech/parity/pull/5414) +- Updating documentation for RPCs [#5392](https://github.com/paritytech/parity/pull/5392) +- Fixing secretstore TODOs - part 1 [#5386](https://github.com/paritytech/parity/pull/5386) +- Fixing disappearing content. [#5399](https://github.com/paritytech/parity/pull/5399) +- Snapshot chunks packed by size [#5318](https://github.com/paritytech/parity/pull/5318) +- APIs wildcards and simple arithmetic. [#5402](https://github.com/paritytech/parity/pull/5402) +- Fixing compilation without dapps. [#5410](https://github.com/paritytech/parity/pull/5410) +- Don't use port 8080 anymore [#5397](https://github.com/paritytech/parity/pull/5397) +- Quick'n'dirty CLI for the light client [#5002](https://github.com/paritytech/parity/pull/5002) +- set gas limit before proving transactions [#5401](https://github.com/paritytech/parity/pull/5401) +- Public node: perf and fixes [#5390](https://github.com/paritytech/parity/pull/5390) +- Straight download path in the readme [#5393](https://github.com/paritytech/parity/pull/5393) +- On-chain ACL checker for secretstore [#5015](https://github.com/paritytech/parity/pull/5015) +- Allow empty-encoded values from QR encoding [#5385](https://github.com/paritytech/parity/pull/5385) +- Update npm build for new inclusions [#5381](https://github.com/paritytech/parity/pull/5381) +- Fix for Ubuntu Dockerfile [#5356](https://github.com/paritytech/parity/pull/5356) +- Secretstore over network [#4974](https://github.com/paritytech/parity/pull/4974) +- Dapps and RPC server merge [#5365](https://github.com/paritytech/parity/pull/5365) +- trigger js build release [#5379](https://github.com/paritytech/parity/pull/5379) +- Update expanse json with fork at block 600000 [#5351](https://github.com/paritytech/parity/pull/5351) +- Futures-based native wrappers for contract ABIs [#5341](https://github.com/paritytech/parity/pull/5341) +- Kovan warp sync fixed [#5337](https://github.com/paritytech/parity/pull/5337) +- Aura eip155 validation transition [#5362](https://github.com/paritytech/parity/pull/5362) +- Shared wordlist for brain wallets [#5331](https://github.com/paritytech/parity/pull/5331) +- Allow signing via Qr [#4881](https://github.com/paritytech/parity/pull/4881) +- Allow entry of url or hash for DappReg meta [#5360](https://github.com/paritytech/parity/pull/5360) +- Adjust tx overlay colours [#5353](https://github.com/paritytech/parity/pull/5353) +- Add ability to disallow API subscriptions [#5366](https://github.com/paritytech/parity/pull/5366) +- EIP-213 (bn128 curve operations) [#4999](https://github.com/paritytech/parity/pull/4999) +- Fix analize output file name [#5357](https://github.com/paritytech/parity/pull/5357) +- Add default eip155 validation [#5346](https://github.com/paritytech/parity/pull/5346) +- Add new seed nodes for Classic chain [#5345](https://github.com/paritytech/parity/pull/5345) +- Shared wordlist for frontend [#5336](https://github.com/paritytech/parity/pull/5336) +- fix rpc tests [#5338](https://github.com/paritytech/parity/pull/5338) +- Public node with accounts and signing in Frontend [#5304](https://github.com/paritytech/parity/pull/5304) +- Rename Status/Status -> Status/NodeStatus [#5332](https://github.com/paritytech/parity/pull/5332) +- Updating paths to repos. [#5330](https://github.com/paritytech/parity/pull/5330) +- Separate status for canceled local transactions. [#5319](https://github.com/paritytech/parity/pull/5319) +- Cleanup the Status View [#5317](https://github.com/paritytech/parity/pull/5317) +- Update UI minimised requests [#5324](https://github.com/paritytech/parity/pull/5324) +- Order signer transactions FIFO [#5321](https://github.com/paritytech/parity/pull/5321) +- updating dependencies [#5028](https://github.com/paritytech/parity/pull/5028) +- Minimise transactions progress [#4942](https://github.com/paritytech/parity/pull/4942) +- Fix eth_sign showing as wallet account [#5309](https://github.com/paritytech/parity/pull/5309) +- Ropsten revival [#5302](https://github.com/paritytech/parity/pull/5302) +- Strict validation transitions [#4988](https://github.com/paritytech/parity/pull/4988) +- Fix default list sorting [#5303](https://github.com/paritytech/parity/pull/5303) +- Use unique owners for multisig wallets [#5298](https://github.com/paritytech/parity/pull/5298) +- Copy all existing i18n strings into zh (as-is translation aid) [#5305](https://github.com/paritytech/parity/pull/5305) +- Fix booleans in Typedinput [#5295](https://github.com/paritytech/parity/pull/5295) +- node kind RPC [#5025](https://github.com/paritytech/parity/pull/5025) +- Fix the use of MobX in playground [#5294](https://github.com/paritytech/parity/pull/5294) +- Fine grained snapshot chunking [#5019](https://github.com/paritytech/parity/pull/5019) +- Add lint:i18n to find missing & extra keys [#5290](https://github.com/paritytech/parity/pull/5290) +- Scaffolding for zh translations, including first-round by @btceth [#5289](https://github.com/paritytech/parity/pull/5289) +- JS package bumps [#5287](https://github.com/paritytech/parity/pull/5287) +- Auto-extract new i18n strings (update) [#5288](https://github.com/paritytech/parity/pull/5288) +- eip100b [#5027](https://github.com/paritytech/parity/pull/5027) +- Set earliest era in snapshot restoration [#5021](https://github.com/paritytech/parity/pull/5021) +- Avoid clogging up tmp when updater dir has bad permissions. [#5024](https://github.com/paritytech/parity/pull/5024) +- Resilient warp sync [#5018](https://github.com/paritytech/parity/pull/5018) +- Create webpack analysis files (size) [#5009](https://github.com/paritytech/parity/pull/5009) +- Dispatch an open event on drag of Parity Bar [#4987](https://github.com/paritytech/parity/pull/4987) +- Various installer and tray apps fixes [#4970](https://github.com/paritytech/parity/pull/4970) +- Export account RPC [#4967](https://github.com/paritytech/parity/pull/4967) +- Switching ValidatorSet [#4961](https://github.com/paritytech/parity/pull/4961) +- Implement PIP messages, request builder, and handlers [#4945](https://github.com/paritytech/parity/pull/4945) +- auto lint [#5003](https://github.com/paritytech/parity/pull/5003) +- Fix FireFox overflows [#5000](https://github.com/paritytech/parity/pull/5000) +- Show busy indicator, focus first field in password change [#4997](https://github.com/paritytech/parity/pull/4997) +- Consistent store naming in the Signer components [#4996](https://github.com/paritytech/parity/pull/4996) +- second (and last) part of rlp refactor [#4901](https://github.com/paritytech/parity/pull/4901) +- Double click to select account creation type [#4986](https://github.com/paritytech/parity/pull/4986) +- Fixes to the Registry dapp [#4984](https://github.com/paritytech/parity/pull/4984) +- Extend api.util [#4979](https://github.com/paritytech/parity/pull/4979) +- Updating JSON-RPC crates [#4934](https://github.com/paritytech/parity/pull/4934) +- splitting part of util into smaller crates [#4956](https://github.com/paritytech/parity/pull/4956) +- Updating syntex et al [#4983](https://github.com/paritytech/parity/pull/4983) +- EIP198 and built-in activation [#4926](https://github.com/paritytech/parity/pull/4926) +- Fix MethodDecoding for Arrays [#4977](https://github.com/paritytech/parity/pull/4977) +- Try to fix WS race condition connection [#4976](https://github.com/paritytech/parity/pull/4976) +- eth_sign where account === undefined [#4964](https://github.com/paritytech/parity/pull/4964) +- Fix references to api outside of `parity.js` [#4981](https://github.com/paritytech/parity/pull/4981) +- Fix Password Dialog form overflow [#4968](https://github.com/paritytech/parity/pull/4968) +- Changing Mutex into RwLock for transaction queue [#4951](https://github.com/paritytech/parity/pull/4951) +- Disable max seal period for external sealing [#4927](https://github.com/paritytech/parity/pull/4927) +- Attach hardware wallets already in addressbook [#4912](https://github.com/paritytech/parity/pull/4912) +- rlp serialization refactor [#4873](https://github.com/paritytech/parity/pull/4873) +- Bump nanomsg [#4965](https://github.com/paritytech/parity/pull/4965) +- Fixed multi-chunk ledger transactions on windows [#4960](https://github.com/paritytech/parity/pull/4960) +- Fix outputs in Contract Constant Queries [#4953](https://github.com/paritytech/parity/pull/4953) +- systemd: Start parity after network.target [#4952](https://github.com/paritytech/parity/pull/4952) +- Remove transaction RPC [#4949](https://github.com/paritytech/parity/pull/4949) +- Swap out ethcore.io url for parity.io [#4947](https://github.com/paritytech/parity/pull/4947) +- Don't remove confirmed requests to early. [#4933](https://github.com/paritytech/parity/pull/4933) +- Ensure sealing work enabled in miner once subscribers added [#4930](https://github.com/paritytech/parity/pull/4930) +- Add z-index to small modals as well [#4923](https://github.com/paritytech/parity/pull/4923) +- Bump nanomsg [#4946](https://github.com/paritytech/parity/pull/4946) +- Bumping multihash and libc [#4943](https://github.com/paritytech/parity/pull/4943) +- Edit ETH value, gas and gas price in Contract Deployment [#4919](https://github.com/paritytech/parity/pull/4919) +- Add ability to configure Secure API [#4922](https://github.com/paritytech/parity/pull/4922) +- Add Token image from URL [#4916](https://github.com/paritytech/parity/pull/4916) +- Use the registry fee in Token Deployment dapp [#4915](https://github.com/paritytech/parity/pull/4915) +- Add reseal max period [#4903](https://github.com/paritytech/parity/pull/4903) +- Detect rust compiler version in Parity build script, closes 4742 [#4907](https://github.com/paritytech/parity/pull/4907) +- Add Vaults logic to First Run [#4914](https://github.com/paritytech/parity/pull/4914) +- Updated gcc and rayon crates to remove outdated num_cpus dependency [#4909](https://github.com/paritytech/parity/pull/4909) +- Renaming evm binary to avoid conflicts. [#4899](https://github.com/paritytech/parity/pull/4899) +- Better error handling for traces RPC [#4849](https://github.com/paritytech/parity/pull/4849) +- Safari SectionList fix [#4895](https://github.com/paritytech/parity/pull/4895) +- Safari Dialog scrolling fix [#4893](https://github.com/paritytech/parity/pull/4893) +- Spelling :) [#4900](https://github.com/paritytech/parity/pull/4900) +- Additional kovan params [#4892](https://github.com/paritytech/parity/pull/4892) +- trigger js-precompiled build [#4898](https://github.com/paritytech/parity/pull/4898) +- Recalculate receipt roots in close_and_lock [#4884](https://github.com/paritytech/parity/pull/4884) +- Reload UI on network switch [#4864](https://github.com/paritytech/parity/pull/4864) +- Update parity-ui-precompiled with branch [#4850](https://github.com/paritytech/parity/pull/4850) +- OSX Installer is no longer experimental [#4882](https://github.com/paritytech/parity/pull/4882) +- Chain-selection from UI [#4859](https://github.com/paritytech/parity/pull/4859) +- removed redundant (and unused) FromJson trait [#4871](https://github.com/paritytech/parity/pull/4871) +- fix typos and grammar [#4880](https://github.com/paritytech/parity/pull/4880) +- Remove old experimental remote-db code [#4872](https://github.com/paritytech/parity/pull/4872) +- removed redundant FixedHash trait, fixes [#4029](https://github.com/paritytech/parity/issues/4029) [#4866](https://github.com/paritytech/parity/pull/4866) +- Reference JSON-RPC more changes-friendly [#4870](https://github.com/paritytech/parity/pull/4870) +- Better handling of Solidity compliation [#4860](https://github.com/paritytech/parity/pull/4860) +- Go through contract links in Transaction List display [#4863](https://github.com/paritytech/parity/pull/4863) +- Fix Gas Price Selector Tooltips [#4865](https://github.com/paritytech/parity/pull/4865) +- Fix auto-updater [#4867](https://github.com/paritytech/parity/pull/4867) +- Make the UI work offline [#4861](https://github.com/paritytech/parity/pull/4861) +- Subscribe to accounts info in Signer / ParityBar [#4856](https://github.com/paritytech/parity/pull/4856) +- Don't link libsnappy explicitly [#4841](https://github.com/paritytech/parity/pull/4841) +- Fix paste in Inputs [#4854](https://github.com/paritytech/parity/pull/4854) +- Extract i18n from shared UI components [#4834](https://github.com/paritytech/parity/pull/4834) +- Fix paste in Inputs [#4844](https://github.com/paritytech/parity/pull/4844) +- Pull contract deployment title from available steps [#4848](https://github.com/paritytech/parity/pull/4848) +- Supress USB error message [#4839](https://github.com/paritytech/parity/pull/4839) +- Fix getTransactionCount in --geth mode [#4837](https://github.com/paritytech/parity/pull/4837) +- CI: test coverage (for core and js) [#4832](https://github.com/paritytech/parity/pull/4832) +- Lowering threshold for transactions above gas limit [#4831](https://github.com/paritytech/parity/pull/4831) +- Fix TxViewer when no `to` (contract deployment) [#4847](https://github.com/paritytech/parity/pull/4847) +- Fix method decoding [#4845](https://github.com/paritytech/parity/pull/4845) +- Add React Hot Reload to dapps + TokenDeploy fix [#4846](https://github.com/paritytech/parity/pull/4846) +- Dapps show multiple times in some cases [#4843](https://github.com/paritytech/parity/pull/4843) +- Fixes to the Registry dapp [#4838](https://github.com/paritytech/parity/pull/4838) +- Show token icons on list summary pages [#4826](https://github.com/paritytech/parity/pull/4826) +- Calibrate step before rejection [#4800](https://github.com/paritytech/parity/pull/4800) +- Add replay protection [#4808](https://github.com/paritytech/parity/pull/4808) +- Better icon on windows [#4804](https://github.com/paritytech/parity/pull/4804) +- Better logic for contract deployments detection [#4821](https://github.com/paritytech/parity/pull/4821) +- Fix wrong default values for contract queries inputs [#4819](https://github.com/paritytech/parity/pull/4819) +- Adjust selection colours/display [#4811](https://github.com/paritytech/parity/pull/4811) +- Update the Wallet Library Registry key [#4817](https://github.com/paritytech/parity/pull/4817) +- Update Wallet to new Wallet Code [#4805](https://github.com/paritytech/parity/pull/4805) diff --git a/docs/CHANGELOG-1.8.md b/docs/CHANGELOG-1.8.md new file mode 100644 index 0000000000000000000000000000000000000000..67d6d0a89b821208de18fab62537cace382b0c62 --- /dev/null +++ b/docs/CHANGELOG-1.8.md @@ -0,0 +1,578 @@ +Note: Parity 1.8 reached End-of-Life on 2018-03-22 (EOL). + +## Parity [v1.8.11](https://github.com/paritytech/parity/releases/tag/v1.8.11) (2018-03-01) + +Parity 1.8.11 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Bump stable to 1.8.11 ([#8010](https://github.com/paritytech/parity/pull/8010)) +- Stable Backports ([#8008](https://github.com/paritytech/parity/pull/8008)) + - Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977)) + - Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965)) + - Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953)) + - Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952)) + +## Parity [v1.8.10](https://github.com/paritytech/parity/releases/tag/v1.8.10) (2018-02-20) + +Parity 1.8.10 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Bump react-qr-reader ([#7941)](https://github.com/paritytech/parity/pull/7941)) + - Bump react-qr-reader + - Explicit add webrtc-adapter, non-napa qrcode-generator +- Fix feature=final ([#7914)](https://github.com/paritytech/parity/pull/7914)) +- Fix snap build stable ([#7897)](https://github.com/paritytech/parity/pull/7897)) +- Backport core PRs to stable ([#7892)](https://github.com/paritytech/parity/pull/7892)) + - Update back-references more aggressively after answering from cache ([#7578)](https://github.com/paritytech/parity/pull/7578)) + - Store updater metadata in a single place ([#7832)](https://github.com/paritytech/parity/pull/7832)) + - Flush keyfiles. Resolves [#7632](https://github.com/paritytech/parity/issues/7632) ([#7868)](https://github.com/paritytech/parity/pull/7868)) + - Fix wallet import ([#7873)](https://github.com/paritytech/parity/pull/7873)) +- Backport Master CI PRs to Stable ([#7889)](https://github.com/paritytech/parity/pull/7889)) + - Add binary identifiers and sha256sum to builds ([#7830)](https://github.com/paritytech/parity/pull/7830)) + - Fix checksums and auto-update push ([#7846)](https://github.com/paritytech/parity/pull/7846)) + - Update gitlab-build.sh ([#7855)](https://github.com/paritytech/parity/pull/7855)) + - Fix installer binary names for macos and windows ([#7881)](https://github.com/paritytech/parity/pull/7881)) + - Update gitlab-test.sh ([#7883)](https://github.com/paritytech/parity/pull/7883)) + - Fix snapcraft nightly ([#7884)](https://github.com/paritytech/parity/pull/7884)) + - Bump stable to 1.8.10 + - Make track stable + +## Parity [v1.8.9](https://github.com/paritytech/parity/releases/tag/v1.8.9) (2018-02-02) + +Parity 1.8.9 is a bug-fix release to improve performance and stability. It restores ERC-20 token balances and adds additional bootnodes for the Ropsten test network. + +The full list of included changes: + +- Update gitlab-build.sh +- Backports stable ([#7779](https://github.com/paritytech/parity/pull/7779)) + - Bump stable to 1.8.9 + - Update ropsten.json ([#7776](https://github.com/paritytech/parity/pull/7776)) +- Fix tokenAddress reference ([#7777](https://github.com/paritytech/parity/pull/7777)) +- Snapcraft push stable + +## Parity [v1.8.8](https://github.com/paritytech/parity/releases/tag/v1.8.8) (2018-02-01) + +Parity 1.8.8 is a bug-fix release to improve performance and stability. It restores ERC-20 token balances, improves networking, fixes database corruptions on client shutdown, and fixes issues with the `--password` command-line flag. Happy syncing! + +The full list of included changes: + +- Gitlab stable ([#7768](https://github.com/paritytech/parity/pull/7768)) + - Fix snapcraft build for stable + - Initial support push snap packages to snapcraft.io + - Edge-devel +- Snapcraft push ans fix build ([#7767](https://github.com/paritytech/parity/pull/7767)) + - Fix snapcraft build for stable + - Initial support push snap packages to snapcraft.io + - Edge-devel +- Remove snapcraft.yml from scripts +- Resolve conflicts +- Token filter balances (throttle) ([#7755](https://github.com/paritytech/parity/pull/7755)) +- Fix snapcraft build (stable) ([#7763](https://github.com/paritytech/parity/pull/7763)) + - Fix snapcraft build for stable + - Fix snapcraft build (stable) +- [Stable] Backports ([#7758](https://github.com/paritytech/parity/pull/7758)) + - Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716)) + - Filter-out nodes.json + - Network: sort node table nodes by failure ratio + - Network: fix node table tests + - Network: fit node failure percentage into buckets of 5% + - Network: consider number of attempts in sorting of node table + - Network: fix node table grumbles + - Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695)) + - Parity: wait for client to drop on shutdown + - Parity: fix grumbles in shutdown wait + - Parity: increase shutdown timeouts + - Wrap --help output to 120 characters ([#7626](https://github.com/paritytech/parity/pull/7626)) + - Update Clap dependency and remove workarounds + - WIP + - Remove line breaks in help messages for now + - Multiple values can only be separated by commas (closes [#7428](https://github.com/paritytech/parity/issues/7428)) + - Grumbles; refactor repeating code; add constant + - Use a single Wrapper rather than allocate a new one for each call + - Wrap --help to 120 characters rather than 100 characters +- Use explicit branch name in push ([#7757](https://github.com/paritytech/parity/pull/7757)) +- Bump stable to 1.8.8 ([#7752](https://github.com/paritytech/parity/pull/7752)) +- Fix js-release in stable ([#7682](https://github.com/paritytech/parity/pull/7682)) +- Update Info.plist +- Fix conditions in gitlab-test ([#7675](https://github.com/paritytech/parity/pull/7675)) +- Remove cargo cache + +## Parity [v1.8.7](https://github.com/paritytech/parity/releases/tag/v1.8.7) (2018-01-24) + +Parity 1.8.7 is the first stable release of the 1.8 channel. It includes various bug and stability fixes. Users on Kovan or other Aura-based networks are advised to upgrade as this release fixes an issue introduced with 1.8.6 and 1.7.12 that causes Proof-of-Authority nodes to stop synchronizing the chain. + +The full list of included changes: + +- Bump stable version ([#7665](https://github.com/paritytech/parity/pull/7665)) + - Bump stable to 1.8.7 +- Backports to stable ([#7661](https://github.com/paritytech/parity/pull/7661)) + - Fixed delegatecall's from/to ([#7568](https://github.com/paritytech/parity/pull/7568)) + - Fixed delegatecall's from/to, closes [#7166](https://github.com/paritytech/parity/issues/7166) + - Added tests for delegatecall traces, [#7167](https://github.com/paritytech/parity/issues/7167) + - Fix Temporarily Invalid blocks handling ([#7613](https://github.com/paritytech/parity/pull/7613)) + - Handle temporarily invalid blocks in sync. + - Fix tests. + - Improve handling of RocksDB corruption ([#7630](https://github.com/paritytech/parity/pull/7630)) + - Kvdb-rocksdb: update rust-rocksdb version + - Kvdb-rocksdb: mark corruptions and attempt repair on db open + - Kvdb-rocksdb: better corruption detection on open + - Kvdb-rocksdb: add corruption_file_name const + - Kvdb-rocksdb: rename mark_corruption to check_for_corruption +- Add docker build for stable and cargo cache ([#7672](https://github.com/paritytech/parity/pull/7672)) +- Fix snapcraft build for stable ([#7669](https://github.com/paritytech/parity/pull/7669)) +- Update .gitlab-ci.yml ([#7599](https://github.com/paritytech/parity/pull/7599)) + - Fix cache:key +- Make 1.8 stable ([#7532](https://github.com/paritytech/parity/pull/7532)) + - Bump 1.8 to stable + - Make js-precompiled stable + +## Parity [v1.8.6](https://github.com/paritytech/parity/releases/tag/v1.8.6) (2018-01-10) + +Parity 1.8.6 fixes a critical issue with the database eventually filling up user's disks. Upgrading is highly recommended as it will significantly improve your user experience. As a bonus, this release should enable users with slower hard-disk drives to catch up with the latest block again. Also, warp-sync performance was significantly improved. Please note, that the initial database compaction after upgrading might temporarily reduce the node's performance. + +In addition to our gas price histogram, this version now allows you to dynamically set the default gas price as percentile from the last 100 blocks (it defaults to median: `50`). + + --gas-price-percentile=[PCT] Set PCT percentile gas price value from + last 100 blocks as default gas price + when sending transactions. + +Last but not least, this release also fixes consensus issues with the Expanse chain enabling Byzantium. If you run Parity configured for Expanse, you might have to resync your chain after the upgrade. + +The full list of included changes: + +- RocksDB fix ([#7508](https://github.com/paritytech/parity/pull/7508)) + - Kvdb: update rust-rocksdb version +- Backports to beta ([#7434](https://github.com/paritytech/parity/pull/7434)) + - Wait for future blocks in AuRa ([#7368](https://github.com/paritytech/parity/pull/7368)) + - Mark future blocks as temporarily invalid. + - Don't check max. + - Fix tracing failed calls. ([#7412](https://github.com/paritytech/parity/pull/7412)) + - Problem: sending any Whisper message fails ([#7421](https://github.com/paritytech/parity/pull/7421)) + - Strict config parsing ([#7433](https://github.com/paritytech/parity/pull/7433)) + - Problem: AuRa's unsafeties around step duration ([#7282](https://github.com/paritytech/parity/pull/7282)) + - Remove expanse chain ([#7437](https://github.com/paritytech/parity/pull/7437)) + - Remove expanse from available chains + - Remove all EXP references from old wallet + - Fix tests + - Remove expanse chain ([#7437](https://github.com/paritytech/parity/pull/7437)) + - Expanse Byzantium update w/ correct metropolis difficulty increment divisor ([#7463](https://github.com/paritytech/parity/pull/7463)) + - Byzantium Update for Expanse + - Expip2 changes - update duration limit + - Fix missing EXPIP-2 fields + - Format numbers as hex + - Fix compilation errors + - Group expanse chain spec fields together + - Set metropolisDifficultyIncrementDivisor for Expanse + - Revert #7437 + - Add Expanse block 900_000 hash checkpoint + - Advance AuRa step as far as we can and prevent invalid blocks. ([#7451](https://github.com/paritytech/parity/pull/7451)) + - Advance AuRa step as far as we can. + - Wait for future blocks. + - Fixed panic when io is not available for export block, closes [#7486](https://github.com/paritytech/parity/issues/7486) ([#7495](https://github.com/paritytech/parity/pull/7495)) + - Update Parity Mainnet Bootnodes ([#7476](https://github.com/paritytech/parity/pull/7476)) + - Replace the Azure HDD bootnodes with the new ones :) + - Expose default gas price percentile configuration in CLI ([#7497](https://github.com/paritytech/parity/pull/7497)) + - Expose gas price percentile. + - Fix light eth_call. + - Fix gas_price in light client +- Backport nonces reservations ([#7439](https://github.com/paritytech/parity/pull/7439)) + - Reserve nonces for signing ([#6834](https://github.com/paritytech/parity/pull/6834)) + - Nonce future - reserve and dispatch + - Single thread nonce tests + - Track status of reserved nonces. + - Initialization of nonce reservations. + - Prospective Signer + - Fix cli tests. + - Fix nonce reservation ([#7025](https://github.com/paritytech/parity/pull/7025)) + - Use nonce reservation per address + - Create hashmap in RPC Apis + - Garbage collect hashmap entries. + - HashMap::retain +- Bump beta to 1.8.6 ([#7442](https://github.com/paritytech/parity/pull/7442)) +- KVDB backports ([#7438](https://github.com/paritytech/parity/pull/7438)) + - Separated kvdb into 3 crates: kvdb, kvdb-memorydb && kvdb-rocksdb ([#6720](https://github.com/paritytech/parity/pull/6720)) + - Separated kvdb into 3 crates: kvdb, kvdb-memorydb && kvdb-rocksdb, ref [#6693](https://github.com/paritytech/parity/issues/6693) + - Fixed kvdb-memorydb && kvdb-rocksdb authors + - Fixed wrong kvdb import in json_tests + - Util tests use kvdb_memorydb instead of kvdb_rocksdb, closes [#6739](https://github.com/paritytech/parity/issues/6739) + - Renamed kvdb_memorydb::in_memory -> kvdb_memorydb::create + - Docs + - Removed redundant mut from kvdb-memorydb + - Upgrade to RocksDB 5.8.8 and tune settings to reduce space amplification ([#7348](https://github.com/paritytech/parity/pull/7348)) + - kvdb-rocksdb: update to RocksDB 5.8.8 + - kvdb-rocksdb: tune RocksDB options + - Switch to level-style compaction + - Increase default block size (16K), and use bigger blocks for HDDs (64K) + - Increase default file size base (64MB SSDs, 256MB HDDs) + - Create a single block cache shared across all column families + - Tune compaction settings using RocksDB helper functions, taking into account + - Memory budget spread across all columns + - Configure backgrounds jobs based on the number of CPUs + - Set some default recommended settings + - ethcore: remove unused config blockchain.db_cache_size + - parity: increase default value for db_cache_size + - kvdb-rocksdb: enable compression on all levels + - kvdb-rocksdb: set global db_write_bufer_size + - kvdb-rocksdb: reduce db_write_bufer_size to force earlier flushing + - kvdb-rocksdb: use master branch for rust-rocksdb dependency + +## Parity [v1.8.5](https://github.com/paritytech/parity/releases/tag/v1.8.5) (2017-12-29) + +Parity 1.8.5 changes the default behavior of JSON-RPC CORS setting, detects same-key engine signers in Aura networks, and updates bootnodes for the Kovan and Foundation networks. + +Note: The default value of `--jsonrpc-cors` option has been altered to disallow (potentially malicious) websites from accessing the low-sensitivity RPCs (viewing exposed accounts, proposing transactions for signing). Currently domains need to be whitelisted manually. To bring back previous behaviour run with `--jsonrpc-cors all` or `--jsonrpc-cors http://example.com`. + +The full list of included changes: + +- Beta Backports ([#7297](https://github.com/paritytech/parity/pull/7297)) + - New warp enodes ([#7287](https://github.com/paritytech/parity/pull/7287)) + - New warp enodes + - Added one more warp enode; replaced spaces with tabs + - Bump beta to 1.8.5 + - Update kovan boot nodes + - Detect different node, same-key signing in aura ([#7245](https://github.com/paritytech/parity/pull/7245)) + - Detect different node, same-key signing in aura + - Reduce scope of warning + - Fix Cargo.lock + - Updating mainnet bootnodes. + - Update bootnodes ([#7363](https://github.com/paritytech/parity/pull/7363)) + - Updating mainnet bootnodes. + - Add additional parity-beta bootnodes. + - Restore old parity bootnodes and update foudation bootnodes +- Fix default CORS. ([#7388](https://github.com/paritytech/parity/pull/7388)) + +## 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. + +The full list of included changes: + +- Backports to beta ([#7043](https://github.com/paritytech/parity/pull/7043)) + - pwasm-std update ([#7018](https://github.com/paritytech/parity/pull/7018)) + - Version 1.8.3 + - Make CLI arguments parsing more backwards compatible ([#7004](https://github.com/paritytech/parity/pull/7004)) + - Skip nonce check for gas estimation ([#6997](https://github.com/paritytech/parity/pull/6997)) + - Events in WASM runtime ([#6967](https://github.com/paritytech/parity/pull/6967)) + - Return decoded seal fields. ([#6932](https://github.com/paritytech/parity/pull/6932)) + - Fix serialization of status in transaction receipts. ([#6926](https://github.com/paritytech/parity/pull/6926)) + - Windows fixes ([#6921](https://github.com/paritytech/parity/pull/6921)) +- Disallow built-in multi-sig deploy (only watch) ([#7014](https://github.com/paritytech/parity/pull/7014)) +- Add hint in ActionParams for splitting code/data ([#6968](https://github.com/paritytech/parity/pull/6968)) + - Action params and embedded params handling + - Fix name-spaces + +## Parity [v1.8.2](https://github.com/paritytech/parity/releases/tag/v1.8.2) (2017-10-26) + +Parity 1.8.2 fixes an important potential consensus issue and a few additional minor issues: + +- `blockNumber` transaction field is now returned correctly in RPC calls. +- Possible crash when `--force-sealing` option is used. + +The full list of included changes: + +- Beta Backports ([#6891](https://github.com/paritytech/parity/pull/6891)) + - Bump to v1.8.2 + - Refactor static context check in CREATE. ([#6886](https://github.com/paritytech/parity/pull/6886)) + - Refactor static context check in CREATE. + - Fix wasm. + - Fix serialization of non-localized transactions ([#6868](https://github.com/paritytech/parity/pull/6868)) + - Fix serialization of non-localized transactions. + - Return proper SignedTransactions representation. + - Allow force sealing and reseal=0 for non-dev chains. ([#6878](https://github.com/paritytech/parity/pull/6878)) + +## Parity [v1.8.1](https://github.com/paritytech/parity/releases/tag/v1.8.1) (2017-10-20) + +Parity 1.8.1 fixes several bugs with token balances, tweaks snapshot-sync, improves the performance of nodes with huge amounts of accounts and changes the Trezor account derivation path. + +**Important Note**: The **Trezor** account derivation path was changed in this release ([#6815](https://github.com/paritytech/parity/pull/6815)) to always use the first account (`m/44'/60'/0'/0/0` instead of `m/44'/60'/0'/0`). This way we enable compatibility with other Ethereum wallets supporting Trezor hardware-wallets. However, **action is required** before upgrading, if you have funds on your Parity Trezor wallet. If you already upgraded to 1.8.1, please downgrade to 1.8.0 first to recover the funds with the following steps: + +1. Make sure you have 1.8.0-beta and your Trezor plugged in. +2. Create a new standard Parity account. Make sure you have backups of the recovery phrase and don't forget the password. +3. Move your funds from the Trezor hardware-wallet account to the freshly generated Parity account. +4. Upgrade to 1.8.1-beta and plug in your Trezor. +5. Move your funds from your Parity account to the new Trezor account. +6. Keep using Parity as normal. + +If you don't want to downgrade or move your funds off your Trezor-device, you can also use the official Trezor application or other wallets allowing to select the derivation path to access the funds. + +The full list of included changes: + +- Add ECIP1017 to Morden config ([#6845](https://github.com/paritytech/parity/pull/6845)) +- Ethstore optimizations ([#6844](https://github.com/paritytech/parity/pull/6844)) +- Bumb to v1.8.1 ([#6843](https://github.com/paritytech/parity/pull/6843)) +- Backport ([#6837](https://github.com/paritytech/parity/pull/6837)) + - Tweaked snapshot sync threshold ([#6829](https://github.com/paritytech/parity/pull/6829)) + - Change keypath derivation logic ([#6815](https://github.com/paritytech/parity/pull/6815)) +- Refresh cached tokens based on registry info & random balances ([#6824](https://github.com/paritytech/parity/pull/6824)) + - Refresh cached tokens based on registry info & random balances ([#6818](https://github.com/paritytech/parity/pull/6818)) + - Don't display errored token images + +## Parity [v1.8.0](https://github.com/paritytech/parity/releases/tag/v1.8.0) (2017-10-15) + +We are happy to announce our newest Parity 1.8 release. Among others, it enables the following features: + +- Full Whisper v6 integration +- Trezor hardware-wallet support +- WASM contract support +- PICOPS KYC-certified accounts and vouching for community-dapps +- Light client compatibility for Proof-of-Authority networks +- Transaction permissioning and permissioned p2p-connections +- Full Byzantium-fork compatibility +- Full Musicoin MCIP-3 UBI-fork compatibility + +Further, users upgrading from 1.7 should acknowledge the following changes: + +- The chain-engine was further abstracted and chain-specs need to be upgraded. [#6134](https://github.com/paritytech/parity/pull/6134) [#6591](https://github.com/paritytech/parity/pull/6591) +- `network_id` was renamed to `chain_id` where applicable. [#6345](https://github.com/paritytech/parity/pull/6345) +- `trace_filter` RPC method now comes with pagination. [#6312](https://github.com/paritytech/parity/pull/6312) +- Added tracing of rewards on closing blocks. [#6194](https://github.com/paritytech/parity/pull/6194) + +The full list of included changes: + +- Updated ethabi to fix auto-update ([#6771](https://github.com/paritytech/parity/pull/6771)) +- Fixed kovan chain validation ([#6760](https://github.com/paritytech/parity/pull/6760)) + - Fixed kovan chain validation + - Fork detection + - Fixed typo +- Bumped fork block number for auto-update ([#6755](https://github.com/paritytech/parity/pull/6755)) +- CLI: Reject invalid argument values rather than ignore them ([#6747](https://github.com/paritytech/parity/pull/6747)) +- Fixed modexp gas calculation overflow ([#6745](https://github.com/paritytech/parity/pull/6745)) +- Backport beta - Fixes Badges ([#6732](https://github.com/paritytech/parity/pull/6732)) + - Fix badges not showing up ([#6730](https://github.com/paritytech/parity/pull/6730)) + - Always fetch meta data first [badges] +- Bump to v1.8.0 in beta +- Fix tokens and badges ([#6725](https://github.com/paritytech/parity/pull/6725)) + - Update new token fetching + - Working Certifications Monitoring + - Update on Certification / Revoke + - Fix none-fetched tokens value display + - Fix tests +- Check vouch status on appId in addition to contentHash ([#6719](https://github.com/paritytech/parity/pull/6719)) + - Check vouch status on appId in addition to contentHash + - Simplify var expansion +- Prevent going offline when restoring or taking a snapshot [#6694](https://github.com/paritytech/parity/pull/6694) +- Graceful exit when invalid CLI flags are passed (#6485) [#6711](https://github.com/paritytech/parity/pull/6711) +- Fixed RETURNDATA out of bounds check [#6718](https://github.com/paritytech/parity/pull/6718) +- Display vouched overlay on dapps [#6710](https://github.com/paritytech/parity/pull/6710) +- Fix gas estimation if `from` is not provided. [#6714](https://github.com/paritytech/parity/pull/6714) +- Emulate signer pubsub on public node [#6708](https://github.com/paritytech/parity/pull/6708) +- Removes dependency on rustc_serialize (#5988) [#6705](https://github.com/paritytech/parity/pull/6705) +- Fixed potential modexp exp len overflow [#6686](https://github.com/paritytech/parity/pull/6686) +- Fix asciiToHex for characters < 0x10 [#6702](https://github.com/paritytech/parity/pull/6702) +- Fix address input [#6701](https://github.com/paritytech/parity/pull/6701) +- Allow signer signing display of markdown [#6707](https://github.com/paritytech/parity/pull/6707) +- Fixed build warnings [#6664](https://github.com/paritytech/parity/pull/6664) +- Fix warp sync blockers detection [#6691](https://github.com/paritytech/parity/pull/6691) +- Difficulty tests [#6687](https://github.com/paritytech/parity/pull/6687) +- Separate migrations from util [#6690](https://github.com/paritytech/parity/pull/6690) +- Changelog for 1.7.3 [#6678](https://github.com/paritytech/parity/pull/6678) +- WASM gas schedule [#6638](https://github.com/paritytech/parity/pull/6638) +- Fix wallet view [#6597](https://github.com/paritytech/parity/pull/6597) +- Byzantium fork block number [#6660](https://github.com/paritytech/parity/pull/6660) +- Fixed RETURNDATA size for built-ins [#6652](https://github.com/paritytech/parity/pull/6652) +- Light Client: fetch transactions/receipts by transaction hash [#6641](https://github.com/paritytech/parity/pull/6641) +- Add Musicoin and MCIP-3 UBI hardfork. [#6621](https://github.com/paritytech/parity/pull/6621) +- fix 1.8 backcompat: revert to manual encoding/decoding of transition proofs [#6665](https://github.com/paritytech/parity/pull/6665) +- Tweaked block download timeouts (#6595) [#6655](https://github.com/paritytech/parity/pull/6655) +- Renamed RPC receipt statusCode field to status [#6650](https://github.com/paritytech/parity/pull/6650) +- SecretStore: session level timeout [#6631](https://github.com/paritytech/parity/pull/6631) +- SecretStore: ShareRemove of 'isolated' nodes [#6630](https://github.com/paritytech/parity/pull/6630) +- SecretStore: exclusive sessions [#6624](https://github.com/paritytech/parity/pull/6624) +- Fixed network protocol version negotiation [#6649](https://github.com/paritytech/parity/pull/6649) +- Updated systemd files for linux (Resolves #6592) [#6598](https://github.com/paritytech/parity/pull/6598) +- move additional_params to machine, fixes registry on non-ethash chains [#6646](https://github.com/paritytech/parity/pull/6646) +- Fix Token Transfer in transaction list [#6589](https://github.com/paritytech/parity/pull/6589) +- Update jsonrpc dependencies and rewrite dapps to futures. [#6522](https://github.com/paritytech/parity/pull/6522) +- Balance queries implemented in WASM runtime [#6639](https://github.com/paritytech/parity/pull/6639) +- Don't expose port 80 for parity anymore [#6633](https://github.com/paritytech/parity/pull/6633) +- WASM Runtime refactoring [#6596](https://github.com/paritytech/parity/pull/6596) +- Fix compilation [#6625](https://github.com/paritytech/parity/pull/6625) +- Downgrade futures to suppress warnings. [#6620](https://github.com/paritytech/parity/pull/6620) +- Add pagination for trace_filter rpc method [#6312](https://github.com/paritytech/parity/pull/6312) +- Disallow pasting recovery phrases on first run [#6602](https://github.com/paritytech/parity/pull/6602) +- fix typo: Unkown => Unknown [#6559](https://github.com/paritytech/parity/pull/6559) +- SecretStore: administrative sessions prototypes [#6605](https://github.com/paritytech/parity/pull/6605) +- fix parity.io link 404 [#6617](https://github.com/paritytech/parity/pull/6617) +- SecretStore: add node to existing session poc + discussion [#6480](https://github.com/paritytech/parity/pull/6480) +- Generalize engine trait [#6591](https://github.com/paritytech/parity/pull/6591) +- Add RPC eth_chainId for querying the current blockchain chain ID [#6329](https://github.com/paritytech/parity/pull/6329) +- Debounce sync status. [#6572](https://github.com/paritytech/parity/pull/6572) +- [Public Node] Disable tx scheduling and hardware wallets [#6588](https://github.com/paritytech/parity/pull/6588) +- Use memmap for dag cache [#6193](https://github.com/paritytech/parity/pull/6193) +- Rename Requests to Batch [#6582](https://github.com/paritytech/parity/pull/6582) +- Use host as ws/dapps url if present. [#6566](https://github.com/paritytech/parity/pull/6566) +- Sync progress and error handling fixes [#6560](https://github.com/paritytech/parity/pull/6560) +- Fixed receipt serialization and RPC [#6555](https://github.com/paritytech/parity/pull/6555) +- Fix number of confirmations for transaction [#6552](https://github.com/paritytech/parity/pull/6552) +- Fix #6540 [#6556](https://github.com/paritytech/parity/pull/6556) +- Fix failing hardware tests [#6553](https://github.com/paritytech/parity/pull/6553) +- Required validators >= num owners in Wallet Creation [#6551](https://github.com/paritytech/parity/pull/6551) +- Random cleanups / improvements to a state [#6472](https://github.com/paritytech/parity/pull/6472) +- Changelog for 1.7.2 [#6363](https://github.com/paritytech/parity/pull/6363) +- Ropsten fork [#6533](https://github.com/paritytech/parity/pull/6533) +- Byzantium updates [#5855](https://github.com/paritytech/parity/pull/5855) +- Fix extension detection [#6452](https://github.com/paritytech/parity/pull/6452) +- Downgrade futures to supress warnings [#6521](https://github.com/paritytech/parity/pull/6521) +- separate trie from util and make its dependencies into libs [#6478](https://github.com/paritytech/parity/pull/6478) +- WASM sha3 test [#6512](https://github.com/paritytech/parity/pull/6512) +- Fix broken JavaScript tests [#6498](https://github.com/paritytech/parity/pull/6498) +- SecretStore: use random key to encrypt channel + session-level nonce [#6470](https://github.com/paritytech/parity/pull/6470) +- Trezor Support [#6403](https://github.com/paritytech/parity/pull/6403) +- Fix compiler warning [#6491](https://github.com/paritytech/parity/pull/6491) +- Fix typo [#6505](https://github.com/paritytech/parity/pull/6505) +- WASM: added math overflow test [#6474](https://github.com/paritytech/parity/pull/6474) +- Fix slow balances [#6471](https://github.com/paritytech/parity/pull/6471) +- WASM runtime update [#6467](https://github.com/paritytech/parity/pull/6467) +- Compatibility with whisper v6 [#6179](https://github.com/paritytech/parity/pull/6179) +- light-poa round 2: allow optional casting of engine client to full client [#6468](https://github.com/paritytech/parity/pull/6468) +- Moved attributes under docs [#6475](https://github.com/paritytech/parity/pull/6475) +- cleanup util dependencies [#6464](https://github.com/paritytech/parity/pull/6464) +- removed redundant earlymergedb trace guards [#6463](https://github.com/paritytech/parity/pull/6463) +- UtilError utilizes error_chain! [#6461](https://github.com/paritytech/parity/pull/6461) +- fixed master [#6465](https://github.com/paritytech/parity/pull/6465) +- Refactor and port CLI from Docopt to Clap (#2066) [#6356](https://github.com/paritytech/parity/pull/6356) +- Add language selector in production [#6317](https://github.com/paritytech/parity/pull/6317) +- eth_call returns output of contract creations [#6420](https://github.com/paritytech/parity/pull/6420) +- Refactor: Don't reexport bigint from util [#6459](https://github.com/paritytech/parity/pull/6459) +- Transaction permissioning [#6441](https://github.com/paritytech/parity/pull/6441) +- Added missing SecretStore tests - signing session [#6411](https://github.com/paritytech/parity/pull/6411) +- Light-client sync for contract-based PoA [#6370](https://github.com/paritytech/parity/pull/6370) +- triehash is separated from util [#6428](https://github.com/paritytech/parity/pull/6428) +- remove re-export of parking_lot in util [#6435](https://github.com/paritytech/parity/pull/6435) +- fix modexp bug: return 0 if base is zero [#6424](https://github.com/paritytech/parity/pull/6424) +- separate semantic_version from util [#6438](https://github.com/paritytech/parity/pull/6438) +- move timer.rs to ethcore [#6437](https://github.com/paritytech/parity/pull/6437) +- remove re-export of ansi_term in util [#6433](https://github.com/paritytech/parity/pull/6433) +- Pub sub blocks [#6139](https://github.com/paritytech/parity/pull/6139) +- replace trait Hashable with fn keccak [#6423](https://github.com/paritytech/parity/pull/6423) +- add more hash backward compatibility test for bloom [#6425](https://github.com/paritytech/parity/pull/6425) +- remove the redundant hasher in Bloom [#6404](https://github.com/paritytech/parity/pull/6404) +- Remove re-export of HeapSizeOf in util (part of #6418) [#6419](https://github.com/paritytech/parity/pull/6419) +- Rewards on closing blocks [#6194](https://github.com/paritytech/parity/pull/6194) +- ensure balances of constructor accounts are kept [#6413](https://github.com/paritytech/parity/pull/6413) +- removed recursion from triedbmut::lookup [#6394](https://github.com/paritytech/parity/pull/6394) +- do not activate genesis epoch in immediate transition validator contract [#6349](https://github.com/paritytech/parity/pull/6349) +- Use git for the snap version [#6271](https://github.com/paritytech/parity/pull/6271) +- Permissioned p2p connections [#6359](https://github.com/paritytech/parity/pull/6359) +- Don't accept transactions above block gas limit. [#6408](https://github.com/paritytech/parity/pull/6408) +- Fix memory tracing. [#6399](https://github.com/paritytech/parity/pull/6399) +- earlydb optimizations [#6393](https://github.com/paritytech/parity/pull/6393) +- Optimized PlainHasher hashing. Trie insertions are >15 faster [#6321](https://github.com/paritytech/parity/pull/6321) +- Trie optimizations [#6389](https://github.com/paritytech/parity/pull/6389) +- small optimizations for triehash [#6392](https://github.com/paritytech/parity/pull/6392) +- Bring back IPFS tests. [#6398](https://github.com/paritytech/parity/pull/6398) +- Running state test using parity-evm [#6355](https://github.com/paritytech/parity/pull/6355) +- Wasm math tests extended [#6354](https://github.com/paritytech/parity/pull/6354) +- Expose health status over RPC [#6274](https://github.com/paritytech/parity/pull/6274) +- fix bloom bitvecjournal storage allocation [#6390](https://github.com/paritytech/parity/pull/6390) +- fixed pending block panic [#6391](https://github.com/paritytech/parity/pull/6391) +- Infoline less opaque for UI/visibility [#6364](https://github.com/paritytech/parity/pull/6364) +- Fix eth_call. [#6365](https://github.com/paritytech/parity/pull/6365) +- updated bigint [#6341](https://github.com/paritytech/parity/pull/6341) +- Optimize trie iter by avoiding redundant copying [#6347](https://github.com/paritytech/parity/pull/6347) +- Only keep a single rocksdb debug log file [#6346](https://github.com/paritytech/parity/pull/6346) +- Tweaked snapshot params [#6344](https://github.com/paritytech/parity/pull/6344) +- Rename network_id to chain_id where applicable. [#6345](https://github.com/paritytech/parity/pull/6345) +- Itertools are no longer reexported from util, optimized triedb iter [#6322](https://github.com/paritytech/parity/pull/6322) +- Better check the created accounts before showing Startup Wizard [#6331](https://github.com/paritytech/parity/pull/6331) +- Better error messages for invalid types in RPC [#6311](https://github.com/paritytech/parity/pull/6311) +- fix panic in parity-evm json tracer [#6338](https://github.com/paritytech/parity/pull/6338) +- WASM math test [#6305](https://github.com/paritytech/parity/pull/6305) +- rlp_derive [#6125](https://github.com/paritytech/parity/pull/6125) +- Fix --chain parsing in parity-evm. [#6314](https://github.com/paritytech/parity/pull/6314) +- Unexpose RPC methods on :8180 [#6295](https://github.com/paritytech/parity/pull/6295) +- Ignore errors from dappsUrl when starting UI. [#6296](https://github.com/paritytech/parity/pull/6296) +- updated bigint with optimized mul and from_big_indian [#6323](https://github.com/paritytech/parity/pull/6323) +- SecretStore: bunch of fixes and improvements [#6168](https://github.com/paritytech/parity/pull/6168) +- Master requires rust 1.19 [#6308](https://github.com/paritytech/parity/pull/6308) +- Add more descriptive error when signing/decrypting using hw wallet. [#6302](https://github.com/paritytech/parity/pull/6302) +- Increase default gas limit for eth_call. [#6299](https://github.com/paritytech/parity/pull/6299) +- rust-toolchain file on master [#6266](https://github.com/paritytech/parity/pull/6266) +- Migrate wasm-tests to updated runtime [#6278](https://github.com/paritytech/parity/pull/6278) +- Extension fixes [#6284](https://github.com/paritytech/parity/pull/6284) +- Fix a hash displayed in tooltip when signing arbitrary data [#6283](https://github.com/paritytech/parity/pull/6283) +- Time should not contribue to overall status. [#6276](https://github.com/paritytech/parity/pull/6276) +- Add --to and --gas-price to evmbin [#6277](https://github.com/paritytech/parity/pull/6277) +- Fix dapps CSP when UI is exposed externally [#6178](https://github.com/paritytech/parity/pull/6178) +- Add warning to web browser and fix links. [#6232](https://github.com/paritytech/parity/pull/6232) +- Update Settings/Proxy view to match entries in proxy.pac [#4771](https://github.com/paritytech/parity/pull/4771) +- Dapp refresh [#5752](https://github.com/paritytech/parity/pull/5752) +- Add support for ConsenSys multisig wallet [#6153](https://github.com/paritytech/parity/pull/6153) +- updated jsonrpc [#6264](https://github.com/paritytech/parity/pull/6264) +- SecretStore: encrypt messages using private key from key store [#6146](https://github.com/paritytech/parity/pull/6146) +- Wasm storage read test [#6255](https://github.com/paritytech/parity/pull/6255) +- propagate stratum submit share error upstream [#6260](https://github.com/paritytech/parity/pull/6260) +- Using multiple NTP servers [#6173](https://github.com/paritytech/parity/pull/6173) +- Add GitHub issue templates. [#6259](https://github.com/paritytech/parity/pull/6259) +- format instant change proofs correctly [#6241](https://github.com/paritytech/parity/pull/6241) +- price-info does not depend on util [#6231](https://github.com/paritytech/parity/pull/6231) +- native-contracts crate does not depend on util any more [#6233](https://github.com/paritytech/parity/pull/6233) +- Bump master to 1.8.0 [#6256](https://github.com/paritytech/parity/pull/6256) +- SecretStore: do not cache ACL contract + on-chain key servers configuration [#6107](https://github.com/paritytech/parity/pull/6107) +- Fix the README badges [#6229](https://github.com/paritytech/parity/pull/6229) +- updated tiny-keccak to 1.3 [#6248](https://github.com/paritytech/parity/pull/6248) +- Small grammatical error [#6244](https://github.com/paritytech/parity/pull/6244) +- Multi-call RPC [#6195](https://github.com/paritytech/parity/pull/6195) +- InstantSeal fix [#6223](https://github.com/paritytech/parity/pull/6223) +- Untrusted RLP length overflow check [#6227](https://github.com/paritytech/parity/pull/6227) +- Chainspec validation [#6197](https://github.com/paritytech/parity/pull/6197) +- Fix cache path when using --base-path [#6212](https://github.com/paritytech/parity/pull/6212) +- removed std reexports from util && fixed broken tests [#6187](https://github.com/paritytech/parity/pull/6187) +- WASM MVP continued [#6132](https://github.com/paritytech/parity/pull/6132) +- Decouple virtual machines [#6184](https://github.com/paritytech/parity/pull/6184) +- Realloc test added [#6177](https://github.com/paritytech/parity/pull/6177) +- Re-enable wallets, fixed forgetting accounts [#6196](https://github.com/paritytech/parity/pull/6196) +- Move more params to the common section. [#6134](https://github.com/paritytech/parity/pull/6134) +- Whisper js [#6161](https://github.com/paritytech/parity/pull/6161) +- typo in uninstaller [#6185](https://github.com/paritytech/parity/pull/6185) +- fix #6052. honor --no-color for signer command [#6100](https://github.com/paritytech/parity/pull/6100) +- Refactor --allow-ips to handle custom ip-ranges [#6144](https://github.com/paritytech/parity/pull/6144) +- Update Changelog for 1.6.10 and 1.7.0 [#6183](https://github.com/paritytech/parity/pull/6183) +- Fix unsoundness in ethash's unsafe code [#6140](https://github.com/paritytech/parity/pull/6140) diff --git a/docs/CHANGELOG-1.9.md b/docs/CHANGELOG-1.9.md new file mode 100644 index 0000000000000000000000000000000000000000..ddb7e9cee1c22c6cf3a8c227439e67fc457a7932 --- /dev/null +++ b/docs/CHANGELOG-1.9.md @@ -0,0 +1,478 @@ +## Parity [v1.9.5](https://github.com/paritytech/parity/releases/tag/v1.9.5) (2018-03-21) + +Parity 1.9.5 is a bug-fix release to improve performance and stability. This release marks the 1.9 track _stable_. + +We are excited to announce support for **Wasm Smart Contracts on Kovan network**. The hard-fork to activate the Wasm-VM will take place on block `6600000`. + +The full list of included changes: + +- Do a meaningful commit that does not contain the words "ci" or "skip" +- Triggering build for stable. +- Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) ([#8152](https://github.com/paritytech/parity/pull/8152)) + - Postpone Kovan hard fork ([#8137](https://github.com/paritytech/parity/pull/8137)) + - ethcore: postpone Kovan hard fork + - util: update version fork metadata + - WASM libraries bump ([#7970](https://github.com/paritytech/parity/pull/7970)) + - update wasmi, parity-wasm, wasm-utils to latest version + - Update to new wasmi & error handling + - also utilize new stack limiter + - fix typo + - replace dependency url + - Cargo.lock update +- Fix scripts. Force JS rebuild. ([#8144](https://github.com/paritytech/parity/pull/8144)) +- Stable Backports ([#8133](https://github.com/paritytech/parity/pull/8133)) + - updater: apply exponential backoff after download failure ([#8059](https://github.com/paritytech/parity/pull/8059)) + - updater: apply exponential backoff after download failure + - updater: reset backoff on new release + - Limit incoming connections. ([#8060](https://github.com/paritytech/parity/pull/8060)) + - Limit ingress connections + - Optimized handshakes logging + - Max code size on Kovan ([#8067](https://github.com/paritytech/parity/pull/8067)) + - Enable code size limit on kovan + - Fix formatting. + - add some dos protection ([#8084](https://github.com/paritytech/parity/pull/8084)) + - more dos protection ([#8104](https://github.com/paritytech/parity/pull/8104)) + - Const time comparison ([#8113](https://github.com/paritytech/parity/pull/8113)) + - Use `subtle::slices_equal` for constant time comparison. + - Also update the existing version of subtle in `ethcrypto` from + - 0.1 to 0.5 + - Test specifically for InvalidPassword error. + - revert removing blooms ([#8066](https://github.com/paritytech/parity/pull/8066)) + - Revert "fix traces, removed bloomchain crate, closes [#7228](https://github.com/paritytech/parity/pull/7228), closes [#7167](https://github.com/paritytech/parity/pull/7167)" + - Revert "fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934))" + - fixed broken logs + - bring back old lock order + - remove migration v13 + - revert CURRENT_VERSION to 12 in migration.rs + - Fix compilation. + - Check one step deeper if we're on release track branches + - add missing pr + - Fix blooms? + - Fix tests compiilation. + - Fix size. +- Check one step deeper if we're on release track branches ([#8134](https://github.com/paritytech/parity/pull/8134)) ([#8140](https://github.com/paritytech/parity/pull/8140)) +- Trigger js build. ([#8121](https://github.com/paritytech/parity/pull/8121)) +- Stable backports ([#8055](https://github.com/paritytech/parity/pull/8055)) + - CI: Fix cargo cache ([#7968](https://github.com/paritytech/parity/pull/7968)) + - Fix cache +Blocking waiting for file lock on the registry index + - Only clean locked cargo cache on windows + - fixed ethstore sign ([#8026](https://github.com/paritytech/parity/pull/8026)) + - fix cache & snapcraft CI build ([#8052](https://github.com/paritytech/parity/pull/8052)) + - Add MCIP-6 Byzyantium transition to Musicoin spec ([#7841](https://github.com/paritytech/parity/pull/7841)) + - Add test chain spec for musicoin byzantium testnet + - Add MCIP-6 Byzyantium transition to Musicoin spec + - Update mcip6_byz.json + - ethcore: update musicoin byzantium block number + - ethcore: update musicoin bootnodes + - Update musicoin.json + - More bootnodes. +- Optimize JS build ([#8093](https://github.com/paritytech/parity/pull/8093)) + - Extract common chunks plugin. + - Fix common CSS. + - Fix js push for stable. + - Remove arguments to getPlugins. +- Stable Backports ([#8058](https://github.com/paritytech/parity/pull/8058)) + - fixed parsing ethash seals and verify_block_undordered ([#8031](https://github.com/paritytech/parity/pull/8031)) + - fix for verify_block_basic crashing on invalid transaction rlp ([#8032](https://github.com/paritytech/parity/pull/8032)) +- Make 1.9 stable ([#8023](https://github.com/paritytech/parity/pull/8023)) + - Make 1.9 stable + - Bump stable to 1.9.5 + - Fix gitlab builds + +## Parity [v1.9.4](https://github.com/paritytech/parity/releases/tag/v1.9.4) (2018-03-01) + +Parity 1.9.4 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Bump beta to 1.9.4 ([#8016](https://github.com/paritytech/parity/pull/8016)) +- Beta Backports ([#8011](https://github.com/paritytech/parity/pull/8011)) + - Fix traces, removed bloomchain crate ([#7979](https://github.com/paritytech/parity/pull/7979)) + - Reject too large packets in snapshot sync. ([#7977](https://github.com/paritytech/parity/pull/7977)) + - Fixed broken logs ([#7934](https://github.com/paritytech/parity/pull/7934)) + - Increase max download limit to 128MB ([#7965](https://github.com/paritytech/parity/pull/7965)) + - Calculate proper keccak256/sha3 using parity. ([#7953](https://github.com/paritytech/parity/pull/7953)) + - Bump WebSockets ([#7952](https://github.com/paritytech/parity/pull/7952)) + - Hardware-wallet/usb-subscribe-refactor ([#7860](https://github.com/paritytech/parity/pull/7860)) + - Make block generator easier to use ([#7888](https://github.com/paritytech/parity/pull/7888)) + +## Parity [v1.9.3](https://github.com/paritytech/parity/releases/tag/v1.9.3) (2018-02-20) + +Parity 1.9.3 is a bug-fix release to improve performance and stability. + +The full list of included changes: + +- Backports ([#7945](https://github.com/paritytech/parity/pull/7945)) + - ECIP 1041 - Remove Difficulty Bomb ([#7905](https://github.com/paritytech/parity/pull/7905)) + - spec: Validate required divisor fields are not 0 ([#7933](https://github.com/paritytech/parity/pull/7933)) + - Kovan WASM fork code ([#7849](https://github.com/paritytech/parity/pull/7849)) +- Gitlab Cargo Cache ([#7944](https://github.com/paritytech/parity/pull/7944)) +- Bump react-qr-reader ([#7943](https://github.com/paritytech/parity/pull/7943)) + - Update react-qr-reader + - Explicit webrtc-adapter dependency (package-lock workaround) + - Iframe with allow (QR, new Chrome policy) +- Backport of [#7844](https://github.com/paritytech/parity/pull/7844) and [#7917](https://github.com/paritytech/parity/pull/7917) to beta ([#7940](https://github.com/paritytech/parity/pull/7940)) + - Randomize the peer we dispatch to + - Fix a division by zero in light client RPC handler +- Wallet allowJsEval: true ([#7913](https://github.com/paritytech/parity/pull/7913)) + - Wallet allowJsEval: true + - Fix unsafe wallet. + - Enable unsafe-eval for all dapps. +- Fix CSP for dapps that require eval. ([#7867](https://github.com/paritytech/parity/pull/7867)) ([#7903](https://github.com/paritytech/parity/pull/7903)) + - Add allowJsEval to manifest. + - Enable 'unsafe-eval' if requested in manifest. +- Fix snap build beta ([#7895](https://github.com/paritytech/parity/pull/7895)) +- Fix snapcraft grade to stable ([#7894](https://github.com/paritytech/parity/pull/7894)) +- Backport Master CI PRs to Beta ([#7890](https://github.com/paritytech/parity/pull/7890)) + - Add binary identifiers and sha256sum to builds ([#7830](https://github.com/paritytech/parity/pull/7830)) + - Fix checksums and auto-update push ([#7846](https://github.com/paritytech/parity/pull/7846)) + - Update gitlab-build.sh ([#7855](https://github.com/paritytech/parity/pull/7855)) + - Fix installer binary names for macos and windows ([#7881](https://github.com/paritytech/parity/pull/7881)) + - Update gitlab-test.sh ([#7883](https://github.com/paritytech/parity/pull/7883)) + - Fix snapcraft nightly ([#7884](https://github.com/paritytech/parity/pull/7884)) +- Backport Core PRs to beta ([#7891](https://github.com/paritytech/parity/pull/7891)) + - Update back-references more aggressively after answering from cache ([#7578](https://github.com/paritytech/parity/pull/7578)) + - Updated WASM Runtime & new interpreter (wasmi) ([#7796](https://github.com/paritytech/parity/pull/7796)) + - Adjust storage update evm-style ([#7812](https://github.com/paritytech/parity/pull/7812)) + - Add new EF ropstens nodes ([#7824](https://github.com/paritytech/parity/pull/7824)) + - Store updater metadata in a single place ([#7832](https://github.com/paritytech/parity/pull/7832)) + - WASM: Disable internal memory ([#7842](https://github.com/paritytech/parity/pull/7842)) + - Add a timeout for light client sync requests ([#7848](https://github.com/paritytech/parity/pull/7848)) + - Flush keyfiles. Resolves [#7632](https://github.com/paritytech/parity/issues/7632) ([#7868](https://github.com/paritytech/parity/pull/7868)) + - Fix wallet import ([#7873](https://github.com/paritytech/parity/pull/7873)) + +## Parity [v1.9.2](https://github.com/paritytech/parity/releases/tag/v1.9.2) (2018-02-02) + +Parity 1.9.2 is a bug-fix release to improve performance and stability. It adds additional bootnodes for the Ropsten test network. + +The full list of included changes: + +- Backports beta ([#7780](https://github.com/paritytech/parity/pull/7780)) + - Bump beta to 1.9.2 + - Update ropsten.json ([#7776](https://github.com/paritytech/parity/pull/7776)) +- Snapcraft push beta + +## Parity [v1.9.1](https://github.com/paritytech/parity/releases/tag/v1.9.1) (2018-02-01) + +Parity 1.9.1 is a bug-fix release to improve performance and stability. It restores ERC-20 token balances, improves networking, fixes database corruptions on client shutdown, and fixes issues with the `--password` command-line flag. Happy syncing, fellow Ethereans! + +In addition, this stabilizes Kovan and other Proof-of-Authority networks. If you run a network with AuRa engine, updating is highly encouraged! + +The full list of included changes: + +- Beta Backports ([#7756](https://github.com/paritytech/parity/pull/7756)) + - Filter-out nodes.json ([#7716](https://github.com/paritytech/parity/pull/7716)) + - Filter-out nodes.json + - network: sort node table nodes by failure ratio + - network: fix node table tests + - network: fit node failure percentage into buckets of 5% + - network: consider number of attempts in sorting of node table + - network: fix node table grumbles + - Fix client not being dropped on shutdown ([#7695](https://github.com/paritytech/parity/pull/7695)) + - parity: wait for client to drop on shutdown + - parity: fix grumbles in shutdown wait + - parity: increase shutdown timeouts + - Wrap --help output to 120 characters ([#7626](https://github.com/paritytech/parity/pull/7626)) + - Update Clap dependency and remove workarounds + - WIP + - Remove line breaks in help messages for now + - Multiple values can only be separated by commas (closes [#7428](https://github.com/paritytech/parity/issues/7428)) + - Grumbles; refactor repeating code; add constant + - Use a single Wrapper rather than allocate a new one for each call + - Wrap --help to 120 characters rather than 100 characte +- Token filter balances (throttle) ([#7742](https://github.com/paritytech/parity/pull/7742)) + - Token filter balances (throttle) + - Cleanups + - Remove unused uniq + - Update @parity/shared to 2.2.23 + - Remove unused code paths +- Bump beta to 1.9.1 ([#7751](https://github.com/paritytech/parity/pull/7751)) +- Explicitly add branch name ([#7754](https://github.com/paritytech/parity/pull/7754)) + - Explicitly add branch name + - Fix cargo update branch to beta +- Revert revert revert ([#7715](https://github.com/paritytech/parity/pull/7715)) + - This reverts commit 568dc33. + +## Parity [v1.9.0](https://github.com/paritytech/parity/releases/tag/v1.9.0) "Velocity" (2018-01-25) + +We are happy to announce our newest Parity 1.9 release. Among others, it enables the following features: + +- It integrates the fully reworked Parity Wallet and DApps browser (a.k.a. "UI 2.0", [#6819](https://github.com/paritytech/parity/pull/6819)). +- It enables devp2p snappy compression ([#6683](https://github.com/paritytech/parity/pull/6683)). +- AuRa Proof-of-Authority chains now disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006)). Existing PoA chains can go through a "maximum uncle count transition" to achieve more stability ([#7196](https://github.com/paritytech/parity/pull/7196)). +- Added Expanse's Byzantium hard-fork ([#7463](https://github.com/paritytech/parity/pull/7463)). +- Added support for Ellaism chain ([#7222](https://github.com/paritytech/parity/pull/7222)). + +Further, users upgrading from 1.8 should acknowledge the following changes: + +- Fixed DELEGATECALL's from/to field ([#7568](https://github.com/paritytech/parity/pull/7568)). +- Set zero nonce and gas price for calls by default ([#6954](https://github.com/paritytech/parity/pull/6954)). +- Create pending blocks with all transactions from the queue ([#6942](https://github.com/paritytech/parity/pull/6942)). +- Remove RPC parameter leniency now that Mist formats correctly ([#6651](https://github.com/paritytech/parity/pull/6651)). Parity stops accepting decimal-formatted block numbers and stops parsing the empty string as empty bytes. +- Public nodes do not support the user interface anymore. If you are running a public node, please stay on the 1.8 branch of the stable releases. + +Additional noteworthy changes: + +- `ethstore` and `ethkey` have been significantly improved ([#6961](https://github.com/paritytech/parity/pull/6961)): + - `ethstore` now supports brute forcing pre-sale wallets given a password list for recovery. + - `ethkey` now supports multi-threaded generation of prefix-matching addresses. + - `ethkey` now supports prefix-matching brain wallets. + - `ethkey` now supports brain-wallets recovery-phrases lookup. This helps to find a correct phrase if you know the address you want to get yet you made a typo backing the phrase up, or forgot a word. + +Read more about Parity 1.9 in our [blog post](http://paritytech.io/velocity-the-fastest-parity-released/). + +The full list of included changes: + +- Add scroll when when too many accounts ([#7677](https://github.com/paritytech/parity/pull/7677)) ([#7679](https://github.com/paritytech/parity/pull/7679)) +- Update installer.nsi +- Fix conditions in gitlab-test ([#7676](https://github.com/paritytech/parity/pull/7676)) + - Fix conditions in gitlab-test + - Update gitlab-test.sh +- Remove cargo cache +- Backports to beta ([#7660](https://github.com/paritytech/parity/pull/7660)) + - Improve handling of RocksDB corruption ([#7630](https://github.com/paritytech/parity/pull/7630)) + - Kvdb-rocksdb: update rust-rocksdb version + - Kvdb-rocksdb: mark corruptions and attempt repair on db open + - Kvdb-rocksdb: better corruption detection on open + - Kvdb-rocksdb: add corruption_file_name const + - Kvdb-rocksdb: rename mark_corruption to check_for_corruption + - Hardening of CSP ([#7621](https://github.com/paritytech/parity/pull/7621)) + - Fixed delegatecall's from/to ([#7568](https://github.com/paritytech/parity/pull/7568)) + - Fixed delegatecall's from/to, closes [#7166](https://github.com/paritytech/parity/issues/7166) + - Added tests for delegatecall traces, [#7167](https://github.com/paritytech/parity/issues/7167) + - Light client RPCs ([#7603](https://github.com/paritytech/parity/pull/7603)) + - Implement registrar. + - Implement eth_getCode + - Don't wait for providers. + - Don't wait for providers. + - Fix linting and wasm tests. + - Problem: AttachedProtocols don't get registered ([#7610](https://github.com/paritytech/parity/pull/7610)) + - Fix Temporarily Invalid blocks handling ([#7613](https://github.com/paritytech/parity/pull/7613)) + - Handle temporarily invalid blocks in sync. + - Fix tests. +- Add docker build for beta ([#7671](https://github.com/paritytech/parity/pull/7671)) + - Add docker build for beta + - Add cargo cache +- Fix snapcraft build for beta ([#7670](https://github.com/paritytech/parity/pull/7670)) +- Update Parity.pkgproj +- update gitlab build from master +- Update references to dapp sources ([#7634](https://github.com/paritytech/parity/pull/7634)) ([#7636](https://github.com/paritytech/parity/pull/7636)) +- Update tokenreg ([#7618](https://github.com/paritytech/parity/pull/7618)) ([#7619](https://github.com/paritytech/parity/pull/7619)) +- Fix cache:key ([#7598](https://github.com/paritytech/parity/pull/7598)) +- Make 1.9 beta ([#7533](https://github.com/paritytech/parity/pull/7533)) +- Trigger js-precompiled ([#7535](https://github.com/paritytech/parity/pull/7535)) +- RocksDB fix ([#7512](https://github.com/paritytech/parity/pull/7512)) +- Update js-api ([#7510](https://github.com/paritytech/parity/pull/7510)) +- Expose default gas price percentile configuration in CLI ([#7497](https://github.com/paritytech/parity/pull/7497)) +- Use https connection ([#7503](https://github.com/paritytech/parity/pull/7503)) +- More thorough changes detection ([#7472](https://github.com/paritytech/parity/pull/7472)) +- Fix small layout issues ([#7500](https://github.com/paritytech/parity/pull/7500)) +- Show all accounts on Topbar ([#7498](https://github.com/paritytech/parity/pull/7498)) +- Update Parity Mainnet Bootnodes ([#7476](https://github.com/paritytech/parity/pull/7476)) +- Fixed panic when io is not available for export block ([#7495](https://github.com/paritytech/parity/pull/7495)) +- Advance AuRa step as far as we can and prevent invalid blocks. ([#7451](https://github.com/paritytech/parity/pull/7451)) +- Update package-lock in js-old ([#7494](https://github.com/paritytech/parity/pull/7494)) +- Update issue template and readme ([#7450](https://github.com/paritytech/parity/pull/7450)) +- Update package-lock.json pinned versions ([#7492](https://github.com/paritytech/parity/pull/7492)) +- Explicit pre-precompiled push checkout ([#7474](https://github.com/paritytech/parity/pull/7474)) +- Trigger js-precompiled ([#7473](https://github.com/paritytech/parity/pull/7473)) +- Expanse Byzantium update w/ correct metropolis difficulty increment divisor ([#7463](https://github.com/paritytech/parity/pull/7463)) +- Updated icons ([#7469](https://github.com/paritytech/parity/pull/7469)) +- Cleanup certifications ([#7454](https://github.com/paritytech/parity/pull/7454)) +- Fix css lint (updated stylelint) ([#7471](https://github.com/paritytech/parity/pull/7471)) +- Upgrade markdown-loader & marked ([#7467](https://github.com/paritytech/parity/pull/7467)) +- Remove JS test for removed code ([#7461](https://github.com/paritytech/parity/pull/7461)) +- Pull in dapp-status ([#7457](https://github.com/paritytech/parity/pull/7457)) +- Bump openssl crate ([#7455](https://github.com/paritytech/parity/pull/7455)) +- Signer updates from global Redux state ([#7452](https://github.com/paritytech/parity/pull/7452)) +- Remove expanse chain ([#7437](https://github.com/paritytech/parity/pull/7437)) +- Store tokens with repeatable id ([#7435](https://github.com/paritytech/parity/pull/7435)) +- Strict config parsing ([#7433](https://github.com/paritytech/parity/pull/7433)) +- Upgrade to RocksDB 5.8.8 and tune settings to reduce space amplification ([#7348](https://github.com/paritytech/parity/pull/7348)) +- Fix status layout ([#7432](https://github.com/paritytech/parity/pull/7432)) +- Fix tracing failed calls. ([#7412](https://github.com/paritytech/parity/pull/7412)) +- Problem: sending any Whisper message fails ([#7421](https://github.com/paritytech/parity/pull/7421)) +- Wait for future blocks in AuRa ([#7368](https://github.com/paritytech/parity/pull/7368)) +- Fix final feature. ([#7426](https://github.com/paritytech/parity/pull/7426)) +- Use RwLock for state DB ([#7425](https://github.com/paritytech/parity/pull/7425)) +- Update branding on UI ([#7370](https://github.com/paritytech/parity/pull/7370)) +- Changelog for 1.8.5 and 1.7.11 ([#7401](https://github.com/paritytech/parity/pull/7401)) +- Added checking tx-type using transactions permission contract for miners ([#7359](https://github.com/paritytech/parity/pull/7359)) +- Standalone dir crate, replaces [#7383](https://github.com/paritytech/parity/issues/7383) ([#7409](https://github.com/paritytech/parity/pull/7409)) +- SecretStore: secretstore_signRawHash method ([#7336](https://github.com/paritytech/parity/pull/7336)) +- SecretStore: return error 404 when there's no key shares for given key on all nodes ([#7331](https://github.com/paritytech/parity/pull/7331)) +- SecretStore: PoA integration initial version ([#7101](https://github.com/paritytech/parity/pull/7101)) +- Update bootnodes ([#7363](https://github.com/paritytech/parity/pull/7363)) +- Fix default CORS settings. ([#7387](https://github.com/paritytech/parity/pull/7387)) +- Fix version ([#7390](https://github.com/paritytech/parity/pull/7390)) +- Wasm runtime update ([#7356](https://github.com/paritytech/parity/pull/7356)) +- Parity-version pr reopen ([#7136](https://github.com/paritytech/parity/pull/7136)) +- Get rid of clippy remainings. ([#7355](https://github.com/paritytech/parity/pull/7355)) +- Avoid using ok_or with allocated argument ([#7357](https://github.com/paritytech/parity/pull/7357)) +- Make accounts refresh time configurable. ([#7345](https://github.com/paritytech/parity/pull/7345)) +- Enable traces for DEV chain ([#7327](https://github.com/paritytech/parity/pull/7327)) +- Problem: AuRa's unsafeties around step duration ([#7282](https://github.com/paritytech/parity/pull/7282)) +- Problem: Cargo.toml file contains [project] key ([#7346](https://github.com/paritytech/parity/pull/7346)) +- Fix broken flex modal layouts ([#7343](https://github.com/paritytech/parity/pull/7343)) +- Fix dappIcon & Fix Signer Pending ([#7338](https://github.com/paritytech/parity/pull/7338)) +- Fix wallet token/badge icons not showing up ([#7333](https://github.com/paritytech/parity/pull/7333)) +- Add Ellaism coin in chain config ([#7222](https://github.com/paritytech/parity/pull/7222)) +- Update bootnodes ([#7296](https://github.com/paritytech/parity/pull/7296)) +- Adds `personal_signTransaction` RPC method ([#6991](https://github.com/paritytech/parity/pull/6991)) +- Fix double initialization of embeded providers. ([#7326](https://github.com/paritytech/parity/pull/7326)) +- Transaction Pool re-implementation ([#6994](https://github.com/paritytech/parity/pull/6994)) +- UI package bump ([#7318](https://github.com/paritytech/parity/pull/7318)) +- Test framework and basic test for whisper ([#7011](https://github.com/paritytech/parity/pull/7011)) +- CI js-precompiled trigger ([#7316](https://github.com/paritytech/parity/pull/7316)) +- Fix inject.js & Signer store duplication ([#7299](https://github.com/paritytech/parity/pull/7299)) +- Detect different node, same-key signing in aura ([#7245](https://github.com/paritytech/parity/pull/7245)) +- New warp enodes ([#7287](https://github.com/paritytech/parity/pull/7287)) +- CSS fixes for v1 ([#7285](https://github.com/paritytech/parity/pull/7285)) +- Wallet subscriptions & refresh ([#7283](https://github.com/paritytech/parity/pull/7283)) +- Update inject web3 dependencies ([#7286](https://github.com/paritytech/parity/pull/7286)) +- Some padding around dapp image ([#7276](https://github.com/paritytech/parity/pull/7276)) +- Expand available middleware methods ([#7275](https://github.com/paritytech/parity/pull/7275)) +- Inject parity script to all dapps // Expand dapps to any ZIP file ([#7260](https://github.com/paritytech/parity/pull/7260)) +- New Homepage ([#7266](https://github.com/paritytech/parity/pull/7266)) +- Update kovan HF block number. ([#7259](https://github.com/paritytech/parity/pull/7259)) +- CHANGELOG for 1.7.10 and 1.8.4 ([#7265](https://github.com/paritytech/parity/pull/7265)) +- Remove extraneous id hashing ([#7269](https://github.com/paritytech/parity/pull/7269)) +- Simplify status + content display overlaps/page fixing ([#7264](https://github.com/paritytech/parity/pull/7264)) +- UI redirect to 127.0.0.1 when localhost requested ([#7236](https://github.com/paritytech/parity/pull/7236)) +- Usability improvements to security token Dialog [#7112](https://github.com/paritytech/parity/issues/7112) ([#7134](https://github.com/paritytech/parity/pull/7134)) +- Don't display unneeded notifications ([#7237](https://github.com/paritytech/parity/pull/7237)) +- Reduce max block timestamp drift to 15 seconds ([#7240](https://github.com/paritytech/parity/pull/7240)) +- Increase allowed time drift to 10s. ([#7238](https://github.com/paritytech/parity/pull/7238)) +- Improve building from source ([#7239](https://github.com/paritytech/parity/pull/7239)) +- Fix/Update method permissions ([#7233](https://github.com/paritytech/parity/pull/7233)) +- Fix aura difficulty race ([#7198](https://github.com/paritytech/parity/pull/7198)) +- Dependency updates ([#7226](https://github.com/paritytech/parity/pull/7226)) +- Display all dapps (shell) & wallet tabs (v1) by default ([#7213](https://github.com/paritytech/parity/pull/7213)) +- Rework dapps list ([#7206](https://github.com/paritytech/parity/pull/7206)) +- Add contributing guidelines and code of conduct. ([#7157](https://github.com/paritytech/parity/pull/7157)) +- Make Signing Requests more visible ([#7204](https://github.com/paritytech/parity/pull/7204)) +- Send each log as a separate notification ([#7175](https://github.com/paritytech/parity/pull/7175)) +- Deleting a mistake comment in calc difficulty ([#7154](https://github.com/paritytech/parity/pull/7154)) +- Maximum uncle count transition ([#7196](https://github.com/paritytech/parity/pull/7196)) +- Update FirstRun for UI-2 ([#7195](https://github.com/paritytech/parity/pull/7195)) +- Update mocha import stubs ([#7191](https://github.com/paritytech/parity/pull/7191)) +- Escape inifinite loop in estimte_gas ([#7075](https://github.com/paritytech/parity/pull/7075)) +- New account selector UI in top bar ([#7179](https://github.com/paritytech/parity/pull/7179)) +- Removed ethcore-util dependency from ethcore-network ([#7180](https://github.com/paritytech/parity/pull/7180)) +- WASM test runner utility upgrade ([#7147](https://github.com/paritytech/parity/pull/7147)) +- React 16 ([#7174](https://github.com/paritytech/parity/pull/7174)) +- Assorted improvements for ethstore and ethkey ([#6961](https://github.com/paritytech/parity/pull/6961)) +- Delete unused package.json (dist bundles) ([#7173](https://github.com/paritytech/parity/pull/7173)) +- Remove *.css.map & *.js.map ([#7168](https://github.com/paritytech/parity/pull/7168)) +- Use git flag to remove old js artifacts ([#7165](https://github.com/paritytech/parity/pull/7165)) +- Cleanup JS build artifacts ([#7164](https://github.com/paritytech/parity/pull/7164)) +- Fixes typo in user config path ([#7159](https://github.com/paritytech/parity/pull/7159)) +- Pull in new dapp-{methods,visible} dapps ([#7150](https://github.com/paritytech/parity/pull/7150)) +- WASM test runner utility ([#7142](https://github.com/paritytech/parity/pull/7142)) +- WASM Remove blockhash error ([#7121](https://github.com/paritytech/parity/pull/7121)) +- ECIP-1039: Monetary policy rounding specification ([#7067](https://github.com/paritytech/parity/pull/7067)) +- Fixed `RotatingLogger` after migrating to new arrayvec ([#7129](https://github.com/paritytech/parity/pull/7129)) +- Push to correct shell branch ([#7135](https://github.com/paritytech/parity/pull/7135)) +- Update js-precompiled ref, trigger JS build ([#7132](https://github.com/paritytech/parity/pull/7132)) +- Fixed build && test ([#7128](https://github.com/paritytech/parity/pull/7128)) +- Update packages, pull in compiled-only repos ([#7125](https://github.com/paritytech/parity/pull/7125)) +- Cleanup top bar, add Home icon for navigation ([#7118](https://github.com/paritytech/parity/pull/7118)) +- WASM storage_read and storage_write don't return anything ([#7110](https://github.com/paritytech/parity/pull/7110)) +- Local dapp development URL ([#7100](https://github.com/paritytech/parity/pull/7100)) +- Remove unused and duplicated files in js-old ([#7082](https://github.com/paritytech/parity/pull/7082)) +- Optimize & group dapp requests ([#7083](https://github.com/paritytech/parity/pull/7083)) +- WASM parse payload from panics ([#7097](https://github.com/paritytech/parity/pull/7097)) +- Fix no-default-features. ([#7096](https://github.com/paritytech/parity/pull/7096)) +- Updated eth-secp256k1 ([#7090](https://github.com/paritytech/parity/pull/7090)) +- Improve Github Issue Template ([#7099](https://github.com/paritytech/parity/pull/7099)) +- Changes necessary to upload crates to crates.io ([#7020](https://github.com/paritytech/parity/pull/7020)) +- Reopened 6860 - iterate over both buffered and unbuffered database entries ([#7048](https://github.com/paritytech/parity/pull/7048)) +- SecretStore: servers set change session api ([#6925](https://github.com/paritytech/parity/pull/6925)) +- Disable uncles by default ([#7006](https://github.com/paritytech/parity/pull/7006)) +- Squashed ethcore-network changes which introduce error-chain ([#7040](https://github.com/paritytech/parity/pull/7040)) +- Removed redundant imports ([#7057](https://github.com/paritytech/parity/pull/7057)) +- CHANGELOG for 1.7.8, 1.7.9, 1.8.2, and 1.8.3 ([#7055](https://github.com/paritytech/parity/pull/7055)) +- Properly display Signer errors (Snackbar display popup) ([#7053](https://github.com/paritytech/parity/pull/7053)) +- Add the desktop file for the snap ([#7059](https://github.com/paritytech/parity/pull/7059)) +- Small performance gain in allocations ([#7054](https://github.com/paritytech/parity/pull/7054)) +- Bump JSON-RPC version ([#7051](https://github.com/paritytech/parity/pull/7051)) +- Fix nonce reservation ([#7025](https://github.com/paritytech/parity/pull/7025)) +- Fixed ethstore-cli output ([#7052](https://github.com/paritytech/parity/pull/7052)) +- Add mui for embed compilation ([#7049](https://github.com/paritytech/parity/pull/7049)) +- Update the snap metadata to keep working strictly confined ([#6993](https://github.com/paritytech/parity/pull/6993)) +- Remove unused js packages (dapp cleanups) ([#7046](https://github.com/paritytech/parity/pull/7046)) +- Gitlog location update ([#7042](https://github.com/paritytech/parity/pull/7042)) +- Move git logging to .git-release.log ([#7041](https://github.com/paritytech/parity/pull/7041)) +- Start from rust root in release update step ([#7039](https://github.com/paritytech/parity/pull/7039)) +- Complete token merge, remove unused files ([#7037](https://github.com/paritytech/parity/pull/7037)) +- Add missing cargo-push.sh shell variable ([#7036](https://github.com/paritytech/parity/pull/7036)) +- Fix npm start script ([#7034](https://github.com/paritytech/parity/pull/7034)) +- Update executable flags on release scripts ([#7035](https://github.com/paritytech/parity/pull/7035)) +- Fix v1 precompiled ([#7033](https://github.com/paritytech/parity/pull/7033)) +- Push precompiled to correct branch (v1) ([#7031](https://github.com/paritytech/parity/pull/7031)) +- Update v1 Wallet Dapp ([#6935](https://github.com/paritytech/parity/pull/6935)) +- WASM tests update ([#7018](https://github.com/paritytech/parity/pull/7018)) +- Events in WASM runtime ([#6967](https://github.com/paritytech/parity/pull/6967)) +- Adds validate_node_url() and refactors boot node check ([#6907](https://github.com/paritytech/parity/pull/6907)) ([#6970](https://github.com/paritytech/parity/pull/6970)) +- Fix windows build (with ui rebuild) ([#7016](https://github.com/paritytech/parity/pull/7016)) +- Make CLI arguments parsing more backwards compatible ([#7004](https://github.com/paritytech/parity/pull/7004)) +- Fixes for parity-extension ([#6990](https://github.com/paritytech/parity/pull/6990)) +- Update ethcore-bigint ([#6992](https://github.com/paritytech/parity/pull/6992)) +- Get local transactions by hash in the light client ([#6874](https://github.com/paritytech/parity/pull/6874)) +- Warn when blacklisted account present in store ([#6875](https://github.com/paritytech/parity/pull/6875)) +- Skip nonce check for gas estimation ([#6997](https://github.com/paritytech/parity/pull/6997)) +- Creating pending block with all transactions from the queue ([#6942](https://github.com/paritytech/parity/pull/6942)) +- Removes `MAX_TX_TO_IMPORT` from `ChainSync` ([#6976](https://github.com/paritytech/parity/pull/6976)) +- SecretStore: versioned keys ([#6910](https://github.com/paritytech/parity/pull/6910)) +- Removes `FUTURE_QUEUE_LIMITS_SHIFT` ([#6962](https://github.com/paritytech/parity/pull/6962)) +- Set zero nonce and gas price for calls by default ([#6954](https://github.com/paritytech/parity/pull/6954)) +- Add hint in ActionParams for splitting code/data ([#6957](https://github.com/paritytech/parity/pull/6957)) +- Return decoded seal fields. ([#6932](https://github.com/paritytech/parity/pull/6932)) +- Fix serialization of status in transaction receipts. ([#6926](https://github.com/paritytech/parity/pull/6926)) +- Reserve nonces for signing ([#6834](https://github.com/paritytech/parity/pull/6834)) +- Windows fixes ([#6921](https://github.com/paritytech/parity/pull/6921)) +- Don't add {css,js}.map from dapps ([#6931](https://github.com/paritytech/parity/pull/6931)) +- Fix JSON tracing for sub-calls. ([#6842](https://github.com/paritytech/parity/pull/6842)) +- Shell updates (bonds, updated Dapps) ([#6897](https://github.com/paritytech/parity/pull/6897)) +- Fix [#6228](https://github.com/paritytech/parity/issues/6228): do not display eth price in cli for etc ([#6877](https://github.com/paritytech/parity/pull/6877)) +- Fix mining help ([#6885](https://github.com/paritytech/parity/pull/6885)) +- Refactor static context check in CREATE. ([#6886](https://github.com/paritytech/parity/pull/6886)) +- Cleanup some configuration options ([#6878](https://github.com/paritytech/parity/pull/6878)) +- Fix serialization of non-localized transactions ([#6868](https://github.com/paritytech/parity/pull/6868)) +- Updated ntp to version 0.3 ([#6854](https://github.com/paritytech/parity/pull/6854)) +- Align README with 1.8 and prepare CHANGELOG with 1.8.1 ([#6833](https://github.com/paritytech/parity/pull/6833)) +- Return error on timed unlock ([#6777](https://github.com/paritytech/parity/pull/6777)) +- Fix dapps tests in master ([#6866](https://github.com/paritytech/parity/pull/6866)) +- Ethstore optimizations ([#6827](https://github.com/paritytech/parity/pull/6827)) +- Add ECIP1017 to Morden config ([#6810](https://github.com/paritytech/parity/pull/6810)) +- Remove all package publishing to npm ([#6838](https://github.com/paritytech/parity/pull/6838)) +- Util crates use tempdir crate instead of devtools to create temp path ([#6807](https://github.com/paritytech/parity/pull/6807)) +- Trigger js build ([#6836](https://github.com/paritytech/parity/pull/6836)) +- Clean-up scripts. ([#6832](https://github.com/paritytech/parity/pull/6832)) +- Tweaked snapshot sync threshold ([#6829](https://github.com/paritytech/parity/pull/6829)) +- Integrate UI 2 ([#6819](https://github.com/paritytech/parity/pull/6819)) +- Refresh cached tokens based on registry info & random balances ([#6818](https://github.com/paritytech/parity/pull/6818)) +- Change keypath derivation logic ([#6815](https://github.com/paritytech/parity/pull/6815)) +- Refactors journaldb as a separate crate ([#6801](https://github.com/paritytech/parity/pull/6801)) +- Trigger UI build. ([#6817](https://github.com/paritytech/parity/pull/6817)) +- Bumped more crate versions ([#6809](https://github.com/paritytech/parity/pull/6809)) +- Fix RPC compilation warnings. ([#6808](https://github.com/paritytech/parity/pull/6808)) +- Remove internal ipc ([#6795](https://github.com/paritytech/parity/pull/6795)) +- Consistent KeyValueDB errors ([#6792](https://github.com/paritytech/parity/pull/6792)) +- Squash remaining warnings ([#6789](https://github.com/paritytech/parity/pull/6789)) +- Forward-port [#6754](https://github.com/paritytech/parity/issues/6754) [#6755](https://github.com/paritytech/parity/issues/6755) ([#6785](https://github.com/paritytech/parity/pull/6785)) +- Removed duplicated versions of clippy ([#6776](https://github.com/paritytech/parity/pull/6776)) +- Updated ethabi to version 4.0 ([#6742](https://github.com/paritytech/parity/pull/6742)) +- Updated rpc_cli and parity to rpassword 1.0 ([#6774](https://github.com/paritytech/parity/pull/6774)) +- Fix sign data typo ([#6750](https://github.com/paritytech/parity/pull/6750)) +- Refactoring/cache 6693 ([#6772](https://github.com/paritytech/parity/pull/6772)) +- Fix CHANGLOG for 1.8.0 ([#6751](https://github.com/paritytech/parity/pull/6751)) +- Removes redundant `mut` in service.rs.in ([#6775](https://github.com/paritytech/parity/pull/6775)) +- Remove redundant `mut` ([#6773](https://github.com/paritytech/parity/pull/6773)) +- Fixed kovan chain validation ([#6758](https://github.com/paritytech/parity/pull/6758)) +- Removed redundant evm deps ([#6757](https://github.com/paritytech/parity/pull/6757)) +- Fixed modexp gas calculation overflow ([#6741](https://github.com/paritytech/parity/pull/6741)) +- Use cc 1.0 instead of gcc ([#6733](https://github.com/paritytech/parity/pull/6733)) +- Version bump to 1.9.0 ([#6727](https://github.com/paritytech/parity/pull/6727)) +- Fix badges not showing up ([#6730](https://github.com/paritytech/parity/pull/6730)) diff --git a/ethash/Cargo.toml b/ethash/Cargo.toml index 87069d6f89abc5083d4b753ea7498a2e2ef23e26..91f1ce56f700aba239fa43b86bc7f1d99ec38baf 100644 --- a/ethash/Cargo.toml +++ b/ethash/Cargo.toml @@ -1,16 +1,21 @@ [package] name = "ethash" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] [lib] [dependencies] log = "0.3" -sha3 = { path = "../util/sha3" } +keccak-hash = { path = "../util/hash" } primal = "0.2.3" -parking_lot = "0.4" +parking_lot = "0.5" crunchy = "0.1.0" +memmap = "0.6" +either = "1.0.0" + +[dev-dependencies] +tempdir = "0.3" [features] -benches = [] \ No newline at end of file +benches = [] diff --git a/ethash/src/cache.rs b/ethash/src/cache.rs new file mode 100644 index 0000000000000000000000000000000000000000..eef426bcf1b95ad7fe5904f4689ab3d90c42a9e3 --- /dev/null +++ b/ethash/src/cache.rs @@ -0,0 +1,355 @@ +// 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 . + +use compute::Light; +use either::Either; +use keccak::{H256, keccak_512}; +use memmap::MmapMut; +use parking_lot::Mutex; +use seed_compute::SeedHashCompute; + +use shared::{ETHASH_CACHE_ROUNDS, NODE_BYTES, NODE_DWORDS, Node, epoch, get_cache_size, to_hex}; + +use std::borrow::Cow; +use std::fs; +use std::io::{self, Read, Write}; +use std::path::{Path, PathBuf}; +use std::slice; +use std::sync::Arc; + +type Cache = Either, MmapMut>; + +#[derive(PartialEq, Eq, Debug, Clone, Copy)] +pub enum OptimizeFor { + Cpu, + Memory, +} + +impl Default for OptimizeFor { + fn default() -> Self { + OptimizeFor::Cpu + } +} + +fn byte_size(cache: &Cache) -> usize { + use self::Either::{Left, Right}; + + match *cache { + Left(ref vec) => vec.len() * NODE_BYTES, + Right(ref mmap) => mmap.len(), + } +} + +fn new_buffer(path: &Path, num_nodes: usize, ident: &H256, optimize_for: OptimizeFor) -> Cache { + let memmap = match optimize_for { + OptimizeFor::Cpu => None, + OptimizeFor::Memory => make_memmapped_cache(path, num_nodes, ident).ok(), + }; + + memmap.map(Either::Right).unwrap_or_else(|| { + Either::Left(make_memory_cache(num_nodes, ident)) + }) +} + +#[derive(Clone)] +pub struct NodeCacheBuilder { + // TODO: Remove this locking and just use an `Rc`? + seedhash: Arc>, + optimize_for: OptimizeFor, +} + +// TODO: Abstract the "optimize for" logic +pub struct NodeCache { + builder: NodeCacheBuilder, + cache_dir: Cow<'static, Path>, + cache_path: PathBuf, + epoch: u64, + cache: Cache, +} + +impl NodeCacheBuilder { + pub fn light(&self, cache_dir: &Path, block_number: u64) -> Light { + Light::new_with_builder(self, cache_dir, block_number) + } + + pub fn light_from_file(&self, cache_dir: &Path, block_number: u64) -> io::Result { + Light::from_file_with_builder(self, cache_dir, block_number) + } + + pub fn new>>(optimize_for: T) -> Self { + NodeCacheBuilder { + seedhash: Arc::new(Mutex::new(SeedHashCompute::new())), + optimize_for: optimize_for.into().unwrap_or_default(), + } + } + + fn block_number_to_ident(&self, block_number: u64) -> H256 { + self.seedhash.lock().hash_block_number(block_number) + } + + fn epoch_to_ident(&self, epoch: u64) -> H256 { + self.seedhash.lock().hash_epoch(epoch) + } + + pub fn from_file>>( + &self, + cache_dir: P, + block_number: u64, + ) -> io::Result { + let cache_dir = cache_dir.into(); + let ident = self.block_number_to_ident(block_number); + + let path = cache_path(cache_dir.as_ref(), &ident); + + let cache = cache_from_path(&path, self.optimize_for)?; + let expected_cache_size = get_cache_size(block_number); + + if byte_size(&cache) == expected_cache_size { + Ok(NodeCache { + builder: self.clone(), + epoch: epoch(block_number), + cache_dir: cache_dir, + cache_path: path, + cache: cache, + }) + } else { + Err(io::Error::new( + io::ErrorKind::InvalidData, + "Node cache is of incorrect size", + )) + } + } + + pub fn new_cache>>( + &self, + cache_dir: P, + block_number: u64, + ) -> NodeCache { + let cache_dir = cache_dir.into(); + let ident = self.block_number_to_ident(block_number); + + let cache_size = get_cache_size(block_number); + + // We use `debug_assert` since it is impossible for `get_cache_size` to return an unaligned + // value with the current implementation. If the implementation changes, CI will catch it. + debug_assert!(cache_size % NODE_BYTES == 0, "Unaligned cache size"); + let num_nodes = cache_size / NODE_BYTES; + + let path = cache_path(cache_dir.as_ref(), &ident); + let nodes = new_buffer(&path, num_nodes, &ident, self.optimize_for); + + NodeCache { + builder: self.clone(), + epoch: epoch(block_number), + cache_dir: cache_dir.into(), + cache_path: path, + cache: nodes, + } + } +} + +impl NodeCache { + pub fn cache_path(&self) -> &Path { + &self.cache_path + } + + pub fn flush(&mut self) -> io::Result<()> { + if let Some(last) = self.epoch.checked_sub(2).map(|ep| { + cache_path(self.cache_dir.as_ref(), &self.builder.epoch_to_ident(ep)) + }) + { + fs::remove_file(last).unwrap_or_else(|error| match error.kind() { + io::ErrorKind::NotFound => (), + _ => warn!("Error removing stale DAG cache: {:?}", error), + }); + } + + consume_cache(&mut self.cache, &self.cache_path) + } +} + +fn make_memmapped_cache(path: &Path, num_nodes: usize, ident: &H256) -> io::Result { + use std::fs::OpenOptions; + + let file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path)?; + file.set_len((num_nodes * NODE_BYTES) as _)?; + + let mut memmap = unsafe { MmapMut::map_mut(&file)? }; + + unsafe { initialize_memory(memmap.as_mut_ptr() as *mut Node, num_nodes, ident) }; + + Ok(memmap) +} + +fn make_memory_cache(num_nodes: usize, ident: &H256) -> Vec { + let mut nodes: Vec = Vec::with_capacity(num_nodes); + // Use uninit instead of unnecessarily writing `size_of::() * num_nodes` 0s + unsafe { + initialize_memory(nodes.as_mut_ptr(), num_nodes, ident); + nodes.set_len(num_nodes); + } + + nodes +} + +fn cache_path<'a, P: Into>>(path: P, ident: &H256) -> PathBuf { + let mut buf = path.into().into_owned(); + buf.push(to_hex(ident)); + buf +} + +fn consume_cache(cache: &mut Cache, path: &Path) -> io::Result<()> { + use std::fs::OpenOptions; + + match *cache { + Either::Left(ref mut vec) => { + let mut file = OpenOptions::new() + .read(true) + .write(true) + .create(true) + .open(&path)?; + + let buf = unsafe { + slice::from_raw_parts_mut(vec.as_mut_ptr() as *mut u8, vec.len() * NODE_BYTES) + }; + + file.write_all(buf).map(|_| ()) + } + Either::Right(ref mmap) => { + mmap.flush() + } + } +} + +fn cache_from_path(path: &Path, optimize_for: OptimizeFor) -> io::Result { + let memmap = match optimize_for { + OptimizeFor::Cpu => None, + OptimizeFor::Memory => { + let file = fs::OpenOptions::new().read(true).write(true).create(true).open(path)?; + unsafe { MmapMut::map_mut(&file).ok() } + }, + }; + + memmap.map(Either::Right).ok_or(()).or_else(|_| { + read_from_path(path).map(Either::Left) + }) +} + +fn read_from_path(path: &Path) -> io::Result> { + use std::fs::File; + use std::mem; + + let mut file = File::open(path)?; + + let mut nodes: Vec = Vec::with_capacity(file.metadata().map(|m| m.len() as _).unwrap_or( + NODE_BYTES * 1_000_000, + )); + file.read_to_end(&mut nodes)?; + + nodes.shrink_to_fit(); + + if nodes.len() % NODE_BYTES != 0 || nodes.capacity() % NODE_BYTES != 0 { + return Err(io::Error::new( + io::ErrorKind::Other, + "Node cache is not a multiple of node size", + )); + } + + let out: Vec = unsafe { + Vec::from_raw_parts( + nodes.as_mut_ptr() as *mut _, + nodes.len() / NODE_BYTES, + nodes.capacity() / NODE_BYTES, + ) + }; + + mem::forget(nodes); + + Ok(out) +} + +impl AsRef<[Node]> for NodeCache { + fn as_ref(&self) -> &[Node] { + match self.cache { + Either::Left(ref vec) => vec, + Either::Right(ref mmap) => unsafe { + let bytes = mmap.as_ptr(); + // This isn't a safety issue, so we can keep this a debug lint. We don't care about + // people manually messing with the files unless it can cause unsafety, but if we're + // generating incorrect files then we want to catch that in CI. + debug_assert_eq!(mmap.len() % NODE_BYTES, 0); + slice::from_raw_parts(bytes as _, mmap.len() / NODE_BYTES) + }, + } + } +} + +// This takes a raw pointer and a counter because `memory` may be uninitialized. `memory` _must_ be +// a pointer to the beginning of an allocated but possibly-uninitialized block of +// `num_nodes * NODE_BYTES` bytes +// +// We have to use raw pointers to read/write uninit, using "normal" indexing causes LLVM to freak +// out. It counts as a read and causes all writes afterwards to be elided. Yes, really. I know, I +// want to refactor this to use less `unsafe` as much as the next rustacean. +unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) { + let dst = memory as *mut u8; + + debug_assert_eq!(ident.len(), 32); + keccak_512::unchecked(dst, NODE_BYTES, ident.as_ptr(), ident.len()); + + for i in 1..num_nodes { + // We use raw pointers here, see above + let dst = memory.offset(i as _) as *mut u8; + let src = memory.offset(i as isize - 1) as *mut u8; + + keccak_512::unchecked(dst, NODE_BYTES, src, NODE_BYTES); + } + + // Now this is initialized, we can treat it as a slice. + let nodes: &mut [Node] = slice::from_raw_parts_mut(memory, num_nodes); + + // For `unroll!`, see below. If the literal in `unroll!` is not the same as the RHS here then + // these have got out of sync! Don't let this happen! + debug_assert_eq!(NODE_DWORDS, 8); + + // This _should_ get unrolled by the compiler, since it's not using the loop variable. + for _ in 0..ETHASH_CACHE_ROUNDS { + for i in 0..num_nodes { + let data_idx = (num_nodes - 1 + i) % num_nodes; + let idx = nodes.get_unchecked_mut(i).as_words()[0] as usize % num_nodes; + + let data = { + let mut data: Node = nodes.get_unchecked(data_idx).clone(); + let rhs: &Node = nodes.get_unchecked(idx); + + unroll! { + for w in 0..8 { + *data.as_dwords_mut().get_unchecked_mut(w) ^= + *rhs.as_dwords().get_unchecked(w); + } + } + + data + }; + + keccak_512::write(&data.bytes, &mut nodes.get_unchecked_mut(i).bytes); + } + } +} diff --git a/ethash/src/compute.rs b/ethash/src/compute.rs index ab2c758df30b9cda4eecb3359999053aa9483b37..48906b9edeb6b9565850631f529becf08dd5f840 100644 --- a/ethash/src/compute.rs +++ b/ethash/src/compute.rs @@ -19,30 +19,16 @@ // TODO: fix endianess for big endian -use primal::is_prime; -use std::cell::Cell; +use keccak::{keccak_512, keccak_256, H256}; +use cache::{NodeCache, NodeCacheBuilder}; +use seed_compute::SeedHashCompute; +use shared::*; +use std::io; + use std::mem; +use std::path::Path; use std::ptr; -use sha3; -use std::slice; -use std::path::{Path, PathBuf}; -use std::io::{self, Read, Write}; -use std::fs::{self, File}; - -use parking_lot::Mutex; - -pub const ETHASH_EPOCH_LENGTH: u64 = 30000; -pub const ETHASH_CACHE_ROUNDS: usize = 3; -pub const ETHASH_MIX_BYTES: usize = 128; -pub const ETHASH_ACCESSES: usize = 64; -pub const ETHASH_DATASET_PARENTS: u32 = 256; - -const DATASET_BYTES_INIT: u64 = 1 << 30; -const DATASET_BYTES_GROWTH: u64 = 1 << 23; -const CACHE_BYTES_INIT: u64 = 1 << 24; -const CACHE_BYTES_GROWTH: u64 = 1 << 17; -const NODE_WORDS: usize = 64 / 4; -const NODE_BYTES: usize = 64; + const MIX_WORDS: usize = ETHASH_MIX_BYTES / 4; const MIX_NODES: usize = MIX_WORDS / NODE_WORDS; const FNV_PRIME: u32 = 0x01000193; @@ -55,48 +41,24 @@ pub struct ProofOfWork { pub mix_hash: H256, } -struct Node { - bytes: [u8; NODE_BYTES], -} - -impl Default for Node { - fn default() -> Self { - Node { bytes: [0u8; NODE_BYTES] } - } -} - -impl Clone for Node { - fn clone(&self) -> Self { - Node { bytes: *&self.bytes } - } -} - -impl Node { - #[inline] - fn as_words(&self) -> &[u32; NODE_WORDS] { - unsafe { mem::transmute(&self.bytes) } - } - - #[inline] - fn as_words_mut(&mut self) -> &mut [u32; NODE_WORDS] { - unsafe { mem::transmute(&mut self.bytes) } - } -} - -pub type H256 = [u8; 32]; - pub struct Light { - cache_dir: PathBuf, block_number: u64, - cache: Vec, - seed_compute: Mutex, + cache: NodeCache, } /// Light cache structure impl Light { - /// Create a new light cache for a given block number - pub fn new>(cache_dir: T, block_number: u64) -> Light { - light_new(cache_dir, block_number) + pub fn new_with_builder( + builder: &NodeCacheBuilder, + cache_dir: &Path, + block_number: u64, + ) -> Self { + let cache = builder.new_cache(cache_dir.to_path_buf(), block_number); + + Light { + block_number: block_number, + cache: cache, + } } /// Calculate the light boundary data @@ -106,107 +68,25 @@ impl Light { light_compute(self, header_hash, nonce) } - pub fn file_path>(cache_dir: T, seed_hash: H256) -> PathBuf { - let mut cache_dir = cache_dir.as_ref().to_path_buf(); - cache_dir.push(to_hex(&seed_hash)); - cache_dir - } - - pub fn from_file>(cache_dir: T, block_number: u64) -> io::Result { - let seed_compute = SeedHashCompute::new(); - let path = Light::file_path(&cache_dir, seed_compute.get_seedhash(block_number)); - let mut file = File::open(path)?; - - let cache_size = get_cache_size(block_number); - if file.metadata()?.len() != cache_size as u64 { - return Err(io::Error::new(io::ErrorKind::Other, "Cache file size mismatch")); - } - let num_nodes = cache_size / NODE_BYTES; - let mut nodes: Vec = Vec::with_capacity(num_nodes); - - unsafe { nodes.set_len(num_nodes) }; - - let buf = unsafe { slice::from_raw_parts_mut(nodes.as_mut_ptr() as *mut u8, cache_size) }; - file.read_exact(buf)?; + pub fn from_file_with_builder( + builder: &NodeCacheBuilder, + cache_dir: &Path, + block_number: u64, + ) -> io::Result { + let cache = builder.from_file(cache_dir.to_path_buf(), block_number)?; Ok(Light { - block_number, - cache_dir: cache_dir.as_ref().to_path_buf(), - cache: nodes, - seed_compute: Mutex::new(seed_compute), + block_number: block_number, + cache: cache, }) } - pub fn to_file(&self) -> io::Result { - let seed_compute = self.seed_compute.lock(); - let path = Light::file_path(&self.cache_dir, seed_compute.get_seedhash(self.block_number)); - - if self.block_number >= ETHASH_EPOCH_LENGTH * 2 { - let deprecated = Light::file_path( - &self.cache_dir, - seed_compute.get_seedhash(self.block_number - ETHASH_EPOCH_LENGTH * 2) - ); - - if deprecated.exists() { - debug!(target: "ethash", "removing: {:?}", &deprecated); - fs::remove_file(deprecated)?; - } - } - - fs::create_dir_all(path.parent().unwrap())?; - let mut file = File::create(&path)?; - - let cache_size = self.cache.len() * NODE_BYTES; - let buf = unsafe { slice::from_raw_parts(self.cache.as_ptr() as *const u8, cache_size) }; - file.write(buf)?; - Ok(path) - } -} - -pub struct SeedHashCompute { - prev_epoch: Cell, - prev_seedhash: Cell, -} - -impl SeedHashCompute { - #[inline] - pub fn new() -> SeedHashCompute { - SeedHashCompute { - prev_epoch: Cell::new(0), - prev_seedhash: Cell::new([0u8; 32]), - } - } - - #[inline] - fn reset_cache(&self) { - self.prev_epoch.set(0); - self.prev_seedhash.set([0u8; 32]); - } - - #[inline] - pub fn get_seedhash(&self, block_number: u64) -> H256 { - let epoch = block_number / ETHASH_EPOCH_LENGTH; - if epoch < self.prev_epoch.get() { - // can't build on previous hash if requesting an older block - self.reset_cache(); - } - if epoch > self.prev_epoch.get() { - let seed_hash = SeedHashCompute::resume_compute_seedhash(self.prev_seedhash.get(), self.prev_epoch.get(), epoch); - self.prev_seedhash.set(seed_hash); - self.prev_epoch.set(epoch); - } - self.prev_seedhash.get() - } - - #[inline] - pub fn resume_compute_seedhash(mut hash: H256, start_epoch: u64, end_epoch: u64) -> H256 { - for _ in start_epoch..end_epoch { - unsafe { sha3::sha3_256(hash[..].as_mut_ptr(), 32, hash[..].as_ptr(), 32) }; - } - hash + pub fn to_file(&mut self) -> io::Result<&Path> { + self.cache.flush()?; + Ok(self.cache.cache_path()) } } -pub fn slow_get_seedhash(block_number: u64) -> H256 { +pub fn slow_hash_block_number(block_number: u64) -> H256 { SeedHashCompute::resume_compute_seedhash([0u8; 32], 0, block_number / ETHASH_EPOCH_LENGTH) } @@ -214,34 +94,6 @@ fn fnv_hash(x: u32, y: u32) -> u32 { return x.wrapping_mul(FNV_PRIME) ^ y; } -fn sha3_512(input: &[u8], output: &mut [u8]) { - unsafe { sha3::sha3_512(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) }; -} - -fn sha3_512_inplace(input: &mut [u8]) { - // This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This - // means that we can reuse the input buffer for both input and output. - unsafe { sha3::sha3_512(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) }; -} - -fn get_cache_size(block_number: u64) -> usize { - let mut sz: u64 = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH); - sz = sz - NODE_BYTES as u64; - while !is_prime(sz / NODE_BYTES as u64) { - sz = sz - 2 * NODE_BYTES as u64; - } - sz as usize -} - -fn get_data_size(block_number: u64) -> usize { - let mut sz: u64 = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH); - sz = sz - ETHASH_MIX_BYTES as u64; - while !is_prime(sz / ETHASH_MIX_BYTES as u64) { - sz = sz - 2 * ETHASH_MIX_BYTES as u64; - } - sz as usize -} - /// Difficulty quick check for POW preverification /// /// `header_hash` The hash of the header @@ -250,23 +102,23 @@ fn get_data_size(block_number: u64) -> usize { /// Boundary recovered from mix hash pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256) -> H256 { unsafe { - // This is safe - the `sha3_512` call below reads the first 40 bytes (which we explicitly set + // This is safe - the `keccak_512` call below reads the first 40 bytes (which we explicitly set // with two `copy_nonoverlapping` calls) but writes the first 64, and then we explicitly write - // the next 32 bytes before we read the whole thing with `sha3_256`. + // the next 32 bytes before we read the whole thing with `keccak_256`. // // This cannot be elided by the compiler as it doesn't know the implementation of - // `sha3_512`. + // `keccak_512`. let mut buf: [u8; 64 + 32] = mem::uninitialized(); ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32); ptr::copy_nonoverlapping(mem::transmute(&nonce), buf[32..].as_mut_ptr(), 8); - sha3::sha3_512(buf.as_mut_ptr(), 64, buf.as_ptr(), 40); + keccak_512::unchecked(buf.as_mut_ptr(), 64, buf.as_ptr(), 40); ptr::copy_nonoverlapping(mix_hash.as_ptr(), buf[64..].as_mut_ptr(), 32); - // This is initialized in `sha3_256` + // This is initialized in `keccak_256` let mut hash: [u8; 32] = mem::uninitialized(); - sha3::sha3_256(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len()); + keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len()); hash } @@ -320,27 +172,23 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) half_mix: unsafe { // Pack `header_hash` and `nonce` together // We explicitly write the first 40 bytes, leaving the last 24 as uninitialized. Then - // `sha3_512` reads the first 40 bytes (4th parameter) and overwrites the entire array, + // `keccak_512` reads the first 40 bytes (4th parameter) and overwrites the entire array, // leaving it fully initialized. let mut out: [u8; NODE_BYTES] = mem::uninitialized(); - ptr::copy_nonoverlapping( - header_hash.as_ptr(), - out.as_mut_ptr(), - header_hash.len(), - ); + ptr::copy_nonoverlapping(header_hash.as_ptr(), out.as_mut_ptr(), header_hash.len()); ptr::copy_nonoverlapping( mem::transmute(&nonce), out[header_hash.len()..].as_mut_ptr(), mem::size_of::(), ); - // compute sha3-512 hash and replicate across mix - sha3::sha3_512( + // compute keccak-512 hash and replicate across mix + keccak_512::unchecked( out.as_mut_ptr(), NODE_BYTES, out.as_ptr(), - header_hash.len() + mem::size_of::() + header_hash.len() + mem::size_of::(), ); Node { bytes: out } @@ -354,7 +202,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) let page_size = 4 * MIX_WORDS; let num_full_pages = (full_size / page_size) as u32; // deref once for better performance - let cache: &[Node] = &light.cache; + let cache: &[Node] = light.cache.as_ref(); let first_val = buf.half_mix.as_words()[0]; debug_assert_eq!(MIX_NODES, 2); @@ -364,14 +212,10 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) let index = { // This is trivially safe, but does not work on big-endian. The safety of this is // asserted in debug builds (see the definition of `make_const_array!`). - let mix_words: &mut [u32; MIX_WORDS] = unsafe { - make_const_array!(MIX_WORDS, &mut mix) - }; - - fnv_hash( - first_val ^ i, - mix_words[i as usize % MIX_WORDS] - ) % num_full_pages + let mix_words: &mut [u32; MIX_WORDS] = + unsafe { make_const_array!(MIX_WORDS, &mut mix) }; + + fnv_hash(first_val ^ i, mix_words[i as usize % MIX_WORDS]) % num_full_pages }; unroll! { @@ -403,9 +247,8 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) // times and set each index, leaving the array fully initialized. THIS ONLY WORKS ON LITTLE- // ENDIAN MACHINES. See a future PR to make this and the rest of the code work correctly on // big-endian arches like mips. - let mut compress: &mut [u32; MIX_WORDS / 4] = unsafe { - make_const_array!(MIX_WORDS / 4, &mut buf.compress_bytes) - }; + let compress: &mut [u32; MIX_WORDS / 4] = + unsafe { make_const_array!(MIX_WORDS / 4, &mut buf.compress_bytes) }; // Compress mix debug_assert_eq!(MIX_WORDS / 4, 8); @@ -427,10 +270,10 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) let value: H256 = unsafe { // We can interpret the buffer as an array of `u8`s, since it's `repr(C)`. let read_ptr: *const u8 = mem::transmute(&buf); - // We overwrite the second half since `sha3_256` has an internal buffer and so allows + // We overwrite the second half since `keccak_256` has an internal buffer and so allows // overlapping arrays as input. let write_ptr: *mut u8 = mem::transmute(&mut buf.compress_bytes); - sha3::sha3_256( + keccak_256::unchecked( write_ptr, buf.compress_bytes.len(), read_ptr, @@ -439,25 +282,21 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64) buf.compress_bytes }; - ProofOfWork { - mix_hash: mix_hash, - value: value, - } + ProofOfWork { mix_hash: mix_hash, value: value } } +// TODO: Use the `simd` crate fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node { let num_parent_nodes = cache.len(); let mut ret = cache[node_index as usize % num_parent_nodes].clone(); ret.as_words_mut()[0] ^= node_index; - sha3_512_inplace(&mut ret.bytes); + keccak_512::inplace(ret.as_bytes_mut()); debug_assert_eq!(NODE_WORDS, 16); for i in 0..ETHASH_DATASET_PARENTS as u32 { - let parent_index = fnv_hash( - node_index ^ i, - ret.as_words()[i as usize % NODE_WORDS], - ) % num_parent_nodes as u32; + let parent_index = fnv_hash(node_index ^ i, ret.as_words()[i as usize % NODE_WORDS]) % + num_parent_nodes as u32; let parent = &cache[parent_index as usize]; unroll! { @@ -467,159 +306,110 @@ fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node { } } - sha3_512_inplace(&mut ret.bytes); + keccak_512::inplace(ret.as_bytes_mut()); ret } -fn light_new>(cache_dir: T, block_number: u64) -> Light { - let seed_compute = SeedHashCompute::new(); - let seedhash = seed_compute.get_seedhash(block_number); - let cache_size = get_cache_size(block_number); - - assert!(cache_size % NODE_BYTES == 0, "Unaligned cache size"); - let num_nodes = cache_size / NODE_BYTES; - - let mut nodes: Vec = Vec::with_capacity(num_nodes); - unsafe { - // Use uninit instead of unnecessarily writing `size_of::() * num_nodes` 0s - nodes.set_len(num_nodes); - - sha3_512(&seedhash[0..32], &mut nodes.get_unchecked_mut(0).bytes); - for i in 1..num_nodes { - sha3::sha3_512(nodes.get_unchecked_mut(i).bytes.as_mut_ptr(), NODE_BYTES, nodes.get_unchecked(i - 1).bytes.as_ptr(), NODE_BYTES); - } - - debug_assert_eq!(NODE_WORDS, 16); - - // This _should_ get unrolled by the compiler, since it's not using the loop variable. - for _ in 0..ETHASH_CACHE_ROUNDS { - for i in 0..num_nodes { - let idx = *nodes.get_unchecked_mut(i).as_words().get_unchecked(0) as usize % num_nodes; - let mut data = nodes.get_unchecked((num_nodes - 1 + i) % num_nodes).clone(); - - unroll! { - for w in 0..16 { - *data.as_words_mut().get_unchecked_mut(w) ^= *nodes.get_unchecked(idx).as_words().get_unchecked(w); - } - } - - sha3_512(&data.bytes, &mut nodes.get_unchecked_mut(i).bytes); - } - } +#[cfg(test)] +mod test { + use super::*; + use std::fs; + use tempdir::TempDir; + + #[test] + fn test_get_cache_size() { + // https://github.com/ethereum/wiki/wiki/Ethash/ef6b93f9596746a088ea95d01ca2778be43ae68f#data-sizes + assert_eq!(16776896usize, get_cache_size(0)); + assert_eq!(16776896usize, get_cache_size(1)); + assert_eq!(16776896usize, get_cache_size(ETHASH_EPOCH_LENGTH - 1)); + assert_eq!(16907456usize, get_cache_size(ETHASH_EPOCH_LENGTH)); + assert_eq!(16907456usize, get_cache_size(ETHASH_EPOCH_LENGTH + 1)); + assert_eq!(284950208usize, get_cache_size(2046 * ETHASH_EPOCH_LENGTH)); + assert_eq!(285081536usize, get_cache_size(2047 * ETHASH_EPOCH_LENGTH)); + assert_eq!(285081536usize, get_cache_size(2048 * ETHASH_EPOCH_LENGTH - 1)); } - Light { - block_number, - cache_dir: cache_dir.as_ref().to_path_buf(), - cache: nodes, - seed_compute: Mutex::new(seed_compute), + #[test] + fn test_get_data_size() { + // https://github.com/ethereum/wiki/wiki/Ethash/ef6b93f9596746a088ea95d01ca2778be43ae68f#data-sizes + assert_eq!(1073739904usize, get_data_size(0)); + assert_eq!(1073739904usize, get_data_size(1)); + assert_eq!(1073739904usize, get_data_size(ETHASH_EPOCH_LENGTH - 1)); + assert_eq!(1082130304usize, get_data_size(ETHASH_EPOCH_LENGTH)); + assert_eq!(1082130304usize, get_data_size(ETHASH_EPOCH_LENGTH + 1)); + assert_eq!(18236833408usize, get_data_size(2046 * ETHASH_EPOCH_LENGTH)); + assert_eq!(18245220736usize, get_data_size(2047 * ETHASH_EPOCH_LENGTH)); } -} -static CHARS: &'static [u8] = b"0123456789abcdef"; -fn to_hex(bytes: &[u8]) -> String { - let mut v = Vec::with_capacity(bytes.len() * 2); - for &byte in bytes.iter() { - v.push(CHARS[(byte >> 4) as usize]); - v.push(CHARS[(byte & 0xf) as usize]); + #[test] + fn test_difficulty_test() { + let hash = [ + 0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, + 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, + 0x05, 0x52, 0x7d, 0x72, + ]; + let mix_hash = [ + 0x1f, 0xff, 0x04, 0xce, 0xc9, 0x41, 0x73, 0xfd, 0x59, 0x1e, 0x3d, 0x89, 0x60, 0xce, + 0x6b, 0xdf, 0x8b, 0x19, 0x71, 0x04, 0x8c, 0x71, 0xff, 0x93, 0x7b, 0xb2, 0xd3, 0x2a, + 0x64, 0x31, 0xab, 0x6d, + ]; + let nonce = 0xd7b3ac70a301a249; + let boundary_good = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3e, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, + 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, + 0xe9, 0x7e, 0x53, 0x84, + ]; + assert_eq!(quick_get_difficulty(&hash, nonce, &mix_hash)[..], boundary_good[..]); + let boundary_bad = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, + 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, + 0xe9, 0x7e, 0x53, 0x84, + ]; + assert!(quick_get_difficulty(&hash, nonce, &mix_hash)[..] != boundary_bad[..]); } - unsafe { String::from_utf8_unchecked(v) } -} - -#[test] -fn test_get_cache_size() { - // https://github.com/ethereum/wiki/wiki/Ethash/ef6b93f9596746a088ea95d01ca2778be43ae68f#data-sizes - assert_eq!(16776896usize, get_cache_size(0)); - assert_eq!(16776896usize, get_cache_size(1)); - assert_eq!(16776896usize, get_cache_size(ETHASH_EPOCH_LENGTH - 1)); - assert_eq!(16907456usize, get_cache_size(ETHASH_EPOCH_LENGTH)); - assert_eq!(16907456usize, get_cache_size(ETHASH_EPOCH_LENGTH + 1)); - assert_eq!(284950208usize, get_cache_size(2046 * ETHASH_EPOCH_LENGTH)); - assert_eq!(285081536usize, get_cache_size(2047 * ETHASH_EPOCH_LENGTH)); - assert_eq!(285081536usize, get_cache_size(2048 * ETHASH_EPOCH_LENGTH - 1)); -} - -#[test] -fn test_get_data_size() { - // https://github.com/ethereum/wiki/wiki/Ethash/ef6b93f9596746a088ea95d01ca2778be43ae68f#data-sizes - assert_eq!(1073739904usize, get_data_size(0)); - assert_eq!(1073739904usize, get_data_size(1)); - assert_eq!(1073739904usize, get_data_size(ETHASH_EPOCH_LENGTH - 1)); - assert_eq!(1082130304usize, get_data_size(ETHASH_EPOCH_LENGTH)); - assert_eq!(1082130304usize, get_data_size(ETHASH_EPOCH_LENGTH + 1)); - assert_eq!(18236833408usize, get_data_size(2046 * ETHASH_EPOCH_LENGTH)); - assert_eq!(18245220736usize, get_data_size(2047 * ETHASH_EPOCH_LENGTH)); -} - -#[test] -fn test_difficulty_test() { - let hash = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72]; - let mix_hash = [0x1f, 0xff, 0x04, 0xce, 0xc9, 0x41, 0x73, 0xfd, 0x59, 0x1e, 0x3d, 0x89, 0x60, 0xce, 0x6b, 0xdf, 0x8b, 0x19, 0x71, 0x04, 0x8c, 0x71, 0xff, 0x93, 0x7b, 0xb2, 0xd3, 0x2a, 0x64, 0x31, 0xab, 0x6d]; - let nonce = 0xd7b3ac70a301a249; - let boundary_good = [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3e, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, 0xe9, 0x7e, 0x53, 0x84]; - assert_eq!(quick_get_difficulty(&hash, nonce, &mix_hash)[..], boundary_good[..]); - let boundary_bad = [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3a, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, 0xe9, 0x7e, 0x53, 0x84]; - assert!(quick_get_difficulty(&hash, nonce, &mix_hash)[..] != boundary_bad[..]); -} - -#[test] -fn test_light_compute() { - let hash = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72]; - let mix_hash = [0x1f, 0xff, 0x04, 0xce, 0xc9, 0x41, 0x73, 0xfd, 0x59, 0x1e, 0x3d, 0x89, 0x60, 0xce, 0x6b, 0xdf, 0x8b, 0x19, 0x71, 0x04, 0x8c, 0x71, 0xff, 0x93, 0x7b, 0xb2, 0xd3, 0x2a, 0x64, 0x31, 0xab, 0x6d]; - let boundary = [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3e, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, 0xe9, 0x7e, 0x53, 0x84]; - let nonce = 0xd7b3ac70a301a249; - // difficulty = 0x085657254bd9u64; - let light = Light::new(&::std::env::temp_dir(), 486382); - let result = light_compute(&light, &hash, nonce); - assert_eq!(result.mix_hash[..], mix_hash[..]); - assert_eq!(result.value[..], boundary[..]); -} - -#[test] -fn test_seed_compute_once() { - let seed_compute = SeedHashCompute::new(); - let hash = [241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253, 147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162]; - assert_eq!(seed_compute.get_seedhash(486382), hash); -} - -#[test] -fn test_seed_compute_zero() { - let seed_compute = SeedHashCompute::new(); - assert_eq!(seed_compute.get_seedhash(0), [0u8; 32]); -} - -#[test] -fn test_seed_compute_after_older() { - let seed_compute = SeedHashCompute::new(); - // calculating an older value first shouldn't affect the result - let _ = seed_compute.get_seedhash(50000); - let hash = [241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253, 147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162]; - assert_eq!(seed_compute.get_seedhash(486382), hash); -} - -#[test] -fn test_seed_compute_after_newer() { - let seed_compute = SeedHashCompute::new(); - // calculating an newer value first shouldn't affect the result - let _ = seed_compute.get_seedhash(972764); - let hash = [241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253, 147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162]; - assert_eq!(seed_compute.get_seedhash(486382), hash); -} + #[test] + fn test_light_compute() { + let hash = [ + 0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, + 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, + 0x05, 0x52, 0x7d, 0x72, + ]; + let mix_hash = [ + 0x1f, 0xff, 0x04, 0xce, 0xc9, 0x41, 0x73, 0xfd, 0x59, 0x1e, 0x3d, 0x89, 0x60, 0xce, + 0x6b, 0xdf, 0x8b, 0x19, 0x71, 0x04, 0x8c, 0x71, 0xff, 0x93, 0x7b, 0xb2, 0xd3, 0x2a, + 0x64, 0x31, 0xab, 0x6d, + ]; + let boundary = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3e, 0x9b, 0x6c, 0x69, 0xbc, 0x2c, 0xe2, 0xa2, + 0x4a, 0x8e, 0x95, 0x69, 0xef, 0xc7, 0xd7, 0x1b, 0x33, 0x35, 0xdf, 0x36, 0x8c, 0x9a, + 0xe9, 0x7e, 0x53, 0x84, + ]; + let nonce = 0xd7b3ac70a301a249; + + let tempdir = TempDir::new("").unwrap(); + // difficulty = 0x085657254bd9u64; + let light = NodeCacheBuilder::new(None).light(tempdir.path(), 486382); + let result = light_compute(&light, &hash, nonce); + assert_eq!(result.mix_hash[..], mix_hash[..]); + assert_eq!(result.value[..], boundary[..]); + } -#[test] -fn test_drop_old_data() { - let path = ::std::env::temp_dir(); - let first = Light::new(&path, 0).to_file().unwrap(); + #[test] + fn test_drop_old_data() { + let tempdir = TempDir::new("").unwrap(); + let builder = NodeCacheBuilder::new(None); + let first = builder.light(tempdir.path(), 0).to_file().unwrap().to_owned(); - let second = Light::new(&path, ETHASH_EPOCH_LENGTH).to_file().unwrap(); - assert!(fs::metadata(&first).is_ok()); + let second = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH).to_file().unwrap().to_owned(); + assert!(fs::metadata(&first).is_ok()); - let _ = Light::new(&path, ETHASH_EPOCH_LENGTH * 2).to_file(); - assert!(fs::metadata(&first).is_err()); - assert!(fs::metadata(&second).is_ok()); + let _ = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH * 2).to_file(); + assert!(fs::metadata(&first).is_err()); + assert!(fs::metadata(&second).is_ok()); - let _ = Light::new(&path, ETHASH_EPOCH_LENGTH * 3).to_file(); - assert!(fs::metadata(&second).is_err()); + let _ = builder.light(tempdir.path(), ETHASH_EPOCH_LENGTH * 3).to_file(); + assert!(fs::metadata(&second).is_err()); + } } diff --git a/ethash/src/keccak.rs b/ethash/src/keccak.rs new file mode 100644 index 0000000000000000000000000000000000000000..8ca4f543844362f13e27a73ea3efb6889f28d257 --- /dev/null +++ b/ethash/src/keccak.rs @@ -0,0 +1,52 @@ +// 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 . + +extern crate keccak_hash as hash; + +pub type H256 = [u8; 32]; + +pub mod keccak_512 { + use super::hash; + + pub use self::hash::keccak_512 as unchecked; + + pub fn write(input: &[u8], output: &mut [u8]) { + unsafe { hash::keccak_512(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) }; + } + + pub fn inplace(input: &mut [u8]) { + // This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This + // means that we can reuse the input buffer for both input and output. + unsafe { hash::keccak_512(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) }; + } +} + +pub mod keccak_256 { + use super::hash; + + pub use self::hash::keccak_256 as unchecked; + + #[allow(dead_code)] + pub fn write(input: &[u8], output: &mut [u8]) { + unsafe { hash::keccak_256(output.as_mut_ptr(), output.len(), input.as_ptr(), input.len()) }; + } + + pub fn inplace(input: &mut [u8]) { + // This is safe since `sha3_*` uses an internal buffer and copies the result to the output. This + // means that we can reuse the input buffer for both input and output. + unsafe { hash::keccak_256(input.as_mut_ptr(), input.len(), input.as_ptr(), input.len()) }; + } +} diff --git a/ethash/src/lib.rs b/ethash/src/lib.rs index 9112546c443a711806fa83a93b087b733f9ef407..9d0c669d9c8c7454774d132699b4196d3a31b915 100644 --- a/ethash/src/lib.rs +++ b/ethash/src/lib.rs @@ -14,28 +14,38 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Ethash implementation -//! See https://github.com/ethereum/wiki/wiki/Ethash - #![cfg_attr(feature = "benches", feature(test))] extern crate primal; -extern crate sha3; extern crate parking_lot; +extern crate either; +extern crate memmap; #[macro_use] extern crate crunchy; #[macro_use] extern crate log; + +#[cfg(test)] +extern crate tempdir; + mod compute; +mod seed_compute; +mod cache; +mod keccak; +mod shared; +pub use cache::{NodeCacheBuilder, OptimizeFor}; +pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number}; +use compute::Light; +use keccak::H256; +use parking_lot::Mutex; +pub use seed_compute::SeedHashCompute; +pub use shared::ETHASH_EPOCH_LENGTH; use std::mem; use std::path::{Path, PathBuf}; -use compute::Light; -pub use compute::{ETHASH_EPOCH_LENGTH, H256, ProofOfWork, SeedHashCompute, quick_get_difficulty, slow_get_seedhash}; use std::sync::Arc; -use parking_lot::Mutex; struct LightCache { recent_epoch: Option, @@ -46,15 +56,17 @@ struct LightCache { /// Light/Full cache manager. pub struct EthashManager { + nodecache_builder: NodeCacheBuilder, cache: Mutex, cache_dir: PathBuf, } impl EthashManager { /// Create a new new instance of ethash manager - pub fn new>(cache_dir: T) -> EthashManager { + pub fn new>>(cache_dir: &Path, optimize_for: T) -> EthashManager { EthashManager { - cache_dir: cache_dir.as_ref().to_path_buf(), + cache_dir: cache_dir.to_path_buf(), + nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default()), cache: Mutex::new(LightCache { recent_epoch: None, recent: None, @@ -96,11 +108,17 @@ impl EthashManager { }; match light { None => { - let light = match Light::from_file(&self.cache_dir, block_number) { + let light = match self.nodecache_builder.light_from_file( + &self.cache_dir, + block_number, + ) { Ok(light) => Arc::new(light), Err(e) => { debug!("Light cache file not found for {}:{}", block_number, e); - let light = Light::new(&self.cache_dir, block_number); + let mut light = self.nodecache_builder.light( + &self.cache_dir, + block_number, + ); if let Err(e) = light.to_file() { warn!("Light cache file write error: {}", e); } @@ -120,7 +138,10 @@ impl EthashManager { #[test] fn test_lru() { - let ethash = EthashManager::new(&::std::env::temp_dir()); + use tempdir::TempDir; + + let tempdir = TempDir::new("").unwrap(); + let ethash = EthashManager::new(tempdir.path(), None); let hash = [0u8; 32]; ethash.compute_light(1, &hash, 1); ethash.compute_light(50000, &hash, 1); @@ -138,24 +159,95 @@ fn test_lru() { mod benchmarks { extern crate test; - use compute::{Light, light_compute, SeedHashCompute}; use self::test::Bencher; + use cache::{NodeCacheBuilder, OptimizeFor}; + use compute::{Light, light_compute}; + + const HASH: [u8; 32] = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, + 0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, + 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72]; + const NONCE: u64 = 0xd7b3ac70a301a249; + + #[bench] + fn bench_light_compute_memmap(b: &mut Bencher) { + use std::env; + + let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let light = builder.light(&env::temp_dir(), 486382); + + b.iter(|| light_compute(&light, &HASH, NONCE)); + } #[bench] - fn bench_light_compute(b: &mut Bencher) { - use ::std::env; + fn bench_light_compute_memory(b: &mut Bencher) { + use std::env; - let hash = [0xf5, 0x7e, 0x6f, 0x3a, 0xcf, 0xc0, 0xdd, 0x4b, 0x5b, 0xf2, 0xbe, 0xe4, 0x0a, 0xb3, 0x35, 0x8a, 0xa6, 0x87, 0x73, 0xa8, 0xd0, 0x9f, 0x5e, 0x59, 0x5e, 0xab, 0x55, 0x94, 0x05, 0x52, 0x7d, 0x72]; - let nonce = 0xd7b3ac70a301a249; - let light = Light::new(env::temp_dir(), 486382); + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let light = builder.light(&env::temp_dir(), 486382); - b.iter(|| light_compute(&light, &hash, nonce)); + b.iter(|| light_compute(&light, &HASH, NONCE)); } #[bench] - fn bench_seedhash(b: &mut Bencher) { - let seed_compute = SeedHashCompute::new(); + #[ignore] + fn bench_light_new_round_trip_memmap(b: &mut Bencher) { + use std::env; + + b.iter(|| { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let light = builder.light(&env::temp_dir(), 486382); + light_compute(&light, &HASH, NONCE); + }); + } + + #[bench] + #[ignore] + fn bench_light_new_round_trip_memory(b: &mut Bencher) { + use std::env; + + b.iter(|| { + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let light = builder.light(&env::temp_dir(), 486382); + light_compute(&light, &HASH, NONCE); + }); + } + + #[bench] + fn bench_light_from_file_round_trip_memory(b: &mut Bencher) { + use std::env; + + let dir = env::temp_dir(); + let height = 486382; + { + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let mut dummy = builder.light(&dir, height); + dummy.to_file().unwrap(); + } + + b.iter(|| { + let builder = NodeCacheBuilder::new(OptimizeFor::Cpu); + let light = builder.light_from_file(&dir, 486382).unwrap(); + light_compute(&light, &HASH, NONCE); + }); + } + + #[bench] + fn bench_light_from_file_round_trip_memmap(b: &mut Bencher) { + use std::env; + + let dir = env::temp_dir(); + let height = 486382; + + { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let mut dummy = builder.light(&dir, height); + dummy.to_file().unwrap(); + } - b.iter(|| seed_compute.get_seedhash(486382)); + b.iter(|| { + let builder = NodeCacheBuilder::new(OptimizeFor::Memory); + let light = builder.light_from_file(&dir, 486382).unwrap(); + light_compute(&light, &HASH, NONCE); + }); } } diff --git a/ethash/src/seed_compute.rs b/ethash/src/seed_compute.rs new file mode 100644 index 0000000000000000000000000000000000000000..04774b3e39e507609c54db43ee1bccd0ca972e8a --- /dev/null +++ b/ethash/src/seed_compute.rs @@ -0,0 +1,109 @@ +// 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 . + +use shared; +use keccak::{keccak_256, H256}; + +use std::cell::Cell; + +pub struct SeedHashCompute { + prev_epoch: Cell, + prev_seedhash: Cell, +} + +impl SeedHashCompute { + #[inline] + pub fn new() -> SeedHashCompute { + SeedHashCompute { + prev_epoch: Cell::new(0), + prev_seedhash: Cell::new([0u8; 32]), + } + } + + #[inline] + fn reset_cache(&self) { + self.prev_epoch.set(0); + self.prev_seedhash.set([0u8; 32]); + } + + #[inline] + pub fn hash_block_number(&self, block_number: u64) -> H256 { + self.hash_epoch(shared::epoch(block_number)) + } + + #[inline] + pub fn hash_epoch(&self, epoch: u64) -> H256 { + if epoch < self.prev_epoch.get() { + // can't build on previous hash if requesting an older block + self.reset_cache(); + } + if epoch > self.prev_epoch.get() { + let seed_hash = SeedHashCompute::resume_compute_seedhash( + self.prev_seedhash.get(), + self.prev_epoch.get(), + epoch, + ); + self.prev_seedhash.set(seed_hash); + self.prev_epoch.set(epoch); + } + self.prev_seedhash.get() + } + + #[inline] + pub fn resume_compute_seedhash(mut hash: H256, start_epoch: u64, end_epoch: u64) -> H256 { + for _ in start_epoch..end_epoch { + keccak_256::inplace(&mut hash); + } + hash + } +} + +#[cfg(test)] +mod tests { + use super::SeedHashCompute; + + #[test] + fn test_seed_compute_once() { + let seed_compute = SeedHashCompute::new(); + let hash = [241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253, 147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162]; + assert_eq!(seed_compute.hash_block_number(486382), hash); + } + + #[test] + fn test_seed_compute_zero() { + let seed_compute = SeedHashCompute::new(); + assert_eq!(seed_compute.hash_block_number(0), [0u8; 32]); + } + + #[test] + fn test_seed_compute_after_older() { + let seed_compute = SeedHashCompute::new(); + // calculating an older value first shouldn't affect the result + let _ = seed_compute.hash_block_number(50000); + let hash = [241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253, 147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162]; + assert_eq!(seed_compute.hash_block_number(486382), hash); + } + + #[test] + fn test_seed_compute_after_newer() { + let seed_compute = SeedHashCompute::new(); + // calculating an newer value first shouldn't affect the result + let _ = seed_compute.hash_block_number(972764); + let hash = [241, 175, 44, 134, 39, 121, 245, 239, 228, 236, 43, 160, 195, 152, 46, 7, 199, 5, 253, 147, 241, 206, 98, 43, 3, 104, 17, 40, 192, 79, 106, 162]; + assert_eq!(seed_compute.hash_block_number(486382), hash); + } + +} diff --git a/ethash/src/shared.rs b/ethash/src/shared.rs new file mode 100644 index 0000000000000000000000000000000000000000..39e1c8eb88479513b64de007d8b8ed4b2e76b7bf --- /dev/null +++ b/ethash/src/shared.rs @@ -0,0 +1,149 @@ +// 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 . + +use primal::is_prime; + +pub const DATASET_BYTES_INIT: u64 = 1 << 30; +pub const DATASET_BYTES_GROWTH: u64 = 1 << 23; +pub const CACHE_BYTES_INIT: u64 = 1 << 24; +pub const CACHE_BYTES_GROWTH: u64 = 1 << 17; + +pub const ETHASH_EPOCH_LENGTH: u64 = 30000; +pub const ETHASH_CACHE_ROUNDS: usize = 3; +pub const ETHASH_MIX_BYTES: usize = 128; +pub const ETHASH_ACCESSES: usize = 64; +pub const ETHASH_DATASET_PARENTS: u32 = 256; +pub const NODE_DWORDS: usize = NODE_WORDS / 2; +pub const NODE_WORDS: usize = NODE_BYTES / 4; +pub const NODE_BYTES: usize = 64; + +pub fn epoch(block_number: u64) -> u64 { + block_number / ETHASH_EPOCH_LENGTH +} + +static CHARS: &'static [u8] = b"0123456789abcdef"; +pub fn to_hex(bytes: &[u8]) -> String { + let mut v = Vec::with_capacity(bytes.len() * 2); + for &byte in bytes.iter() { + v.push(CHARS[(byte >> 4) as usize]); + v.push(CHARS[(byte & 0xf) as usize]); + } + + unsafe { String::from_utf8_unchecked(v) } +} + +pub fn get_cache_size(block_number: u64) -> usize { + // TODO: Memoise + let mut sz: u64 = CACHE_BYTES_INIT + CACHE_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH); + sz = sz - NODE_BYTES as u64; + while !is_prime(sz / NODE_BYTES as u64) { + sz = sz - 2 * NODE_BYTES as u64; + } + sz as usize +} + +pub fn get_data_size(block_number: u64) -> usize { + // TODO: Memoise + let mut sz: u64 = DATASET_BYTES_INIT + DATASET_BYTES_GROWTH * (block_number / ETHASH_EPOCH_LENGTH); + sz = sz - ETHASH_MIX_BYTES as u64; + while !is_prime(sz / ETHASH_MIX_BYTES as u64) { + sz = sz - 2 * ETHASH_MIX_BYTES as u64; + } + sz as usize +} + +pub type NodeBytes = [u8; NODE_BYTES]; +pub type NodeWords = [u32; NODE_WORDS]; +pub type NodeDwords = [u64; NODE_DWORDS]; + +macro_rules! static_assert_size_eq { + (@inner $a:ty, $b:ty, $($rest:ty),*) => { + fn first() { + static_assert_size_eq!($a, $b); + } + + fn second() { + static_assert_size_eq!($b, $($rest),*); + } + }; + (@inner $a:ty, $b:ty) => { + unsafe { + let val: $b = ::std::mem::uninitialized(); + let _: $a = ::std::mem::transmute(val); + } + }; + ($($rest:ty),*) => { + static_assert_size_eq!(size_eq: $($rest),*); + }; + ($name:ident : $($rest:ty),*) => { + #[allow(dead_code)] + fn $name() { + static_assert_size_eq!(@inner $($rest),*); + } + }; +} + +static_assert_size_eq!(Node, NodeBytes, NodeWords, NodeDwords); + +#[repr(C)] +pub union Node { + pub dwords: NodeDwords, + pub words: NodeWords, + pub bytes: NodeBytes, +} + +impl Clone for Node { + fn clone(&self) -> Self { + unsafe { Node { bytes: *&self.bytes } } + } +} + +// We use `inline(always)` because I was experiencing an 100% slowdown and `perf` showed that these +// calls were taking up ~30% of the runtime. Adding these annotations fixes the issue. Remove at +// your peril, if and only if you have benchmarks to prove that this doesn't reintroduce the +// performance regression. It's not caused by the `debug_assert_eq!` either, your guess is as good +// as mine. +impl Node { + #[inline(always)] + pub fn as_bytes(&self) -> &NodeBytes { + unsafe { &self.bytes } + } + + #[inline(always)] + pub fn as_bytes_mut(&mut self) -> &mut NodeBytes { + unsafe { &mut self.bytes } + } + + #[inline(always)] + pub fn as_words(&self) -> &NodeWords { + unsafe { &self.words } + } + + #[inline(always)] + pub fn as_words_mut(&mut self) -> &mut NodeWords { + unsafe { &mut self.words } + } + + #[inline(always)] + pub fn as_dwords(&self) -> &NodeDwords { + unsafe { &self.dwords } + } + + #[inline(always)] + pub fn as_dwords_mut(&mut self) -> &mut NodeDwords { + unsafe { &mut self.dwords } + } +} diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index c49e318989b994b5af39313e8cd7e81f0c49dcfa..065bbc5cc5999ca4fc3c3937d3f669d4eb4896f9 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -3,74 +3,84 @@ description = "Ethcore library" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] -build = "build.rs" - -[build-dependencies] -"ethcore-ipc-codegen" = { path = "../ipc/codegen" } [dependencies] -bit-set = "0.4" -bloomchain = "0.1" -bn = { git = "https://github.com/paritytech/bn" } +ansi_term = "0.10" +bloomchain = { path = "../util/bloomchain" } +bn = { git = "https://github.com/paritytech/bn", default-features = false } byteorder = "1.0" -clippy = { version = "0.0.103", optional = true} common-types = { path = "types" } -crossbeam = "0.2.9" -env_logger = "0.4" -ethabi = "2.0" +crossbeam = "0.3" ethash = { path = "../ethash" } ethcore-bloom-journal = { path = "../util/bloom" } -ethcore-devtools = { path = "../devtools" } +ethcore-bytes = { path = "../util/bytes" } +hashdb = { path = "../util/hashdb" } +memorydb = { path = "../util/memorydb" } +patricia-trie = { path = "../util/patricia_trie" } ethcore-io = { path = "../util/io" } -ethcore-ipc = { path = "../ipc/rpc" } -ethcore-ipc-nano = { path = "../ipc/nano" } ethcore-logger = { path = "../logger" } +ethcore-miner = { path = "../miner" } ethcore-stratum = { path = "../stratum" } -ethcore-util = { path = "../util" } +ethcore-transaction = { path = "./transaction" } +ethereum-types = "0.2" +memory-cache = { path = "../util/memory_cache" } +ethabi = "5.1" +ethabi-derive = "5.0" +ethabi-contract = "5.0" ethjson = { path = "../json" } ethkey = { path = "../ethkey" } ethstore = { path = "../ethstore" } evm = { path = "evm" } -futures = "0.1" +futures-cpupool = "0.1" hardware-wallet = { path = "../hw" } -hyper = { git = "https://github.com/paritytech/hyper", default-features = false } +heapsize = "0.4" itertools = "0.5" -lazy_static = "0.2" -linked-hash-map = "0.3.0" +lazy_static = "1.0" log = "0.3" -lru-cache = "0.1.0" -native-contracts = { path = "native_contracts" } -num = "0.1" +lru-cache = "0.1" +num = { version = "0.1", default-features = false, features = ["bigint"] } num_cpus = "1.2" +parity-machine = { path = "../machine" } +parking_lot = "0.5" price-info = { path = "../price-info" } -rand = "0.3" +rayon = "0.8" +rand = "0.4" rlp = { path = "../util/rlp" } +rlp_compress = { path = "../util/rlp_compress" } rlp_derive = { path = "../util/rlp_derive" } +kvdb = { path = "../util/kvdb" } +kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } +kvdb-memorydb = { path = "../util/kvdb-memorydb" } +util-error = { path = "../util/error" } +snappy = { git = "https://github.com/paritytech/rust-snappy" } +stop-guard = { path = "../util/stop-guard" } +migration = { path = "../util/migration" } +macros = { path = "../util/macros" } rust-crypto = "0.2.34" rustc-hex = "1.0" -semver = "0.6" stats = { path = "../util/stats" } -time = "0.1" -transient-hashmap = "0.4" +trace-time = { path = "../util/trace-time" } using_queue = { path = "../util/using_queue" } table = { path = "../util/table" } -bloomable = { path = "../util/bloomable" } vm = { path = "vm" } wasm = { path = "wasm" } +keccak-hash = { path = "../util/hash" } +triehash = { path = "../util/triehash" } +unexpected = { path = "../util/unexpected" } +journaldb = { path = "../util/journaldb" } [dev-dependencies] -native-contracts = { path = "native_contracts", features = ["test_contracts"] } +tempdir = "0.3" +trie-standardmap = { path = "../util/trie-standardmap" } [features] jit = ["evm/jit"] evm-debug = ["slow-blocks"] -evm-debug-tests = ["evm-debug"] +evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"] slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms -json-tests = [] +json-tests = ["ethcore-transaction/json-tests"] test-heavy = [] -dev = ["clippy"] default = [] benches = [] -ipc = [] diff --git a/ethcore/benches/evm.rs b/ethcore/benches/evm.rs new file mode 100644 index 0000000000000000000000000000000000000000..324e3382e57603b6be8706fef472d1c904595d42 --- /dev/null +++ b/ethcore/benches/evm.rs @@ -0,0 +1,98 @@ +// 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 . + +#![feature(test)] + +extern crate test; +extern crate ethcore_util as util; +extern crate rand; +extern crate bn; +extern crate crypto; +extern crate ethkey; +extern crate rustc_hex; +extern crate ethcore_bigint; + +use self::test::{Bencher}; +use rand::{StdRng}; + + +#[bench] +fn bn_128_pairing(b: &mut Bencher) { + use bn::{pairing, G1, G2, Fr, Group}; + + let rng = &mut ::rand::thread_rng(); + + let sk0 = Fr::random(rng); + let sk1 = Fr::random(rng); + + let pk0 = G1::one() * sk0; + let pk1 = G2::one() * sk1; + + b.iter(|| { + let _ = pairing(pk0, pk1); + }); +} + +#[bench] +fn bn_128_mul(b: &mut Bencher) { + use bn::{AffineG1, G1, Fr, Group}; + + let mut rng = StdRng::new().unwrap(); + let p: G1 = G1::random(&mut rng); + let fr = Fr::random(&mut rng); + + b.iter(|| { + let _ = AffineG1::from_jacobian(p * fr); + }); +} + +#[bench] +fn sha256(b: &mut Bencher) { + use crypto::sha2::Sha256; + use crypto::digest::Digest; + + let mut input: [u8; 256] = [0; 256]; + let mut out = [0; 32]; + + b.iter(|| { + let mut sha = Sha256::new(); + sha.input(&input); + sha.result(&mut input[0..32]); + }); +} + +#[bench] +fn ecrecover(b: &mut Bencher) { + use rustc_hex::FromHex; + use ethkey::{Signature, recover as ec_recover}; + use ethcore_bigint::hash::H256; + let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let hash = H256::from_slice(&input[0..32]); + let v = H256::from_slice(&input[32..64]); + let r = H256::from_slice(&input[64..96]); + let s = H256::from_slice(&input[96..128]); + + let bit = match v[31] { + 27 | 28 if &v.0[..31] == &[0; 31] => v[31] - 27, + _ => { return; }, + }; + + let s = Signature::from_rsv(&r, &s, bit); + b.iter(|| { + let _ = ec_recover(&s, &hash); + }); +} + diff --git a/ethcore/build.rs b/ethcore/build.rs deleted file mode 100644 index 8fe38e757f8ddca6c9c910fae5f8f219b10d1b66..0000000000000000000000000000000000000000 --- a/ethcore/build.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -extern crate ethcore_ipc_codegen; - -fn main() { - ethcore_ipc_codegen::derive_ipc_cond("src/client/traits.rs", cfg!(feature="ipc")).unwrap(); - ethcore_ipc_codegen::derive_ipc_cond("src/snapshot/snapshot_service_trait.rs", cfg!(feature="ipc")).unwrap(); - ethcore_ipc_codegen::derive_ipc_cond("src/client/chain_notify.rs", cfg!(feature="ipc")).unwrap(); -} diff --git a/ethcore/evm/Cargo.toml b/ethcore/evm/Cargo.toml index 2780703da07b8498f96b5ae722ec3a486b11c775..6efc05f4e2f0484ae7d7ee6f915e14a6d224d92d 100644 --- a/ethcore/evm/Cargo.toml +++ b/ethcore/evm/Cargo.toml @@ -5,21 +5,20 @@ authors = ["Parity Technologies "] [dependencies] bit-set = "0.4" -byteorder = "1.0" -common-types = { path = "../types" } -ethcore-util = { path = "../../util" } +ethereum-types = "0.2" evmjit = { path = "../../evmjit", optional = true } -ethjson = { path = "../../json" } -lazy_static = "0.2" +heapsize = "0.4" +lazy_static = "1.0" log = "0.3" -rlp = { path = "../../util/rlp" } vm = { path = "../vm" } -parity-wasm = "0.12" -ethcore-logger = { path = "../../logger" } -wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } +keccak-hash = { path = "../../util/hash" } +parking_lot = "0.5" +memory-cache = { path = "../../util/memory_cache" } [dev-dependencies] rustc-hex = "1.0" [features] jit = ["evmjit"] +evm-debug = [] +evm-debug-tests = ["evm-debug"] diff --git a/ethcore/evm/src/benches/mod.rs b/ethcore/evm/src/benches/mod.rs index ecb7d379adf1fa2e46ef363001dcb218d4bf956a..c87fda7bbfb538a980919733c5c9b0c7c9bee847 100644 --- a/ethcore/evm/src/benches/mod.rs +++ b/ethcore/evm/src/benches/mod.rs @@ -24,6 +24,8 @@ extern crate test; use self::test::{Bencher, black_box}; +use bigint::prelude::U256; +use bigint::hash::H256; use util::*; use vm::ActionParams; use evm::{self, Factory, VMType}; diff --git a/ethcore/evm/src/evm.rs b/ethcore/evm/src/evm.rs index d593143a6399f6a7c7b6d285860469a47dd0c91c..16dffe77c5381d9bf368b78916535c284532ea29 100644 --- a/ethcore/evm/src/evm.rs +++ b/ethcore/evm/src/evm.rs @@ -17,7 +17,7 @@ //! Evm interface. use std::{ops, cmp, fmt}; -use util::{U128, U256, U512}; +use ethereum_types::{U128, U256, U512}; use vm::{Ext, Result, ReturnData, GasLeft, Error}; /// Finalization result. Gas Left: either it is a known value, or it needs to be computed by processing @@ -45,7 +45,7 @@ impl Finalize for Result { fn finalize(self, ext: E) -> Result { match self { Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }), - Ok(GasLeft::NeedsReturn {gas_left, data, apply_state}) => ext.ret(&gas_left, &data).map(|gas_left| FinalizationResult { + Ok(GasLeft::NeedsReturn {gas_left, data, apply_state}) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult { gas_left: gas_left, apply_state: apply_state, return_data: data, @@ -149,7 +149,7 @@ impl CostType for usize { #[cfg(test)] mod tests { - use util::U256; + use ethereum_types::U256; use super::CostType; #[test] diff --git a/ethcore/evm/src/factory.rs b/ethcore/evm/src/factory.rs index 20275dbff540fd0974f37557dde23df8222edfc4..140f1620a309fd7fb1b196dafa2d0b66af4c69ce 100644 --- a/ethcore/evm/src/factory.rs +++ b/ethcore/evm/src/factory.rs @@ -18,7 +18,7 @@ //! use std::sync::Arc; use vm::Vm; -use util::U256; +use ethereum_types::U256; use super::interpreter::SharedCache; use super::vmtype::VMType; @@ -33,7 +33,7 @@ impl Factory { /// Create fresh instance of VM /// Might choose implementation depending on supplied gas. #[cfg(feature = "jit")] - pub fn create(&self, gas: U256) -> Box { + pub fn create(&self, gas: &U256) -> Box { match self.evm { VMType::Jit => { Box::new(super::jit::JitEvm::default()) @@ -49,7 +49,7 @@ impl Factory { /// Create fresh instance of VM /// Might choose implementation depending on supplied gas. #[cfg(not(feature = "jit"))] - pub fn create(&self, gas: U256) -> Box { + pub fn create(&self, gas: &U256) -> Box { match self.evm { VMType::Interpreter => if Self::can_fit_in_usize(gas) { Box::new(super::interpreter::Interpreter::::new(self.evm_cache.clone())) @@ -68,8 +68,8 @@ impl Factory { } } - fn can_fit_in_usize(gas: U256) -> bool { - gas == U256::from(gas.low_u64() as usize) + fn can_fit_in_usize(gas: &U256) -> bool { + gas == &U256::from(gas.low_u64() as usize) } } @@ -95,7 +95,7 @@ impl Default for Factory { #[test] fn test_create_vm() { - let _vm = Factory::default().create(U256::zero()); + let _vm = Factory::default().create(&U256::zero()); } /// Create tests by injecting different VM factories diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 83be0c95460e1b2cda0e670fb9e5f556d9d3e6d8..3fb9fb933962a48b2489c5684c19defc63cec6ff 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -81,7 +81,7 @@ fn test_get_swap_position() { assert_eq!(get_swap_position(SWAP10), 10); } -/// Returns number of topcis to take from stack +/// Returns number of topics to take from stack /// LOG0 -> 0 pub fn get_log_topics (i: Instruction) -> usize { assert!(i >= LOG0 && i <= LOG4); diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 161c7db39b6108dc2a712657636866edaae6e4d6..beb22447fe4c08257d27868c040e93d8d2d87db9 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::cmp; -use util::*; +use ethereum_types::{U256, H256}; use super::u256_to_address; use {evm, vm}; @@ -31,7 +31,6 @@ macro_rules! overflowing { }} } -#[cfg_attr(feature="dev", allow(enum_variant_names))] enum Request { Gas(Cost), GasMem(Cost, Cost), @@ -100,7 +99,6 @@ impl Gasometer { } } - #[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` diff --git a/ethcore/evm/src/interpreter/informant.rs b/ethcore/evm/src/interpreter/informant.rs index a2a2c84c55690c127e03b5b8f51bca5bdb044e6d..f07d11ff7aa5f3a86f5020eff29a0bc624efb5de 100644 --- a/ethcore/evm/src/interpreter/informant.rs +++ b/ethcore/evm/src/interpreter/informant.rs @@ -39,11 +39,11 @@ mod inner { use std::collections::HashMap; use std::time::{Instant, Duration}; - use evm::interpreter::stack::Stack; - use evm::instructions::{Instruction, InstructionInfo, INSTRUCTIONS}; - use evm::{CostType}; + use bigint::prelude::U256; - use util::U256; + use interpreter::stack::Stack; + use instructions::{Instruction, InstructionInfo, INSTRUCTIONS}; + use CostType; macro_rules! evm_debug { ($x: expr) => { @@ -110,7 +110,7 @@ mod inner { } pub fn after_instruction(&mut self, instruction: Instruction) { - let mut stats = self.stats.entry(instruction).or_insert_with(|| Stats::default()); + let stats = self.stats.entry(instruction).or_insert_with(|| Stats::default()); let took = self.last_instruction.elapsed(); stats.note(took); } diff --git a/ethcore/evm/src/interpreter/memory.rs b/ethcore/evm/src/interpreter/memory.rs index 9aa9babc789c84f103eadef3fbce75065a129c97..f646d01985d83dce2f1dc95e1b25c1e729ce1844 100644 --- a/ethcore/evm/src/interpreter/memory.rs +++ b/ethcore/evm/src/interpreter/memory.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::U256; +use ethereum_types::U256; use vm::ReturnData; const MAX_RETURN_WASTE_BYTES: usize = 16384; @@ -134,7 +134,7 @@ impl Memory for Vec { #[cfg(test)] mod tests { - use util::U256; + use ethereum_types::U256; use super::Memory; #[test] diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index cb8fe3a5240bfa0141fe039cdc70d5ec66c7940b..05d1fb78853fc0dfacd5bf421dd0d37c78aae8d9 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -26,6 +26,8 @@ mod shared_cache; use std::marker::PhantomData; use std::{cmp, mem}; use std::sync::Arc; +use hash::keccak; +use ethereum_types::{U256, U512, H256, Address}; use vm::{ self, ActionParams, ActionValue, CallType, MessageCallResult, @@ -42,8 +44,6 @@ pub use self::shared_cache::SharedCache; use bit_set::BitSet; -use util::*; - type ProgramCounter = usize; const ONE: U256 = U256([1, 0, 0, 0]); @@ -63,7 +63,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. @@ -133,7 +132,9 @@ impl vm::Vm for Interpreter { reader.position += 1; // TODO: make compile-time removable if too much of a performance hit. - do_trace = do_trace && ext.trace_next_instruction(reader.position - 1, instruction); + do_trace = do_trace && ext.trace_next_instruction( + reader.position - 1, instruction, gasometer.current_gas.as_u256(), + ); let info = &infos[instruction as usize]; self.verify_instruction(ext, instruction, info, &stack)?; @@ -180,7 +181,7 @@ impl vm::Vm for Interpreter { match result { InstructionResult::JumpToPosition(position) => { if valid_jump_destinations.is_none() { - let code_hash = params.code_hash.clone().unwrap_or_else(|| code.sha3()); + let code_hash = params.code_hash.clone().unwrap_or_else(|| keccak(code.as_ref())); valid_jump_destinations = Some(self.cache.jump_destinations(&code_hash, code)); } let jump_destinations = valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed"); @@ -284,7 +285,6 @@ impl Interpreter { } } - #[cfg_attr(feature="dev", allow(too_many_arguments))] fn exec_instruction( &mut self, gas: Cost, @@ -319,27 +319,39 @@ impl Interpreter { let init_off = stack.pop_back(); let init_size = stack.pop_back(); - let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); - let contract_code = self.mem.read_slice(init_off, init_size); - let can_create = ext.balance(¶ms.address)? >= endowment && ext.depth() < ext.schedule().max_depth; + if ext.is_static() { + return Err(vm::Error::MutableCallInStaticContext); + } + // clear return data buffer before creating new call frame. + self.return_data = ReturnData::empty(); + + let can_create = ext.balance(¶ms.address)? >= endowment && ext.depth() < ext.schedule().max_depth; if !can_create { stack.push(U256::zero()); return Ok(InstructionResult::UnusedGas(create_gas)); } + let contract_code = self.mem.read_slice(init_off, init_size); + let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; + let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme); return match create_result { ContractCreateResult::Created(address, gas_left) => { stack.push(address_to_u256(address)); Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater."))) }, + ContractCreateResult::Reverted(gas_left, return_data) => { + stack.push(U256::zero()); + self.return_data = return_data; + Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater."))) + }, ContractCreateResult::Failed => { stack.push(U256::zero()); Ok(InstructionResult::Ok) - } + }, }; }, instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => { @@ -350,8 +362,10 @@ impl Interpreter { let code_address = stack.pop_back(); let code_address = u256_to_address(&code_address); - let value = if instruction == instructions::DELEGATECALL || instruction == instructions::STATICCALL { + let value = if instruction == instructions::DELEGATECALL { None + } else if instruction == instructions::STATICCALL { + Some(U256::zero()) } else { Some(stack.pop_back()) }; @@ -370,6 +384,9 @@ impl Interpreter { // Get sender & receive addresses, check if we have balance let (sender_address, receive_address, has_balance, call_type) = match instruction { instructions::CALL => { + if ext.is_static() && value.map_or(false, |v| !v.is_zero()) { + return Err(vm::Error::MutableCallInStaticContext); + } let has_balance = ext.balance(¶ms.address)? >= value.expect("value set for all but delegate call; qed"); (¶ms.address, &code_address, has_balance, CallType::Call) }, @@ -378,10 +395,13 @@ impl Interpreter { (¶ms.address, ¶ms.address, has_balance, CallType::CallCode) }, instructions::DELEGATECALL => (¶ms.sender, ¶ms.address, true, CallType::DelegateCall), - instructions::STATICCALL => (¶ms.sender, ¶ms.address, true, CallType::StaticCall), + instructions::STATICCALL => (¶ms.address, &code_address, true, CallType::StaticCall), _ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction)) }; + // clear return data buffer before creating new call frame. + self.return_data = ReturnData::empty(); + let can_call = has_balance && ext.depth() < ext.schedule().max_depth; if !can_call { stack.push(U256::zero()); @@ -400,12 +420,17 @@ impl Interpreter { MessageCallResult::Success(gas_left, data) => { stack.push(U256::one()); self.return_data = data; - Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater then current one"))) + Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one"))) + }, + MessageCallResult::Reverted(gas_left, data) => { + stack.push(U256::zero()); + self.return_data = data; + Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one"))) }, MessageCallResult::Failed => { stack.push(U256::zero()); Ok(InstructionResult::Ok) - } + }, }; }, instructions::RETURN => { @@ -464,8 +489,8 @@ impl Interpreter { instructions::SHA3 => { let offset = stack.pop_back(); let size = stack.pop_back(); - let sha3 = self.mem.read_slice(offset, size).sha3(); - stack.push(U256::from(&*sha3)); + let k = keccak(self.mem.read_slice(offset, size)); + stack.push(U256::from(&*k)); }, instructions::SLOAD => { let key = H256::from(&stack.pop_back()); @@ -543,6 +568,14 @@ impl Interpreter { Self::copy_data_to_memory(&mut self.mem, stack, params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8])); }, instructions::RETURNDATACOPY => { + { + let source_offset = stack.peek(1); + let size = stack.peek(2); + let return_data_len = U256::from(self.return_data.len()); + if source_offset.saturating_add(*size) > return_data_len { + return Err(vm::Error::OutOfBounds); + } + } Self::copy_data_to_memory(&mut self.mem, stack, &*self.return_data); }, instructions::CODECOPY => { @@ -880,8 +913,13 @@ mod tests { use rustc_hex::FromHex; use vmtype::VMType; use factory::Factory; - use vm::{self, ActionParams, ActionValue}; + use vm::{Vm, ActionParams, ActionValue}; use vm::tests::{FakeExt, test_finalize}; + use ethereum_types::U256; + + fn interpreter(gas: &U256) -> Box { + Factory::new(VMType::Interpreter, 1).create(gas) + } #[test] fn should_not_fail_on_tracing_mem() { @@ -898,11 +936,32 @@ mod tests { ext.tracing = true; let gas_left = { - let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas); + let mut vm = interpreter(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; assert_eq!(ext.calls.len(), 1); assert_eq!(gas_left, 248_212.into()); } + + #[test] + fn should_not_overflow_returndata() { + let code = "6001600160000360003e00".from_hex().unwrap(); + + let mut params = ActionParams::default(); + params.address = 5.into(); + params.gas = 300_000.into(); + params.gas_price = 1.into(); + params.code = Some(Arc::new(code)); + let mut ext = FakeExt::new_byzantium(); + ext.balances.insert(5.into(), 1_000_000_000.into()); + ext.tracing = true; + + let err = { + let mut vm = interpreter(¶ms.gas); + test_finalize(vm.exec(params, &mut ext)).err().unwrap() + }; + + assert_eq!(err, ::vm::Error::OutOfBounds); + } } diff --git a/ethcore/evm/src/interpreter/shared_cache.rs b/ethcore/evm/src/interpreter/shared_cache.rs index a93afa79a06bad5118645fdb36991da438d1c971..30bc5b677d5243a9f6d593f98923e96b680e752f 100644 --- a/ethcore/evm/src/interpreter/shared_cache.rs +++ b/ethcore/evm/src/interpreter/shared_cache.rs @@ -15,9 +15,11 @@ // along with Parity. If not, see . use std::sync::Arc; -use util::{H256, HeapSizeOf, Mutex}; -use util::sha3::*; -use util::cache::MemoryLruCache; +use hash::KECCAK_EMPTY; +use heapsize::HeapSizeOf; +use ethereum_types::H256; +use parking_lot::Mutex; +use memory_cache::MemoryLruCache; use bit_set::BitSet; use super::super::instructions; @@ -49,7 +51,7 @@ impl SharedCache { /// Get jump destinations bitmap for a contract. pub fn jump_destinations(&self, code_hash: &H256, code: &[u8]) -> Arc { - if code_hash == &SHA3_EMPTY { + if code_hash == &KECCAK_EMPTY { return Self::find_jump_destinations(code); } diff --git a/ethcore/evm/src/jit.rs b/ethcore/evm/src/jit.rs index 22262cbb6d44f29bee3b15483d9c6566dec3a623..d94bb7b8e084a94980041ef8420036cdb87a4fe1 100644 --- a/ethcore/evm/src/jit.rs +++ b/ethcore/evm/src/jit.rs @@ -15,6 +15,8 @@ // along with Parity. If not, see . //! Just in time compiler execution environment. +use bigint::prelude::U256; +use bigint::hash::H256; use util::*; use evmjit; use evm::{self, GasLeft}; diff --git a/ethcore/evm/src/lib.rs b/ethcore/evm/src/lib.rs index 833b266646911ec1030a41078e40c18968e904ac..b61c8aa2a9dc41c0a8202e1b1bd8c4d982187a43 100644 --- a/ethcore/evm/src/lib.rs +++ b/ethcore/evm/src/lib.rs @@ -16,20 +16,18 @@ //! Ethereum virtual machine. -extern crate byteorder; extern crate bit_set; -extern crate common_types as types; -extern crate ethcore_util as util; -extern crate ethjson; -extern crate rlp; -extern crate parity_wasm; -extern crate wasm_utils; -extern crate ethcore_logger; +extern crate ethereum_types; +extern crate parking_lot; +extern crate heapsize; extern crate vm; +extern crate keccak_hash as hash; +extern crate memory_cache; #[macro_use] extern crate lazy_static; +#[cfg_attr(feature = "evm-debug", macro_use)] extern crate log; #[cfg(feature = "jit")] diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index 7263d1779d5388762b93c7b51fcc5b6aee419f59..a219ae988076f0040ef3b3dd79cd88c1a6f67f2f 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -20,7 +20,7 @@ use std::hash::Hash; use std::sync::Arc; use std::collections::{HashMap, HashSet}; use rustc_hex::FromHex; -use util::*; +use ethereum_types::{U256, H256, Address}; use vm::{self, ActionParams, ActionValue}; use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize}; use factory::Factory; @@ -38,7 +38,7 @@ fn test_add(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -58,7 +58,7 @@ fn test_sha3(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -78,7 +78,7 @@ fn test_address(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -100,7 +100,7 @@ fn test_origin(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -122,7 +122,7 @@ fn test_sender(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -157,7 +157,7 @@ fn test_extcodecopy(factory: super::Factory) { ext.codes.insert(sender, Arc::new(sender_code)); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -177,7 +177,7 @@ fn test_log_empty(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -209,7 +209,7 @@ fn test_log_sender(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -234,7 +234,7 @@ fn test_blockhash(factory: super::Factory) { ext.blockhashes.insert(U256::zero(), blockhash.clone()); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -256,7 +256,7 @@ fn test_calldataload(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -277,7 +277,7 @@ fn test_author(factory: super::Factory) { ext.info.author = author; let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -297,7 +297,7 @@ fn test_timestamp(factory: super::Factory) { ext.info.timestamp = timestamp; let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -317,7 +317,7 @@ fn test_number(factory: super::Factory) { ext.info.number = number; let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -337,7 +337,7 @@ fn test_difficulty(factory: super::Factory) { ext.info.difficulty = difficulty; let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -357,7 +357,7 @@ fn test_gas_limit(factory: super::Factory) { ext.info.gas_limit = gas_limit; let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -375,7 +375,7 @@ fn test_mul(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -393,7 +393,7 @@ fn test_sub(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -411,7 +411,7 @@ fn test_div(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -429,7 +429,7 @@ fn test_div_zero(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -447,7 +447,7 @@ fn test_mod(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -466,7 +466,7 @@ fn test_smod(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -485,7 +485,7 @@ fn test_sdiv(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -504,7 +504,7 @@ fn test_exp(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -524,7 +524,7 @@ fn test_comparison(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -545,7 +545,7 @@ fn test_signed_comparison(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -566,7 +566,7 @@ fn test_bitops(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -589,7 +589,7 @@ fn test_addmod_mulmod(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -610,7 +610,7 @@ fn test_byte(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -629,7 +629,7 @@ fn test_signextend(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -649,7 +649,7 @@ fn test_badinstruction_int() { let mut ext = FakeExt::new(); let err = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap_err() }; @@ -669,7 +669,7 @@ fn test_pop(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -689,7 +689,7 @@ fn test_extops(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -712,7 +712,7 @@ fn test_jumps(factory: super::Factory) { let mut ext = FakeExt::new(); let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -722,7 +722,6 @@ fn test_jumps(factory: super::Factory) { assert_eq!(gas_left, U256::from(54_117)); } - evm_test!{test_calls: test_calls_jit, test_calls_int} fn test_calls(factory: super::Factory) { let code = "600054602d57600160005560006000600060006050610998610100f160006000600060006050610998610100f25b".from_hex().unwrap(); @@ -741,7 +740,7 @@ fn test_calls(factory: super::Factory) { }; let gas_left = { - let mut vm = factory.create(params.gas); + let mut vm = factory.create(¶ms.gas); test_finalize(vm.exec(params, &mut ext)).unwrap() }; @@ -767,6 +766,27 @@ fn test_calls(factory: super::Factory) { assert_eq!(ext.calls.len(), 2); } +evm_test!{test_create_in_staticcall: test_create_in_staticcall_jit, test_create_in_staticcall_int} +fn test_create_in_staticcall(factory: super::Factory) { + let code = "600060006064f000".from_hex().unwrap(); + + let address = Address::from(0x155); + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.address = address.clone(); + let mut ext = FakeExt::new_byzantium(); + ext.is_static = true; + + let err = { + let mut vm = factory.create(¶ms.gas); + test_finalize(vm.exec(params, &mut ext)).unwrap_err() + }; + + assert_eq!(err, vm::Error::MutableCallInStaticContext); + assert_eq!(ext.calls.len(), 0); +} + fn assert_set_contains(set: &HashSet, val: &T) { let contains = set.contains(val); if !contains { diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index 9fda78f475c10848f1293dfbbed95a07d45fcb8e..b8f5d5fb541837a67aaf5f9a49f35fe8d498dd25 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -3,35 +3,42 @@ description = "Parity Light Client Implementation" homepage = "http://parity.io" license = "GPL-3.0" name = "ethcore-light" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] -build = "build.rs" - -[build-dependencies] -"ethcore-ipc-codegen" = { path = "../../ipc/codegen", optional = true } [dependencies] log = "0.3" ethcore = { path = ".."} -ethcore-util = { path = "../../util" } +ethcore-bytes = { path = "../../util/bytes" } +ethcore-transaction = { path = "../transaction" } +ethereum-types = "0.2" +memorydb = { path = "../../util/memorydb" } +patricia-trie = { path = "../../util/patricia_trie" } ethcore-network = { path = "../../util/network" } ethcore-io = { path = "../../util/io" } -ethcore-ipc = { path = "../../ipc/rpc", optional = true } -ethcore-devtools = { path = "../../devtools" } -evm = { path = "../evm" } +hashdb = { path = "../../util/hashdb" } +heapsize = "0.4" vm = { path = "../vm" } +plain_hasher = { path = "../../util/plain_hasher" } rlp = { path = "../../util/rlp" } rlp_derive = { path = "../../util/rlp_derive" } -time = "0.1" smallvec = "0.4" futures = "0.1" -rand = "0.3" +rand = "0.4" itertools = "0.5" bincode = "0.8.0" serde = "1.0" serde_derive = "1.0" +parking_lot = "0.5" stats = { path = "../../util/stats" } +keccak-hash = { path = "../../util/hash" } +triehash = { path = "../../util/triehash" } +kvdb = { path = "../../util/kvdb" } +memory-cache = { path = "../../util/memory_cache" } + +[dev-dependencies] +kvdb-memorydb = { path = "../../util/kvdb-memorydb" } +tempdir = "0.3" [features] default = [] -ipc = ["ethcore-ipc", "ethcore-ipc-codegen"] diff --git a/ethcore/light/build.rs b/ethcore/light/build.rs deleted file mode 100644 index b9c79f77888ea5e0e226bdcb91d37c44b5906629..0000000000000000000000000000000000000000 --- a/ethcore/light/build.rs +++ /dev/null @@ -1,27 +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 . - -#[cfg(feature = "ipc")] -extern crate ethcore_ipc_codegen; - -#[cfg(feature = "ipc")] -fn main() { - ethcore_ipc_codegen::derive_binary("src/types/mod.rs.in").unwrap(); - ethcore_ipc_codegen::derive_ipc_cond("src/provider.rs", true).unwrap(); -} - -#[cfg(not(feature = "ipc"))] -fn main() { } \ No newline at end of file diff --git a/ethcore/light/src/cache.rs b/ethcore/light/src/cache.rs index 9a5a3638fb2178c63deaf5330deafb120cd81102..b63fd07576e005fd92b7058fdee045b34418aaca 100644 --- a/ethcore/light/src/cache.rs +++ b/ethcore/light/src/cache.rs @@ -25,9 +25,10 @@ use ethcore::header::BlockNumber; use ethcore::receipt::Receipt; use stats::Corpus; -use time::{SteadyTime, Duration}; -use util::{U256, H256, HeapSizeOf}; -use util::cache::MemoryLruCache; +use std::time::{Instant, Duration}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, U256}; +use memory_cache::MemoryLruCache; /// Configuration for how much data to cache. #[derive(Debug, Clone, PartialEq, Eq)] @@ -68,7 +69,7 @@ pub struct Cache { bodies: MemoryLruCache, receipts: MemoryLruCache>, chain_score: MemoryLruCache, - corpus: Option<(Corpus, SteadyTime)>, + corpus: Option<(Corpus, Instant)>, corpus_expiration: Duration, } @@ -138,7 +139,7 @@ impl Cache { /// Get gas price corpus, if recent enough. pub fn gas_price_corpus(&self) -> Option> { - let now = SteadyTime::now(); + let now = Instant::now(); self.corpus.as_ref().and_then(|&(ref corpus, ref tm)| { if *tm + self.corpus_expiration >= now { @@ -151,7 +152,7 @@ impl Cache { /// Set the cached gas price corpus. pub fn set_gas_price_corpus(&mut self, corpus: Corpus) { - self.corpus = Some((corpus, SteadyTime::now())) + self.corpus = Some((corpus, Instant::now())) } /// Get the memory used. @@ -174,18 +175,18 @@ impl HeapSizeOf for Cache { #[cfg(test)] mod tests { use super::Cache; - use time::Duration; + use std::time::Duration; #[test] fn corpus_inaccessible() { - let mut cache = Cache::new(Default::default(), Duration::hours(5)); + let mut cache = Cache::new(Default::default(), Duration::from_secs(5 * 3600)); cache.set_gas_price_corpus(vec![].into()); assert_eq!(cache.gas_price_corpus(), Some(vec![].into())); { let corpus_time = &mut cache.corpus.as_mut().unwrap().1; - *corpus_time = *corpus_time - Duration::hours(6); + *corpus_time = *corpus_time - Duration::from_secs(6 * 3600); } assert!(cache.gas_price_corpus().is_none()); } diff --git a/ethcore/light/src/cht.rs b/ethcore/light/src/cht.rs index 7f2ccc3a82c725f10319f050a9334f99d9fc38d5..6f5ebf808e886ce380e7b3bbac0a01171b3b51bc 100644 --- a/ethcore/light/src/cht.rs +++ b/ethcore/light/src/cht.rs @@ -21,8 +21,11 @@ //! we discarded. use ethcore::ids::BlockId; -use util::{Bytes, H256, U256, HashDB, MemoryDB}; -use util::trie::{self, TrieMut, TrieDBMut, Trie, TrieDB, Recorder}; +use ethereum_types::{H256, U256}; +use hashdb::HashDB; +use memorydb::MemoryDB; +use bytes::Bytes; +use trie::{self, TrieMut, TrieDBMut, Trie, TrieDB, Recorder}; use rlp::{RlpStream, UntrustedRlp}; // encode a key. @@ -130,7 +133,7 @@ pub fn compute_root(cht_num: u64, iterable: I) -> Option } if v.len() == SIZE as usize { - Some(::util::triehash::trie_root(v)) + Some(::triehash::trie_root(v)) } else { None } diff --git a/ethcore/light/src/client/fetch.rs b/ethcore/light/src/client/fetch.rs new file mode 100644 index 0000000000000000000000000000000000000000..86269c695fc4b6aa422a84cd5987410b52e0d7a2 --- /dev/null +++ b/ethcore/light/src/client/fetch.rs @@ -0,0 +1,85 @@ +// 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 . + +//! Trait for fetching chain data. + +use std::sync::Arc; + +use ethcore::encoded; +use ethcore::engines::{EthEngine, StateDependentProof}; +use ethcore::machine::EthereumMachine; +use ethcore::header::Header; +use ethcore::receipt::Receipt; +use futures::future::IntoFuture; +use ethereum_types::H256; + +/// Provides full chain data. +pub trait ChainDataFetcher: Send + Sync + 'static { + /// Error type when data unavailable. + type Error: ::std::fmt::Debug; + + /// Future for fetching block body. + type Body: IntoFuture; + /// Future for fetching block receipts. + type Receipts: IntoFuture, Error=Self::Error>; + /// Future for fetching epoch transition + type Transition: IntoFuture, Error=Self::Error>; + + /// Fetch a block body. + fn block_body(&self, header: &Header) -> Self::Body; + + /// Fetch block receipts. + fn block_receipts(&self, header: &Header) -> Self::Receipts; + + /// Fetch epoch transition proof at given header. + fn epoch_transition( + &self, + _hash: H256, + _engine: Arc, + _checker: Arc> + ) -> Self::Transition; +} + +/// Fetcher implementation which cannot fetch anything. +pub struct Unavailable; + +/// Create a fetcher which has all data unavailable. +pub fn unavailable() -> Unavailable { Unavailable } + +impl ChainDataFetcher for Unavailable { + type Error = &'static str; + + type Body = Result; + type Receipts = Result, &'static str>; + type Transition = Result, &'static str>; + + fn block_body(&self, _header: &Header) -> Self::Body { + Err("fetching block bodies unavailable") + } + + fn block_receipts(&self, _header: &Header) -> Self::Receipts { + Err("fetching block receipts unavailable") + } + + fn epoch_transition( + &self, + _hash: H256, + _engine: Arc, + _checker: Arc> + ) -> Self::Transition { + Err("fetching epoch transition proofs unavailable") + } +} diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index d6ac109c794b8272dfca50a80b5d4bedc1cdb9a8..3bbd6cb9506a15cc75227d215f64485e27c670ee 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -18,11 +18,12 @@ //! //! Unlike a full node's `BlockChain` this doesn't store much in the database. //! It stores candidates for the last 2048-4096 blocks as well as CHT roots for -//! historical blocks all the way to the genesis. +//! historical blocks all the way to the genesis. If the engine makes use +//! of epoch transitions, those are stored as well. //! //! This is separate from the `BlockChain` for two reasons: //! - It stores only headers (and a pruned subset of them) -//! - To allow for flexibility in the database layout once that's incorporated. +//! - To allow for flexibility in the database layout.. use std::collections::BTreeMap; use std::sync::Arc; @@ -30,17 +31,24 @@ use std::sync::Arc; use cht; use ethcore::block_status::BlockStatus; -use ethcore::error::BlockError; +use ethcore::error::{Error, BlockImportError, BlockError}; use ethcore::encoded; use ethcore::header::Header; use ethcore::ids::BlockId; +use ethcore::spec::{Spec, SpecHardcodedSync}; +use ethcore::engines::epoch::{ + Transition as EpochTransition, + PendingTransition as PendingEpochTransition +}; use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp, UntrustedRlp}; -use util::{H256, U256, HeapSizeOf, RwLock}; -use util::kvdb::{DBTransaction, KeyValueDB}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, H264, U256}; +use plain_hasher::H256FastMap; +use kvdb::{DBTransaction, KeyValueDB}; use cache::Cache; -use util::Mutex; +use parking_lot::{Mutex, RwLock}; use smallvec::SmallVec; @@ -52,6 +60,9 @@ const HISTORY: u64 = 2048; /// The best block key. Maps to an RLP list: [best_era, last_era] const CURRENT_KEY: &'static [u8] = &*b"best_and_latest"; +/// Key storing the last canonical epoch transition. +const LAST_CANONICAL_TRANSITION: &'static [u8] = &*b"canonical_transition"; + /// Information about a block. #[derive(Debug, Clone)] pub struct BlockDescriptor { @@ -99,7 +110,6 @@ impl Encodable for Entry { impl Decodable for Entry { fn decode(rlp: &UntrustedRlp) -> Result { - let mut candidates = SmallVec::<[Candidate; 3]>::new(); for item in rlp.iter() { @@ -129,16 +139,59 @@ fn era_key(number: u64) -> String { format!("candidates_{}", number) } +fn pending_transition_key(block_hash: H256) -> H264 { + const LEADING: u8 = 1; + + let mut key = H264::default(); + + key[0] = LEADING; + key.0[1..].copy_from_slice(&block_hash.0[..]); + + key +} + +fn transition_key(block_hash: H256) -> H264 { + const LEADING: u8 = 2; + + let mut key = H264::default(); + + key[0] = LEADING; + key.0[1..].copy_from_slice(&block_hash.0[..]); + + key +} + +// encode last canonical transition entry: header and proof. +fn encode_canonical_transition(header: &Header, proof: &[u8]) -> Vec { + let mut stream = RlpStream::new_list(2); + stream.append(header).append(&proof); + stream.out() +} + +// decode last canonical transition entry. +fn decode_canonical_transition(t: &[u8]) -> Result<(Header, &[u8]), DecoderError> { + let rlp = UntrustedRlp::new(t); + + Ok((rlp.val_at(0)?, rlp.at(1)?.data()?)) +} + /// Pending changes from `insert` to be applied after the database write has finished. pub struct PendingChanges { best_block: Option, // new best block. } +/// Whether or not the hardcoded sync feature is allowed. +pub enum HardcodedSync { + Allow, + Deny, +} + /// Header chain. See module docs for more details. pub struct HeaderChain { genesis_header: encoded::Header, // special-case the genesis. candidates: RwLock>, best_block: RwLock, + live_epoch_proofs: RwLock>, db: Arc, col: Option, cache: Arc>, @@ -146,8 +199,17 @@ pub struct HeaderChain { impl HeaderChain { /// Create a new header chain given this genesis block and database to read from. - pub fn new(db: Arc, col: Option, genesis: &[u8], cache: Arc>) -> Result { - use ethcore::views::HeaderView; + pub fn new( + db: Arc, + col: Option, + spec: &Spec, + cache: Arc>, + allow_hs: HardcodedSync, + ) -> Result { + let mut live_epoch_proofs = ::std::collections::HashMap::default(); + + let genesis = ::rlp::encode(&spec.genesis_header()).into_vec(); + let decoded_header = spec.genesis_header(); let chain = if let Some(current) = db.get(col, CURRENT_KEY)? { let (best_number, highest_number) = { @@ -158,12 +220,24 @@ impl HeaderChain { let mut cur_number = highest_number; let mut candidates = BTreeMap::new(); - // load all era entries and referenced headers within them. + // load all era entries, referenced headers within them, + // and live epoch proofs. while let Some(entry) = db.get(col, era_key(cur_number).as_bytes())? { let entry: Entry = ::rlp::decode(&entry); trace!(target: "chain", "loaded header chain entry for era {} with {} candidates", cur_number, entry.candidates.len()); + for c in &entry.candidates { + let key = transition_key(c.hash); + + if let Some(proof) = db.get(col, &*key)? { + live_epoch_proofs.insert(c.hash, EpochTransition { + block_hash: c.hash, + block_number: cur_number, + proof: proof.into_vec(), + }); + } + } candidates.insert(cur_number, entry); cur_number -= 1; @@ -173,7 +247,7 @@ impl HeaderChain { let best_block = { let era = match candidates.get(&best_number) { Some(era) => era, - None => return Err(format!("Database corrupt: highest block referenced but no data.")), + None => return Err(Error::Database("Database corrupt: highest block referenced but no data.".into())), }; let best = &era.candidates[0]; @@ -185,29 +259,77 @@ impl HeaderChain { }; HeaderChain { - genesis_header: encoded::Header::new(genesis.to_owned()), + genesis_header: encoded::Header::new(genesis), best_block: RwLock::new(best_block), candidates: RwLock::new(candidates), + live_epoch_proofs: RwLock::new(live_epoch_proofs), db: db, col: col, cache: cache, } + } else { - let g_view = HeaderView::new(genesis); - HeaderChain { - genesis_header: encoded::Header::new(genesis.to_owned()), + let chain = HeaderChain { + genesis_header: encoded::Header::new(genesis), best_block: RwLock::new(BlockDescriptor { - hash: g_view.hash(), + hash: decoded_header.hash(), number: 0, - total_difficulty: g_view.difficulty(), + total_difficulty: *decoded_header.difficulty(), }), candidates: RwLock::new(BTreeMap::new()), - db: db, + live_epoch_proofs: RwLock::new(live_epoch_proofs), + db: db.clone(), col: col, cache: cache, + }; + + // insert the hardcoded sync into the database. + if let (&Some(ref hardcoded_sync), HardcodedSync::Allow) = (&spec.hardcoded_sync, allow_hs) { + let mut batch = db.transaction(); + + // insert the hardcoded CHT roots into the database. + for (cht_num, cht_root) in hardcoded_sync.chts.iter().enumerate() { + batch.put(col, cht_key(cht_num as u64).as_bytes(), &::rlp::encode(cht_root)); + } + + let decoded_header = hardcoded_sync.header.decode(); + let decoded_header_num = decoded_header.number(); + + // write the block in the DB. + info!(target: "chain", "Inserting hardcoded block #{} in chain", + decoded_header_num); + let pending = chain.insert_with_td(&mut batch, decoded_header, + hardcoded_sync.total_difficulty, None)?; + + // check that we have enough hardcoded CHT roots. avoids panicking later. + let cht_num = cht::block_to_cht_number(decoded_header_num - 1) + .expect("specs provided a hardcoded block with height 0"); + if cht_num >= hardcoded_sync.chts.len() as u64 { + warn!(target: "chain", "specs didn't provide enough CHT roots for its \ + hardcoded block ; falling back to non-hardcoded sync \ + mode"); + } else { + db.write_buffered(batch); + chain.apply_pending(pending); + } } + + chain }; + // instantiate genesis epoch data if it doesn't exist. + if let None = chain.db.get(col, LAST_CANONICAL_TRANSITION)? { + let genesis_data = spec.genesis_epoch_data() + .map_err(|s| Error::Database(s.into()))?; + + { + let mut batch = chain.db.transaction(); + let data = encode_canonical_transition(&decoded_header, &genesis_data); + batch.put_vec(col, LAST_CANONICAL_TRANSITION, data); + chain.db.write(batch)?; + } + } + Ok(chain) } @@ -216,10 +338,47 @@ impl HeaderChain { /// This blindly trusts that the data given to it is sensible. /// Returns a set of pending changes to be applied with `apply_pending` /// before the next call to insert and after the transaction has been written. - pub fn insert(&self, transaction: &mut DBTransaction, header: Header) -> Result { + /// + /// If the block is an epoch transition, provide the transition along with + /// the header. + pub fn insert( + &self, + transaction: &mut DBTransaction, + header: Header, + transition_proof: Option>, + ) -> Result { + self.insert_inner(transaction, header, None, transition_proof) + } + + /// Insert a pre-verified header, with a known total difficulty. Similary to `insert`. + /// + /// This blindly trusts that the data given to it is sensible. + pub fn insert_with_td( + &self, + transaction: &mut DBTransaction, + header: Header, + total_difficulty: U256, + transition_proof: Option>, + ) -> Result { + self.insert_inner(transaction, header, Some(total_difficulty), transition_proof) + } + + fn insert_inner( + &self, + transaction: &mut DBTransaction, + header: Header, + total_difficulty: Option, + transition_proof: Option>, + ) -> Result { let hash = header.hash(); let number = header.number(); let parent_hash = *header.parent_hash(); + let transition = transition_proof.map(|proof| EpochTransition { + block_hash: hash, + block_number: number, + proof: proof, + }); + let mut pending = PendingChanges { best_block: None, }; @@ -227,18 +386,24 @@ impl HeaderChain { // hold candidates the whole time to guard import order. let mut candidates = self.candidates.write(); - // find parent details. - let parent_td = - if number == 1 { - self.genesis_header.difficulty() - } else { - candidates.get(&(number - 1)) - .and_then(|entry| entry.candidates.iter().find(|c| c.hash == parent_hash)) - .map(|c| c.total_difficulty) - .ok_or_else(|| BlockError::UnknownParent(parent_hash))? - }; + // find total difficulty. + let total_difficulty = match total_difficulty { + Some(td) => td, + None => { + let parent_td = + if number == 1 { + self.genesis_header.difficulty() + } else { + candidates.get(&(number - 1)) + .and_then(|entry| entry.candidates.iter().find(|c| c.hash == parent_hash)) + .map(|c| c.total_difficulty) + .ok_or_else(|| BlockError::UnknownParent(parent_hash)) + .map_err(BlockImportError::Block)? + }; - let total_difficulty = parent_td + *header.difficulty(); + parent_td + *header.difficulty() + }, + }; // insert headers and candidates entries and write era to disk. { @@ -260,8 +425,13 @@ impl HeaderChain { transaction.put(self.col, era_key(number).as_bytes(), &::rlp::encode(&*cur_era)) } - let raw = ::rlp::encode(&header); - transaction.put(self.col, &hash[..], &*raw); + if let Some(transition) = transition { + transaction.put(self.col, &*transition_key(hash), &transition.proof); + self.live_epoch_proofs.write().insert(hash, transition); + } + + let raw = header.encoded().into_inner(); + transaction.put_vec(self.col, &hash[..], raw); let (best_num, is_new_best) = { let cur_best = self.best_block.read(); @@ -314,8 +484,10 @@ impl HeaderChain { let cht_num = cht::block_to_cht_number(earliest_era) .expect("fails only for number == 0; genesis never imported; qed"); + let mut last_canonical_transition = None; let cht_root = { let mut i = earliest_era; + let mut live_epoch_proofs = self.live_epoch_proofs.write(); // iterable function which removes the candidates as it goes // along. this will only be called until the CHT is complete. @@ -326,7 +498,25 @@ impl HeaderChain { i += 1; + // prune old blocks and epoch proofs. for ancient in &era_entry.candidates { + let maybe_transition = live_epoch_proofs.remove(&ancient.hash); + if let Some(epoch_transition) = maybe_transition { + transaction.delete(self.col, &*transition_key(ancient.hash)); + + if ancient.hash == era_entry.canonical_hash { + last_canonical_transition = match self.db.get(self.col, &ancient.hash) { + Err(e) => { + warn!(target: "chain", "Error reading from DB: {}\n + ", e); + None + } + Ok(None) => panic!("stored candidates always have corresponding headers; qed"), + Ok(Some(header)) => Some((epoch_transition, ::rlp::decode(&header))), + }; + } + } + transaction.delete(self.col, &ancient.hash); } @@ -340,6 +530,12 @@ impl HeaderChain { // write the CHT root to the database. debug!(target: "chain", "Produced CHT {} root: {:?}", cht_num, cht_root); transaction.put(self.col, cht_key(cht_num).as_bytes(), &::rlp::encode(&cht_root)); + + // update the last canonical transition proof + if let Some((epoch_transition, header)) = last_canonical_transition { + let x = encode_canonical_transition(&header, &epoch_transition.proof); + transaction.put_vec(self.col, LAST_CANONICAL_TRANSITION, x); + } } } @@ -353,6 +549,65 @@ impl HeaderChain { Ok(pending) } + /// Generates the specifications for hardcoded sync. This is typically only called manually + /// from time to time by a Parity developer in order to update the chain specifications. + /// + /// Returns `None` if we are at the genesis block, or if an error happens . + pub fn read_hardcoded_sync(&self) -> Result, Error> { + let mut chts = Vec::new(); + let mut cht_num = 0; + + loop { + let cht = match self.cht_root(cht_num) { + Some(cht) => cht, + None if cht_num != 0 => { + // end of the iteration + let h_num = 1 + cht_num as u64 * cht::SIZE; + let header = if let Some(header) = self.block_header(BlockId::Number(h_num)) { + header + } else { + let msg = format!("header of block #{} not found in DB ; database in an \ + inconsistent state", h_num); + return Err(Error::Database(msg.into())); + }; + + let decoded = header.decode(); + + let entry: Entry = { + let bytes = self.db.get(self.col, era_key(h_num).as_bytes())? + .ok_or_else(|| { + let msg = format!("entry for era #{} not found in DB ; database \ + in an inconsistent state", h_num); + Error::Database(msg.into()) + })?; + ::rlp::decode(&bytes) + }; + + let total_difficulty = entry.candidates.iter() + .find(|c| c.hash == decoded.hash()) + .ok_or_else(|| { + let msg = "no candidate matching block found in DB ; database in an \ + inconsistent state"; + Error::Database(msg.into()) + })? + .total_difficulty; + + break Ok(Some(SpecHardcodedSync { + header: header, + total_difficulty: total_difficulty, + chts: chts, + })); + }, + None => { + break Ok(None); + }, + }; + + chts.push(cht); + cht_num += 1; + } + } + /// Apply pending changes from a previous `insert` operation. /// Must be done before the next `insert` call. pub fn apply_pending(&self, pending: PendingChanges) { @@ -365,13 +620,13 @@ impl HeaderChain { /// will be returned. pub fn block_hash(&self, id: BlockId) -> Option { match id { - BlockId::Earliest => Some(self.genesis_hash()), + BlockId::Earliest | BlockId::Number(0) => Some(self.genesis_hash()), BlockId::Hash(hash) => Some(hash), BlockId::Number(num) => { if self.best_block.read().number < num { return None } self.candidates.read().get(&num).map(|entry| entry.canonical_hash) } - BlockId::Latest | BlockId::Pending => { + BlockId::Latest => { Some(self.best_block.read().hash) } } @@ -413,7 +668,7 @@ impl HeaderChain { self.candidates.read().get(&num).map(|entry| entry.canonical_hash) .and_then(load_from_db) } - BlockId::Latest | BlockId::Pending => { + BlockId::Latest => { // hold candidates hear to prevent deletion of the header // as we read it. let _candidates = self.candidates.read(); @@ -449,7 +704,7 @@ impl HeaderChain { if self.best_block.read().number < num { return None } candidates.get(&num).map(|era| era.candidates[0].total_difficulty) } - BlockId::Latest | BlockId::Pending => Some(self.best_block.read().total_difficulty) + BlockId::Latest => Some(self.best_block.read().total_difficulty) } } @@ -486,7 +741,7 @@ impl HeaderChain { /// Get the genesis hash. pub fn genesis_hash(&self) -> H256 { - ::util::Hashable::sha3(&self.genesis_header) + self.genesis_header.hash() } /// Get the best block's data. @@ -516,6 +771,56 @@ impl HeaderChain { false => BlockStatus::Unknown, } } + + /// Insert a pending transition. + pub fn insert_pending_transition(&self, batch: &mut DBTransaction, hash: H256, t: PendingEpochTransition) { + let key = pending_transition_key(hash); + batch.put(self.col, &*key, &*::rlp::encode(&t)); + } + + /// Get pending transition for a specific block hash. + pub fn pending_transition(&self, hash: H256) -> Option { + let key = pending_transition_key(hash); + match self.db.get(self.col, &*key) { + Ok(val) => val.map(|x| ::rlp::decode(&x)), + Err(e) => { + warn!(target: "chain", "Error reading from database: {}", e); + None + } + } + } + + /// Get the transition to the epoch the given parent hash is part of + /// or transitions to. + /// This will give the epoch that any children of this parent belong to. + /// + /// The header corresponding the the parent hash must be stored already. + pub fn epoch_transition_for(&self, parent_hash: H256) -> Option<(Header, Vec)> { + // slow path: loop back block by block + let live_proofs = self.live_epoch_proofs.read(); + + for hdr in self.ancestry_iter(BlockId::Hash(parent_hash)) { + if let Some(transition) = live_proofs.get(&hdr.hash()).cloned() { + return Some((hdr.decode(), transition.proof)) + } + } + + // any blocks left must be descendants of the last canonical transition block. + match self.db.get(self.col, LAST_CANONICAL_TRANSITION) { + Ok(x) => { + let x = x.expect("last canonical transition always instantiated; qed"); + + let (hdr, proof) = decode_canonical_transition(&x) + .expect("last canonical transition always encoded correctly; qed"); + + Some((hdr, proof.to_vec())) + } + Err(e) => { + warn!("Error reading from DB: {}", e); + None + } + } + } } impl HeapSizeOf for HeaderChain { @@ -545,19 +850,22 @@ impl<'a> Iterator for AncestryIter<'a> { #[cfg(test)] mod tests { - use super::HeaderChain; + use super::{HeaderChain, HardcodedSync}; use std::sync::Arc; + use ethereum_types::U256; use ethcore::ids::BlockId; use ethcore::header::Header; use ethcore::spec::Spec; use cache::Cache; + use kvdb::KeyValueDB; + use kvdb_memorydb; - use time::Duration; - use util::Mutex; + use std::time::Duration; + use parking_lot::Mutex; - fn make_db() -> Arc<::util::KeyValueDB> { - Arc::new(::util::kvdb::in_memory(0)) + fn make_db() -> Arc { + Arc::new(kvdb_memorydb::create(0)) } #[test] @@ -566,9 +874,9 @@ mod tests { let genesis_header = spec.genesis_header(); let db = make_db(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -577,11 +885,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * i.into()); + header.set_difficulty(*genesis_header.difficulty() * i as u32); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -599,9 +907,9 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -610,11 +918,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * i.into()); + header.set_difficulty(*genesis_header.difficulty() * i as u32); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -629,11 +937,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * i.into()); + header.set_difficulty(*genesis_header.difficulty() * i as u32); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -653,11 +961,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * (i * i).into()); + header.set_difficulty(*genesis_header.difficulty() * U256::from(i * i)); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -680,16 +988,13 @@ mod tests { #[test] fn earliest_is_latest() { let spec = Spec::new_test(); - let genesis_header = spec.genesis_header(); let db = make_db(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); - - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache).unwrap(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); + let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); assert!(chain.block_header(BlockId::Earliest).is_some()); assert!(chain.block_header(BlockId::Latest).is_some()); - assert!(chain.block_header(BlockId::Pending).is_some()); } #[test] @@ -697,10 +1002,11 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); { - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(), + HardcodedSync::Allow).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); for i in 1..10000 { @@ -708,11 +1014,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * i.into()); + header.set_difficulty(*genesis_header.difficulty() * i as u32); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -720,7 +1026,8 @@ mod tests { } } - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(), + HardcodedSync::Allow).unwrap(); assert!(chain.block_header(BlockId::Number(10)).is_none()); assert!(chain.block_header(BlockId::Number(9000)).is_some()); assert!(chain.cht_root(2).is_some()); @@ -733,10 +1040,11 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); { - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(), + HardcodedSync::Allow).unwrap(); let mut parent_hash = genesis_header.hash(); let mut rolling_timestamp = genesis_header.timestamp(); @@ -746,11 +1054,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * i.into()); + header.set_difficulty(*genesis_header.difficulty() * i as u32); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -763,11 +1071,11 @@ mod tests { header.set_parent_hash(parent_hash); header.set_number(i); header.set_timestamp(rolling_timestamp); - header.set_difficulty(*genesis_header.difficulty() * i.into() * 1000.into()); + header.set_difficulty(*genesis_header.difficulty() * U256::from(i as u32 * 1000u32)); parent_hash = header.hash(); let mut tx = db.transaction(); - let pending = chain.insert(&mut tx, header).unwrap(); + let pending = chain.insert(&mut tx, header, None).unwrap(); db.write(tx).unwrap(); chain.apply_pending(pending); @@ -778,7 +1086,8 @@ mod tests { } // after restoration, non-canonical eras should still be loaded. - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(), + HardcodedSync::Allow).unwrap(); assert_eq!(chain.block_header(BlockId::Latest).unwrap().number(), 10); assert!(chain.candidates.read().get(&100).is_some()) } @@ -788,12 +1097,120 @@ mod tests { let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); let db = make_db(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); - let chain = HeaderChain::new(db.clone(), None, &::rlp::encode(&genesis_header), cache.clone()).unwrap(); + let chain = HeaderChain::new(db.clone(), None, &spec, cache.clone(), + HardcodedSync::Allow).unwrap(); assert!(chain.block_header(BlockId::Earliest).is_some()); assert!(chain.block_header(BlockId::Number(0)).is_some()); assert!(chain.block_header(BlockId::Hash(genesis_header.hash())).is_some()); } + + #[test] + fn epoch_transitions_available_after_cht() { + let spec = Spec::new_test(); + let genesis_header = spec.genesis_header(); + let db = make_db(); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); + + let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); + + let mut parent_hash = genesis_header.hash(); + let mut rolling_timestamp = genesis_header.timestamp(); + for i in 1..6 { + let mut header = Header::new(); + header.set_parent_hash(parent_hash); + header.set_number(i); + header.set_timestamp(rolling_timestamp); + header.set_difficulty(*genesis_header.difficulty() * i as u32); + parent_hash = header.hash(); + + let mut tx = db.transaction(); + let epoch_proof = if i == 3 { + Some(vec![1, 2, 3, 4]) + } else { + None + }; + + let pending = chain.insert(&mut tx, header, epoch_proof).unwrap(); + db.write(tx).unwrap(); + chain.apply_pending(pending); + + rolling_timestamp += 10; + } + + // these 3 should end up falling back to the genesis epoch proof in DB + for i in 0..3 { + let hash = chain.block_hash(BlockId::Number(i)).unwrap(); + assert_eq!(chain.epoch_transition_for(hash).unwrap().1, Vec::::new()); + } + + // these are live. + for i in 3..6 { + let hash = chain.block_hash(BlockId::Number(i)).unwrap(); + assert_eq!(chain.epoch_transition_for(hash).unwrap().1, vec![1, 2, 3, 4]); + } + + for i in 6..10000 { + let mut header = Header::new(); + header.set_parent_hash(parent_hash); + header.set_number(i); + header.set_timestamp(rolling_timestamp); + header.set_difficulty(*genesis_header.difficulty() * i as u32); + parent_hash = header.hash(); + + let mut tx = db.transaction(); + let pending = chain.insert(&mut tx, header, None).unwrap(); + db.write(tx).unwrap(); + chain.apply_pending(pending); + + rolling_timestamp += 10; + } + + // no live blocks have associated epoch proofs -- make sure we aren't leaking memory. + assert!(chain.live_epoch_proofs.read().is_empty()); + assert_eq!(chain.epoch_transition_for(parent_hash).unwrap().1, vec![1, 2, 3, 4]); + } + + #[test] + fn hardcoded_sync_gen() { + let spec = Spec::new_test(); + let genesis_header = spec.genesis_header(); + let db = make_db(); + + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); + + let chain = HeaderChain::new(db.clone(), None, &spec, cache, HardcodedSync::Allow).unwrap(); + + let mut parent_hash = genesis_header.hash(); + let mut rolling_timestamp = genesis_header.timestamp(); + let mut total_difficulty = *genesis_header.difficulty(); + let h_num = 3 * ::cht::SIZE + 1; + for i in 1..10000 { + let mut header = Header::new(); + header.set_parent_hash(parent_hash); + header.set_number(i); + header.set_timestamp(rolling_timestamp); + let diff = *genesis_header.difficulty() * i as u32; + header.set_difficulty(diff); + if i <= h_num { + total_difficulty = total_difficulty + diff; + } + parent_hash = header.hash(); + + let mut tx = db.transaction(); + let pending = chain.insert(&mut tx, header, None).unwrap(); + db.write(tx).unwrap(); + chain.apply_pending(pending); + + rolling_timestamp += 10; + } + + let hardcoded_sync = chain.read_hardcoded_sync().unwrap().unwrap(); + assert_eq!(hardcoded_sync.chts.len(), 3); + assert_eq!(hardcoded_sync.total_difficulty, total_difficulty); + let decoded: Header = hardcoded_sync.header.decode(); + assert_eq!(decoded.number(), h_num); + } } diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index d1cdfe9aa8a27e4191f1e6a65a28690346989f04..cf603d853f07bbe118cf30443a53e7fc87e2511e 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -19,22 +19,25 @@ use std::sync::{Weak, Arc}; use ethcore::block_status::BlockStatus; -use ethcore::client::{ClientReport, EnvInfo}; -use ethcore::engines::Engine; -use ethcore::error::BlockImportError; +use ethcore::client::{ClientReport, EnvInfo, ClientIoMessage}; +use ethcore::engines::{epoch, EthEngine, EpochChange, EpochTransition, Proof}; +use ethcore::machine::EthereumMachine; +use ethcore::error::{Error, BlockImportError}; use ethcore::ids::BlockId; -use ethcore::header::Header; +use ethcore::header::{BlockNumber, Header}; use ethcore::verification::queue::{self, HeaderQueue}; use ethcore::blockchain_info::BlockChainInfo; -use ethcore::spec::Spec; -use ethcore::service::ClientIoMessage; +use ethcore::spec::{Spec, SpecHardcodedSync}; use ethcore::encoded; use io::IoChannel; +use parking_lot::{Mutex, RwLock}; +use ethereum_types::{H256, U256}; +use futures::{IntoFuture, Future}; -use util::{H256, U256, Mutex, RwLock}; -use util::kvdb::{KeyValueDB, CompactionProfile}; +use kvdb::KeyValueDB; -use self::header_chain::{AncestryIter, HeaderChain}; +use self::fetch::ChainDataFetcher; +use self::header_chain::{AncestryIter, HeaderChain, HardcodedSync}; use cache::Cache; @@ -43,6 +46,8 @@ pub use self::service::Service; mod header_chain; mod service; +pub mod fetch; + /// Configuration for the light client. #[derive(Debug, Clone)] pub struct Config { @@ -50,16 +55,12 @@ pub struct Config { pub queue: queue::Config, /// Chain column in database. pub chain_column: Option, - /// Database cache size. `None` => rocksdb default. - pub db_cache_size: Option, - /// State db compaction profile - pub db_compaction: CompactionProfile, - /// Should db have WAL enabled? - pub db_wal: bool, /// Should it do full verification of blocks? pub verify_full: bool, /// Should it check the seal of blocks? pub check_seal: bool, + /// Disable hardcoded sync. + pub no_hardcoded_sync: bool, } impl Default for Config { @@ -67,17 +68,18 @@ impl Default for Config { Config { queue: Default::default(), chain_column: None, - db_cache_size: None, - db_compaction: CompactionProfile::default(), - db_wal: true, verify_full: true, check_seal: true, + no_hardcoded_sync: false, } } } /// Trait for interacting with the header chain abstractly. pub trait LightChainClient: Send + Sync { + /// Adds a new `LightChainNotify` listener. + fn add_listener(&self, listener: Weak); + /// Get chain info. fn chain_info(&self) -> BlockChainInfo; @@ -108,7 +110,7 @@ pub trait LightChainClient: Send + Sync { fn env_info(&self, id: BlockId) -> Option; /// Get a handle to the consensus engine. - fn engine(&self) -> &Arc; + fn engine(&self) -> &Arc; /// Query whether a block is known. fn is_known(&self, hash: &H256) -> bool; @@ -126,7 +128,7 @@ pub trait LightChainClient: Send + Sync { fn cht_root(&self, i: usize) -> Option; /// Get the EIP-86 transition block number. - fn eip86_transition(&self) -> u64; + fn eip86_transition(&self) -> BlockNumber; /// Get a report of import activity since the last call. fn report(&self) -> ClientReport; @@ -154,47 +156,58 @@ impl AsLightClient for T { } /// Light client implementation. -pub struct Client { +pub struct Client { queue: HeaderQueue, - engine: Arc, + engine: Arc, chain: HeaderChain, report: RwLock, import_lock: Mutex<()>, db: Arc, listeners: RwLock>>, + fetcher: T, verify_full: bool, } -impl Client { +impl Client { /// Create a new `Client`. - pub fn new(config: Config, db: Arc, chain_col: Option, spec: &Spec, io_channel: IoChannel, cache: Arc>) -> Result { - let gh = ::rlp::encode(&spec.genesis_header()); - + pub fn new( + config: Config, + db: Arc, + chain_col: Option, + spec: &Spec, + fetcher: T, + io_channel: IoChannel, + cache: Arc> + ) -> Result { Ok(Client { queue: HeaderQueue::new(config.queue, spec.engine.clone(), io_channel, config.check_seal), engine: spec.engine.clone(), - chain: HeaderChain::new(db.clone(), chain_col, &gh, cache)?, + chain: { + let hs_cfg = if config.no_hardcoded_sync { HardcodedSync::Deny } else { HardcodedSync::Allow }; + HeaderChain::new(db.clone(), chain_col, &spec, cache, hs_cfg)? + }, report: RwLock::new(ClientReport::default()), import_lock: Mutex::new(()), db: db, listeners: RwLock::new(vec![]), + fetcher: fetcher, verify_full: config.verify_full, }) } + /// Generates the specifications for hardcoded sync. This is typically only called manually + /// from time to time by a Parity developer in order to update the chain specifications. + /// + /// Returns `None` if we are at the genesis block. + pub fn read_hardcoded_sync(&self) -> Result, Error> { + self.chain.read_hardcoded_sync() + } + /// Adds a new `LightChainNotify` listener. pub fn add_listener(&self, listener: Weak) { self.listeners.write().push(listener); } - /// Create a new `Client` backed purely in-memory. - /// This will ignore all database options in the configuration. - pub fn in_memory(config: Config, spec: &Spec, io_channel: IoChannel, cache: Arc>) -> Self { - let db = ::util::kvdb::in_memory(0); - - Client::new(config, Arc::new(db), None, spec, io_channel, cache).expect("New DB creation infallible; qed") - } - /// Import a header to the queue for additional verification. pub fn import_header(&self, header: Header) -> Result { self.queue.import(header).map_err(Into::into) @@ -291,19 +304,33 @@ impl Client { continue } - // TODO: `epoch_end_signal`, `is_epoch_end`. - // proofs we get from the network would be _complete_, whereas we need - // _incomplete_ signals + let write_proof_result = match self.check_epoch_signal(&verified_header) { + Ok(Some(proof)) => self.write_pending_proof(&verified_header, proof), + Ok(None) => Ok(()), + Err(e) => + panic!("Unable to fetch epoch transition proof: {:?}", e), + }; + + if let Err(e) = write_proof_result { + warn!(target: "client", "Error writing pending transition proof to DB: {:?} \ + The node may not be able to synchronize further.", e); + } + + let epoch_proof = self.engine.is_epoch_end( + &verified_header, + &|h| self.chain.block_header(BlockId::Hash(h)).map(|hdr| hdr.decode()), + &|h| self.chain.pending_transition(h), + ); let mut tx = self.db.transaction(); - let pending = match self.chain.insert(&mut tx, verified_header) { + let pending = match self.chain.insert(&mut tx, verified_header, epoch_proof) { Ok(pending) => { good.push(hash); self.report.write().blocks_imported += 1; pending } Err(e) => { - debug!(target: "client", "Error importing header {:?}: {}", (num, hash), e); + debug!(target: "client", "Error importing header {:?}: {:?}", (num, hash), e); bad.push(hash); continue; } @@ -330,13 +357,13 @@ impl Client { /// Get blockchain mem usage in bytes. pub fn chain_mem_used(&self) -> usize { - use util::HeapSizeOf; + use heapsize::HeapSizeOf; self.chain.heap_size_of_children() } /// Get a handle to the verification engine. - pub fn engine(&self) -> &Arc { + pub fn engine(&self) -> &Arc { &self.engine } @@ -399,7 +426,7 @@ impl Client { }; // Verify Block Family - let verify_family_result = self.engine.verify_block_family(&verified_header, &parent_header.decode(), None); + let verify_family_result = self.engine.verify_block_family(&verified_header, &parent_header.decode()); if let Err(e) = verify_family_result { warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", verified_header.number(), verified_header.hash(), e); @@ -408,7 +435,7 @@ impl Client { }; // "external" verification. - let verify_external_result = self.engine.verify_block_external(&verified_header, None); + let verify_external_result = self.engine.verify_block_external(&verified_header); if let Err(e) = verify_external_result { warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", verified_header.number(), verified_header.hash(), e); @@ -419,9 +446,80 @@ impl Client { true } + + fn check_epoch_signal(&self, verified_header: &Header) -> Result>, T::Error> { + use ethcore::machine::{AuxiliaryRequest, AuxiliaryData}; + + let mut block: Option> = None; + let mut receipts: Option> = None; + + loop { + + + let is_signal = { + let auxiliary = AuxiliaryData { + bytes: block.as_ref().map(|x| &x[..]), + receipts: receipts.as_ref().map(|x| &x[..]), + }; + + self.engine.signals_epoch_end(verified_header, auxiliary) + }; + + // check with any auxiliary data fetched so far + match is_signal { + EpochChange::No => return Ok(None), + EpochChange::Yes(proof) => return Ok(Some(proof)), + EpochChange::Unsure(unsure) => { + let (b, r) = match unsure { + AuxiliaryRequest::Body => + (Some(self.fetcher.block_body(verified_header)), None), + AuxiliaryRequest::Receipts => + (None, Some(self.fetcher.block_receipts(verified_header))), + AuxiliaryRequest::Both => ( + Some(self.fetcher.block_body(verified_header)), + Some(self.fetcher.block_receipts(verified_header)), + ), + }; + + if let Some(b) = b { + block = Some(b.into_future().wait()?.into_inner()); + } + + if let Some(r) = r { + receipts = Some(r.into_future().wait()?); + } + } + } + } + } + + // attempts to fetch the epoch proof from the network until successful. + fn write_pending_proof(&self, header: &Header, proof: Proof) -> Result<(), T::Error> { + let proof = match proof { + Proof::Known(known) => known, + Proof::WithState(state_dependent) => { + self.fetcher.epoch_transition( + header.hash(), + self.engine.clone(), + state_dependent + ).into_future().wait()? + } + }; + + let mut batch = self.db.transaction(); + self.chain.insert_pending_transition(&mut batch, header.hash(), epoch::PendingTransition { + proof: proof, + }); + self.db.write_buffered(batch); + Ok(()) + } } -impl LightChainClient for Client { +impl LightChainClient for Client { + fn add_listener(&self, listener: Weak) { + Client::add_listener(self, listener) + } + fn chain_info(&self) -> BlockChainInfo { Client::chain_info(self) } fn queue_header(&self, header: Header) -> Result { @@ -456,7 +554,7 @@ impl LightChainClient for Client { Client::env_info(self, id) } - fn engine(&self) -> &Arc { + fn engine(&self) -> &Arc { Client::engine(self) } @@ -480,7 +578,7 @@ impl LightChainClient for Client { Client::cht_root(self, i) } - fn eip86_transition(&self) -> u64 { + fn eip86_transition(&self) -> BlockNumber { self.engine().params().eip86_transition } @@ -488,3 +586,35 @@ impl LightChainClient for Client { Client::report(self) } } + +impl ::ethcore::client::ChainInfo for Client { + fn chain_info(&self) -> BlockChainInfo { + Client::chain_info(self) + } +} + +impl ::ethcore::client::EngineClient for Client { + fn update_sealing(&self) { } + fn submit_seal(&self, _block_hash: H256, _seal: Vec>) { } + fn broadcast_consensus_message(&self, _message: Vec) { } + + fn epoch_transition_for(&self, parent_hash: H256) -> Option { + self.chain.epoch_transition_for(parent_hash).map(|(hdr, proof)| EpochTransition { + block_hash: hdr.hash(), + block_number: hdr.number(), + proof: proof, + }) + } + + fn as_full_client(&self) -> Option<&::ethcore::client::BlockChainClient> { + None + } + + fn block_number(&self, id: BlockId) -> Option { + self.block_header(id).map(|hdr| hdr.number()) + } + + fn block_header(&self, id: BlockId) -> Option { + Client::block_header(self, id) + } +} diff --git a/ethcore/light/src/client/service.rs b/ethcore/light/src/client/service.rs index 83949a2f18efd1f2a77a467ad7edc585c5ef5b20..3d13be16b4a8f0ab72b8b5412e0d3a75e97ec9b4 100644 --- a/ethcore/light/src/client/service.rs +++ b/ethcore/light/src/client/service.rs @@ -18,73 +18,68 @@ //! Just handles block import messages and passes them to the client. use std::fmt; -use std::path::Path; use std::sync::Arc; +use ethcore::client::ClientIoMessage; use ethcore::db; -use ethcore::service::ClientIoMessage; +use ethcore::error::Error as CoreError; use ethcore::spec::Spec; use io::{IoContext, IoError, IoHandler, IoService}; -use util::kvdb::{Database, DatabaseConfig}; +use kvdb::KeyValueDB; use cache::Cache; -use util::Mutex; +use parking_lot::Mutex; -use super::{Client, Config as ClientConfig}; +use super::{ChainDataFetcher, Client, Config as ClientConfig}; /// Errors on service initialization. #[derive(Debug)] pub enum Error { - /// Database error. - Database(String), + /// Core error. + Core(CoreError), /// I/O service error. Io(IoError), } +impl From for Error { + #[inline] + fn from(err: CoreError) -> Error { + Error::Core(err) + } +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::Database(ref msg) => write!(f, "Database error: {}", msg), + Error::Core(ref msg) => write!(f, "Core error: {}", msg), Error::Io(ref err) => write!(f, "I/O service error: {}", err), } } } /// Light client service. -pub struct Service { - client: Arc, +pub struct Service { + client: Arc>, io_service: IoService, } -impl Service { +impl Service { /// Start the service: initialize I/O workers and client itself. - pub fn start(config: ClientConfig, spec: &Spec, path: &Path, cache: Arc>) -> Result { - - // initialize database. - let mut db_config = DatabaseConfig::with_columns(db::NUM_COLUMNS); - - // give all rocksdb cache to the header chain column. - if let Some(size) = config.db_cache_size { - db_config.set_cache(db::COL_LIGHT_CHAIN, size); - } - - db_config.compaction = config.db_compaction; - db_config.wal = config.db_wal; - - let db = Arc::new(Database::open( - &db_config, - &path.to_str().expect("DB path could not be converted to string.") - ).map_err(Error::Database)?); + pub fn start(config: ClientConfig, spec: &Spec, fetcher: T, db: Arc, cache: Arc>) -> Result { let io_service = IoService::::start().map_err(Error::Io)?; let client = Arc::new(Client::new(config, db, db::COL_LIGHT_CHAIN, spec, + fetcher, io_service.channel(), cache, - ).map_err(Error::Database)?); + )?); + io_service.register_handler(Arc::new(ImportBlocks(client.clone()))).map_err(Error::Io)?; + spec.engine.register_client(Arc::downgrade(&client) as _); + Ok(Service { client: client, io_service: io_service, @@ -97,14 +92,14 @@ impl Service { } /// Get a handle to the client. - pub fn client(&self) -> &Arc { + pub fn client(&self) -> &Arc> { &self.client } } -struct ImportBlocks(Arc); +struct ImportBlocks(Arc>); -impl IoHandler for ImportBlocks { +impl IoHandler for ImportBlocks { fn message(&self, _io: &IoContext, message: &ClientIoMessage) { if let ClientIoMessage::BlockVerified = *message { self.0.import_verified(); @@ -115,20 +110,22 @@ impl IoHandler for ImportBlocks { #[cfg(test)] mod tests { use super::Service; - use devtools::RandomTempPath; use ethcore::spec::Spec; - + use std::sync::Arc; use cache::Cache; - use time::Duration; - use util::Mutex; + use client::fetch; + use std::time::Duration; + use parking_lot::Mutex; + use kvdb_memorydb; + use ethcore::db::NUM_COLUMNS; #[test] fn it_works() { + let db = Arc::new(kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0))); let spec = Spec::new_test(); - let temp_path = RandomTempPath::new(); - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(6 * 3600)))); - Service::start(Default::default(), &spec, temp_path.as_path(), cache).unwrap(); + Service::start(Default::default(), &spec, fetch::unavailable(), db, cache).unwrap(); } } diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index c2ab483d2242d9c33492550fc3860372bc6fa751..1ffe0079c18ae398661ec969abd51d04c5be1c69 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -38,21 +38,8 @@ pub mod net; pub mod on_demand; pub mod transaction_queue; pub mod cache; - -#[cfg(not(feature = "ipc"))] pub mod provider; -#[cfg(feature = "ipc")] -pub mod provider { - #![allow(dead_code, unused_assignments, unused_variables, missing_docs)] // codegen issues - include!(concat!(env!("OUT_DIR"), "/provider.rs")); -} - -#[cfg(feature = "ipc")] -pub mod remote { - pub use provider::LightProviderClient; -} - mod types; pub use self::cache::Cache; @@ -69,23 +56,32 @@ extern crate log; extern crate bincode; extern crate ethcore_io as io; extern crate ethcore_network as network; -extern crate ethcore_util as util; +extern crate ethcore_bytes as bytes; +extern crate ethcore_transaction as transaction; +extern crate ethereum_types; extern crate ethcore; -extern crate evm; +extern crate hashdb; +extern crate heapsize; extern crate futures; extern crate itertools; +extern crate memorydb; +extern crate patricia_trie as trie; +extern crate plain_hasher; extern crate rand; extern crate rlp; +extern crate parking_lot; #[macro_use] extern crate rlp_derive; extern crate serde; extern crate smallvec; extern crate stats; -extern crate time; extern crate vm; +extern crate keccak_hash as hash; +extern crate triehash; +extern crate kvdb; +extern crate memory_cache; -#[cfg(feature = "ipc")] -extern crate ethcore_ipc as ipc; - #[cfg(test)] -extern crate ethcore_devtools as devtools; +extern crate kvdb_memorydb; +#[cfg(test)] +extern crate tempdir; diff --git a/ethcore/light/src/net/context.rs b/ethcore/light/src/net/context.rs index 33009d7f60718ec8d8a407c57a584bd69f87fca7..613e26b1f1190e7829bd570615c6cb369f0f3996 100644 --- a/ethcore/light/src/net/context.rs +++ b/ethcore/light/src/net/context.rs @@ -47,7 +47,7 @@ pub trait IoContext { } -impl<'a> IoContext for NetworkContext<'a> { +impl IoContext for T where T: ?Sized + NetworkContext { fn send(&self, peer: PeerId, packet_id: u8, packet_body: Vec) { if let Err(e) = self.send(peer, packet_id, packet_body) { debug!(target: "pip", "Error sending packet to peer {}: {}", peer, e); diff --git a/ethcore/light/src/net/error.rs b/ethcore/light/src/net/error.rs index 57897834871713243e0625381faa3225565038ab..35349c553925c7e0b396762333314576111d0d12 100644 --- a/ethcore/light/src/net/error.rs +++ b/ethcore/light/src/net/error.rs @@ -17,10 +17,8 @@ //! Defines error types and levels of punishment to use upon //! encountering. -use rlp::DecoderError; -use network::NetworkError; - use std::fmt; +use {rlp, network}; /// Levels of punishment. /// @@ -41,9 +39,9 @@ pub enum Punishment { #[derive(Debug)] pub enum Error { /// An RLP decoding error. - Rlp(DecoderError), + Rlp(rlp::DecoderError), /// A network error. - Network(NetworkError), + Network(network::Error), /// Out of credits. NoCredits, /// Unrecognized packet code. @@ -92,14 +90,14 @@ impl Error { } } -impl From for Error { - fn from(err: DecoderError) -> Self { +impl From for Error { + fn from(err: rlp::DecoderError) -> Self { Error::Rlp(err) } } -impl From for Error { - fn from(err: NetworkError) -> Self { +impl From for Error { + fn from(err: network::Error) -> Self { Error::Network(err) } } diff --git a/ethcore/light/src/net/load_timer.rs b/ethcore/light/src/net/load_timer.rs index a169b86d96f13c6e9f36b7204544ce6de801dd6d..c6e524a4412eca8142ff19aed7b6bb920d216825 100644 --- a/ethcore/light/src/net/load_timer.rs +++ b/ethcore/light/src/net/load_timer.rs @@ -27,12 +27,12 @@ use std::collections::{HashMap, VecDeque}; use std::fs::File; use std::path::PathBuf; +use std::time::{Duration, Instant}; use request::{CompleteRequest, Kind}; use bincode; -use time; -use util::{RwLock, Mutex}; +use parking_lot::{RwLock, Mutex}; /// Number of time periods samples should be kept for. pub const MOVING_SAMPLE_SIZE: usize = 256; @@ -62,6 +62,7 @@ fn hardcoded_serve_time(kind: Kind) -> u64 { Kind::Storage => 2_000_000, Kind::Code => 1_500_000, Kind::Execution => 250, // per gas. + Kind::Signal => 500_000, } } @@ -106,7 +107,7 @@ impl LoadDistribution { }; LoadTimer { - start: time::precise_time_ns(), + start: Instant::now(), n: n, dist: self, kind: kind, @@ -150,10 +151,10 @@ impl LoadDistribution { store.store(&*samples); } - fn update(&self, kind: Kind, elapsed: u64, n: u64) { + fn update(&self, kind: Kind, elapsed: Duration, n: u64) { macro_rules! update_counters { ($counters: expr) => { - $counters.0 = $counters.0.saturating_add(elapsed); + $counters.0 = $counters.0.saturating_add({ elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64 }); $counters.1 = $counters.1.saturating_add(n); } }; @@ -179,7 +180,7 @@ impl LoadDistribution { /// A timer for a single request. /// On drop, this will update the distribution. pub struct LoadTimer<'a> { - start: u64, + start: Instant, n: u64, dist: &'a LoadDistribution, kind: Kind, @@ -187,7 +188,7 @@ pub struct LoadTimer<'a> { impl<'a> Drop for LoadTimer<'a> { fn drop(&mut self) { - let elapsed = time::precise_time_ns() - self.start; + let elapsed = self.start.elapsed(); self.dist.update(self.kind, elapsed, self.n); } } @@ -224,7 +225,7 @@ mod tests { let dist = LoadDistribution::load(&NullStore); assert_eq!(dist.expected_time_ns(Kind::Headers), hardcoded_serve_time(Kind::Headers)); - dist.update(Kind::Headers, 100_000, 100); + dist.update(Kind::Headers, Duration::new(0, 100_000), 100); dist.end_period(&NullStore); assert_eq!(dist.expected_time_ns(Kind::Headers), 1000); @@ -237,7 +238,7 @@ mod tests { let mut sum = 0; for (i, x) in (0..10).map(|x| x * 10_000).enumerate() { - dist.update(Kind::Headers, x, 1); + dist.update(Kind::Headers, Duration::new(0, x), 1); dist.end_period(&NullStore); sum += x; @@ -247,7 +248,7 @@ mod tests { // should be weighted below the maximum entry. let arith_average = (sum as f64 / (i + 1) as f64) as u64; - assert!(moving_average < x); + assert!(moving_average < x as u64); // when there are only 2 entries, they should be equal due to choice of // ALPHA = 1/N. @@ -263,8 +264,9 @@ mod tests { #[test] fn file_store() { - let path = ::devtools::RandomTempPath::new(); - let store = FileStore(path.as_path().clone()); + let tempdir = ::tempdir::TempDir::new("").unwrap(); + let path = tempdir.path().join("file"); + let store = FileStore(path); let mut samples = store.load(); assert!(samples.is_empty()); diff --git a/ethcore/light/src/net/mod.rs b/ethcore/light/src/net/mod.rs index 046dc68bd0943f08863f9091f2a9bda13c7666b6..60fe172e23c4e30827bb14a0df9609dab6bd6536 100644 --- a/ethcore/light/src/net/mod.rs +++ b/ethcore/light/src/net/mod.rs @@ -18,14 +18,15 @@ //! //! This uses a "Provider" to answer requests. -use ethcore::transaction::UnverifiedTransaction; +use transaction::UnverifiedTransaction; use io::TimerToken; use network::{HostInfo, NetworkProtocolHandler, NetworkContext, PeerId}; use rlp::{RlpStream, UntrustedRlp}; -use util::hash::H256; -use util::{DBValue, Mutex, RwLock, U256}; -use time::{Duration, SteadyTime}; +use ethereum_types::{H256, U256}; +use kvdb::DBValue; +use parking_lot::{Mutex, RwLock}; +use std::time::{Duration, Instant}; use std::collections::{HashMap, HashSet}; use std::fmt; @@ -72,7 +73,7 @@ const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3; const RECALCULATE_COSTS_INTERVAL_MS: u64 = 60 * 60 * 1000; // minimum interval between updates. -const UPDATE_INTERVAL_MS: i64 = 5000; +const UPDATE_INTERVAL_MS: u64 = 5000; /// Supported protocol versions. pub const PROTOCOL_VERSIONS: &'static [u8] = &[1]; @@ -102,26 +103,26 @@ mod packet { // relay transactions to peers. pub const SEND_TRANSACTIONS: u8 = 0x06; - // request and respond with epoch transition proof - pub const REQUEST_EPOCH_PROOF: u8 = 0x07; - pub const EPOCH_PROOF: u8 = 0x08; + // two packets were previously meant to be reserved for epoch proofs. + // these have since been moved to requests. } // timeouts for different kinds of requests. all values are in milliseconds. mod timeout { - pub const HANDSHAKE: i64 = 2500; - pub const ACKNOWLEDGE_UPDATE: i64 = 5000; - pub const BASE: i64 = 1500; // base timeout for packet. + pub const HANDSHAKE: u64 = 2500; + pub const ACKNOWLEDGE_UPDATE: u64 = 5000; + pub const BASE: u64 = 1500; // base timeout for packet. // timeouts per request within packet. - pub const HEADERS: i64 = 250; // per header? - pub const TRANSACTION_INDEX: i64 = 100; - pub const BODY: i64 = 50; - pub const RECEIPT: i64 = 50; - pub const PROOF: i64 = 100; // state proof - pub const CONTRACT_CODE: i64 = 100; - pub const HEADER_PROOF: i64 = 100; - pub const TRANSACTION_PROOF: i64 = 1000; // per gas? + pub const HEADERS: u64 = 250; // per header? + pub const TRANSACTION_INDEX: u64 = 100; + pub const BODY: u64 = 50; + pub const RECEIPT: u64 = 50; + pub const PROOF: u64 = 100; // state proof + pub const CONTRACT_CODE: u64 = 100; + pub const HEADER_PROOF: u64 = 100; + pub const TRANSACTION_PROOF: u64 = 1000; // per gas? + pub const EPOCH_SIGNAL: u64 = 200; } /// A request id. @@ -143,7 +144,7 @@ impl fmt::Display for ReqId { // may not have received one for. struct PendingPeer { sent_head: H256, - last_update: SteadyTime, + last_update: Instant, } /// Relevant data to each peer. Not accessible publicly, only `pub` due to @@ -154,13 +155,13 @@ pub struct Peer { capabilities: Capabilities, remote_flow: Option<(Credits, FlowParams)>, sent_head: H256, // last chain head we've given them. - last_update: SteadyTime, + last_update: Instant, pending_requests: RequestSet, failed_requests: Vec, propagated_transactions: HashSet, skip_update: bool, local_flow: Arc, - awaiting_acknowledge: Option<(SteadyTime, Arc)>, + awaiting_acknowledge: Option<(Instant, Arc)>, } /// Whether or not a peer was kept by a handler @@ -287,7 +288,7 @@ pub type PeerMap = HashMap>; mod id_guard { use network::PeerId; - use util::RwLockReadGuard; + use parking_lot::RwLockReadGuard; use super::{PeerMap, ReqId}; @@ -428,7 +429,11 @@ impl LightProtocol { // compute and deduct cost. let pre_creds = creds.current(); - let cost = params.compute_cost_multi(requests.requests()); + let cost = match params.compute_cost_multi(requests.requests()) { + Some(cost) => cost, + None => return Err(Error::NotServer), + }; + creds.deduct_cost(cost)?; trace!(target: "pip", "requesting from peer {}. Cost: {}; Available: {}", @@ -442,7 +447,7 @@ impl LightProtocol { }); // begin timeout. - peer.pending_requests.insert(req_id, requests, cost, SteadyTime::now()); + peer.pending_requests.insert(req_id, requests, cost, Instant::now()); Ok(req_id) } } @@ -452,7 +457,7 @@ impl LightProtocol { /// The announcement is expected to be valid. pub fn make_announcement(&self, io: &IoContext, mut announcement: Announcement) { let mut reorgs_map = HashMap::new(); - let now = SteadyTime::now(); + let now = Instant::now(); // update stored capabilities self.capabilities.write().update_from(&announcement); @@ -465,7 +470,7 @@ impl LightProtocol { // the timer approach will skip 1 (possibly 2) in rare occasions. if peer_info.sent_head == announcement.head_hash || peer_info.status.head_num >= announcement.head_num || - now - peer_info.last_update < Duration::milliseconds(UPDATE_INTERVAL_MS) { + now - peer_info.last_update < Duration::from_millis(UPDATE_INTERVAL_MS) { continue } @@ -532,7 +537,7 @@ impl LightProtocol { Some(peer_info) => { let mut peer_info = peer_info.lock(); let peer_info: &mut Peer = &mut *peer_info; - let req_info = peer_info.pending_requests.remove(&req_id, SteadyTime::now()); + let req_info = peer_info.pending_requests.remove(&req_id, Instant::now()); let last_batched = peer_info.pending_requests.is_empty(); let flow_info = peer_info.remote_flow.as_mut(); @@ -582,12 +587,6 @@ impl LightProtocol { packet::SEND_TRANSACTIONS => self.relay_transactions(peer, io, rlp), - packet::REQUEST_EPOCH_PROOF | packet::EPOCH_PROOF => { - // ignore these for now, but leave them specified. - debug!(target: "pip", "Ignoring request/response for epoch proof"); - Ok(()) - } - other => { Err(Error::UnrecognizedPacket(other)) } @@ -600,14 +599,14 @@ impl LightProtocol { // check timeouts and punish peers. fn timeout_check(&self, io: &IoContext) { - let now = SteadyTime::now(); + let now = Instant::now(); // handshake timeout { let mut pending = self.pending_peers.write(); let slowpokes: Vec<_> = pending.iter() .filter(|&(_, ref peer)| { - peer.last_update + Duration::milliseconds(timeout::HANDSHAKE) <= now + peer.last_update + Duration::from_millis(timeout::HANDSHAKE) <= now }) .map(|(&p, _)| p) .collect(); @@ -620,7 +619,7 @@ impl LightProtocol { } // request and update ack timeouts - let ack_duration = Duration::milliseconds(timeout::ACKNOWLEDGE_UPDATE); + let ack_duration = Duration::from_millis(timeout::ACKNOWLEDGE_UPDATE); { for (peer_id, peer) in self.peers.read().iter() { let peer = peer.lock(); @@ -710,7 +709,7 @@ impl LightProtocol { self.pending_peers.write().insert(*peer, PendingPeer { sent_head: chain_info.best_block_hash, - last_update: SteadyTime::now(), + last_update: Instant::now(), }); trace!(target: "pip", "Sending status to peer {}", peer); @@ -772,7 +771,7 @@ impl LightProtocol { *self.flow_params.write() = new_params.clone(); let peers = self.peers.read(); - let now = SteadyTime::now(); + let now = Instant::now(); let packet_body = { let mut stream = RlpStream::new_list(3); @@ -903,7 +902,7 @@ impl LightProtocol { // the maximum amount of requests we'll fill in a single packet. const MAX_REQUESTS: usize = 256; - use ::request::RequestBuilder; + use ::request::Builder; use ::request::CompleteRequest; let peers = self.peers.read(); @@ -918,7 +917,7 @@ impl LightProtocol { let peer: &mut Peer = &mut *peer; let req_id: u64 = raw.val_at(0)?; - let mut request_builder = RequestBuilder::default(); + let mut request_builder = Builder::default(); trace!(target: "pip", "Received requests (id: {}) from peer {}", req_id, peer_id); @@ -928,7 +927,7 @@ impl LightProtocol { peer.local_credits.deduct_cost(peer.local_flow.base_cost())?; for request_rlp in raw.at(1)?.iter().take(MAX_REQUESTS) { let request: Request = request_rlp.as_val()?; - let cost = peer.local_flow.compute_cost(&request); + let cost = peer.local_flow.compute_cost(&request).ok_or(Error::NotServer)?; peer.local_credits.deduct_cost(cost)?; request_builder.push(request).map_err(|_| Error::BadBackReference)?; } @@ -943,13 +942,14 @@ impl LightProtocol { match complete_req { CompleteRequest::Headers(req) => self.provider.block_headers(req).map(Response::Headers), CompleteRequest::HeaderProof(req) => self.provider.header_proof(req).map(Response::HeaderProof), - CompleteRequest::TransactionIndex(_) => None, // don't answer these yet, but leave them in protocol. + CompleteRequest::TransactionIndex(req) => self.provider.transaction_index(req).map(Response::TransactionIndex), CompleteRequest::Body(req) => self.provider.block_body(req).map(Response::Body), CompleteRequest::Receipts(req) => self.provider.block_receipts(req).map(Response::Receipts), CompleteRequest::Account(req) => self.provider.account_proof(req).map(Response::Account), CompleteRequest::Storage(req) => self.provider.storage_proof(req).map(Response::Storage), CompleteRequest::Code(req) => self.provider.contract_code(req).map(Response::Code), CompleteRequest::Execution(req) => self.provider.transaction_proof(req).map(Response::Execution), + CompleteRequest::Signal(req) => self.provider.epoch_signal(req).map(Response::Signal), } }); @@ -1089,23 +1089,23 @@ impl NetworkProtocolHandler for LightProtocol { } fn read(&self, io: &NetworkContext, peer: &PeerId, packet_id: u8, data: &[u8]) { - self.handle_packet(io, peer, packet_id, data); + self.handle_packet(&io, peer, packet_id, data); } fn connected(&self, io: &NetworkContext, peer: &PeerId) { - self.on_connect(peer, io); + self.on_connect(peer, &io); } fn disconnected(&self, io: &NetworkContext, peer: &PeerId) { - self.on_disconnect(*peer, io); + self.on_disconnect(*peer, &io); } fn timeout(&self, io: &NetworkContext, timer: TimerToken) { match timer { - TIMEOUT => self.timeout_check(io), - TICK_TIMEOUT => self.tick_handlers(io), - PROPAGATE_TIMEOUT => self.propagate_transactions(io), - RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(io), + TIMEOUT => self.timeout_check(&io), + TICK_TIMEOUT => self.tick_handlers(&io), + PROPAGATE_TIMEOUT => self.propagate_transactions(&io), + RECALCULATE_COSTS_TIMEOUT => self.begin_new_cost_period(&io), _ => warn!(target: "pip", "received timeout on unknown token {}", timer), } } diff --git a/ethcore/light/src/net/request_credits.rs b/ethcore/light/src/net/request_credits.rs index 950fa24d804060a89d50eab644dec67f337d0d4c..f97ce85bcdfd911ddc0413bf2f5c9c1a90fcb8c3 100644 --- a/ethcore/light/src/net/request_credits.rs +++ b/ethcore/light/src/net/request_credits.rs @@ -30,8 +30,8 @@ use request::{self, Request}; use super::error::Error; use rlp::*; -use util::U256; -use time::{Duration, SteadyTime}; +use ethereum_types::U256; +use std::time::{Duration, Instant}; /// Credits value. /// @@ -41,7 +41,7 @@ use time::{Duration, SteadyTime}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Credits { estimate: U256, - recharge_point: SteadyTime, + recharge_point: Instant, } impl Credits { @@ -53,7 +53,7 @@ impl Credits { /// a response to a request. pub fn update_to(&mut self, value: U256) { self.estimate = value; - self.recharge_point = SteadyTime::now(); + self.recharge_point = Instant::now(); } /// Maintain ratio to current limit against an old limit. @@ -79,18 +79,42 @@ impl Credits { } /// A cost table, mapping requests to base and per-request costs. +/// Costs themselves may be missing. #[derive(Debug, Clone, PartialEq, Eq)] pub struct CostTable { base: U256, // cost per packet. - headers: U256, // cost per header - transaction_index: U256, - body: U256, - receipts: U256, - account: U256, - storage: U256, - code: U256, - header_proof: U256, - transaction_proof: U256, // cost per gas. + headers: Option, // cost per header + transaction_index: Option, + body: Option, + receipts: Option, + account: Option, + storage: Option, + code: Option, + header_proof: Option, + transaction_proof: Option, // cost per gas. + epoch_signal: Option, +} + +impl CostTable { + fn costs_set(&self) -> usize { + let mut num_set = 0; + + { + let mut incr_if_set = |cost: &Option<_>| if cost.is_some() { num_set += 1 }; + incr_if_set(&self.headers); + incr_if_set(&self.transaction_index); + incr_if_set(&self.body); + incr_if_set(&self.receipts); + incr_if_set(&self.account); + incr_if_set(&self.storage); + incr_if_set(&self.code); + incr_if_set(&self.header_proof); + incr_if_set(&self.transaction_proof); + incr_if_set(&self.epoch_signal); + } + + num_set + } } impl Default for CostTable { @@ -98,30 +122,32 @@ impl Default for CostTable { // arbitrarily chosen constants. CostTable { base: 100000.into(), - headers: 10000.into(), - transaction_index: 10000.into(), - body: 15000.into(), - receipts: 5000.into(), - account: 25000.into(), - storage: 25000.into(), - code: 20000.into(), - header_proof: 15000.into(), - transaction_proof: 2.into(), + headers: Some(10000.into()), + transaction_index: Some(10000.into()), + body: Some(15000.into()), + receipts: Some(5000.into()), + account: Some(25000.into()), + storage: Some(25000.into()), + code: Some(20000.into()), + header_proof: Some(15000.into()), + transaction_proof: Some(2.into()), + epoch_signal: Some(10000.into()), } } } impl Encodable for CostTable { fn rlp_append(&self, s: &mut RlpStream) { - fn append_cost(s: &mut RlpStream, cost: &U256, kind: request::Kind) { - s.begin_list(2); - - // hack around https://github.com/paritytech/parity/issues/4356 - Encodable::rlp_append(&kind, s); - s.append(cost); + fn append_cost(s: &mut RlpStream, cost: &Option, kind: request::Kind) { + if let Some(ref cost) = *cost { + s.begin_list(2); + // hack around https://github.com/paritytech/parity/issues/4356 + Encodable::rlp_append(&kind, s); + s.append(cost); + } } - s.begin_list(10).append(&self.base); + s.begin_list(1 + self.costs_set()).append(&self.base); append_cost(s, &self.headers, request::Kind::Headers); append_cost(s, &self.transaction_index, request::Kind::TransactionIndex); append_cost(s, &self.body, request::Kind::Body); @@ -131,6 +157,7 @@ impl Encodable for CostTable { append_cost(s, &self.code, request::Kind::Code); append_cost(s, &self.header_proof, request::Kind::HeaderProof); append_cost(s, &self.transaction_proof, request::Kind::Execution); + append_cost(s, &self.epoch_signal, request::Kind::Signal); } } @@ -147,6 +174,7 @@ impl Decodable for CostTable { let mut code = None; let mut header_proof = None; let mut transaction_proof = None; + let mut epoch_signal = None; for cost_list in rlp.iter().skip(1) { let cost = cost_list.val_at(1)?; @@ -160,23 +188,29 @@ impl Decodable for CostTable { request::Kind::Code => code = Some(cost), request::Kind::HeaderProof => header_proof = Some(cost), request::Kind::Execution => transaction_proof = Some(cost), + request::Kind::Signal => epoch_signal = Some(cost), } } - let unwrap_cost = |cost: Option| cost.ok_or(DecoderError::Custom("Not all costs specified in cost table.")); - - Ok(CostTable { + let table = CostTable { base: base, - headers: unwrap_cost(headers)?, - transaction_index: unwrap_cost(transaction_index)?, - body: unwrap_cost(body)?, - receipts: unwrap_cost(receipts)?, - account: unwrap_cost(account)?, - storage: unwrap_cost(storage)?, - code: unwrap_cost(code)?, - header_proof: unwrap_cost(header_proof)?, - transaction_proof: unwrap_cost(transaction_proof)?, - }) + headers: headers, + transaction_index: transaction_index, + body: body, + receipts: receipts, + account: account, + storage: storage, + code: code, + header_proof: header_proof, + transaction_proof: transaction_proof, + epoch_signal: epoch_signal, + }; + + if table.costs_set() == 0 { + Err(DecoderError::Custom("no cost types set.")) + } else { + Ok(table) + } } } @@ -224,7 +258,7 @@ impl FlowParams { let serve_per_second = serve_per_second.max(1.0 / 10_000.0); // as a percentage of the recharge per second. - U256::from((recharge as f64 / serve_per_second) as u64) + Some(U256::from((recharge as f64 / serve_per_second) as u64)) }; let costs = CostTable { @@ -238,6 +272,7 @@ impl FlowParams { code: cost_for_kind(Kind::Code), header_proof: cost_for_kind(Kind::HeaderProof), transaction_proof: cost_for_kind(Kind::Execution), + epoch_signal: cost_for_kind(Kind::Signal), }; FlowParams { @@ -249,12 +284,12 @@ impl FlowParams { /// Create effectively infinite flow params. pub fn free() -> Self { - let free_cost: U256 = 0.into(); + let free_cost: Option = Some(0.into()); FlowParams { limit: (!0u64).into(), recharge: 1.into(), costs: CostTable { - base: free_cost.clone(), + base: 0.into(), headers: free_cost.clone(), transaction_index: free_cost.clone(), body: free_cost.clone(), @@ -263,7 +298,8 @@ impl FlowParams { storage: free_cost.clone(), code: free_cost.clone(), header_proof: free_cost.clone(), - transaction_proof: free_cost, + transaction_proof: free_cost.clone(), + epoch_signal: free_cost, } } } @@ -282,9 +318,9 @@ impl FlowParams { /// Compute the actual cost of a request, given the kind of request /// and number of requests made. - pub fn compute_cost(&self, request: &Request) -> U256 { + pub fn compute_cost(&self, request: &Request) -> Option { match *request { - Request::Headers(ref req) => self.costs.headers * req.max.into(), + Request::Headers(ref req) => self.costs.headers.map(|c| c * U256::from(req.max)), Request::HeaderProof(_) => self.costs.header_proof, Request::TransactionIndex(_) => self.costs.transaction_index, Request::Body(_) => self.costs.body, @@ -292,33 +328,42 @@ impl FlowParams { Request::Account(_) => self.costs.account, Request::Storage(_) => self.costs.storage, Request::Code(_) => self.costs.code, - Request::Execution(ref req) => self.costs.transaction_proof * req.gas, + Request::Execution(ref req) => self.costs.transaction_proof.map(|c| c * req.gas), + Request::Signal(_) => self.costs.epoch_signal, } } /// Compute the cost of a set of requests. /// This is the base cost plus the cost of each individual request. - pub fn compute_cost_multi(&self, requests: &[Request]) -> U256 { - requests.iter().fold(self.costs.base, |cost, req| cost + self.compute_cost(req)) + pub fn compute_cost_multi(&self, requests: &[Request]) -> Option { + let mut cost = self.costs.base; + for request in requests { + match self.compute_cost(request) { + Some(c) => cost = cost + c, + None => return None, + } + } + + Some(cost) } /// Create initial credits. pub fn create_credits(&self) -> Credits { Credits { estimate: self.limit, - recharge_point: SteadyTime::now(), + recharge_point: Instant::now(), } } /// Recharge the given credits based on time passed since last /// update. pub fn recharge(&self, credits: &mut Credits) { - let now = SteadyTime::now(); + let now = Instant::now(); // recompute and update only in terms of full seconds elapsed // in order to keep the estimate as an underestimate. - let elapsed = (now - credits.recharge_point).num_seconds(); - credits.recharge_point = credits.recharge_point + Duration::seconds(elapsed); + let elapsed = (now - credits.recharge_point).as_secs(); + credits.recharge_point = credits.recharge_point + Duration::from_secs(elapsed); let elapsed: U256 = elapsed.into(); @@ -399,6 +444,6 @@ mod tests { ); assert_eq!(flow_params2.costs, flow_params3.costs); - assert_eq!(flow_params.costs.headers, flow_params2.costs.headers * 2.into()); + assert_eq!(flow_params.costs.headers.unwrap(), flow_params2.costs.headers.unwrap() * 2u32); } } diff --git a/ethcore/light/src/net/request_set.rs b/ethcore/light/src/net/request_set.rs index 35182f0bf81b2b997daab8ee15bf1cc972194c1f..27e6c28bc2d1171b5cd3bf3f0f0c4bb78a3c752f 100644 --- a/ethcore/light/src/net/request_set.rs +++ b/ethcore/light/src/net/request_set.rs @@ -23,13 +23,12 @@ use std::collections::{BTreeMap, HashMap}; use std::iter::FromIterator; +use std::time::{Duration, Instant}; use request::Request; use request::NetworkRequests as Requests; use net::{timeout, ReqId}; -use util::U256; - -use time::{Duration, SteadyTime}; +use ethereum_types::U256; // Request set entry: requests + cost. #[derive(Debug)] @@ -40,7 +39,7 @@ struct Entry(Requests, U256); pub struct RequestSet { counter: u64, cumulative_cost: U256, - base: Option, + base: Option, ids: HashMap, reqs: BTreeMap, } @@ -59,7 +58,7 @@ impl Default for RequestSet { impl RequestSet { /// Push requests onto the stack. - pub fn insert(&mut self, req_id: ReqId, req: Requests, cost: U256, now: SteadyTime) { + pub fn insert(&mut self, req_id: ReqId, req: Requests, cost: U256, now: Instant) { let counter = self.counter; self.cumulative_cost = self.cumulative_cost + cost; @@ -74,7 +73,7 @@ impl RequestSet { } /// Remove a set of requests from the stack. - pub fn remove(&mut self, req_id: &ReqId, now: SteadyTime) -> Option { + pub fn remove(&mut self, req_id: &ReqId, now: Instant) -> Option { let id = match self.ids.remove(&req_id) { Some(id) => id, None => return None, @@ -94,7 +93,7 @@ impl RequestSet { /// Check for timeout against the given time. Returns true if /// has timed out, false otherwise. - pub fn check_timeout(&self, now: SteadyTime) -> bool { + pub fn check_timeout(&self, now: Instant) -> bool { let base = match self.base.as_ref().cloned() { Some(base) => base, None => return false, @@ -128,7 +127,7 @@ impl RequestSet { // helper to calculate timeout for a specific set of requests. // it's a base amount + some amount per request. fn compute_timeout(reqs: &Requests) -> Duration { - Duration::milliseconds(reqs.requests().iter().fold(timeout::BASE, |tm, req| { + Duration::from_millis(reqs.requests().iter().fold(timeout::BASE, |tm, req| { tm + match *req { Request::Headers(_) => timeout::HEADERS, Request::HeaderProof(_) => timeout::HEADER_PROOF, @@ -139,6 +138,7 @@ fn compute_timeout(reqs: &Requests) -> Duration { Request::Storage(_) => timeout::PROOF, Request::Code(_) => timeout::CONTRACT_CODE, Request::Execution(_) => timeout::TRANSACTION_PROOF, + Request::Signal(_) => timeout::EPOCH_SIGNAL, } })) } @@ -146,35 +146,35 @@ fn compute_timeout(reqs: &Requests) -> Duration { #[cfg(test)] mod tests { use net::ReqId; - use request::RequestBuilder; - use time::{SteadyTime, Duration}; + use request::Builder; + use std::time::{Instant, Duration}; use super::{RequestSet, compute_timeout}; #[test] fn multi_timeout() { - let test_begin = SteadyTime::now(); + let test_begin = Instant::now(); let mut req_set = RequestSet::default(); - let the_req = RequestBuilder::default().build(); + let the_req = Builder::default().build(); let req_time = compute_timeout(&the_req); req_set.insert(ReqId(0), the_req.clone(), 0.into(), test_begin); - req_set.insert(ReqId(1), the_req, 0.into(), test_begin + Duration::seconds(1)); + req_set.insert(ReqId(1), the_req, 0.into(), test_begin + Duration::from_secs(1)); assert_eq!(req_set.base, Some(test_begin)); let test_end = test_begin + req_time; assert!(req_set.check_timeout(test_end)); - req_set.remove(&ReqId(0), test_begin + Duration::seconds(1)).unwrap(); + req_set.remove(&ReqId(0), test_begin + Duration::from_secs(1)).unwrap(); assert!(!req_set.check_timeout(test_end)); - assert!(req_set.check_timeout(test_end + Duration::seconds(1))); + assert!(req_set.check_timeout(test_end + Duration::from_secs(1))); } #[test] fn cumulative_cost() { - let the_req = RequestBuilder::default().build(); - let test_begin = SteadyTime::now(); - let test_end = test_begin + Duration::seconds(1); + let the_req = Builder::default().build(); + let test_begin = Instant::now(); + let test_end = test_begin + Duration::from_secs(1); let mut req_set = RequestSet::default(); for i in 0..5 { diff --git a/ethcore/light/src/net/status.rs b/ethcore/light/src/net/status.rs index 7328264303c603fa788f11eefa4bd3958143c05c..0f811bbe40845f96f340a0c13b6a17f8fbf71bec 100644 --- a/ethcore/light/src/net/status.rs +++ b/ethcore/light/src/net/status.rs @@ -17,7 +17,7 @@ //! Peer status and capabilities. use rlp::{DecoderError, Encodable, Decodable, RlpStream, UntrustedRlp}; -use util::{H256, U256}; +use ethereum_types::{H256, U256}; use super::request_credits::FlowParams; @@ -373,7 +373,7 @@ pub fn write_announcement(announcement: &Announcement) -> Vec { mod tests { use super::*; use super::super::request_credits::FlowParams; - use util::{U256, H256}; + use ethereum_types::{U256, H256}; use rlp::{RlpStream, UntrustedRlp}; #[test] diff --git a/ethcore/light/src/net/tests/mod.rs b/ethcore/light/src/net/tests/mod.rs index ef86c08f56ac3b1458227ae241f10a42f4a14eca..c3c792b786a5be0122b864b018cd5995294c3e4d 100644 --- a/ethcore/light/src/net/tests/mod.rs +++ b/ethcore/light/src/net/tests/mod.rs @@ -20,9 +20,9 @@ use ethcore::blockchain_info::BlockChainInfo; use ethcore::client::{EachBlockWith, TestBlockChainClient}; use ethcore::ids::BlockId; -use ethcore::transaction::{Action, PendingTransaction}; use ethcore::encoded; use network::{PeerId, NodeId}; +use transaction::{Action, PendingTransaction}; use net::context::IoContext; use net::status::{Capabilities, Status}; @@ -32,14 +32,15 @@ use request; use request::*; use rlp::*; -use util::{Address, H256, U256}; +use ethereum_types::{H256, U256, Address}; use std::sync::Arc; +use std::time::Instant; // helper for encoding a single request into a packet. // panics on bad backreference. fn encode_single(request: Request) -> NetworkRequests { - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); builder.push(request).unwrap(); builder.build() } @@ -114,6 +115,16 @@ impl Provider for TestProvider { self.0.client.block_header(id) } + fn transaction_index(&self, req: request::CompleteTransactionIndexRequest) + -> Option + { + Some(request::TransactionIndexResponse { + num: 100, + hash: req.hash, + index: 55, + }) + } + fn block_body(&self, req: request::CompleteBodyRequest) -> Option { self.0.client.block_body(req) } @@ -156,6 +167,12 @@ impl Provider for TestProvider { None } + fn epoch_signal(&self, _req: request::CompleteSignalRequest) -> Option { + Some(request::SignalResponse { + signal: vec![1, 2, 3, 4], + }) + } + fn ready_transactions(&self) -> Vec { self.0.client.ready_transactions() } @@ -300,7 +317,7 @@ fn get_block_headers() { let headers: Vec<_> = (0..10).map(|i| provider.client.block_header(BlockId::Number(i + 1)).unwrap()).collect(); assert_eq!(headers.len(), 10); - let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()); + let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap(); let response = vec![Response::Headers(HeadersResponse { headers: headers, @@ -336,7 +353,7 @@ fn get_block_bodies() { proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &my_status); } - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); let mut bodies = Vec::new(); for i in 0..10 { @@ -353,7 +370,7 @@ fn get_block_bodies() { let request_body = make_packet(req_id, &requests); let response = { - let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()); + let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap(); let mut response_stream = RlpStream::new_list(3); response_stream.append(&req_id).append(&new_creds).append_list(&bodies); @@ -392,7 +409,7 @@ fn get_block_receipts() { .take(10) .collect(); - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); let mut receipts = Vec::new(); for hash in block_hashes.iter().cloned() { builder.push(Request::Receipts(IncompleteReceiptsRequest { hash: hash.into() })).unwrap(); @@ -408,7 +425,7 @@ fn get_block_receipts() { let response = { assert_eq!(receipts.len(), 10); - let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()); + let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap(); let mut response_stream = RlpStream::new_list(3); response_stream.append(&req_id).append(&new_creds).append_list(&receipts); @@ -440,7 +457,7 @@ fn get_state_proofs() { let key1: H256 = U256::from(11223344).into(); let key2: H256 = U256::from(99988887).into(); - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); builder.push(Request::Account(IncompleteAccountRequest { block_hash: H256::default().into(), address_hash: key1.into(), @@ -467,7 +484,7 @@ fn get_state_proofs() { }).unwrap()), ]; - let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()); + let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap(); let mut response_stream = RlpStream::new_list(3); response_stream.append(&req_id).append(&new_creds).append_list(&responses); @@ -509,7 +526,7 @@ fn get_contract_code() { code: key1.iter().chain(key2.iter()).cloned().collect(), })]; - let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()); + let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap(); let mut response_stream = RlpStream::new_list(3); @@ -521,6 +538,49 @@ fn get_contract_code() { proto.handle_packet(&expected, &1, packet::REQUEST, &request_body); } +#[test] +fn epoch_signal() { + let capabilities = capabilities(); + + let (provider, proto) = setup(capabilities.clone()); + let flow_params = proto.flow_params.read().clone(); + + let cur_status = status(provider.client.chain_info()); + + { + let packet_body = write_handshake(&cur_status, &capabilities, &proto); + proto.on_connect(&1, &Expect::Send(1, packet::STATUS, packet_body.clone())); + proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &packet_body); + } + + let req_id = 112; + let request = Request::Signal(request::IncompleteSignalRequest { + block_hash: H256([1; 32]).into(), + }); + + let requests = encode_single(request.clone()); + let request_body = make_packet(req_id, &requests); + + let response = { + let response = vec![Response::Signal(SignalResponse { + signal: vec![1, 2, 3, 4], + })]; + + let limit = *flow_params.limit(); + let cost = flow_params.compute_cost_multi(requests.requests()).unwrap(); + + let new_creds = limit - cost; + + let mut response_stream = RlpStream::new_list(3); + response_stream.append(&req_id).append(&new_creds).append_list(&response); + + response_stream.out() + }; + + let expected = Expect::Respond(packet::RESPONSE, response); + proto.handle_packet(&expected, &1, packet::REQUEST, &request_body); +} + #[test] fn proof_of_execution() { let capabilities = capabilities(); @@ -553,9 +613,8 @@ fn proof_of_execution() { let response = { let limit = *flow_params.limit(); - let cost = flow_params.compute_cost_multi(requests.requests()); + let cost = flow_params.compute_cost_multi(requests.requests()).unwrap(); - println!("limit = {}, cost = {}", limit, cost); let new_creds = limit - cost; let mut response_stream = RlpStream::new_list(3); @@ -603,16 +662,16 @@ fn id_guard() { let mut pending_requests = RequestSet::default(); - pending_requests.insert(req_id_1, req.clone(), 0.into(), ::time::SteadyTime::now()); - pending_requests.insert(req_id_2, req, 1.into(), ::time::SteadyTime::now()); + pending_requests.insert(req_id_1, req.clone(), 0.into(), Instant::now()); + pending_requests.insert(req_id_2, req, 1.into(), Instant::now()); - proto.peers.write().insert(peer_id, ::util::Mutex::new(Peer { + proto.peers.write().insert(peer_id, ::parking_lot::Mutex::new(Peer { local_credits: flow_params.create_credits(), status: status(provider.client.chain_info()), capabilities: capabilities.clone(), remote_flow: Some((flow_params.create_credits(), (&*flow_params).clone())), sent_head: provider.client.chain_info().best_block_hash, - last_update: ::time::SteadyTime::now(), + last_update: Instant::now(), pending_requests: pending_requests, failed_requests: Vec::new(), propagated_transactions: Default::default(), @@ -661,3 +720,46 @@ fn id_guard() { assert_eq!(peer_info.failed_requests, &[req_id_1]); } } + +#[test] +fn get_transaction_index() { + let capabilities = capabilities(); + + let (provider, proto) = setup(capabilities.clone()); + let flow_params = proto.flow_params.read().clone(); + + let cur_status = status(provider.client.chain_info()); + + { + let packet_body = write_handshake(&cur_status, &capabilities, &proto); + proto.on_connect(&1, &Expect::Send(1, packet::STATUS, packet_body.clone())); + proto.handle_packet(&Expect::Nothing, &1, packet::STATUS, &packet_body); + } + + let req_id = 112; + let key1: H256 = U256::from(11223344).into(); + + let request = Request::TransactionIndex(IncompleteTransactionIndexRequest { + hash: key1.into(), + }); + + let requests = encode_single(request.clone()); + let request_body = make_packet(req_id, &requests); + let response = { + let response = vec![Response::TransactionIndex(TransactionIndexResponse { + num: 100, + hash: key1, + index: 55, + })]; + + let new_creds = *flow_params.limit() - flow_params.compute_cost_multi(requests.requests()).unwrap(); + + let mut response_stream = RlpStream::new_list(3); + + response_stream.append(&req_id).append(&new_creds).append_list(&response); + response_stream.out() + }; + + let expected = Expect::Respond(packet::RESPONSE, response); + proto.handle_packet(&expected, &1, packet::REQUEST, &request_body); +} diff --git a/ethcore/light/src/on_demand/mod.rs b/ethcore/light/src/on_demand/mod.rs index 42469725bbf89b7dcbdeb159fa0b1e9654ceddfd..64794d49e720c630060ab5c646a743e4359c3ef3 100644 --- a/ethcore/light/src/on_demand/mod.rs +++ b/ethcore/light/src/on_demand/mod.rs @@ -18,16 +18,18 @@ //! The request service is implemented using Futures. Higher level request handlers //! will take the raw data received here and extract meaningful results from it. +use std::cmp; use std::collections::HashMap; use std::marker::PhantomData; use std::sync::Arc; use ethcore::executed::{Executed, ExecutionError}; -use futures::{Async, Poll, Future}; -use futures::sync::oneshot::{self, Sender, Receiver, Canceled}; +use futures::{Poll, Future}; +use futures::sync::oneshot::{self, Receiver, Canceled}; use network::PeerId; -use util::{RwLock, Mutex}; +use parking_lot::{RwLock, Mutex}; +use rand; use net::{ self, Handler, PeerStatus, Status, Capabilities, @@ -74,8 +76,8 @@ impl Peer { // Attempted request info and sender to put received value. struct Pending { - requests: basic_request::Requests, - net_requests: basic_request::Requests, + requests: basic_request::Batch, + net_requests: basic_request::Batch, required_capabilities: Capabilities, responses: Vec, sender: oneshot::Sender>, @@ -90,7 +92,14 @@ impl Pending { match self.requests[idx].respond_local(cache) { Some(response) => { self.requests.supply_response_unchecked(&response); + + // update header and back-references after each from-cache + // response to ensure that the requests are left in a consistent + // state and increase the likelihood of being able to answer + // the next request from cache. self.update_header_refs(idx, &response); + self.fill_unanswered(); + self.responses.push(response); } None => break, @@ -151,7 +160,7 @@ impl Pending { fn update_net_requests(&mut self) { use request::IncompleteRequest; - let mut builder = basic_request::RequestBuilder::default(); + let mut builder = basic_request::Builder::default(); let num_answered = self.requests.num_answered(); let mut mapping = move |idx| idx - num_answered; @@ -195,6 +204,9 @@ fn guess_capabilities(requests: &[CheckedRequest]) -> Capabilities { caps.serve_headers = true, CheckedRequest::HeaderByHash(_, _) => caps.serve_headers = true, + CheckedRequest::TransactionIndex(_, _) => {} // hashes yield no info. + CheckedRequest::Signal(_, _) => + caps.serve_headers = true, CheckedRequest::Body(ref req, _) => if let Ok(ref hdr) = req.0.as_ref() { update_since(&mut caps.serve_chain_since, hdr.number()); }, @@ -279,7 +291,7 @@ impl OnDemand { return Ok(receiver); } - let mut builder = basic_request::RequestBuilder::default(); + let mut builder = basic_request::Builder::default(); let responses = Vec::with_capacity(requests.len()); @@ -342,29 +354,6 @@ impl OnDemand { // dispatch pending requests, and discard those for which the corresponding // receiver has been dropped. fn dispatch_pending(&self, ctx: &BasicContext) { - - // wrapper future for calling `poll_cancel` on our `Senders` to preserve - // the invariant that it's always within a task. - struct CheckHangup<'a, T: 'a>(&'a mut Sender); - - impl<'a, T: 'a> Future for CheckHangup<'a, T> { - type Item = bool; - type Error = (); - - fn poll(&mut self) -> Poll { - Ok(Async::Ready(match self.0.poll_cancel() { - Ok(Async::NotReady) => false, // hasn't hung up. - _ => true, // has hung up. - })) - } - } - - // check whether a sender's hung up (using `wait` to preserve the task invariant) - // returns true if has hung up, false otherwise. - fn check_hangup(send: &mut Sender) -> bool { - CheckHangup(send).wait().expect("CheckHangup always returns ok; qed") - } - if self.pending.read().is_empty() { return } let mut pending = self.pending.write(); @@ -374,12 +363,12 @@ impl OnDemand { // then, try and find a peer who can serve it. let peers = self.peers.read(); *pending = ::std::mem::replace(&mut *pending, Vec::new()).into_iter() - .filter_map(|mut pending| match check_hangup(&mut pending.sender) { - false => Some(pending), - true => None, - }) + .filter(|pending| !pending.sender.is_canceled()) .filter_map(|pending| { - for (peer_id, peer) in peers.iter() { // .shuffle? + // the peer we dispatch to is chosen randomly + let num_peers = peers.len(); + let rng = rand::random::() % cmp::max(num_peers, 1); + for (peer_id, peer) in peers.iter().chain(peers.iter()).skip(rng).take(num_peers) { // TODO: see which requests can be answered by the cache? if !peer.can_fulfill(&pending.required_capabilities) { diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index 6a22013494193279667ddf08bffb55b5248c3602..e7303ad884eb28e1780570f414e70f5c26624e5b 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -20,19 +20,24 @@ use std::sync::Arc; use ethcore::basic_account::BasicAccount; use ethcore::encoded; -use ethcore::engines::Engine; +use ethcore::engines::{EthEngine, StateDependentProof}; +use ethcore::machine::EthereumMachine; use ethcore::receipt::Receipt; use ethcore::state::{self, ProvedExecution}; -use ethcore::transaction::SignedTransaction; +use transaction::SignedTransaction; use vm::EnvInfo; +use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY, KECCAK_EMPTY_LIST_RLP, keccak}; use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field}; use rlp::{RlpStream, UntrustedRlp}; -use util::{Address, Bytes, DBValue, HashDB, Mutex, H256, U256}; -use util::memorydb::MemoryDB; -use util::sha3::{Hashable, SHA3_NULL_RLP, SHA3_EMPTY, SHA3_EMPTY_LIST_RLP}; -use util::trie::{Trie, TrieDB, TrieError}; +use ethereum_types::{H256, U256, Address}; +use parking_lot::Mutex; +use hashdb::HashDB; +use kvdb::DBValue; +use bytes::Bytes; +use memorydb::MemoryDB; +use trie::{Trie, TrieDB, TrieError}; const SUPPLIED_MATCHES: &'static str = "supplied responses always match produced requests; enforced by `check_response`; qed"; @@ -43,6 +48,8 @@ pub enum Request { HeaderProof(HeaderProof), /// A request for a header by hash. HeaderByHash(HeaderByHash), + /// A request for the index of a transaction. + TransactionIndex(TransactionIndex), /// A request for block receipts. Receipts(BlockReceipts), /// A request for a block body. @@ -53,6 +60,8 @@ pub enum Request { Code(Code), /// A request for proof of execution. Execution(TransactionProof), + /// A request for epoch change signal. + Signal(Signal), } /// A request argument. @@ -128,11 +137,13 @@ macro_rules! impl_single { // implement traits for each kind of request. impl_single!(HeaderProof, HeaderProof, (H256, U256)); impl_single!(HeaderByHash, HeaderByHash, encoded::Header); +impl_single!(TransactionIndex, TransactionIndex, net_request::TransactionIndexResponse); impl_single!(Receipts, BlockReceipts, Vec); impl_single!(Body, Body, encoded::Block); impl_single!(Account, Account, Option); impl_single!(Code, Code, Bytes); impl_single!(Execution, TransactionProof, super::ExecutionResult); +impl_single!(Signal, Signal, Vec); macro_rules! impl_args { () => { @@ -236,11 +247,13 @@ impl From for HeaderRef { pub enum CheckedRequest { HeaderProof(HeaderProof, net_request::IncompleteHeaderProofRequest), HeaderByHash(HeaderByHash, net_request::IncompleteHeadersRequest), + TransactionIndex(TransactionIndex, net_request::IncompleteTransactionIndexRequest), Receipts(BlockReceipts, net_request::IncompleteReceiptsRequest), Body(Body, net_request::IncompleteBodyRequest), Account(Account, net_request::IncompleteAccountRequest), Code(Code, net_request::IncompleteCodeRequest), Execution(TransactionProof, net_request::IncompleteExecutionRequest), + Signal(Signal, net_request::IncompleteSignalRequest) } impl From for CheckedRequest { @@ -261,6 +274,12 @@ impl From for CheckedRequest { }; CheckedRequest::HeaderProof(req, net_req) } + Request::TransactionIndex(req) => { + let net_req = net_request::IncompleteTransactionIndexRequest { + hash: req.0.clone(), + }; + CheckedRequest::TransactionIndex(req, net_req) + } Request::Body(req) => { let net_req = net_request::IncompleteBodyRequest { hash: req.0.field(), @@ -276,7 +295,7 @@ impl From for CheckedRequest { Request::Account(req) => { let net_req = net_request::IncompleteAccountRequest { block_hash: req.header.field(), - address_hash: ::util::Hashable::sha3(&req.address).into(), + address_hash: ::hash::keccak(&req.address).into(), }; CheckedRequest::Account(req, net_req) } @@ -299,6 +318,12 @@ impl From for CheckedRequest { }; CheckedRequest::Execution(req, net_req) } + Request::Signal(req) => { + let net_req = net_request::IncompleteSignalRequest { + block_hash: req.hash.into(), + }; + CheckedRequest::Signal(req, net_req) + } } } } @@ -311,11 +336,13 @@ impl CheckedRequest { match self { CheckedRequest::HeaderProof(_, req) => NetRequest::HeaderProof(req), CheckedRequest::HeaderByHash(_, req) => NetRequest::Headers(req), + CheckedRequest::TransactionIndex(_, req) => NetRequest::TransactionIndex(req), CheckedRequest::Receipts(_, req) => NetRequest::Receipts(req), CheckedRequest::Body(_, req) => NetRequest::Body(req), CheckedRequest::Account(_, req) => NetRequest::Account(req), CheckedRequest::Code(_, req) => NetRequest::Code(req), CheckedRequest::Execution(_, req) => NetRequest::Execution(req), + CheckedRequest::Signal(_, req) => NetRequest::Signal(req), } } @@ -366,7 +393,7 @@ impl CheckedRequest { } CheckedRequest::Receipts(ref check, ref req) => { // empty transactions -> no receipts - if check.0.as_ref().ok().map_or(false, |hdr| hdr.receipts_root() == SHA3_NULL_RLP) { + if check.0.as_ref().ok().map_or(false, |hdr| hdr.receipts_root() == KECCAK_NULL_RLP) { return Some(Response::Receipts(Vec::new())); } @@ -377,7 +404,7 @@ impl CheckedRequest { CheckedRequest::Body(ref check, ref req) => { // check for empty body. if let Some(hdr) = check.0.as_ref().ok() { - if hdr.transactions_root() == SHA3_NULL_RLP && hdr.uncles_hash() == SHA3_EMPTY_LIST_RLP { + if hdr.transactions_root() == KECCAK_NULL_RLP && hdr.uncles_hash() == KECCAK_EMPTY_LIST_RLP { let mut stream = RlpStream::new_list(3); stream.append_raw(hdr.rlp().as_raw(), 1); stream.begin_list(0); @@ -422,7 +449,7 @@ impl CheckedRequest { }) } CheckedRequest::Code(_, ref req) => { - if req.code_hash.as_ref().map_or(false, |&h| h == SHA3_EMPTY) { + if req.code_hash.as_ref().map_or(false, |&h| h == KECCAK_EMPTY) { Some(Response::Code(Vec::new())) } else { None @@ -438,11 +465,13 @@ macro_rules! match_me { match $me { CheckedRequest::HeaderProof($check, $req) => $e, CheckedRequest::HeaderByHash($check, $req) => $e, + CheckedRequest::TransactionIndex($check, $req) => $e, CheckedRequest::Receipts($check, $req) => $e, CheckedRequest::Body($check, $req) => $e, CheckedRequest::Account($check, $req) => $e, CheckedRequest::Code($check, $req) => $e, CheckedRequest::Execution($check, $req) => $e, + CheckedRequest::Signal($check, $req) => $e, } } } @@ -465,11 +494,13 @@ impl IncompleteRequest for CheckedRequest { _ => Ok(()), } } + CheckedRequest::TransactionIndex(_, ref req) => req.check_outputs(f), CheckedRequest::Receipts(_, ref req) => req.check_outputs(f), CheckedRequest::Body(_, ref req) => req.check_outputs(f), CheckedRequest::Account(_, ref req) => req.check_outputs(f), CheckedRequest::Code(_, ref req) => req.check_outputs(f), CheckedRequest::Execution(_, ref req) => req.check_outputs(f), + CheckedRequest::Signal(_, ref req) => req.check_outputs(f), } } @@ -485,11 +516,13 @@ impl IncompleteRequest for CheckedRequest { match self { CheckedRequest::HeaderProof(_, req) => req.complete().map(CompleteRequest::HeaderProof), CheckedRequest::HeaderByHash(_, req) => req.complete().map(CompleteRequest::Headers), + CheckedRequest::TransactionIndex(_, req) => req.complete().map(CompleteRequest::TransactionIndex), CheckedRequest::Receipts(_, req) => req.complete().map(CompleteRequest::Receipts), CheckedRequest::Body(_, req) => req.complete().map(CompleteRequest::Body), CheckedRequest::Account(_, req) => req.complete().map(CompleteRequest::Account), CheckedRequest::Code(_, req) => req.complete().map(CompleteRequest::Code), CheckedRequest::Execution(_, req) => req.complete().map(CompleteRequest::Execution), + CheckedRequest::Signal(_, req) => req.complete().map(CompleteRequest::Signal), } } @@ -526,6 +559,9 @@ impl net_request::CheckedRequest for CheckedRequest { CheckedRequest::HeaderByHash(ref prover, _) => expect!((&NetResponse::Headers(ref res), &CompleteRequest::Headers(ref req)) => prover.check_response(cache, &req.start, &res.headers).map(Response::HeaderByHash)), + CheckedRequest::TransactionIndex(ref prover, _) => + expect!((&NetResponse::TransactionIndex(ref res), _) => + prover.check_response(cache, res).map(Response::TransactionIndex)), CheckedRequest::Receipts(ref prover, _) => expect!((&NetResponse::Receipts(ref res), _) => prover.check_response(cache, &res.receipts).map(Response::Receipts)), @@ -541,6 +577,9 @@ impl net_request::CheckedRequest for CheckedRequest { CheckedRequest::Execution(ref prover, _) => expect!((&NetResponse::Execution(ref res), _) => prover.check_response(cache, &res.items).map(Response::Execution)), + CheckedRequest::Signal(ref prover, _) => + expect!((&NetResponse::Signal(ref res), _) => + prover.check_response(cache, &res.signal).map(Response::Signal)), } } } @@ -553,6 +592,8 @@ pub enum Response { HeaderProof((H256, U256)), /// Response to a header-by-hash request. HeaderByHash(encoded::Header), + /// Response to a transaction-index request. + TransactionIndex(net_request::TransactionIndexResponse), /// Response to a receipts request. Receipts(Vec), /// Response to a block body request. @@ -564,6 +605,8 @@ pub enum Response { Code(Vec), /// Response to a request for proved execution. Execution(super::ExecutionResult), + /// Response to a request for epoch change signal. + Signal(Vec), } impl net_request::ResponseLike for Response { @@ -571,8 +614,8 @@ impl net_request::ResponseLike for Response { match *self { Response::HeaderProof((ref hash, _)) => f(0, Output::Hash(*hash)), Response::Account(None) => { - f(0, Output::Hash(SHA3_EMPTY)); // code hash - f(1, Output::Hash(SHA3_NULL_RLP)); // storage root. + f(0, Output::Hash(KECCAK_EMPTY)); // code hash + f(1, Output::Hash(KECCAK_NULL_RLP)); // storage root. } Response::Account(Some(ref acc)) => { f(0, Output::Hash(acc.code_hash)); @@ -688,7 +731,7 @@ impl HeaderByHash { }; let header = headers.get(0).ok_or(Error::Empty)?; - let hash = header.sha3(); + let hash = header.hash(); match hash == expected_hash { true => { cache.lock().insert_block_header(hash, header.clone()); @@ -699,6 +742,33 @@ impl HeaderByHash { } } +/// Request for a transaction index. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct TransactionIndex(pub Field); + +impl TransactionIndex { + /// Check a response for the transaction index. + // + // TODO: proper checking involves looking at canonicality of the + // hash w.r.t. the current best block header. + // + // unlike all other forms of request, we don't know the header to check + // until we make this request. + // + // This would require lookups in the database or perhaps CHT requests, + // which aren't currently possible. + // + // Also, returning a result that is not locally canonical doesn't necessarily + // indicate misbehavior, so the punishment scheme would need to be revised. + pub fn check_response( + &self, + _cache: &Mutex<::cache::Cache>, + res: &net_request::TransactionIndexResponse, + ) -> Result { + Ok(res.clone()) + } +} + /// Request for a block, with header for verification. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Body(pub HeaderRef); @@ -708,12 +778,12 @@ impl Body { pub fn check_response(&self, cache: &Mutex<::cache::Cache>, body: &encoded::Body) -> Result { // check the integrity of the the body against the header let header = self.0.as_ref()?; - let tx_root = ::util::triehash::ordered_trie_root(body.rlp().at(0).iter().map(|r| r.as_raw().to_vec())); + let tx_root = ::triehash::ordered_trie_root(body.rlp().at(0).iter().map(|r| r.as_raw())); if tx_root != header.transactions_root() { return Err(Error::WrongTrieRoot(header.transactions_root(), tx_root)); } - let uncles_hash = body.rlp().at(1).as_raw().sha3(); + let uncles_hash = keccak(body.rlp().at(1).as_raw()); if uncles_hash != header.uncles_hash() { return Err(Error::WrongHash(header.uncles_hash(), uncles_hash)); } @@ -738,7 +808,7 @@ impl BlockReceipts { /// Check a response with receipts against the stored header. pub fn check_response(&self, cache: &Mutex<::cache::Cache>, receipts: &[Receipt]) -> Result, Error> { let receipts_root = self.0.as_ref()?.receipts_root(); - let found_root = ::util::triehash::ordered_trie_root(receipts.iter().map(|r| ::rlp::encode(r).into_vec())); + let found_root = ::triehash::ordered_trie_root(receipts.iter().map(|r| ::rlp::encode(r))); match receipts_root == found_root { true => { @@ -768,7 +838,7 @@ impl Account { let mut db = MemoryDB::new(); for node in proof { db.insert(&node[..]); } - match TrieDB::new(&db, &state_root).and_then(|t| t.get(&self.address.sha3()))? { + match TrieDB::new(&db, &state_root).and_then(|t| t.get(&keccak(&self.address)))? { Some(val) => { let rlp = UntrustedRlp::new(&val); Ok(Some(BasicAccount { @@ -800,7 +870,7 @@ impl Code { code_hash: &H256, code: &[u8] ) -> Result, Error> { - let found_hash = code.sha3(); + let found_hash = keccak(code); if &found_hash == code_hash { Ok(code.to_vec()) } else { @@ -820,7 +890,7 @@ pub struct TransactionProof { // TODO: it's not really possible to provide this if the header is unknown. pub env_info: EnvInfo, /// Consensus engine. - pub engine: Arc, + pub engine: Arc, } impl TransactionProof { @@ -835,7 +905,7 @@ impl TransactionProof { state_items, root, &self.tx, - &*self.engine, + self.engine.machine(), &self.env_info, ); @@ -847,20 +917,45 @@ impl TransactionProof { } } +/// Request for epoch signal. +/// Provide engine and state-dependent proof checker. +#[derive(Clone)] +pub struct Signal { + /// Block hash and number to fetch proof for. + pub hash: H256, + /// Consensus engine, used to check the proof. + pub engine: Arc, + /// Special checker for the proof. + pub proof_check: Arc>, +} + +impl Signal { + /// Check the signal, returning the signal or indicate that it's bad. + pub fn check_response(&self, _: &Mutex<::cache::Cache>, signal: &[u8]) -> Result, Error> { + self.proof_check.check_proof(self.engine.machine(), signal) + .map(|_| signal.to_owned()) + .map_err(|_| Error::BadProof) + } +} + #[cfg(test)] mod tests { use super::*; - use util::{MemoryDB, Address, Mutex, H256}; - use util::trie::{Trie, TrieMut, SecTrieDB, SecTrieDBMut}; - use util::trie::recorder::Recorder; - - use ethcore::client::{BlockChainClient, TestBlockChainClient, EachBlockWith}; + use std::time::Duration; + use ethereum_types::{H256, Address}; + use memorydb::MemoryDB; + use parking_lot::Mutex; + use trie::{Trie, TrieMut, SecTrieDB, SecTrieDBMut}; + use trie::recorder::Recorder; + use hash::keccak; + + use ethcore::client::{BlockChainClient, BlockInfo, TestBlockChainClient, EachBlockWith}; use ethcore::header::Header; use ethcore::encoded; - use ethcore::receipt::Receipt; + use ethcore::receipt::{Receipt, TransactionOutcome}; fn make_cache() -> ::cache::Cache { - ::cache::Cache::new(Default::default(), ::time::Duration::seconds(1)) + ::cache::Cache::new(Default::default(), Duration::from_secs(1)) } #[test] @@ -926,15 +1021,15 @@ mod tests { #[test] fn check_receipts() { let receipts = (0..5).map(|_| Receipt { - state_root: Some(H256::random()), + outcome: TransactionOutcome::StateRoot(H256::random()), gas_used: 21_000u64.into(), log_bloom: Default::default(), logs: Vec::new(), }).collect::>(); let mut header = Header::new(); - let receipts_root = ::util::triehash::ordered_trie_root( - receipts.iter().map(|x| ::rlp::encode(x).into_vec()) + let receipts_root = ::triehash::ordered_trie_root( + receipts.iter().map(|x| ::rlp::encode(x)) ); header.set_receipts_root(receipts_root); @@ -998,7 +1093,7 @@ mod tests { #[test] fn check_code() { let code = vec![1u8; 256]; - let code_hash = ::util::Hashable::sha3(&code); + let code_hash = keccak(&code); let header = Header::new(); let req = Code { header: encoded::Header::new(::rlp::encode(&header).into_vec()).into(), diff --git a/ethcore/light/src/on_demand/tests.rs b/ethcore/light/src/on_demand/tests.rs index 10c4ceae5f19d65cdf3f69f7705913b6bf3ff5c7..999f2e669a5cecc1044135059f23a92a1b48ec82 100644 --- a/ethcore/light/src/on_demand/tests.rs +++ b/ethcore/light/src/on_demand/tests.rs @@ -22,8 +22,9 @@ use ethcore::header::{Header, Seal}; use futures::Future; use network::{PeerId, NodeId}; use net::*; -use util::{H256, Mutex}; -use time::Duration; +use ethereum_types::H256; +use parking_lot::Mutex; +use std::time::Duration; use ::request::{self as basic_request, Response}; use std::sync::Arc; @@ -87,7 +88,7 @@ struct Harness { impl Harness { fn create() -> Self { - let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::minutes(1)))); + let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::from_secs(60)))); Harness { service: OnDemand::new_test(cache), } diff --git a/ethcore/light/src/provider.rs b/ethcore/light/src/provider.rs index 3632783caa95f38ef3979c5ff8512f9b9afd7bc5..1d9af0ac19b15dd4ebf41a85b1f9d2ce1f5b41e9 100644 --- a/ethcore/light/src/provider.rs +++ b/ethcore/light/src/provider.rs @@ -14,17 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! A provider for the LES protocol. This is typically a full node, who can +//! A provider for the PIP protocol. This is typically a full node, who can //! give as much data as necessary to its peers. use std::sync::Arc; use ethcore::blockchain_info::BlockChainInfo; -use ethcore::client::{BlockChainClient, ProvingBlockChainClient}; -use ethcore::transaction::PendingTransaction; +use ethcore::client::{BlockChainClient, ProvingBlockChainClient, ChainInfo, BlockInfo as ClientBlockInfo}; use ethcore::ids::BlockId; use ethcore::encoded; -use util::{RwLock, H256}; +use ethereum_types::H256; +use parking_lot::RwLock; +use transaction::PendingTransaction; use cht::{self, BlockInfo}; use client::{LightChainClient, AsLightClient}; @@ -33,7 +34,6 @@ use transaction_queue::TransactionQueue; use request; /// Defines the operations that a provider for the light subprotocol must fulfill. -#[cfg_attr(feature = "ipc", ipc(client_ident="LightProviderClient"))] pub trait Provider: Send + Sync { /// Provide current blockchain info. fn chain_info(&self) -> BlockChainInfo; @@ -101,6 +101,10 @@ pub trait Provider: Send + Sync { /// Get a block header by id. fn block_header(&self, id: BlockId) -> Option; + /// Get a transaction index by hash. + fn transaction_index(&self, req: request::CompleteTransactionIndexRequest) + -> Option; + /// Fulfill a block body request. fn block_body(&self, req: request::CompleteBodyRequest) -> Option; @@ -126,12 +130,15 @@ pub trait Provider: Send + Sync { /// Provide a proof-of-execution for the given transaction proof request. /// Returns a vector of all state items necessary to execute the transaction. fn transaction_proof(&self, req: request::CompleteExecutionRequest) -> Option; + + /// Provide epoch signal data at given block hash. This should be just the + fn epoch_signal(&self, req: request::CompleteSignalRequest) -> Option; } // Implementation of a light client data provider for a client. impl Provider for T { fn chain_info(&self) -> BlockChainInfo { - BlockChainClient::chain_info(self) + ChainInfo::chain_info(self) } fn reorg_depth(&self, a: &H256, b: &H256) -> Option { @@ -143,7 +150,19 @@ impl Provider for T { } fn block_header(&self, id: BlockId) -> Option { - BlockChainClient::block_header(self, id) + ClientBlockInfo::block_header(self, id) + } + + fn transaction_index(&self, req: request::CompleteTransactionIndexRequest) + -> Option + { + use ethcore::ids::TransactionId; + + self.transaction_receipt(TransactionId::Hash(req.hash)).map(|receipt| request::TransactionIndexResponse { + num: receipt.block_number, + hash: receipt.block_hash, + index: receipt.transaction_index as u64, + }) } fn block_body(&self, req: request::CompleteBodyRequest) -> Option { @@ -241,7 +260,7 @@ impl Provider for T { } fn transaction_proof(&self, req: request::CompleteExecutionRequest) -> Option { - use ethcore::transaction::Transaction; + use transaction::Transaction; let id = BlockId::Hash(req.block_hash); let nonce = match self.nonce(&req.from, id.clone()) { @@ -264,6 +283,12 @@ impl Provider for T { fn ready_transactions(&self) -> Vec { BlockChainClient::ready_transactions(self) } + + fn epoch_signal(&self, req: request::CompleteSignalRequest) -> Option { + self.epoch_signal(req.block_hash).map(|signal| request::SignalResponse { + signal: signal, + }) + } } /// The light client "provider" implementation. This wraps a `LightClient` and @@ -301,6 +326,12 @@ impl Provider for LightProvider { self.client.as_light_client().block_header(id) } + fn transaction_index(&self, _req: request::CompleteTransactionIndexRequest) + -> Option + { + None + } + fn block_body(&self, _req: request::CompleteBodyRequest) -> Option { None } @@ -329,6 +360,10 @@ impl Provider for LightProvider { None } + fn epoch_signal(&self, _req: request::CompleteSignalRequest) -> Option { + None + } + fn ready_transactions(&self) -> Vec { let chain_info = self.chain_info(); self.txqueue.read().ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) diff --git a/ethcore/light/src/transaction_queue.rs b/ethcore/light/src/transaction_queue.rs index b0e7483a3ff9b7bddf1071eff7165443088c182d..156152253dd6666708c8e3638abf8adc6d25a11d 100644 --- a/ethcore/light/src/transaction_queue.rs +++ b/ethcore/light/src/transaction_queue.rs @@ -23,12 +23,13 @@ //! accounts for which they create transactions, this queue is structured in an //! address-wise manner. +use std::fmt; use std::collections::{BTreeMap, HashMap}; use std::collections::hash_map::Entry; -use ethcore::error::{TransactionError, TransactionImportResult}; -use ethcore::transaction::{Condition, PendingTransaction, SignedTransaction}; -use util::{Address, U256, H256, H256FastMap}; +use transaction::{self, Condition, PendingTransaction, SignedTransaction}; +use ethereum_types::{H256, U256, Address}; +use plain_hasher::H256FastMap; // Knowledge of an account's current nonce. #[derive(Debug, Clone, PartialEq, Eq)] @@ -99,38 +100,57 @@ impl AccountTransactions { } // attempt to move transactions from the future queue into the current queue. - fn adjust_future(&mut self) { + fn adjust_future(&mut self) -> Vec { + let mut promoted = Vec::new(); let mut next_nonce = self.next_nonce(); loop { match self.future.remove(&next_nonce) { - Some(tx) => self.current.push(tx), + Some(tx) => { + promoted.push(tx.hash); + self.current.push(tx) + }, None => break, } next_nonce = next_nonce + 1.into(); } + + promoted } } +type Listener = Box; + /// Light transaction queue. See module docs for more details. -#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[derive(Default)] pub struct TransactionQueue { by_account: HashMap, by_hash: H256FastMap, + listeners: Vec, +} + +impl fmt::Debug for TransactionQueue { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("TransactionQueue") + .field("by_account", &self.by_account) + .field("by_hash", &self.by_hash) + .field("listeners", &self.listeners.len()) + .finish() + } } impl TransactionQueue { /// Import a pending transaction to be queued. - pub fn import(&mut self, tx: PendingTransaction) -> Result { + pub fn import(&mut self, tx: PendingTransaction) -> Result { let sender = tx.sender(); let hash = tx.hash(); let nonce = tx.nonce; let tx_info = TransactionInfo::from(&tx); - if self.by_hash.contains_key(&hash) { return Err(TransactionError::AlreadyImported) } + if self.by_hash.contains_key(&hash) { return Err(transaction::Error::AlreadyImported) } - let res = match self.by_account.entry(sender) { + let (res, promoted) = match self.by_account.entry(sender) { Entry::Vacant(entry) => { entry.insert(AccountTransactions { cur_nonce: CurrentNonce::Assumed(nonce), @@ -138,14 +158,14 @@ impl TransactionQueue { future: BTreeMap::new(), }); - TransactionImportResult::Current + (transaction::ImportResult::Current, vec![hash]) } Entry::Occupied(mut entry) => { let acct_txs = entry.get_mut(); if &nonce < acct_txs.cur_nonce.value() { // don't accept txs from before known current nonce. if acct_txs.cur_nonce.is_known() { - return Err(TransactionError::Old) + return Err(transaction::Error::Old) } // lower our assumption until corrected later. @@ -160,7 +180,7 @@ impl TransactionQueue { let old = ::std::mem::replace(&mut acct_txs.current[idx], tx_info); self.by_hash.remove(&old.hash); - TransactionImportResult::Current + (transaction::ImportResult::Current, vec![hash]) } Err(idx) => { let cur_len = acct_txs.current.len(); @@ -182,21 +202,22 @@ impl TransactionQueue { acct_txs.future.insert(future_nonce, future); } - TransactionImportResult::Current + (transaction::ImportResult::Current, vec![hash]) } else if idx == cur_len && acct_txs.current.last().map_or(false, |f| f.nonce + 1.into() != nonce) { trace!(target: "txqueue", "Queued future transaction for {}, nonce={}", sender, nonce); let future_nonce = nonce; acct_txs.future.insert(future_nonce, tx_info); - TransactionImportResult::Future + (transaction::ImportResult::Future, vec![]) } else { trace!(target: "txqueue", "Queued current transaction for {}, nonce={}", sender, nonce); // insert, then check if we've filled any gaps. acct_txs.current.insert(idx, tx_info); - acct_txs.adjust_future(); + let mut promoted = acct_txs.adjust_future(); + promoted.insert(0, hash); - TransactionImportResult::Current + (transaction::ImportResult::Current, promoted) } } } @@ -204,6 +225,7 @@ impl TransactionQueue { }; self.by_hash.insert(hash, tx); + self.notify(&promoted); Ok(res) } @@ -319,13 +341,30 @@ impl TransactionQueue { self.by_hash.remove(&hash); } } + + /// Get a transaction by hash. + pub fn get(&self, hash: &H256) -> Option<&PendingTransaction> { + self.by_hash.get(&hash) + } + + /// Add a transaction queue listener. + pub fn add_listener(&mut self, f: Listener) { + self.listeners.push(f); + } + + /// Notifies all listeners about new pending transaction. + fn notify(&self, hashes: &[H256]) { + for listener in &self.listeners { + listener(hashes) + } + } } #[cfg(test)] mod tests { use super::TransactionQueue; - use util::Address; - use ethcore::transaction::{Transaction, PendingTransaction, Condition}; + use ethereum_types::Address; + use transaction::{Transaction, PendingTransaction, Condition}; #[test] fn queued_senders() { diff --git a/ethcore/light/src/types/mod.rs b/ethcore/light/src/types/mod.rs index 63fe7426787f11ca544fdbd7ad8f8027bd97d6e0..eba551b533c396d027c868f893165caba2d8315e 100644 --- a/ethcore/light/src/types/mod.rs +++ b/ethcore/light/src/types/mod.rs @@ -14,11 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Types used in the public (IPC) api which require custom code generation. -#![cfg_attr(feature = "ipc", allow(dead_code, unused_assignments, unused_variables))] // codegen issues - -#[cfg(feature = "ipc")] -include!(concat!(env!("OUT_DIR"), "/mod.rs.in")); - -#[cfg(not(feature = "ipc"))] -include!("mod.rs.in"); +pub mod request; diff --git a/ethcore/light/src/types/mod.rs.in b/ethcore/light/src/types/mod.rs.in deleted file mode 100644 index eba551b533c396d027c868f893165caba2d8315e..0000000000000000000000000000000000000000 --- a/ethcore/light/src/types/mod.rs.in +++ /dev/null @@ -1,17 +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 . - -pub mod request; diff --git a/ethcore/light/src/types/request/builder.rs b/ethcore/light/src/types/request/batch.rs similarity index 87% rename from ethcore/light/src/types/request/builder.rs rename to ethcore/light/src/types/request/batch.rs index 0b413677d31284884ae3c83c6c90280155c84bc2..21f1264672dd0b97e30cc15db5da35ea4040387a 100644 --- a/ethcore/light/src/types/request/builder.rs +++ b/ethcore/light/src/types/request/batch.rs @@ -25,23 +25,23 @@ use request::{ }; /// Build chained requests. Push them onto the series with `push`, -/// and produce a `Requests` object with `build`. Outputs are checked for consistency. +/// and produce a `Batch` object with `build`. Outputs are checked for consistency. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct RequestBuilder { +pub struct Builder { output_kinds: HashMap<(usize, usize), OutputKind>, requests: Vec, } -impl Default for RequestBuilder { +impl Default for Builder { fn default() -> Self { - RequestBuilder { + Builder { output_kinds: HashMap::new(), requests: Vec::new(), } } } -impl RequestBuilder { +impl Builder { /// Attempt to push a request onto the request chain. Fails if the request /// references a non-existent output of a prior request. pub fn push(&mut self, request: T) -> Result<(), NoSuchOutput> { @@ -62,9 +62,9 @@ impl RequestBuilder { &self.output_kinds } - /// Convert this into a "requests" object. - pub fn build(self) -> Requests { - Requests { + /// Convert this into a "batch" object. + pub fn build(self) -> Batch { + Batch { outputs: HashMap::new(), requests: self.requests, answered: 0, @@ -74,13 +74,13 @@ impl RequestBuilder { /// Requests pending responses. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Requests { +pub struct Batch { outputs: HashMap<(usize, usize), Output>, requests: Vec, answered: usize, } -impl Requests { +impl Batch { /// Get access to the underlying slice of requests. // TODO: unimplemented -> Vec, // do we _have to_ allocate? pub fn requests(&self) -> &[T] { &self.requests } @@ -94,10 +94,10 @@ impl Requests { } /// Map requests from one type into another. - pub fn map_requests(self, f: F) -> Requests + pub fn map_requests(self, f: F) -> Batch where F: FnMut(T) -> U, U: IncompleteRequest { - Requests { + Batch { outputs: self.outputs, requests: self.requests.into_iter().map(f).collect(), answered: self.answered, @@ -105,7 +105,7 @@ impl Requests { } } -impl Requests { +impl Batch { /// Get the next request as a filled request. Returns `None` when all requests answered. pub fn next_complete(&self) -> Option { if self.is_complete() { @@ -113,7 +113,7 @@ impl Requests { } else { Some(self.requests[self.answered].clone() .complete() - .expect("All outputs checked as invariant of `Requests` object; qed")) + .expect("All outputs checked as invariant of `Batch` object; qed")) } } @@ -149,7 +149,7 @@ impl Requests { } } -impl Requests { +impl Batch { /// Supply a response for the next request. /// Fails on: wrong request kind, all requests answered already. pub fn supply_response(&mut self, env: &T::Environment, response: &T::Response) @@ -170,7 +170,7 @@ impl Requests { } } -impl Requests { +impl Batch { /// For each request, produce a response. /// The responses vector produced goes up to the point where the responder /// first returns `None`, an invalid response, or until all requests have been responded to. @@ -193,7 +193,7 @@ impl Requests { } } -impl Deref for Requests { +impl Deref for Batch { type Target = [T]; fn deref(&self) -> &[T] { @@ -201,7 +201,7 @@ impl Deref for Requests { } } -impl DerefMut for Requests { +impl DerefMut for Batch { fn deref_mut(&mut self) -> &mut [T] { &mut self.requests[..] } @@ -210,12 +210,12 @@ impl DerefMut for Requests { #[cfg(test)] mod tests { use request::*; - use super::RequestBuilder; - use util::H256; + use super::Builder; + use ethereum_types::H256; #[test] fn all_scalar() { - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { num: 100.into(), })).unwrap(); @@ -227,7 +227,7 @@ mod tests { #[test] #[should_panic] fn missing_backref() { - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { num: Field::BackReference(100, 3), })).unwrap(); @@ -236,7 +236,7 @@ mod tests { #[test] #[should_panic] fn wrong_kind() { - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); assert!(builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { num: 100.into(), })).is_ok()); @@ -247,7 +247,7 @@ mod tests { #[test] fn good_backreference() { - let mut builder = RequestBuilder::default(); + let mut builder = Builder::default(); builder.push(Request::HeaderProof(IncompleteHeaderProofRequest { num: 100.into(), // header proof puts hash at output 0. })).unwrap(); diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs index 51f916b15117dcd194b68b133f53415d73979ce9..bd68c6a0a20dec74f5bda3dd846832252f3272f5 100644 --- a/ethcore/light/src/types/request/mod.rs +++ b/ethcore/light/src/types/request/mod.rs @@ -17,9 +17,9 @@ //! Light protocol request types. use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; -use util::H256; +use ethereum_types::H256; -mod builder; +mod batch; // re-exports of request types. pub use self::header::{ @@ -67,8 +67,13 @@ pub use self::execution::{ Incomplete as IncompleteExecutionRequest, Response as ExecutionResponse, }; +pub use self::epoch_signal::{ + Complete as CompleteSignalRequest, + Incomplete as IncompleteSignalRequest, + Response as SignalResponse, +}; -pub use self::builder::{RequestBuilder, Requests}; +pub use self::batch::{Batch, Builder}; /// Error indicating a reference to a non-existent or wrongly-typed output. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -199,7 +204,6 @@ pub enum OutputKind { /// Either a hash or a number. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "ipc", binary)] pub enum HashOrNumber { /// Block hash variant. Hash(H256), @@ -236,7 +240,7 @@ impl Encodable for HashOrNumber { } /// Type alias for "network requests". -pub type NetworkRequests = Requests; +pub type NetworkRequests = Batch; /// All request types, as they're sent over the network. /// They may be incomplete, with back-references to outputs @@ -261,6 +265,8 @@ pub enum Request { Code(IncompleteCodeRequest), /// A request for proof of execution, Execution(IncompleteExecutionRequest), + /// A request for an epoch signal. + Signal(IncompleteSignalRequest), } /// All request types, in an answerable state. @@ -284,6 +290,8 @@ pub enum CompleteRequest { Code(CompleteCodeRequest), /// A request for proof of execution, Execution(CompleteExecutionRequest), + /// A request for an epoch signal. + Signal(CompleteSignalRequest), } impl CompleteRequest { @@ -299,6 +307,7 @@ impl CompleteRequest { CompleteRequest::Storage(_) => Kind::Storage, CompleteRequest::Code(_) => Kind::Code, CompleteRequest::Execution(_) => Kind::Execution, + CompleteRequest::Signal(_) => Kind::Signal, } } } @@ -316,6 +325,7 @@ impl Request { Request::Storage(_) => Kind::Storage, Request::Code(_) => Kind::Code, Request::Execution(_) => Kind::Execution, + Request::Signal(_) => Kind::Signal, } } } @@ -332,6 +342,7 @@ impl Decodable for Request { Kind::Storage => Ok(Request::Storage(rlp.val_at(1)?)), Kind::Code => Ok(Request::Code(rlp.val_at(1)?)), Kind::Execution => Ok(Request::Execution(rlp.val_at(1)?)), + Kind::Signal => Ok(Request::Signal(rlp.val_at(1)?)), } } } @@ -353,6 +364,7 @@ impl Encodable for Request { Request::Storage(ref req) => s.append(req), Request::Code(ref req) => s.append(req), Request::Execution(ref req) => s.append(req), + Request::Signal(ref req) => s.append(req), }; } } @@ -374,6 +386,7 @@ impl IncompleteRequest for Request { Request::Storage(ref req) => req.check_outputs(f), Request::Code(ref req) => req.check_outputs(f), Request::Execution(ref req) => req.check_outputs(f), + Request::Signal(ref req) => req.check_outputs(f), } } @@ -388,6 +401,7 @@ impl IncompleteRequest for Request { Request::Storage(ref req) => req.note_outputs(f), Request::Code(ref req) => req.note_outputs(f), Request::Execution(ref req) => req.note_outputs(f), + Request::Signal(ref req) => req.note_outputs(f), } } @@ -402,6 +416,7 @@ impl IncompleteRequest for Request { Request::Storage(ref mut req) => req.fill(oracle), Request::Code(ref mut req) => req.fill(oracle), Request::Execution(ref mut req) => req.fill(oracle), + Request::Signal(ref mut req) => req.fill(oracle), } } @@ -416,6 +431,7 @@ impl IncompleteRequest for Request { Request::Storage(req) => req.complete().map(CompleteRequest::Storage), Request::Code(req) => req.complete().map(CompleteRequest::Code), Request::Execution(req) => req.complete().map(CompleteRequest::Execution), + Request::Signal(req) => req.complete().map(CompleteRequest::Signal), } } @@ -430,6 +446,7 @@ impl IncompleteRequest for Request { Request::Storage(ref mut req) => req.adjust_refs(mapping), Request::Code(ref mut req) => req.adjust_refs(mapping), Request::Execution(ref mut req) => req.adjust_refs(mapping), + Request::Signal(ref mut req) => req.adjust_refs(mapping), } } } @@ -471,6 +488,8 @@ pub enum Kind { Code = 7, /// A request for transaction execution + state proof. Execution = 8, + /// A request for epoch transition signal. + Signal = 9, } impl Decodable for Kind { @@ -485,6 +504,7 @@ impl Decodable for Kind { 6 => Ok(Kind::Storage), 7 => Ok(Kind::Code), 8 => Ok(Kind::Execution), + 9 => Ok(Kind::Signal), _ => Err(DecoderError::Custom("Unknown PIP request ID.")), } } @@ -517,6 +537,8 @@ pub enum Response { Code(CodeResponse), /// A response for proof of execution, Execution(ExecutionResponse), + /// A response for epoch change signal. + Signal(SignalResponse), } impl ResponseLike for Response { @@ -532,6 +554,7 @@ impl ResponseLike for Response { Response::Storage(ref res) => res.fill_outputs(f), Response::Code(ref res) => res.fill_outputs(f), Response::Execution(ref res) => res.fill_outputs(f), + Response::Signal(ref res) => res.fill_outputs(f), } } } @@ -549,6 +572,7 @@ impl Response { Response::Storage(_) => Kind::Storage, Response::Code(_) => Kind::Code, Response::Execution(_) => Kind::Execution, + Response::Signal(_) => Kind::Signal, } } } @@ -565,6 +589,7 @@ impl Decodable for Response { Kind::Storage => Ok(Response::Storage(rlp.val_at(1)?)), Kind::Code => Ok(Response::Code(rlp.val_at(1)?)), Kind::Execution => Ok(Response::Execution(rlp.val_at(1)?)), + Kind::Signal => Ok(Response::Signal(rlp.val_at(1)?)), } } } @@ -586,6 +611,7 @@ impl Encodable for Response { Response::Storage(ref res) => s.append(res), Response::Code(ref res) => s.append(res), Response::Execution(ref res) => s.append(res), + Response::Signal(ref res) => s.append(res), }; } } @@ -760,7 +786,8 @@ pub mod header { pub mod header_proof { use super::{Field, NoSuchOutput, OutputKind, Output}; use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; - use util::{Bytes, U256, H256}; + use ethereum_types::{H256, U256}; + use bytes::Bytes; /// Potentially incomplete header proof request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -854,7 +881,7 @@ pub mod header_proof { /// Request and response for transaction index. pub mod transaction_index { use super::{Field, NoSuchOutput, OutputKind, Output}; - use util::H256; + use ethereum_types::H256; /// Potentially incomplete transaction index request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -932,7 +959,7 @@ pub mod transaction_index { pub mod block_receipts { use super::{Field, NoSuchOutput, OutputKind, Output}; use ethcore::receipt::Receipt; - use util::H256; + use ethereum_types::H256; /// Potentially incomplete block receipts request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1001,7 +1028,7 @@ pub mod block_body { use super::{Field, NoSuchOutput, OutputKind, Output}; use ethcore::encoded; use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; - use util::H256; + use ethereum_types::H256; /// Potentially incomplete block body request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1067,7 +1094,7 @@ pub mod block_body { impl Decodable for Response { fn decode(rlp: &UntrustedRlp) -> Result { use ethcore::header::Header as FullHeader; - use ethcore::transaction::UnverifiedTransaction; + use transaction::UnverifiedTransaction; // check body validity. let _: Vec = rlp.list_at(0)?; @@ -1089,7 +1116,8 @@ pub mod block_body { /// A request for an account proof. pub mod account { use super::{Field, NoSuchOutput, OutputKind, Output}; - use util::{Bytes, U256, H256}; + use ethereum_types::{H256, U256}; + use bytes::Bytes; /// Potentially incomplete request for an account proof. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1188,7 +1216,8 @@ pub mod account { /// A request for a storage proof. pub mod storage { use super::{Field, NoSuchOutput, OutputKind, Output}; - use util::{Bytes, H256}; + use ethereum_types::H256; + use bytes::Bytes; /// Potentially incomplete request for an storage proof. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1296,7 +1325,8 @@ pub mod storage { /// A request for contract code. pub mod contract_code { use super::{Field, NoSuchOutput, OutputKind, Output}; - use util::{Bytes, H256}; + use ethereum_types::H256; + use bytes::Bytes; /// Potentially incomplete contract code request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1380,9 +1410,11 @@ pub mod contract_code { /// A request for proof of execution. pub mod execution { use super::{Field, NoSuchOutput, OutputKind, Output}; - use ethcore::transaction::Action; + use transaction::Action; use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; - use util::{Bytes, Address, U256, H256, DBValue}; + use ethereum_types::{H256, U256, Address}; + use kvdb::DBValue; + use bytes::Bytes; /// Potentially incomplete execution proof request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1501,6 +1533,105 @@ pub mod execution { } } +/// A request for epoch signal data. +pub mod epoch_signal { + use super::{Field, NoSuchOutput, OutputKind, Output}; + use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; + use ethereum_types::H256; + use bytes::Bytes; + + /// Potentially incomplete epoch signal request. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Incomplete { + /// The block hash to request the signal for. + pub block_hash: Field, + } + + impl Decodable for Incomplete { + fn decode(rlp: &UntrustedRlp) -> Result { + Ok(Incomplete { + block_hash: rlp.val_at(0)?, + }) + } + } + + impl Encodable for Incomplete { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(1).append(&self.block_hash); + } + } + + impl super::IncompleteRequest for Incomplete { + type Complete = Complete; + type Response = Response; + + fn check_outputs(&self, mut f: F) -> Result<(), NoSuchOutput> + where F: FnMut(usize, usize, OutputKind) -> Result<(), NoSuchOutput> + { + if let Field::BackReference(req, idx) = self.block_hash { + f(req, idx, OutputKind::Hash)?; + } + + Ok(()) + } + + fn note_outputs(&self, _: F) where F: FnMut(usize, OutputKind) {} + + fn fill(&mut self, oracle: F) where F: Fn(usize, usize) -> Result { + if let Field::BackReference(req, idx) = self.block_hash { + self.block_hash = match oracle(req, idx) { + Ok(Output::Hash(block_hash)) => Field::Scalar(block_hash.into()), + _ => Field::BackReference(req, idx), + } + } + } + + fn complete(self) -> Result { + Ok(Complete { + block_hash: self.block_hash.into_scalar()?, + }) + } + + fn adjust_refs(&mut self, mut mapping: F) where F: FnMut(usize) -> usize { + self.block_hash.adjust_req(&mut mapping); + } + } + + /// A complete request. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Complete { + /// The block hash to request the epoch signal for. + pub block_hash: H256, + } + + /// The output of a request for an epoch signal. + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct Response { + /// The requested epoch signal. + pub signal: Bytes, + } + + impl super::ResponseLike for Response { + /// Fill reusable outputs by providing them to the function. + fn fill_outputs(&self, _: F) where F: FnMut(usize, Output) {} + } + + impl Decodable for Response { + fn decode(rlp: &UntrustedRlp) -> Result { + + Ok(Response { + signal: rlp.as_val()?, + }) + } + } + + impl Encodable for Response { + fn rlp_append(&self, s: &mut RlpStream) { + s.append(&self.signal); + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -1591,7 +1722,7 @@ mod tests { let full_req = Request::TransactionIndex(req.clone()); let res = TransactionIndexResponse { num: 1000, - hash: ::util::H256::random(), + hash: ::ethereum_types::H256::random(), index: 4, }; let full_res = Response::TransactionIndex(res.clone()); @@ -1604,13 +1735,15 @@ mod tests { #[test] fn receipts_roundtrip() { + use ethcore::receipt::{Receipt, TransactionOutcome}; let req = IncompleteReceiptsRequest { hash: Field::Scalar(Default::default()), }; let full_req = Request::Receipts(req.clone()); + let receipt = Receipt::new(TransactionOutcome::Unknown, Default::default(), Vec::new()); let res = ReceiptsResponse { - receipts: vec![Default::default(), Default::default()], + receipts: vec![receipt.clone(), receipt], }; let full_res = Response::Receipts(res.clone()); @@ -1622,7 +1755,7 @@ mod tests { #[test] fn body_roundtrip() { - use ethcore::transaction::{Transaction, UnverifiedTransaction}; + use transaction::{Transaction, UnverifiedTransaction}; let req = IncompleteBodyRequest { hash: Field::Scalar(Default::default()), }; @@ -1712,12 +1845,12 @@ mod tests { #[test] fn execution_roundtrip() { - use util::DBValue; + use kvdb::DBValue; let req = IncompleteExecutionRequest { block_hash: Field::Scalar(Default::default()), from: Default::default(), - action: ::ethcore::transaction::Action::Create, + action: ::transaction::Action::Create, gas: 100_000.into(), gas_price: 0.into(), value: 100_000_001.into(), @@ -1747,7 +1880,7 @@ mod tests { let reqs: Vec<_> = (0..10).map(|_| IncompleteExecutionRequest { block_hash: Field::Scalar(Default::default()), from: Default::default(), - action: ::ethcore::transaction::Action::Create, + action: ::transaction::Action::Create, gas: 100_000.into(), gas_price: 0.into(), value: 100_000_001.into(), @@ -1765,6 +1898,7 @@ mod tests { #[test] fn responses_vec() { + use ethcore::receipt::{Receipt, TransactionOutcome}; let mut stream = RlpStream::new_list(2); stream.begin_list(0).begin_list(0); @@ -1772,7 +1906,7 @@ mod tests { let reqs = vec![ Response::Headers(HeadersResponse { headers: vec![] }), Response::HeaderProof(HeaderProofResponse { proof: vec![], hash: Default::default(), td: 100.into()}), - Response::Receipts(ReceiptsResponse { receipts: vec![Default::default()] }), + Response::Receipts(ReceiptsResponse { receipts: vec![Receipt::new(TransactionOutcome::Unknown, Default::default(), Vec::new())] }), Response::Body(BodyResponse { body: body }), Response::Account(AccountResponse { proof: vec![], @@ -1789,4 +1923,22 @@ mod tests { let raw = ::rlp::encode_list(&reqs); assert_eq!(::rlp::decode_list::(&raw), reqs); } + + #[test] + fn epoch_signal_roundtrip() { + let req = IncompleteSignalRequest { + block_hash: Field::Scalar(Default::default()), + }; + + let full_req = Request::Signal(req.clone()); + let res = SignalResponse { + signal: vec![1, 2, 3, 4, 5, 6, 7, 6, 5, 4], + }; + let full_res = Response::Signal(res.clone()); + + check_roundtrip(req); + check_roundtrip(full_req); + check_roundtrip(res); + check_roundtrip(full_res); + } } diff --git a/ethcore/migrations/Cargo.toml b/ethcore/migrations/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..561925be4c5a23f2e0a5d46ebb18fa5b40971e2e --- /dev/null +++ b/ethcore/migrations/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ethcore-migrations" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +migration = { path = "../../util/migration" } diff --git a/ethcore/src/migrations/mod.rs b/ethcore/migrations/src/lib.rs similarity index 86% rename from ethcore/src/migrations/mod.rs rename to ethcore/migrations/src/lib.rs index 76b10fd1915c3608874e9468597deb7625ab396b..429c39102cb305adb184bffe35c7818c3a758ff4 100644 --- a/ethcore/src/migrations/mod.rs +++ b/ethcore/migrations/src/lib.rs @@ -16,18 +16,9 @@ //! Database migrations. -use util::migration::ChangeColumns; +extern crate migration; -pub mod state; -pub mod blocks; -pub mod extras; - -mod v9; -pub use self::v9::ToV9; -pub use self::v9::Extract; - -mod v10; -pub use self::v10::ToV10; +use migration::ChangeColumns; /// The migration from v10 to v11. /// Adds a column for node info. diff --git a/ethcore/native_contracts/Cargo.toml b/ethcore/native_contracts/Cargo.toml deleted file mode 100644 index 2f91a4848674ad1e1a4c18b84aaea80bf589d999..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "native-contracts" -description = "Generated Rust code for Ethereum contract ABIs" -version = "0.1.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[dependencies] -ethabi = "2.0" -futures = "0.1" -byteorder = "1.0" -ethcore-bigint = { path = "../../util/bigint" } - -[build-dependencies] -native-contract-generator = { path = "generator" } - -[features] -default = [] -test_contracts = [] diff --git a/ethcore/native_contracts/build.rs b/ethcore/native_contracts/build.rs deleted file mode 100644 index e7985b3880b2a0a0d6a0c10f45fc1f113c35cb84..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/build.rs +++ /dev/null @@ -1,60 +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 . - -extern crate native_contract_generator; - -use std::path::Path; -use std::fs::File; -use std::io::Write; - -// TODO: just walk the "res" directory and generate whole crate automatically. -const KEY_SERVER_SET_ABI: &'static str = include_str!("res/key_server_set.json"); -const REGISTRY_ABI: &'static str = include_str!("res/registrar.json"); -const URLHINT_ABI: &'static str = include_str!("res/urlhint.json"); -const SERVICE_TRANSACTION_ABI: &'static str = include_str!("res/service_transaction.json"); -const SECRETSTORE_ACL_STORAGE_ABI: &'static str = include_str!("res/secretstore_acl_storage.json"); -const VALIDATOR_SET_ABI: &'static str = include_str!("res/validator_set.json"); -const VALIDATOR_REPORT_ABI: &'static str = include_str!("res/validator_report.json"); -const PEER_SET_ABI: &'static str = include_str!("res/peer_set.json"); - -const TEST_VALIDATOR_SET_ABI: &'static str = include_str!("res/test_validator_set.json"); - -fn build_file(name: &str, abi: &str, filename: &str) { - let code = ::native_contract_generator::generate_module(name, abi).unwrap(); - - let out_dir = ::std::env::var("OUT_DIR").unwrap(); - let dest_path = Path::new(&out_dir).join(filename); - let mut f = File::create(&dest_path).unwrap(); - - f.write_all(code.as_bytes()).unwrap(); -} - -fn build_test_contracts() { - build_file("ValidatorSet", TEST_VALIDATOR_SET_ABI, "test_validator_set.rs"); -} - -fn main() { - build_file("KeyServerSet", KEY_SERVER_SET_ABI, "key_server_set.rs"); - build_file("Registry", REGISTRY_ABI, "registry.rs"); - build_file("Urlhint", URLHINT_ABI, "urlhint.rs"); - build_file("ServiceTransactionChecker", SERVICE_TRANSACTION_ABI, "service_transaction.rs"); - build_file("SecretStoreAclStorage", SECRETSTORE_ACL_STORAGE_ABI, "secretstore_acl_storage.rs"); - build_file("ValidatorSet", VALIDATOR_SET_ABI, "validator_set.rs"); - build_file("ValidatorReport", VALIDATOR_REPORT_ABI, "validator_report.rs"); - build_file("PeerSet", PEER_SET_ABI, "peer_set.rs"); - - build_test_contracts(); -} diff --git a/ethcore/native_contracts/generator/Cargo.toml b/ethcore/native_contracts/generator/Cargo.toml deleted file mode 100644 index a599e756eba039cc3f36d650ccdccb7bdd614c84..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/generator/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "native-contract-generator" -description = "Generates Rust code for ethereum contract ABIs" -version = "0.1.0" -authors = ["Parity Technologies "] - -[dependencies] -ethabi = "2.0" -heck = "0.2" diff --git a/ethcore/native_contracts/generator/src/lib.rs b/ethcore/native_contracts/generator/src/lib.rs deleted file mode 100644 index 996ee496926e5ad5bab2ab3ec4e111ecd3e517de..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/generator/src/lib.rs +++ /dev/null @@ -1,358 +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 . - -//! Rust code contract generator. -//! The code generated will require a dependence on the `ethcore-bigint::prelude`, -//! `ethabi`, `byteorder`, and `futures` crates. -//! This currently isn't hygienic, so compilation of generated code may fail -//! due to missing crates or name collisions. This will change when -//! it can be ported to a procedural macro. - -use ethabi::Contract; -use ethabi::spec::{Interface, ParamType, Error as AbiError}; -use heck::SnakeCase; - -extern crate ethabi; -extern crate heck; - -/// Errors in generation. -#[derive(Debug)] -pub enum Error { - /// Bad ABI. - Abi(AbiError), - /// Unsupported parameter type in given function. - UnsupportedType(String, ParamType), -} - -/// Given an ABI string, generate code for a a Rust module containing -/// a struct which can be used to call it. -// TODO: make this a proc macro when that's possible. -pub fn generate_module(struct_name: &str, abi: &str) -> Result { - let contract = Contract::new(Interface::load(abi.as_bytes()).map_err(Error::Abi)?); - let functions = generate_functions(&contract)?; - - Ok(format!(r##" -use byteorder::{{BigEndian, ByteOrder}}; -use futures::{{future, Future, IntoFuture, BoxFuture}}; -use ethabi::{{Contract, Interface, Token, Event}}; -use bigint; - -/// Generated Rust bindings to an Ethereum contract. -#[derive(Clone, Debug)] -pub struct {name} {{ - contract: Contract, - /// Address to make calls to. - pub address: bigint::prelude::H160, -}} - -const ABI: &'static str = r#"{abi_str}"#; - -impl {name} {{ - /// Create a new instance of `{name}` with an address. - /// Calls can be made, given a callback for dispatching calls asynchronously. - pub fn new(address: bigint::prelude::H160) -> Self {{ - let contract = Contract::new(Interface::load(ABI.as_bytes()) - .expect("ABI checked at generation-time; qed")); - {name} {{ - contract: contract, - address: address, - }} - }} - - /// Access the underlying `ethabi` contract. - pub fn contract(this: &Self) -> &Contract {{ - &this.contract - }} - - {functions} -}} -"##, - name = struct_name, - abi_str = abi, - functions = functions, - )) -} - -// generate function bodies from the ABI. -fn generate_functions(contract: &Contract) -> Result { - let mut functions = String::new(); - for function in contract.functions() { - let name = function.name(); - let snake_name = name.to_snake_case(); - let inputs = function.input_params(); - let outputs = function.output_params(); - - let (input_params, to_tokens) = input_params_codegen(&inputs) - .map_err(|bad_type| Error::UnsupportedType(name.into(), bad_type))?; - - let (output_type, decode_outputs) = output_params_codegen(&outputs) - .map_err(|bad_type| Error::UnsupportedType(name.into(), bad_type))?; - - functions.push_str(&format!(r##" -/// Call the function "{abi_name}" on the contract. -/// -/// Inputs: {abi_inputs:?} -/// Outputs: {abi_outputs:?} -pub fn {snake_name}(&self, call: F, {params}) -> BoxFuture<{output_type}, String> - where - F: FnOnce(bigint::prelude::H160, Vec) -> U, - U: IntoFuture, Error=String>, - U::Future: Send + 'static -{{ - let function = self.contract.function(r#"{abi_name}"#) - .expect("function existence checked at compile-time; qed"); - let call_addr = self.address; - - let call_future = match function.encode_call({to_tokens}) {{ - Ok(call_data) => (call)(call_addr, call_data), - Err(e) => return future::err(format!("Error encoding call: {{:?}}", e)).boxed(), - }}; - - call_future - .into_future() - .and_then(move |out| function.decode_output(out).map_err(|e| format!("{{:?}}", e))) - .map(Vec::into_iter) - .and_then(|mut outputs| {decode_outputs}) - .boxed() -}} - "##, - abi_name = name, - abi_inputs = inputs, - abi_outputs = outputs, - snake_name = snake_name, - params = input_params, - output_type = output_type, - to_tokens = to_tokens, - decode_outputs = decode_outputs, - )) - } - - Ok(functions) -} - -// generate code for params in function signature and turning them into tokens. -// -// two pieces of code are generated: the first gives input types for the function signature, -// and the second gives code to tokenize those inputs. -// -// params of form `param_0: type_0, param_1: type_1, ...` -// tokenizing code of form `{let mut tokens = Vec::new(); tokens.push({param_X}); tokens }` -// -// returns any unsupported param type encountered. -fn input_params_codegen(inputs: &[ParamType]) -> Result<(String, String), ParamType> { - let mut params = String::new(); - let mut to_tokens = "{ let mut tokens = Vec::new();".to_string(); - - for (index, param_type) in inputs.iter().enumerate() { - let param_name = format!("param_{}", index); - let rust_type = rust_type(param_type.clone())?; - let (needs_mut, tokenize_code) = tokenize(¶m_name, param_type.clone()); - - params.push_str(&format!("{}{}: {}, ", - if needs_mut { "mut " } else { "" }, param_name, rust_type)); - - to_tokens.push_str(&format!("tokens.push({{ {} }});", tokenize_code)); - } - - to_tokens.push_str(" tokens }"); - Ok((params, to_tokens)) -} - -// generate code for outputs of the function and detokenizing them. -// -// two pieces of code are generated: the first gives an output type for the function signature -// as a tuple, and the second gives code to get that tuple from a deque of tokens. -// -// produce output type of the form (type_1, type_2, ...) without trailing comma. -// produce code for getting this output type from `outputs: Vec::IntoIter`, where -// an `Err(String)` can be returned. -// -// returns any unsupported param type encountered. -fn output_params_codegen(outputs: &[ParamType]) -> Result<(String, String), ParamType> { - let mut output_type = "(".to_string(); - let mut decode_outputs = "Ok((".to_string(); - - for (index, output) in outputs.iter().cloned().enumerate() { - let rust_type = rust_type(output.clone())?; - - output_type.push_str(&rust_type); - - decode_outputs.push_str(&format!( - r#" - outputs - .next() - .and_then(|output| {{ {} }}) - .ok_or_else(|| "Wrong output type".to_string())? - "#, - detokenize("output", output) - )); - - // don't append trailing commas for the last element - // so we can reuse the same code for single-output contracts, - // since T == (T) != (T,) - if index < outputs.len() - 1 { - output_type.push_str(", "); - decode_outputs.push_str(", "); - } - } - - output_type.push_str(")"); - decode_outputs.push_str("))"); - Ok((output_type, decode_outputs)) -} - -// create code for an argument type from param type. -fn rust_type(input: ParamType) -> Result { - Ok(match input { - ParamType::Address => "bigint::prelude::H160".into(), - ParamType::FixedBytes(len) if len <= 32 => format!("bigint::prelude::H{}", len * 8), - ParamType::Bytes | ParamType::FixedBytes(_) => "Vec".into(), - ParamType::Int(width) => match width { - 8 | 16 | 32 | 64 => format!("i{}", width), - _ => return Err(ParamType::Int(width)), - }, - ParamType::Uint(width) => match width { - 8 | 16 | 32 | 64 => format!("u{}", width), - 128 | 160 | 256 => format!("bigint::prelude::U{}", width), - _ => return Err(ParamType::Uint(width)), - }, - ParamType::Bool => "bool".into(), - ParamType::String => "String".into(), - ParamType::Array(kind) => format!("Vec<{}>", rust_type(*kind)?), - other => return Err(other), - }) -} - -// create code for tokenizing this parameter. -// returns (needs_mut, code), where needs_mut indicates mutability required. -// panics on unsupported types. -fn tokenize(name: &str, input: ParamType) -> (bool, String) { - let mut needs_mut = false; - let code = match input { - ParamType::Address => format!("Token::Address({}.0)", name), - ParamType::Bytes => format!("Token::Bytes({})", name), - ParamType::FixedBytes(len) if len <= 32 => - format!("Token::FixedBytes({}.0.to_vec())", name), - ParamType::FixedBytes(len) => { - needs_mut = true; - format!("{}.resize({}, 0); Token::FixedBytes({})", name, len, name) - } - ParamType::Int(width) => match width { - 8 => format!("let mut r = [0xff; 32]; r[31] = {}; Token::Int(r)", name), - 16 | 32 | 64 => - format!("let mut r = [0xff; 32]; BigEndian::write_i{}(&mut r[{}..], {}); Token::Int(r))", - width, 32 - (width / 8), name), - _ => panic!("Signed int with more than 64 bits not supported."), - }, - ParamType::Uint(width) => format!( - "let mut r = [0; 32]; {}.to_big_endian(&mut r); Token::Uint(r)", - if width <= 64 { format!("bigint::prelude::U256::from({} as u64)", name) } - else { format!("bigint::prelude::U256::from({})", name) } - ), - ParamType::Bool => format!("Token::Bool({})", name), - ParamType::String => format!("Token::String({})", name), - ParamType::Array(kind) => { - let (needs_mut, code) = tokenize("i", *kind); - format!("Token::Array({}.into_iter().map(|{}i| {{ {} }}).collect())", - name, if needs_mut { "mut " } else { "" }, code) - } - ParamType::FixedArray(_, _) => panic!("Fixed-length arrays not supported."), - }; - - (needs_mut, code) -} - -// create code for detokenizing this parameter. -// takes an output type and the identifier of a token. -// expands to code that evaluates to a Option -// panics on unsupported types. -fn detokenize(name: &str, output_type: ParamType) -> String { - match output_type { - ParamType::Address => format!("{}.to_address().map(bigint::prelude::H160)", name), - ParamType::Bytes => format!("{}.to_bytes()", name), - ParamType::FixedBytes(len) if len <= 32 => { - // ensure no panic on slice too small. - let read_hash = format!("b.resize({}, 0); bigint::prelude::H{}::from_slice(&b[..{}])", - len, len * 8, len); - - format!("{}.to_fixed_bytes().map(|mut b| {{ {} }})", - name, read_hash) - } - ParamType::FixedBytes(_) => format!("{}.to_fixed_bytes()", name), - ParamType::Int(width) => { - let read_int = match width { - 8 => "i[31] as i8".into(), - 16 | 32 | 64 => format!("BigEndian::read_i{}(&i[{}..])", width, 32 - (width / 8)), - _ => panic!("Signed integers over 64 bytes not allowed."), - }; - format!("{}.to_int().map(|i| {})", name, read_int) - } - ParamType::Uint(width) => { - let read_uint = match width { - 8 | 16 | 32 | 64 => format!("bigint::prelude::U256(u).low_u64() as u{}", width), - _ => format!("bigint::prelude::U{}::from(&u[..])", width), - }; - - format!("{}.to_uint().map(|u| {})", name, read_uint) - } - ParamType::Bool => format!("{}.to_bool()", name), - ParamType::String => format!("{}.to_string()", name), - ParamType::Array(kind) => { - let read_array = format!("x.into_iter().map(|a| {{ {} }}).collect::>>()", - detokenize("a", *kind)); - - format!("{}.to_array().and_then(|x| {{ {} }})", - name, read_array) - } - ParamType::FixedArray(_, _) => panic!("Fixed-length arrays not supported.") - } -} - -#[cfg(test)] -mod tests { - use ethabi::spec::ParamType; - - #[test] - fn input_types() { - assert_eq!(::input_params_codegen(&[]).unwrap().0, ""); - assert_eq!(::input_params_codegen(&[ParamType::Address]).unwrap().0, "param_0: bigint::prelude::H160, "); - assert_eq!(::input_params_codegen(&[ParamType::Address, ParamType::Bytes]).unwrap().0, - "param_0: bigint::prelude::H160, param_1: Vec, "); - } - - #[test] - fn output_types() { - assert_eq!(::output_params_codegen(&[]).unwrap().0, "()"); - assert_eq!(::output_params_codegen(&[ParamType::Address]).unwrap().0, "(bigint::prelude::H160)"); - assert_eq!(::output_params_codegen(&[ParamType::Address, ParamType::Array(Box::new(ParamType::Bytes))]).unwrap().0, - "(bigint::prelude::H160, Vec>)"); - } - - #[test] - fn rust_type() { - assert_eq!(::rust_type(ParamType::FixedBytes(32)).unwrap(), "bigint::prelude::H256"); - assert_eq!(::rust_type(ParamType::Array(Box::new(ParamType::FixedBytes(32)))).unwrap(), - "Vec"); - - assert_eq!(::rust_type(ParamType::Uint(64)).unwrap(), "u64"); - assert!(::rust_type(ParamType::Uint(63)).is_err()); - - assert_eq!(::rust_type(ParamType::Int(32)).unwrap(), "i32"); - assert_eq!(::rust_type(ParamType::Uint(256)).unwrap(), "bigint::prelude::U256"); - } - - // codegen tests will need bootstrapping of some kind. -} diff --git a/ethcore/native_contracts/res/key_server_set.json b/ethcore/native_contracts/res/key_server_set.json deleted file mode 100644 index 93f68837a7675bdffa356455e19818df8fbd35c9..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/res/key_server_set.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"keyServersList","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getKeyServerPublic","outputs":[{"name":"","type":"bytes"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getKeyServers","outputs":[{"name":"","type":"address[]"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"keyServer","type":"address"}],"name":"getKeyServerAddress","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"keyServer","type":"address"}],"name":"removeKeyServer","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"keyServerPublic","type":"bytes"},{"name":"keyServerIp","type":"string"}],"name":"addKeyServer","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keyServer","type":"address"}],"name":"KeyServerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"keyServer","type":"address"}],"name":"KeyServerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] \ No newline at end of file diff --git a/ethcore/native_contracts/res/urlhint.json b/ethcore/native_contracts/res/urlhint.json deleted file mode 100644 index 629f166bbb107739deea4d0f7634cd74246c3b18..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/res/urlhint.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - {"constant":false,"inputs":[{"name":"_content","type":"bytes32"},{"name":"_url","type":"string"}],"name":"hintURL","outputs":[],"type":"function"}, - {"constant":false,"inputs":[{"name":"_content","type":"bytes32"},{"name":"_accountSlashRepo","type":"string"},{"name":"_commit","type":"bytes20"}],"name":"hint","outputs":[],"type":"function"}, - {"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"entries","outputs":[{"name":"accountSlashRepo","type":"string"},{"name":"commit","type":"bytes20"},{"name":"owner","type":"address"}],"type":"function"}, - {"constant":false,"inputs":[{"name":"_content","type":"bytes32"}],"name":"unhint","outputs":[],"type":"function"} -] diff --git a/ethcore/native_contracts/src/key_server_set.rs b/ethcore/native_contracts/src/key_server_set.rs deleted file mode 100644 index 60b137aae98fd497223843e7b4e9766617fe41ec..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/key_server_set.rs +++ /dev/null @@ -1,21 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Secret store Key Server set contract. - -include!(concat!(env!("OUT_DIR"), "/key_server_set.rs")); diff --git a/ethcore/native_contracts/src/lib.rs b/ethcore/native_contracts/src/lib.rs deleted file mode 100644 index 733dea80e6a3d29dc1a3b80f385118979e714000..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/lib.rs +++ /dev/null @@ -1,44 +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 . - -//! Native contracts useful for Parity. These are type-safe wrappers -//! autogenerated at compile-time from Ethereum ABIs, and can be instantiated -//! given any closure which can dispatch calls to them asynchronously. - -extern crate futures; -extern crate byteorder; -extern crate ethabi; -extern crate ethcore_bigint as bigint; - -mod key_server_set; -mod registry; -mod urlhint; -mod service_transaction; -mod secretstore_acl_storage; -mod validator_set; -mod validator_report; -mod peer_set; - -pub mod test_contracts; - -pub use self::key_server_set::KeyServerSet; -pub use self::registry::Registry; -pub use self::urlhint::Urlhint; -pub use self::service_transaction::ServiceTransactionChecker; -pub use self::secretstore_acl_storage::SecretStoreAclStorage; -pub use self::validator_set::ValidatorSet; -pub use self::validator_report::ValidatorReport; -pub use self::peer_set::PeerSet; diff --git a/ethcore/native_contracts/src/peer_set.rs b/ethcore/native_contracts/src/peer_set.rs deleted file mode 100644 index 09d0ecbb8d11e4d94e74d000d74be08b255a2a67..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/peer_set.rs +++ /dev/null @@ -1,21 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Peer set contract. - -include!(concat!(env!("OUT_DIR"), "/peer_set.rs")); diff --git a/ethcore/native_contracts/src/registry.rs b/ethcore/native_contracts/src/registry.rs deleted file mode 100644 index 3b3a6414d74ec7865004a675904b4c89b3f6eadb..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/registry.rs +++ /dev/null @@ -1,22 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Registrar contract: maps names to addresses and data. -// TODO: testing. - -include!(concat!(env!("OUT_DIR"), "/registry.rs")); diff --git a/ethcore/native_contracts/src/secretstore_acl_storage.rs b/ethcore/native_contracts/src/secretstore_acl_storage.rs deleted file mode 100644 index 3ebfcfb750a4399480ba21889c2911f3c177beeb..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/secretstore_acl_storage.rs +++ /dev/null @@ -1,22 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Secret store ACL storage contract. -// TODO: testing. - -include!(concat!(env!("OUT_DIR"), "/secretstore_acl_storage.rs")); diff --git a/ethcore/native_contracts/src/service_transaction.rs b/ethcore/native_contracts/src/service_transaction.rs deleted file mode 100644 index ee3b17552b9015e30449143aec8b2bbce8b8c2f9..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/service_transaction.rs +++ /dev/null @@ -1,22 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Service transaction contract. -// TODO: testing. - -include!(concat!(env!("OUT_DIR"), "/service_transaction.rs")); diff --git a/ethcore/native_contracts/src/test_contracts/mod.rs b/ethcore/native_contracts/src/test_contracts/mod.rs deleted file mode 100644 index 44810b3b763180355f113cc9edb692926ef55d13..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/test_contracts/mod.rs +++ /dev/null @@ -1,21 +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 . - -//! Contracts used for testing. - -pub mod validator_set; - -pub use self::validator_set::ValidatorSet; diff --git a/ethcore/native_contracts/src/test_contracts/validator_set.rs b/ethcore/native_contracts/src/test_contracts/validator_set.rs deleted file mode 100644 index 8a63c90dd8e7992d856841e0ba6c1d89a505f69f..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/test_contracts/validator_set.rs +++ /dev/null @@ -1,21 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Test validator set contract. - -include!(concat!(env!("OUT_DIR"), "/test_validator_set.rs")); diff --git a/ethcore/native_contracts/src/urlhint.rs b/ethcore/native_contracts/src/urlhint.rs deleted file mode 100644 index d2085e5934d558b29bca157a4f85108b3a93f379..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/urlhint.rs +++ /dev/null @@ -1,22 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Registrar contract: maps names to arbitrary URL. -// TODO: testing. - -include!(concat!(env!("OUT_DIR"), "/urlhint.rs")); diff --git a/ethcore/native_contracts/src/validator_report.rs b/ethcore/native_contracts/src/validator_report.rs deleted file mode 100644 index d77b07c716c7dcdaf5fe35a00c594bb2eaff5761..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/validator_report.rs +++ /dev/null @@ -1,22 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Validator reporting. -// TODO: testing. - -include!(concat!(env!("OUT_DIR"), "/validator_report.rs")); diff --git a/ethcore/native_contracts/src/validator_set.rs b/ethcore/native_contracts/src/validator_set.rs deleted file mode 100644 index 0a69913e0ff615df8588fcda969e991a90ac4b2e..0000000000000000000000000000000000000000 --- a/ethcore/native_contracts/src/validator_set.rs +++ /dev/null @@ -1,22 +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 . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Validator set contract. -// TODO: testing. - -include!(concat!(env!("OUT_DIR"), "/validator_set.rs")); diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml index e885ef1d105727e5aabbdabb5782d5aec31902fb..c183853d151c52319884e286fde6bd0b9a646ead 100644 --- a/ethcore/node_filter/Cargo.toml +++ b/ethcore/node_filter/Cargo.toml @@ -3,14 +3,22 @@ description = "Parity smart network connections" homepage = "http://parity.io" license = "GPL-3.0" name = "node-filter" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] [dependencies] ethcore = { path = ".."} -ethcore-util = { path = "../../util" } -ethcore-io = { path = "../../util/io" } -ethcore-network = { path = "../../util/network" } -native-contracts = { path = "../native_contracts" } -futures = "0.1" +ethcore-bytes = { path = "../../util/bytes" } +ethcore-network-devp2p = { path = "../../util/network-devp2p" } +ethereum-types = "0.2" log = "0.3" +parking_lot = "0.5" +ethabi = "5.1" +ethabi-derive = "5.0" +ethabi-contract = "5.0" +lru-cache = "0.1" + +[dev-dependencies] +kvdb-memorydb = { path = "../../util/kvdb-memorydb" } +ethcore-io = { path = "../../util/io" } +tempdir = "0.3" diff --git a/ethcore/native_contracts/res/peer_set.json b/ethcore/node_filter/res/peer_set.json similarity index 100% rename from ethcore/native_contracts/res/peer_set.json rename to ethcore/node_filter/res/peer_set.json diff --git a/ethcore/node_filter/src/lib.rs b/ethcore/node_filter/src/lib.rs index d3dcbaa3be051e83aa584cc9077501545d24e72b..945f552faf01faf15dc00a9dfd0513ec28631ddb 100644 --- a/ethcore/node_filter/src/lib.rs +++ b/ethcore/node_filter/src/lib.rs @@ -16,40 +16,57 @@ //! Smart contract based node filter. +extern crate ethabi; extern crate ethcore; -extern crate ethcore_util as util; -extern crate ethcore_network as network; -extern crate native_contracts; -extern crate futures; -#[cfg(test)] extern crate ethcore_io as io; -#[macro_use] extern crate log; +extern crate ethcore_bytes as bytes; +extern crate ethcore_network_devp2p as network; +extern crate ethereum_types; +extern crate lru_cache; +extern crate parking_lot; + +#[macro_use] +extern crate ethabi_derive; +#[macro_use] +extern crate ethabi_contract; +#[cfg(test)] +extern crate ethcore_io as io; +#[cfg(test)] +extern crate kvdb_memorydb; +#[cfg(test)] +extern crate tempdir; +#[macro_use] +extern crate log; use std::sync::Weak; -use std::collections::HashMap; -use native_contracts::PeerSet as Contract; -use network::{NodeId, ConnectionFilter, ConnectionDirection}; + +use lru_cache::LruCache; +use parking_lot::Mutex; + +use bytes::Bytes; use ethcore::client::{BlockChainClient, BlockId, ChainNotify}; -use util::{Mutex, Address, H256, Bytes}; -use futures::Future; +use ethereum_types::{H256, Address}; +use network::{NodeId, ConnectionFilter, ConnectionDirection}; + +use_contract!(peer_set, "PeerSet", "res/peer_set.json"); const MAX_CACHE_SIZE: usize = 4096; /// Connection filter that uses a contract to manage permissions. pub struct NodeFilter { - contract: Mutex>, + contract: peer_set::PeerSet, client: Weak, contract_address: Address, - permission_cache: Mutex>, + permission_cache: Mutex>, } impl NodeFilter { /// Create a new instance. Accepts a contract address. pub fn new(client: Weak, contract_address: Address) -> NodeFilter { NodeFilter { - contract: Mutex::new(None), + contract: peer_set::PeerSet::default(), client: client, contract_address: contract_address, - permission_cache: Mutex::new(HashMap::new()), + permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)), } } @@ -63,40 +80,30 @@ impl ConnectionFilter for NodeFilter { fn connection_allowed(&self, own_id: &NodeId, connecting_id: &NodeId, _direction: ConnectionDirection) -> bool { let mut cache = self.permission_cache.lock(); - if let Some(res) = cache.get(connecting_id) { + if let Some(res) = cache.get_mut(connecting_id) { return *res; } - let mut contract = self.contract.lock(); - if contract.is_none() { - *contract = Some(Contract::new(self.contract_address)); - } - - let allowed = match (self.client.upgrade(), &*contract) { - (Some(ref client), &Some(ref contract)) => { - let own_low = H256::from_slice(&own_id[0..32]); - let own_high = H256::from_slice(&own_id[32..64]); - let id_low = H256::from_slice(&connecting_id[0..32]); - let id_high = H256::from_slice(&connecting_id[32..64]); - let allowed = contract.connection_allowed( - |addr, data| futures::done(client.call_contract(BlockId::Latest, addr, data)), - own_low, - own_high, - id_low, - id_high, - ).wait().unwrap_or_else(|e| { - debug!("Error callling peer set contract: {:?}", e); - false - }); - - allowed - } - _ => false, + let client = match self.client.upgrade() { + Some(client) => client, + None => return false, }; - if cache.len() < MAX_CACHE_SIZE { - cache.insert(*connecting_id, allowed); - } + let address = self.contract_address; + let own_low = H256::from_slice(&own_id[0..32]); + let own_high = H256::from_slice(&own_id[32..64]); + let id_low = H256::from_slice(&connecting_id[0..32]); + let id_high = H256::from_slice(&connecting_id[32..64]); + + let allowed = self.contract.functions() + .connection_allowed() + .call(own_low, own_high, id_low, id_high, &|data| client.call_contract(BlockId::Latest, address, data)) + .unwrap_or_else(|e| { + debug!("Error callling peer set contract: {:?}", e); + false + }); + + cache.insert(*connecting_id, allowed); allowed } } @@ -117,18 +124,20 @@ mod test { use ethcore::spec::Spec; use ethcore::client::{BlockChainClient, Client, ClientConfig}; use ethcore::miner::Miner; - use util::{Address}; + use ethereum_types::Address; use network::{ConnectionDirection, ConnectionFilter, NodeId}; use io::IoChannel; use super::NodeFilter; + use tempdir::TempDir; /// Contract code: https://gist.github.com/arkpar/467dbcc73cbb85b0997a7a10ffa0695f #[test] fn node_filter() { let contract_addr = Address::from_str("0000000000000000000000000000000000000005").unwrap(); let data = include_bytes!("../res/node_filter.json"); - let spec = Spec::load(::std::env::temp_dir(), &data[..]).unwrap(); - let client_db = Arc::new(::util::kvdb::in_memory(::ethcore::db::NUM_COLUMNS.unwrap_or(0))); + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::load(&tempdir.path(), &data[..]).unwrap(); + let client_db = Arc::new(::kvdb_memorydb::create(::ethcore::db::NUM_COLUMNS.unwrap_or(0))); let client = Client::new( ClientConfig::default(), diff --git a/ethcore/res/authority_round.json b/ethcore/res/authority_round.json index a56618d1c7d9a80f2f5bb7a28bf6c8bcbbec5e6b..8d54244379878a0b75f7842f2e05983063f2205c 100644 --- a/ethcore/res/authority_round.json +++ b/ethcore/res/authority_round.json @@ -20,7 +20,11 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x69" + "networkID" : "0x69", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -41,6 +45,10 @@ "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/res/authority_round_empty_steps.json b/ethcore/res/authority_round_empty_steps.json new file mode 100644 index 0000000000000000000000000000000000000000..b884e8e15a349a72ce52d61cafd16c16c24d0927 --- /dev/null +++ b/ethcore/res/authority_round_empty_steps.json @@ -0,0 +1,51 @@ +{ + "name": "TestAuthorityRoundEmptySteps", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 1, + "startStep": 2, + "validators": { + "list": [ + "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e", + "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1" + ] + }, + "blockReward": "10", + "immediateTransitions": true, + "emptyStepsTransition": "1", + "maximumEmptySteps": "2" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x69" + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x222222" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }, + "7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "1000000000" }, + "82a978b3f5962a5b0957d9ee9eef472ee55b42f1": { "balance": "1000000000" } + } +} diff --git a/ethcore/res/basic_authority.json b/ethcore/res/basic_authority.json index 192b48cada6b1f27db20b6b08775f2dbd9adc892..35711be0112663fdd375077f74a71bb1c3e3471e 100644 --- a/ethcore/res/basic_authority.json +++ b/ethcore/res/basic_authority.json @@ -15,7 +15,11 @@ "accountStartNonce": "0x0100000", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x69" + "networkID" : "0x69", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -33,6 +37,10 @@ "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } } } diff --git a/ethcore/res/constructor.json b/ethcore/res/constructor.json index 9b1de7020700746f38b3deeecdf651e61cd11b86..f4e22ea2d82380fd649e29963e4ba5b16611418e 100644 --- a/ethcore/res/constructor.json +++ b/ethcore/res/constructor.json @@ -1,14 +1,21 @@ { "name": "GenesisConstructor", "engine": { - "null": null + "null": { + "params": {} + } }, "params": { "gasLimitBoundDivisor": "0x0400", "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2" + "networkID" : "0x2", + "registrar" : "0x0000000000000000000000000000000000001337", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -26,6 +33,10 @@ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "balance": "1", "constructor": "60606040526000805460ff19166001179055346000575b6075806100246000396000f300606060405263ffffffff60e060020a60003504166394b91deb81146022575b6000565b34600057602c6040565b604080519115158252519081900360200190f35b60005460ff16815600a165627a7a723058207882eb60ebce23178b3fa06d4cd8e5adc17711937ccddacb18a04abca2a2c9ee0029" } + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000001337": { "balance": "1", "constructor": "60606040526000805460ff19166001179055346000575b6075806100246000396000f300606060405263ffffffff60e060020a60003504166394b91deb81146022575b6000565b34600057602c6040565b604080519115158252519081900360200190f35b60005460ff16815600a165627a7a723058207882eb60ebce23178b3fa06d4cd8e5adc17711937ccddacb18a04abca2a2c9ee0029" } } } diff --git a/ethcore/native_contracts/res/registrar.json b/ethcore/res/contracts/registrar.json similarity index 100% rename from ethcore/native_contracts/res/registrar.json rename to ethcore/res/contracts/registrar.json diff --git a/ethcore/native_contracts/res/service_transaction.json b/ethcore/res/contracts/service_transaction.json similarity index 100% rename from ethcore/native_contracts/res/service_transaction.json rename to ethcore/res/contracts/service_transaction.json diff --git a/ethcore/native_contracts/res/test_validator_set.json b/ethcore/res/contracts/test_validator_set.json similarity index 100% rename from ethcore/native_contracts/res/test_validator_set.json rename to ethcore/res/contracts/test_validator_set.json diff --git a/ethcore/res/contracts/tx_acl.json b/ethcore/res/contracts/tx_acl.json new file mode 100644 index 0000000000000000000000000000000000000000..cc924cafb81d9cbe6c023b87081cbc386c41c7b9 --- /dev/null +++ b/ethcore/res/contracts/tx_acl.json @@ -0,0 +1 @@ +[{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"allowedTxTypes","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] diff --git a/ethcore/native_contracts/res/validator_report.json b/ethcore/res/contracts/validator_report.json similarity index 100% rename from ethcore/native_contracts/res/validator_report.json rename to ethcore/res/contracts/validator_report.json diff --git a/ethcore/native_contracts/res/validator_set.json b/ethcore/res/contracts/validator_set.json similarity index 100% rename from ethcore/native_contracts/res/validator_set.json rename to ethcore/res/contracts/validator_set.json diff --git a/ethcore/res/ethereum/byzantium_test.json b/ethcore/res/ethereum/byzantium_test.json new file mode 100644 index 0000000000000000000000000000000000000000..40c7e465991c46c30693b7ee2b88e3c3e5897ae9 --- /dev/null +++ b/ethcore/res/ethereum/byzantium_test.json @@ -0,0 +1,61 @@ +{ + "name": "Byzantium (Test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "homesteadTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": "0x0", + "eip649Transition": "0x0" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip98Transition": "0xffffffffffffffff", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + } +} diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index bfd64248e9022ecb809596dca5b3c98fffe99472..a4c6fe9f227737239c53cc0555c1710194a1baf2 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -7,21 +7,21 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": 1150000, "eip150Transition": 2500000, "eip160Transition": 3000000, "ecip1010PauseTransition": 3000000, "ecip1010ContinueTransition": 5000000, "ecip1017EraRounds": 5000000, - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", + "bombDefuseTransition": 5900000 } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", @@ -31,7 +31,6 @@ "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f", "eip155Transition": 3000000, - "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff" }, diff --git a/ethcore/res/ethereum/metropolis_test.json b/ethcore/res/ethereum/constantinople_test.json similarity index 61% rename from ethcore/res/ethereum/metropolis_test.json rename to ethcore/res/ethereum/constantinople_test.json index a452e5a80a121b35e01d85fb3c40443868bcdf7f..7b137e86fa0732b9aa25ebbcf13ac4bc42f6a450 100644 --- a/ethcore/res/ethereum/metropolis_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -1,34 +1,39 @@ { - "name": "Metropolis (Test)", + "name": "Byzantium (Test)", "engine": { "Ethash": { "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x0", "eip150Transition": "0x0", "eip160Transition": "0x0", "eip161abcTransition": "0x0", "eip161dTransition": "0x0", - "maxCodeSize": 24576 + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": "0x0", + "eip649Transition": "0x0" } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x0", - "eip86Transition": "0x0", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip98Transition": "0xffffffffffffffff", "eip140Transition": "0x0", "eip210Transition": "0x0", - "eip155Transition": "0x0" + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -48,6 +53,10 @@ "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json index 22ebf5500584053537f7a74b65e515c603aa08dd..60157c5716804ee7fda43b6a7dd8a094b75f94e7 100644 --- a/ethcore/res/ethereum/eip150_test.json +++ b/ethcore/res/ethereum/eip150_test.json @@ -6,18 +6,17 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x0", "eip150Transition": "0x0", "eip160Transition": "0x7fffffffffffffff", "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff", - "maxCodeSize": 24576 + "eip161dTransition": "0x7fffffffffffffff" } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", @@ -25,7 +24,9 @@ "networkID" : "0x1", "eip98Transition": "0x7fffffffffffffff", "eip86Transition": "0x7fffffffffffffff", - "eip155Transition": "0x7fffffffffffffff" + "eip155Transition": "0x7fffffffffffffff", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x7fffffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index 50d28570b78e51e4c0b32c71399bbafc56495b9d..ac1c0a5d1e3cc60fbb6ed128256209d1889d6ce4 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -6,18 +6,17 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x0", "eip150Transition": "0x0", "eip160Transition": "0x0", "eip161abcTransition": "0x0", - "eip161dTransition": "0x0", - "maxCodeSize": 24576 + "eip161dTransition": "0x0" } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", @@ -25,7 +24,9 @@ "networkID" : "0x1", "eip98Transition": "0x7fffffffffffffff", "eip86Transition": "0x7fffffffffffffff", - "eip155Transition": "0x7fffffffffffffff" + "eip155Transition": "0x7fffffffffffffff", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/ellaism.json b/ethcore/res/ethereum/ellaism.json new file mode 100644 index 0000000000000000000000000000000000000000..3036992eb7bae4fba69fa91a9a9e893ab728c717 --- /dev/null +++ b/ethcore/res/ethereum/ellaism.json @@ -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 } } } } + } +} diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index d79ab6b3c3b72d170b0ece24b8f5b4225df4e9c3..b9b734e313df34f740d9e1ca23b222d6a1dcc1a3 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -6,8 +6,9 @@ "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", - "difficultyIncrementDivisor": "60", + "difficultyIncrementDivisor": "0x3C", "durationLimit": "0x3C", + "blockReward": "0x6f05b59d3b200000", "homesteadTransition": "0x30d40", "difficultyHardforkTransition": "0x59d9", "difficultyHardforkBoundDivisor": "0x0200", @@ -15,23 +16,34 @@ "eip150Transition": "0x927C0", "eip160Transition": "0x927C0", "eip161abcTransition": "0x927C0", - "eip161dTransition": "0x927C0" + "eip161dTransition": "0x927C0", + "eip100bTransition": "0xC3500", + "metropolisDifficultyIncrementDivisor": "0x1E", + "eip649Transition": "0xC3500", + "eip649Reward": "0x3782DACE9D900000", + "expip2Transition": "0xC3500", + "expip2DurationLimit": "0x1E" } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x6f05b59d3b200000", "registrar" : "0x6c221ca53705f3497ec90ca7b84c59ae7382fc21", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID": "0x1", "chainID": "0x2", + "forkBlock": "0xDBBA0", + "forkCanonHash": "0x8e7bed51e24f5174090408664ac476b90b5e1199a947af7442f1ac88263fc8c7", "subprotocolName": "exp", "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff", - "eip155Transition": "0x927C0" + "eip155Transition": "0x927C0", + "eip140Transition": "0xC3500", + "eip211Transition": "0xC3500", + "eip214Transition": "0xC3500", + "eip658Transition": "0xC3500" }, "genesis": { "seal": { @@ -53,7 +65,6 @@ "enode://96d3919b903e7f5ad59ac2f73c43be9172d9d27e2771355db03fd194732b795829a31fe2ea6de109d0804786c39a807e155f065b4b94c6fce167becd0ac02383@45.55.22.34:42786", "enode://5f6c625bf287e3c08aad568de42d868781e961cbda805c8397cfb7be97e229419bef9a5a25a75f97632787106bba8a7caf9060fab3887ad2cfbeb182ab0f433f@46.101.182.53:42786", "enode://d33a8d4c2c38a08971ed975b750f21d54c927c0bf7415931e214465a8d01651ecffe4401e1db913f398383381413c78105656d665d83f385244ab302d6138414@128.199.183.48:42786", - "enode://df872f81e25f72356152b44cab662caf1f2e57c3a156ecd20e9ac9246272af68a2031b4239a0bc831f2c6ab34733a041464d46b3ea36dce88d6c11714446e06b@178.62.208.109:42786", "enode://f6f0d6b9b7d02ec9e8e4a16e38675f3621ea5e69860c739a65c1597ca28aefb3cec7a6d84e471ac927d42a1b64c1cbdefad75e7ce8872d57548ddcece20afdd1@159.203.64.95:42786" ], "accounts": { @@ -61,6 +72,10 @@ "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0xC3500", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0xC3500", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0xC3500", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0xC3500", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "bb94f0ceb32257275b2a7a9c094c13e469b4563e": { "balance": "10000000000000000000000000" }, diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index b30453082771a1cab1046b59d03a2d2b2bccc4de..53322e6ffecc1fb33c6c367ee3372ce606393998 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -7,6 +7,7 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x118c30", "daoHardforkTransition": "0x1d4c00", "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", @@ -132,13 +133,14 @@ "eip160Transition": 2675000, "eip161abcTransition": 2675000, "eip161dTransition": 2675000, - "maxCodeSize": 24576 + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": 4370000, + "eip649Transition": 4370000 } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xe3389675d0338462dC76C6f9A3e432550c36A142", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", @@ -147,9 +149,14 @@ "forkBlock": "0x1d4c00", "forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb", "eip155Transition": 2675000, - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip86Transition": "0x7fffffffffffff", + "maxCodeSize": 24576, + "maxCodeSizeTransition": 2675000, + "eip140Transition": 4370000, + "eip211Transition": 4370000, + "eip214Transition": 4370000, + "eip658Transition": 4370000 }, "genesis": { "seal": { @@ -166,35 +173,2636 @@ "gasLimit": "0x1388", "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, + "hardcodedSync": { + "header": "f90219a061d694007fbaca6e23e73e29c8c6a60099abc740ab7e27ae3cd1b9c6a47efef7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347945a0b54d5dc17e0aadc383d2db43b0a0d3e029c4ca0a2f1bdabc1a72737de1c22a76cacc8fc162366904f759a99db7d6d19efee3090a0ac5f5b236e8977928a2ce43c7569ea5a74919643cb0b06d7540407b1ea1298f0a04356ddc5d77c83923a6541260308be167386e0969a608a017770c9e38091cfcab90100a00010002001009080011010141088000004000080081100000a002023000002204204801204084000c000010008000000000880080020c0000440200460000290005010c01c80800080004800100406003380000400402040000028084002a80087000008090a00200100544020019580022000000306100a0080100084020006809000e80000010000254810002000000a240050014200002002c10809202030006422022000203012000241089300080400000009001021020200012410348500028290230408100302000000058c0000020c08c20480081040020260004008481000080000800010010060020000e00020002140100a8988000004400201870b9af4a66df8038350a8018379d54483799eba845ab0426d984554482e45544846414e532e4f52472d3231323134313232a05eeccc80302d8fecca48a47be03654b5a41b5e5f296f271f910ebae631124f518890074810024c6c2b", + "totalDifficulty": "3144406426008470895785", + "CHTs": [ + "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", + "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", + "0x816e7463af7b5d2fcb804ba55f09e8452182b0ba6c995a34e144245d76333d55", + "0x3793af64c1ddc07ab61b2ba120034d91c02183ff788f07d3120fd4e6a48305b5", + "0x14c6106a17e041032210bfa0ca80d11860a1c6d95175d55eff39f97b8d8acded", + "0x396f832bfa3a9c494e9245471f0e65552613d87b6fe62128103590d95de72c2d", + "0xb060979f095c170a776b2b50a1e2ab0ffea80f6e522753fa36ad6f106ee32e9f", + "0x8f452e7cbd8a333ed04d819a143a8d3a75fe8c58418e7fc420bb2a717c0d4d2f", + "0x37fe1b0cf156bfc07571569af210540be753777903a308d5707538fffed75b59", + "0x6f0561d017cfc123b3f0d37b044e4f7231516b8731a1cab89afb569238643c33", + "0x3c1740c410a88c60fe8ccdc44e0ef2cf7f7314818dbf1648c01d0d94fbffc211", + "0xfb98115a7d6df8aaa40115f883014fe97300869bc016648e918fbf2df9608d41", + "0xef1099ab5ca4b79369048678d3ba78122fc081b00b6fd0f6907302a260d58266", + "0x969575f411dd78fdc5b4def0331fc93702029cc3c78851331a0f47dd0faae70b", + "0x9e53053e362be51c0fd25eaafd9e7c5c969d9f2ce8db4b3d4d830cbff347b0c8", + "0xf9de29944954d2b71a93532fc26916ae12fee72d42a79adaf940b0bf75d0ef89", + "0x28b2ce6635e60e06d643750798779023b2a807d9d089ae9ef7f223eebc15a71e", + "0x5295c06cbaff06f42bd8f5d9cbe94a840885caed02f9c9ba6da44a888ef796de", + "0x576eae673a4cbba4c7c7a56b47835ea64ae5989d67d119ebc8e568df40d908a9", + "0x891c0d38bc5e55620615da42ed77ab33806a042512034bcee134279dde1054be", + "0xbab05999d657426a11a902eb4c85ac52e2b72dd1cf38584cf2baeb2c3727bb44", + "0x3bd7e5a966f6dd2dc456948a8efca5584f5a4e0033f3037843a42073dda1f71b", + "0xc4f773ab1e34290f9a3d9ac6ede4749c5dec547353dddea494169d86f71107a3", + "0x993bf037ea9dd58b52027fb6f39332dab867c1e72af34a49d58a5a12f26bcca3", + "0x48b2d8d506eb8fc9dc0402fef26952111449aca0f90d0079f0526435d4e3183b", + "0xfef8f61df240e956f43759d2f481938421e064a9bd6a3be7a53b1213cc9588bb", + "0x5abf01f5066cf1091acdd1f99fbd5fd963633feafc42f9047534a3c1522004a5", + "0xa0f6205842260988161183b51bc36fae458fa184dd61844617d5c5d26fa78346", + "0x77309182fdc26d15dd8d9dd05040d7dc623412785708d8aac39eedee63931944", + "0x661c93311b94b7d4cdcbc0973225c794e71898a2b906922a6c1e8f7e9e289dc3", + "0x9d5d329ee8d9fffaee0111688d31a308dfaac922dcd61f818edd5303d0955be0", + "0x716ca25b184b64ba273b978de098f9946413f6fcc95bfba5cf1169e7e03dd611", + "0xa2e8d5cefa5804894fb42a106340b00de3286fee0992b5887b2cf471539d74a9", + "0xf846e05c9e9e9cb4cd2b7cbae7ae183a43a59ab02251954db632e538adacc357", + "0xbc01b4e23ea082a193e4c1012b1da91f3b4cb762009ca320bc8ed294af874e79", + "0x9218114a32da3ecf660d4d51b101bb51bb17c771561c1946c099be082f0a96b3", + "0x3b4edf03dfd53081cf40c0b90b35c1ccf7c7fe96cf131172eef5eec62f620ea8", + "0xb15758944263c67bdf528d4d7fe05737fbdbf7ffedce5f891a4ddf76177d2609", + "0x1f119374c385240f7b4ba1ec3d502be2c12c159411d5393ff2bd38cf87033625", + "0x8a8d5a93f3475813926b13a4d53f21b28dc79ade2b50830c0b9043e9fcd81576", + "0xcc22f7e2bb9c06c15ca3d82df852ed9097a2ddc687ee389e662de000db0c84fc", + "0xc2047e0dab711db791aadb642f8102abaacf7231b8dbdbe1f60573b0be015a31", + "0x1b4088ceee7783e4563945f162bd5da67020ca377a18d615923e8564d6709f85", + "0xd73450686e33bbda9eef53a95a86e5a0514156b98a5b7dfc6fdc0adb0b83cbcf", + "0xb374076ec961360e38d3486a31c3f72225440984c4c47ca790b4961d94152159", + "0x4f723f4fbd31d63a5421390e68aba0aff97249875688a7d9ab9a339d9aac7bc1", + "0x5fe51ff982edcad6c0052fcdf9a70e8f325c8140ab75848c5d7b0d670bd7edc2", + "0xc3ad483c7cc23bf8d6ae3e3e829bf126d5eeea9c53b566a6da95bef573b9c779", + "0x3c9e50ed9eb57cc055fd9a65a6cdaba2030d8b41f81348f296d7410c1d24ced0", + "0x0c6dfc1f626ff9e85ff072c154152bb3f122a2c1a45bc2d9e7da9b2d5278149a", + "0x92f4452dbdb4fe70e84ecd47af4b1af90975219797cebd451beceb6997ab024d", + "0x9a3d00686736b5b838308da4b8f0aa9edccfaba64621ce2988cea6ea2a267efd", + "0x8d602d0bef069177102726d5ccd93d19805fb5771a350a41e32755ce740b9047", + "0x6681e4097667a22ad3713acc27b6f87abd54583230581933bed9245c2c457ac3", + "0x53077caeabcd926466319a3ee5c51c32e01e1812a65313f113f814d53e9f1dd9", + "0x4dd4c33e99d86ba84f976c639333fc072e262c0b76dfdf2f589300af54048c0a", + "0xbc3b9837a6fa54616dcdb8088080e276e2e99a23c8e7de4109504293703d524e", + "0x24316b344cecd5e601cc0acc91ff94f481ca3fa26d8478644a9d8bcaeb0359b3", + "0xa7bafd3c5f4e3f6b5c078d50eb318d91e867b0e1c966027e3e7458eb104ccd63", + "0xc8da46b7d778980d120357c8de2bba336f5a2ac7a9f4183a0ee1f7597ed47d25", + "0x7469fc5d8c9c648cd10e538710e0f126542e59a82484e7fe56b73f4ec52c36c7", + "0x993bb7c0487ff61c97e4f1533446ae35b6346642e1230f2441da8b354111d597", + "0x90e3944732f86a2254dc4f30650f8438dfd0b777561fb02a8ab1c60438569c24", + "0x4e8472483679b54bdc600010fdd164f54771d7a99fa9272c683b610fff72507b", + "0xf72a861a2ebc232c25529c0f94c59996e64c59c36a1326a183cf171bddf2a75c", + "0x7f222999ba9113e2a64fd026a8f7244e6d2ae8f2a7e7d8d2d6fbde6fdf0b629f", + "0x3304e769f730522c1c5aa745c448075df026b8f82a4dece84fd70d0457050985", + "0x9ee5e3ccaaf94461dff9df8c4805ca831f58a1586af4ece3cab14a45f3b784db", + "0x21e4364859063e20153d2d06eae4d2c9e99354bf97fbff68406d8825d18dbce3", + "0x4805355b72b1b61b07814059f80b4da0351291cc932292f23069197a74127726", + "0x14474f45f38d7ea51418e5f03751c8bfbfb9b3e2957d3051e862aa3c57a63c43", + "0x69372cee3e2807d10ecb72d404a033568a159a5b15d2007537ed9a758164b29f", + "0x147223b51001166a4e65372c9c706f011f1ae94f4bdc9ba6e8960017e8898703", + "0x11a1e48a5c1d7088c0ccb8177d54db9e9f91a99aa7c24f702cd93f4646f181ee", + "0x809c902b2f4b8760c3d2e820c93d6df69a5d184a43a6c654ebe7067e7212137d", + "0x749367027756c27215b2f57168ef15d3b39062c9f79b3777f7fa19e8073de775", + "0x6a9fae37364f97e36e56df97acb1b7d066a608d8366d7e008854756dd28fe748", + "0xdc2f1b7a8aeda15e6bf4f5f424bc54828cc8520e2e7ba27bd8e28ba2b543aae7", + "0xe0fabc892d5c8b4342ff488b76a0400425ea70774f207c546fbf2f9f5b105dcb", + "0x151fb5e02d8eb3c3192cb8c039bcb4c121c4ebeea5e7f98927b85a730a24bbf9", + "0xfeb2f2ea368d0bd4c0b0bd97b444c365bdc0ac9ce2862b0d0162387727edd236", + "0x1eaf828231ebbae54737111bf3c7181fe3d7e9070def1313470d3f81c89f01c7", + "0x8a1b0565013cff488bbe3f35df86fb41c7aedf4d911130802c473f4ddb74d6d6", + "0xce9158b5c903312fa636e074e3efe413184652581a4877d40a0085965dc0bf9a", + "0x1cf602c6306affe2916fa09d3c8c018f23fc44dec8af8e83fa0008c98b4dda72", + "0x189dc4569e96cab937265ecaea76a0880ec97d5b84ac1fbd0cd2d2b36a8c34c3", + "0xd698bd07e485767c1da30bb218265e1304f6eaf426749ccba67478817af84bd4", + "0x47d7e101de73bb0ca97a0bb70094e81b82c63e519a6b2aa5fe10ca7351232870", + "0xb0d441b6c41072889c4a982306c9a40dff77b43425ecc4d771c22f3199eb7708", + "0x7893071deba67f2fc8e1b18bedcac4dbc05a020f37c764c555eadc42dd9d29d3", + "0x3c6d636db3621757d60b2d0e1804e19528ce60c9feed1ead93731820ff19b11c", + "0xde87aaa462b461c4a33e0739ef4cf56d442b7967ac7c5280816a959046b128b6", + "0xb237b17650adcbcf580b64b500ecaa7ca36921a11ad92c1e8992c57cc1a7f618", + "0xec379725db43fefe61f2495f7f7e0531d852e21f896ae806144c4d9b4b986e96", + "0x65ac5548988825831f0887b9ff0f2c13b7f3b49e4a67c39b1694e76414249f6d", + "0x76053b72ec9e6fcf0a28ef273d3e1b0842c3c2c0e905f5b5a3535ffab216c8db", + "0x2ab1e87489eb1daeaf8882c6baa0a8726aeac522e9c4eb4df71e35af2d22cc10", + "0x8c9c6adcabe253b311f6a9b8165ff9c5e26e4cf41f1acd80837e77fc15526a86", + "0xf143155230223a3f126c757b85e193a9129f1bdf97c0ce1f2785f14d40911f30", + "0x8c510d9dca593534f3ed316f240ffb9343d1e3cd6d005df6a75a1b354da0b36e", + "0x3440975cf818a718beff35a85d19bcbbd67e1b16ca9d78af34dcde31a28b3288", + "0xf56ef9c57109f9cb7a925bbb6d453efc19e8a45b331f76153d20a87d86a8b0d8", + "0x19a360772872003f08508a28a362c6e05650b385c24a928ddad4d562bfccf412", + "0x643720694b3773ecf20437d54a6be701810feff233f435dc701dbe88c9a6a13c", + "0xf8c0babe99aa26ecbfc91b304d9cd54ccfb37354c4fdbeb3207bb6d4647fabd6", + "0x481ccc7213d0188e817c071c4cc3a71c96befb9aa98cab964012fd7a8267834a", + "0x02d83ca8d92e0fe6ce7643ae93af60e38ab5659a84c04beba678ceef654aec12", + "0x24e6b4bcd0d97df196f2371532771593fe17be8fcb89f1e1164bcce8616088b9", + "0x3dc91775c50c04812f755f3b48d3d6a0cc599c586ce9d105e2cf4f3e4527b515", + "0xcdc215f05398ea3942d3a38078a3602cbe8ac549d4bf0e4a54191ceb2aff8f76", + "0xee02874e444b784f4265cc60b86a17382d277d03c8bce8a33241460ea8950699", + "0x35c34bc84736fdcbc4d4e2e089f30bcd186a052b2f6dcb639fc45a0aeb6969f8", + "0xbbb3ff849c36659bf2c00feaad9f7b3a342b5cfcf3555b7c2e467a0dc84e90e8", + "0x0584bc60fbe3fae9088c214fb519030646c3240f77180a0bedecd3e9c9f47f89", + "0x9d18a665d89439ad2c97427bdab3e598f5bc0da6a0ede2378f95c5bc31f10d12", + "0xe8a5bdd0ffd33a6fd03cf003c6d2afbe8493e0f0cb69e6366e22b4d1ff985101", + "0x7ca955f4e01eef756b680d09c25626cf50013faa20a12b0a334fd048a04e7b91", + "0x064254551457bd5e7a260a41ed3643746202d503813ceaf42660f9bd1983be34", + "0x1191044e354ea1e3daa25ed2175a6517659e96733d9065d81492ffe4472fb96f", + "0xc823514cf3566b1bb2e19a35e0ef0980bc483fa820d13ae2cfdbf15fd426c272", + "0x413f941f192d0ab77bac68268f45e2c9adbee23a3324d4ae8748d09735355a2d", + "0xa66c94b9603b3058b730baeba1b79d52f548ceeb5bac487903f92481060f6804", + "0xa84d4a8860bdff1fdae6bcefcdcf700fab7857444ef1e76d8259b005872a4636", + "0x9fa64d44edd9c097458d3901612a4b6f655a1421ebb68541cb1a4bdbbe24911e", + "0x402027770edb387510241a68a235723c6c5c95aed54dab058c43d21a6bb48c41", + "0x776281b7e341a66491603b7ae8ed7cc82b99febac43f94cb1c4dda73b17aab63", + "0xfecbaf0fc5a02dcf49095514ce26df927def3cf51f37e04471545aae2364f936", + "0xc477d9293f0ace7243f8b9c89f01210b8f96b4affc9d3332147ea2e2b693c99e", + "0x4a8b9afb9d9097831b2497296b0fd0fae76ab8a596213daed35cf87e6bbefaed", + "0x594c4e9851eddbb4a6c2ac72aaa244ff35d67262efb20935360360d39f7c7ecc", + "0x14b7ef22c46ba8400979b6c06f3b3023607145a5cc6b5b793daae758cb655245", + "0x3a9d233553d1ca4d9862a70ef133a5fb2df75276fb24297b0bd2927a39459450", + "0x22c5e227d5fa7616603bbf36c5e4ee7dbf285fb0cf403a3ae982da70c825cad0", + "0xc2c8d439c7bd884665da56e3b680a5e58ad1e98627fdbec6fa67d7bbfad33a9b", + "0x7d5682cd9f28493ba4b87be141ec99701bbcd1aaadf9840b81de1fc07d4ffb18", + "0x8845f626c5f78d1bea281f892727437f9de8f976e4c4fec6060b2115f1862db5", + "0x769fdf0bcdbaec1ffe98cd3500ce8341b4d7ea2dad5fadb0258212306ccc75f9", + "0x185569d1980147fcdfcd0e0068ab380f0cfa58a690334a558bc1fd0d07897e96", + "0x0ed70ccff752df46f981043c5279ac3f13e7f62c2bdb9a0a9817a1c119ef6402", + "0xbe121e28349e80d601ab997af844aa03ea6492e88d75d3d46517d8f835e3c3fd", + "0xa7aa5f0bb95566292d22891faa75b7ff2020b69fecc8a22d796cc3a60953d98f", + "0xa2611b092b00f78fe639c4fba0274ae474fa448b3f2e4b8aa4d06c654720d478", + "0x8e425115b98f5e41c8b5d03a9e17d56d30050d85dd06cfff12f002c546a256ba", + "0x988b449fbd8c35855154fb4eb22ba6b7b7095be26203d137f484c67facd40dc5", + "0x567c43ac5dabeff01d6997543ec7abf7998088a355a6ba8e70f41a243dd1343a", + "0x6f560cb650142aed532f17de763d61d021cdec2716b0d2cb27b3a64052abb874", + "0x7e4ce5fab8f4f1fd41f9e5f10204032ae7e0e38093b1d07699318975b33910ec", + "0x91a0820eec5390916bf464b1d16c00b5d94386c4c9f4cdf7e0b3cbe40747fbc9", + "0x9c59451a9a242123efa72c5fbd1564b7bcc0067ea9d025336d228ed26b9ba6c0", + "0x1043a5ab3f5a3bced84faaae0e783abb3b81c2b967bbd976042cb5d897d28146", + "0xfc37b3b3c0be392ad2a5e36c120eace1d14e637ac806e79a750b9a6be3c742a7", + "0xce2ccbada44a8db5144073e69914b322dc015273a75b85ea43fd9e21037c760c", + "0x6cf8336b5a410e10604f93351242cb3a6929968212abdf85b4ca9321115b8fdf", + "0xabbe9781950362be1e206d91ea1bdd6f32ea2c6df65b277cb89050ca1deb9296", + "0x922a6b85add6839494c3edff389aa1b054409c330b4a4e2a6c0e4f9bc85b36a9", + "0xc26dcdfa135a09b7eef1e99b445fb66aefb8bceb6ea715b81d78ba87cd56ed8d", + "0x87d647fa7dcde81a0e133aa949d574befefbceab24a42ae4f3809d2bb52a2d9b", + "0x85ee37fa7154568b9dee8a539340f99c7f1bbc7b9be1f2055636ed9dfc074e4d", + "0x8b0114dc9e249f1de4bb3d055790e4bf18aa28a938f39e8a457ab4a43b0dd613", + "0x3be36db134f4c00fc9e1bc376213c7073389c993b0b0744cba619688d6c037d1", + "0xfaf987eb2e066ad8871c489c23102ec5c58add2d13e62d56f2821cc1f4d66d84", + "0x678478da2955e6876ac49c5146e9f7c376dbf2f170f6404054ae4385e72f3f19", + "0x85d8d9dd6c2a8f6b6a1c0fc0cb55ca870d9a7aae1621c143c3176a3a81fcc29c", + "0x76f4dfa4c3387408c823a75aeb872ff39af3820375ff52f7aecb41c96e4faf2a", + "0x6e530647f2e4232063de2fa8f673989d7834d8cdf529791032888f2833880b80", + "0x64422b4dfff6cba0eb6deaeb4593eefc40a357469a7f7c3be078f80c66161333", + "0x5c7ab740510a4183832bd78e6d6105b0f9f928611f7d62ef96aa8dd8da48a72d", + "0x0bbf405e29f015d24e64f063d50ec6c616af64622b1a4132cde86f926e93850f", + "0xd9ba81ea0790f1f8adccd0bd203c7adeec2b490381b822d6b15293cac2f26206", + "0x4f78619baa34f2278022c509671a38d29366936d6860e79ab540ea46b66ba782", + "0x00c1f10211d7604e59a327239f00dc6d036a93416b7871cb214e8eaa52571834", + "0x1b6636708f97485675c0e5b21eb749ee4a5fd0dd886e6690090856bcc5178ec0", + "0x71366e853968c1bbbbf8e3d6e13100dd589521f8db9e561dd20ff8709b5c1a96", + "0x0d2c35a01646cb09e2b56b5792ac03047848bef7415ae26f787cd54ef8f327da", + "0x1c5b71047f99db30453e502c9acdf422d3bf97b0d42b9223ea1b8b9924bb0cb1", + "0x9988eb36e4a669638e3242e5ada3e6596c5e4ef36a83ed2d3348d35fbed4d3d0", + "0x8f00020f98f02af0749df39fb2f534d356e3dbe809bdb3f435c4a575d661d6db", + "0xf70a509c0d1c60afcafc7cc492c5ad575fdcadf6ca8e0e5f184c62dd52021129", + "0x72cdb6544dd469ab42e270e51d136b314c27ed0d6682f914cf3e0398399d2d5d", + "0xd5584896e649b618ab8257859e42ef7798c37cc85103a8019cec10b1524519f3", + "0xd70636cf5cbe78ba86b8de902f83f9c550a8ee31a019da6fcb0b1ab0a02bd31f", + "0x79a506d61c89cb7b1aef845484956389d5f6077fd10f8d1ede1e92474eac15cf", + "0xa66c0575cfea08bc6abbba03b0d10be7bdcfe6c5da9058cb34c22af2c8f3f1d9", + "0xfde316523b6b41fedcf11d776a53bd27fe3058c3912059197cda083a14410689", + "0x6774beba5e02630a7e4379fed7175f0f3d9f8fb5333451f25d5b044521ed38ed", + "0xb513ee7cf03529c88633176792a6b08585ff6163fe174f68e285d6315ffe33aa", + "0x4482f3d82f65f0fdf71fdf669403e0b835b5458e567dbd295b4f51d22f01650c", + "0x1cf0c0859b1839ebfb872a570e0c17886d8d7f26067bcd16af7f9f0415001aa0", + "0x231be14cb1cec949a4e806a7b3aebdb074d58e5a1c48b85c35138d5d3e967e0b", + "0xe8f0a0ef68efb2ea1bfb5d47e3c9446900329ff89a3ab7eccde41e09ec3e79b9", + "0x16348cb5e49e61010da09a5ad3cef83ab369ee3d0f28079584c23749cfa30238", + "0x6d33bc7f502436bfd0d574c3f6b1155c69f8a80e55c42c353e9e68abb46d932e", + "0x0e5d40ed7351b59846ca3dd8cc9c0eb71d4659e0add0dbfb0bb7f518bf45c821", + "0xb1ba4509de4c0f1212b2b07d949740f15ef8df9af8e7e9d765e6b407a0c5d717", + "0xa99615bb15371a15b92c119f8632f1ad7c29d6eb9a69e0ccf33a9dd268cffd54", + "0xfc3601e7f85e4b8e996bddcf1b34cb6c20462e21c715782da12d8e08a01cd21b", + "0x872b0f4f3ef00cc5cc6fdd71091de96c02f5898826fda4f837832f302497b51a", + "0xb34656439e4474e075d8ef523f6f74ef292a22281e6dc0b8fabdfd2339389919", + "0x048d4dc500031aa56d89e799499a86d6dacddea795ddc4571669fa55d694345f", + "0x684b8762b97a9d650f0f0e5edee73b60a29f6e75573bd6244518b11c4a571533", + "0x5d20bbacb93f7b03d92ae0ce8296bfd113a808ab3a8bd7703838d7e8356b6714", + "0x25efac3c3bc3d4f10ed9918fd9581d68eaa18fb72d3ce7ca8e36525d8cdcae73", + "0x48b593a335aa2699a5bb5a60394845c7e4c78046e050aee1c7f8831249f75b26", + "0x6db7243073caa6e5c0442f2f3926885fae0385e0238a69784ea8a00c854ef8c0", + "0x3a104e4932193c644e2135008d78c5153a9331e6d9dde878357c250a3b42b5e7", + "0x74b3b4666fa9811702d4eebf9680053043160be3a6c31a0105c703e07d530710", + "0x179f67ff0710067d3180ec03d664fb3d9936e8777603b051ebad4cbd0aad7763", + "0x38d5fd43ca73f66127a0166ae074324471b1a92e6f4bf99fde235ac408b35562", + "0x1f43748a027e7731c2fe5343ba7b61d7c6c6933ea45466b439a43eee1a3ad398", + "0x6b130b75bc42dbbf76ad97287a3a130ea29122ce7e48c5a8bd1e80a5f3121364", + "0xcd17f77d87174ab6ad6f2dc60d37144aed40b3620a9e6c9ac3e328aeae3097de", + "0x3b7fe9ef499348315c1a2877bd7fa44b622fcabc588687a6de4d2f75aad3f642", + "0x6c73525865791a7ca8410363d634f6babfaba581d7a0252c7f57dc8c8cec583d", + "0xdb16b0220e129be4c929888a8a46d21d422a352ac7b0360711d786eacb56598e", + "0x44fb22efd89e585079bca47bde1073dc052f8ddbad2c27cd8e2839bd4350b18a", + "0x1e6f1395d417a94162117b9371abf3f781a4b05d787f6a38fb0101bc36e548da", + "0x3eddd0764196fe15d7ac7069c04c4bf23070e57931493e9a0127fc521187b698", + "0xec104582dffc06da3cc1af1c8dc7522d26ab2408dc0f62051da2ebae1ec1cbf3", + "0x3616cc0faf8a5f5c19cbeb482be2ea8de01b2a3e81f067366c715607cf29078c", + "0xd37ca9cd5dc7c3c4e2d2f1b3c8db2a016b52444f1c088680c8544b6cea30cfe3", + "0xc3d85c7899da428a305d941e3637e33eb4981f071ee07c1ee1c82aba7c248167", + "0x62975f10a20de37466b1822859f11774efa4f37fb701f6cc0695d206bbb51582", + "0xd940124857e67e220e3d4dc27eb75ff048aadd9b7fb29b680cc3743b3ab6365b", + "0xc89ac3aa4725191e56fbc87d41caac2c692dd5adae638bf741f0ded040ca66e4", + "0x97454878805915bcb60c9915af0fe0558987dabe5d506e03898dede96544dec1", + "0x6ce55ffc54eec31d980ece5204876a3f366f3148a4b8c10cd190153cfc96defd", + "0xa4e923671f4ff6dfde2f11cca452ed4208808e93e1131de4ce0804cbe2e0d3ad", + "0x772d1c2a0e70fe37ac0ea8d7b4a789f92997bd654809f20f0ff7ad76a6d975c3", + "0x8d5de87bc2484465a4876b462ebc1339bc13b8229e6df4f1a9e9b458f5e9adcd", + "0xdb33cbb2dad0eb38613d69392951c6062eb669035691882fdafc526133d15d21", + "0xb22b8c0887f71de2da3d81a5fec2213ccb8a32060211077e2ed1613cf7962e94", + "0xffbc5a82fe0c2b3f3f34343ba6823f35884c8b1dd80fbaa68fd5f33a960034ce", + "0x9640ded5be08a8a7a2e6291a91bdd58bd108205f4cef5209ddd338ad764fa9b9", + "0xaea7f934206d00a592502b8b85159e64b56def4c72db3a790ab46ca81c75d672", + "0xb99ace258fe4e6be541c6e3468913f4f32ef9e9d1375c889e17ceea0c606e729", + "0xc54ae75381803d00b52ea6fa620766662e6f7946d550208743fa64d3aaf22c54", + "0x4e773cd4fb2347b796595cc67eb2b5c7be6409bd8b1944f4cafecb6fc5a60a0b", + "0x263f3826196c238c24d4c792c3c45fc913d4cb94c2d3871827ba43faecbf4d94", + "0x7ae1714256e21b9b45778795cdedfad1160d571004f5ea6debc16406bc2161f6", + "0x0c271dc055d8fb1ba9bf133f3c85628ac3c2b588091768380a881a6183514b51", + "0xa5f41cb430b02fb1027d8e99cd94dd6666516c785d7f618a0894f38f811bdeed", + "0xbf6665cbf1037e0085808897d8b04932a6ced6755fa52555ac00737e8029c7b5", + "0xaaca2ffc61693a6f379e54af473802770b3971f6accef49e5a2e8fc122e0a490", + "0x7a3eb7782e2c02776aa29964689cb1b880201e1b81c8cef39738d7f7235fb022", + "0x7bf417dda75c46efba6a8344775915d2b69f954afd66d8f52576e106d7a7eee2", + "0x3a324507874480d0f4e8466ed6602c99fcaa7907b61e9f2b3f100740f7866fe0", + "0x3589941fb7bfda9bf50ad93cfed18cfdf199a6468074416aa513cf83cc00dd2a", + "0x66b0965611bba105667a3990de5acdbd398d8d6e2cd0276b83814c4647bfe461", + "0x703258ca6154ec4cb1b9162678e3bb546ca6f9e626702f5f62dda98fdc0fcf26", + "0x2a9a8e3537b714cb3e158f7ecc816239786ea3787b1a3bd40482f02eb0b21595", + "0x46104b558f57296b0775d63ee4da42a716c234f3dbd7479204f35b31f4b3d55c", + "0xe7d9d0a86cc8b76526acb8e260de17508874d1db6ad19a4a84210a010212d43b", + "0x04af6e8bd51cf4c4307b2381b2e0c54cd991ca3c7f49b8cdcaff3aead70efe48", + "0xab8fe05db68e486bf2be0c507b834b6e496c1d1fe560cd3210ed7fbf0e9b867a", + "0x0e6b5f226d0bcfbd1f0a2f61189592d8974b16376fef3d0a67f757b796ad6854", + "0xaab68c29b061f8f72d9f3c6f2e318a7125a01010fb0c547835fa31e72d8eeabe", + "0x0446f90437150e4ec6246be5c718e5054d62cbf5878479457d522948c6e87f83", + "0xd1b4669e21c0b175589c0942d4423cd2b438de6665f0bca10818eb6246a07749", + "0xc20d1a68c015d886ef8fc3dede0d116199480164238617667280f833a4dcbb3c", + "0xe67504ba38aee984e9118960827ddce0eaae3d8797bfc87afd4638cb1867e41c", + "0xd3e985af3bf3e3ad0dbcdbed9ff1b04037bd1ff2e71886db3842a29f0ee8c4b6", + "0x8b809d1ae7a835f318f471ce227f7e7ff563a15d1e2463e8fce5852c9a3f9ce4", + "0xc232b56170a5796aa4333d29ad8ba43dab2233e0cf7b48d100aeaa4b2491d6da", + "0x9c338ecb25290e91a83978df4f5b7076b299ba5d87074c36ec96da0b3aa9351d", + "0x616a6134eee1221e531fc6d6b5861f5ced64e9b56505b169da67ca3c47cb54ad", + "0x4afd1e60cbeb40301c2ccc7129042f9a944f4a383a4f34b8acd7aa454fcd0e7e", + "0xd52d1be650ed156ba12b0d6be4b7fda1fe89927bd7626ec0ae45663848144e7d", + "0xa212644d968f7d3d89c6f12c3c3077184943d986dd9cd391d48f8f98eb1bc6a2", + "0x8e3374acfb9d1724fd7f84c22fda25f91737efde3d667f607b364e51beabecee", + "0xd77eb30cd87046093b27be1a09d93cfa5261b780b99116a79d6c16be7db838ec", + "0x05093b9e39e2d9f4fa95ff386cb2af67861359ea6228242be6b323c1eed5c7c3", + "0x8bb25606225d3451a981af24506a549e2bf62a362149e4c77ac72eef6316e691", + "0xd2749fc4a37792b3716634e3dfb8a80ba3e30fd73bc119069d507bfe7efd8a1a", + "0x3b58bef2d77a04b3281e6cf80f984b9067290bfe02a596b2295ccad38e887a33", + "0x2f69797f1800e5da4a4086909058ec857695a220644e61788b24ccfaf7e77137", + "0xd81872c67fbbd1a69d4805cce578b9f36bfd768d3fcbc2fd610182a7696e23b2", + "0x2d3bc9fd303c12ed1ca7efe27d85c7b5ffb8e079e59c86977a113bbbf863549a", + "0xbaef802512a7ea5006cf816c51c35fdae44a86daaeb6e9dd8fd0c37b4f744875", + "0x2e7fb70924e6f0b74541f2f4cb13f49bb3bd577f5bfe1bc29d805b0e7e1a3df1", + "0xe3918602d83478eb416dcf80103b09a051d5cffc71b0cb21461c5031d38befb7", + "0x87dae7dbb38501d6e84f738c11615dd9eda5f7b77e096a765caebea6a8c691c2", + "0xa19f74ad3f4e218fcfb15e4af95713cfff4f5f58169b789167e2b62617023697", + "0x744930fd0046b3f7de0ecf721e3b36e4b36c0f49eb98bb0c9ed33d40e76a2017", + "0x5bc7194687200989382831785b43f7f5efb23105ee2dd7a620a61622a2afec44", + "0x3672af2176d897cb8f64f2decfd924d74581bd85916be85e53f2542a54a24b94", + "0xe2e2dd1875e9265072d96bda4640ec6beefdfa9a91241ae078cec4c2a1c9b8b3", + "0x5866de65d88610e6123b7a57e28e196afac484045261d1a16b83fa232ba267bf", + "0x7224db0ae652be5fe9017454dd40c744c75e513841b5cd11d5fcaff598265c7d", + "0x04438fdfb56d125bb13f6b8bdaced6946299f8a32610205fabf4a8db9c06af60", + "0x9e9af6a569b87a4717b94d8253a0078409bbce7bc08874e091163b621a75b999", + "0xc8a39c68a74f23d615ad49d9d175086bf4e1047a750165bb071e3cdb70e1d639", + "0x10515734fb6d38cbb9a7ef33ec7831646636f845ac40cb24b08c432422763466", + "0x1604dce1fd615791c66246a7cd82edbfe860a5ac48d000cac1984faebc00cafe", + "0x56311f68cc563946e251d8c0ea74adeee6ed8dd7aba8f6ea85367defd5dbdc41", + "0x3fc81adf318fa6db1c4e7ff5424b235943667f2f3dce5119618e0273eb23c93b", + "0x38576704f6ca62083130dca418a9b68e374944d63521fc3f4b7039754d62f63f", + "0x56e2a402baabf470d0f9c3496d75e2c26c26ac159b996c370b118a313a9e9464", + "0x501af705914bfccf4ad29c38eee21641590cd8d334dce9055d90bff57b8fa556", + "0xa734b7f045d2a23ce602b032357a66763714c6e4785768f07d55c22d2f1de372", + "0xc80e2c739a3d142a4018bfe2074da8da33c471b93f5e7b44bb150b9eb63e956b", + "0x7a0b1355d05b1bf4c634651bbb2b6d65cb0a9772c30e4024f5e781e5d404376c", + "0x73827f7c7a15db5c17a986f31dd92de05579b0bb8def065e5f1cee472d00281d", + "0xcd64ee4b2a912d48e6beb06e7d6c9c236b5815434c0ee21cca0a13ff23dfb85f", + "0x768d2fa63c53689ed899f47c6f78844ace885fa18a36da427428f4af46a9e1d9", + "0x643c26723d5a4831d3d07f8692a6dc4456bb6190ce2abf1abf69159942d5d548", + "0x03e20a75c4546d5f54bbd7fd3e54c795c180b880563bf78ec55530a89188a9a6", + "0xa0ea4095dd9fc6f817c656913f8cde4044e2806488be48770de5574c0b5d5f8a", + "0xeead5fac8f3c83c5a10df161d95bcf1d27184c9fb9fbd813ec5f61347c11280e", + "0x5afba4426fcae0f1769e581fa6af97b5ef8fd417771f10405e1c9d09a74357d6", + "0x087f65be7fc2a14f216d7ce418a03fcf1e6169e8620db65c11d1ed6c0afed240", + "0xf9a7e93c40788db39b241e03afe329b6336187fbafa40c97ac405fefc1eccfc1", + "0xb02450b58c5afdd0907ee745263aa6beef662646b96b9ed28b0dbcea4f358667", + "0x5029f1169c92671ecaad7239f40fd93adf3ec07ce2ed0c4cac38b0cc8034def7", + "0xc8465a93a1ba7ec3296d98e0b01ad27bdbf16a347c5517b450905d3c3668d505", + "0xb85cd82c551bcb30a747b2258327dccb04094f918e36c3f120f55fc35abf59d9", + "0x1721b2fb8963696cdf32385fe87e8ec2c2d7fa34e099bb65498e4a030e20a1c3", + "0x6b6dab262c1a32a67353409d2f8b791b1799ee6a8e3c880877af0bc5cc5b812a", + "0xa634110e4766d3451718061efb890238796370da3c4a53a91faa96c8944d2423", + "0x91ec6c6f807285599e0a179d0d246caf10152e733acf3bb967bae35fb36561ec", + "0xc3b2012d5cc8d796d1890d39e2b1730dd53df0b98274bbfef8c93bd969912852", + "0xd036b9b29589cc551bf27ab95b6366d772e7d692d8fba48f473a2fc2d023dbe2", + "0xc51229a0306e56a53bdab1fda497281e23aba6ab17301c2eef3ce3d01f56989a", + "0x2652cb79e0c18dfdf545562b8569cc2775a1b0b1b465cbdc5880b40ffff22676", + "0xf24e0d6c03961043cb41638596c4ca02e2a2522a3e828dc4613a72ce5a535a67", + "0x01725e03a7cbfe2d6c5623829e4d419bbeecd1c7f925dbf1667979bb4da6650a", + "0x3b0c9824b726b2b556c6c46af48b84f856154490a51d775ba06aad48055bcbd7", + "0x2be2f1cb826d7575e53bc5e14f1882d73bfe145ed91b2ff56a885f66e136db46", + "0xd16752cc862f33b14f5976049dadc4f15f147f2fa76c50bafb38a7cb25c8f881", + "0x66b3ba188143bd421009c082031696bfd6d29fe7b9c3345e7e70bf6a470a05ec", + "0x83e017e8701b533c9fd22e30d63c3781b0ac9ec1dff4433fe7fb5c8f6f4e67ba", + "0xe4782b025953c5980653abd26eb95de1bee0524c14a74b970ec5615f98ed6768", + "0xeda29e9b36262e7c79ef9c0b60fddc66bae542b19caeddcdedf439573f773cf9", + "0xbc02ac1f023993253394ca965f4394bb40f9c7822ed6b2cbdd249e4b72f9b637", + "0x8e1bde0f2541d20b7f7e8179014e0f6b98eee5c1e0278ff1de38f4c13fdb4161", + "0x7b762d3d64aded9ff99e3423d7e676dd307b765ca6f1295e079ac53d5a4788b1", + "0x1027bb44ade6a1f82f11e9f298fd3957a9636bfbb97457c319e3d57ce72146b3", + "0x963864b3164578d4a7e58de16593273067a641de752b6df2c9b8bfaf970392f1", + "0x16bdf92929fe3629a57f737d83328d034c36bbdcd006301f28dcf52e1d1cb542", + "0x69952e47225f1aa86d952afb0fa8c668ae710a10cb6a94477d518c8f771f5c30", + "0xe68895f4ae2e4a35fb7e0730a5ef9c3e3030f6351ff6381f77e6311912ced98b", + "0xf28d799eeec538dcb2f371cfc6aa16f4a6808ddef0e6fd0cf72fde291d94f8ad", + "0x5a404922a9bfe57eb85deb66d8d83c869ddf96eae17e7fdfafef19c19efa1eec", + "0x96b735672e85aa95c2f8b4bd5ac80942923cff64a24991b3103e4ee39fb9a8d1", + "0x83d922f50174810fc45daa5a607a9b4fce69d8ab86f428ac57ffdcd9c2ff2908", + "0x3b0ce5a62116eafbf445afff0674112f01e1dca0e2af2b72d0cbbdc452177d65", + "0xe86cc93417c7dbcd4b5f051f4dca1394d272dcc2101a9e94a140b20f5e4c8b59", + "0x99b3e1d593b682e1b6454675593ed6828f8f4c5888b965981e3a7c602d89d031", + "0x81e0eafc2a2adf3d94938c413cd9f588e7525b91f39a689dfc3d0ce6aeb812a0", + "0x699e692ff89a918eee6d19a63caeb07832dabf1eb28d04ec97150c87045d9129", + "0x90ff00b66a14d821b05f692ee6d100dd61abef3234fd29e94bc84574439ed2e0", + "0x2de5779a122ccd84a88c3adc4edf7c1c03dd1d3e89ab45657885aadaa087e833", + "0x775a5587a907aa5ff13bafed032dd96c312b19dcda1b0e74e8a4bd327fe90e50", + "0x4fa48215f975442e6b9ea0629d308667242a7fe89f0cd0eae55ef1d35a3d6ab6", + "0x2e24c24731902f1b9e4042eae9e946b9d884dfa9f733ea5d4f7e778b68daed9b", + "0xf23a4a6061f45b1ff2095adf02ded238b37a0ffa9653fa9c1b0069e37e8552be", + "0x62b94eeb74bca8d9ea91aaeec5c13a05dae022806df28b92ecee99b47de999c7", + "0xbe6c1797cad2d5d9ddac3b3adcbf1622241e2560e3407139e24dde3fd8d3e435", + "0x7df0788058bea0911f2e30133c835515bd777f7aa9cab6bcd27eb3c0a6e360ea", + "0xd87066a4721ce567f44abf179184381d81c1c487158a6c57b5f2455472209a5e", + "0x0aec7d3081c3ee7d61f36e8c7e62ab74e41f00b664b690a341b9ff7feb5adce6", + "0x16345b31779e80499dc01f9ccaa0e9981b2b336500f33cb1f2943b66ccbf74d9", + "0x9ed6c6685dfa2b65903db0b234f4539906121330c5d55e6b2a2fd30549b2dc23", + "0x6539602958d9166335a7a0396ad72be611661bdd40c786cf9b0f382039c6b46a", + "0x72bbb4a201de75b9a4b5cf7381308953234c62f295df08b919c12535febf6fea", + "0x2d37293863f6b90f43979ba5944bec302008957e07b7c7f2292074a0a3934674", + "0x22677859ad20cf8b924d516b9f979652ac91a27459a4eba5455beac7f5f23128", + "0x704c898c04ead58c2fdb2c753359d10934e66b326f104be28ca7a32ef05a2bc1", + "0xca2b1ac29937067b761b57b58ae4069eecc799dbe089342bea274e56fde3d1bf", + "0x4a9773e6a2e75dcf1ff46c8f9931b8170a3609023f47c0ea9c4af000798bbc22", + "0x7e4dcb6c256eca2cbe9d168cc78c2702c373fd6e69c210d0713e2766baba148a", + "0x399ea7dbb66b95bae693402eec304f9cb6f4c6ab729d90ca569fcc2bb24d6442", + "0x49d0e561773458f834c96e8fb9496d4cdf83f2cfab75824cb1eabf8e8962c18d", + "0x80a0a209e41d0c3ff07ffe6a7f1af67997662494a327fa7f3bcb7209340974ed", + "0x2bdd6d6e7ae3f4386fc655817e92563e80f46e1b277be22f81a689de7637ea1f", + "0xb77f32374161e54c50dbc38822760874d966f9e098a2ea7aedf650adf25cc0ad", + "0xb49b1decd65a998a3dae2e4725eaff56276af3f0c50b2a3a35b6e94738d32808", + "0x319f78ae885011458f47ff1a110881cb4ac6a78c7d4d7a2656ddca73a88b58e2", + "0xd9fa2f47bedc0b405df34c98582b553dde76a46d38ac86d9d357ea0aca60ec2b", + "0x4283ac57e82bd08970ada71f4617728bcc467eeebb19c3aa20208a82b18fb508", + "0xf2ea3a5ac3bc77ff64f7c686305044cfe539856fb2833cbefcb283317012062c", + "0x840a9b8c756c3c3de7170c3597bbd085747b97419c01bbe484fc4cc7924736ce", + "0xa88682b957deb995307ed875c4044246d779e3f8c584cad75162fee119613806", + "0x7b9195c23833f65832a44d097290d8573b43e6f3e47dcb8c3826ef9a52fb4ff7", + "0x57bb0076c87f2e7187ea92f9f7643eb5b4b823b8eae9f6e74c8b676dd86b81a2", + "0x68593a8268b245a5c7506a05860755cce1be795994a7d736aba41ead4c025a68", + "0x90e21d5927d39329874688312eeb5296677ecccbbb9c6bdd4400c50c9bda09c4", + "0x773c0cde2d1f44575c89106a01881eb5d9593bc762a40be03ba979496ad7d229", + "0xc1dd843534e9844bcf406cc03b277e71d4e73026635412e25f3555d099f26a55", + "0xdf3f794bbd98096cbfa17e168c0de845383abf52fea618937ed81d31cfdd88db", + "0x1b05b1f316013609fbf813cae674f193a9bd8a75631b55278bbd37513b85641b", + "0x429321ddb251fadec6b6f794acdd8cc9d93512b98af23d20749d93c3c9fdbc36", + "0x6cac90b28ed13c907d094bad45574aabe2355e13e6a9504b6001e5fbb9c25235", + "0x89b43a3f63a2ce4f67071a121f447d7e843948395616116ddeb57a8714becd3e", + "0x6de560c95a0483d51410f66f38884947dfc787e1c61d14421129773010b46e0d", + "0xa0ba45049971dd4b906e73f917fd16312646d53c0cdfdc3eefe53628a58973e8", + "0x3d4a4f7155eac18fb5a126dcae2035155a140a84718f33bb20d2f1461e8cedb7", + "0x1cc19669bd91087d2046770cdc34e8f995cbdf2a0cc62bda70d6074ed58acefb", + "0x7c1c4aa1817de27c62f35d66927d924376798c954d65ba3ba02c0528d11d748d", + "0xf0d67a8f3c5306165cffd44476249c254898bcb26c937f10e8ae244edab1b972", + "0xcc20c5ecb1d3e83bd56e9213761f8320bd40982ab5fb669bed774b4490637932", + "0x7935073eb3e5c37ed1135cb22bfeb0e21727d170d106465fc35de75e8d56cf41", + "0x7d968e74212c501d0bc26ebb816b57a37a8cd2720caddb5bf66f489e13a61bc7", + "0x2c134dcc35d50c63a13bd8868137e0240280f049d7e392b97ff5f76d00aa1296", + "0xfd046f06c1d46d9125a119f786acdd76a85fc596f21cb15f367933b717ba7d83", + "0x9f5f067e4af3c8e92d2d54dd061620f0a13a66006b162a1eab4b1707499597df", + "0x8a6e1fb6205a423ec2920d448a376b95cac7233d5312287bd850471fb49e4f8b", + "0x2a6ea987659383f9885d24c935fe56de39d45caa89e60ba1768189318974ed7e", + "0xc2df6c8a4eae77eeaf11d7e5e2198ec4a33f19f5995caab4db6577fc1ce7b957", + "0x1e2ae8a42eb937749284820e50f11dfbfb606ddac3efb201e0b2664dd0196d63", + "0x4d63bb91f9f8a9965c460326f0604a27ecb0fc56f2126c6b3519b08a895747b7", + "0x9a46c2ec5dcef6f5c5b76d4b08b9d5085709182243cb8308a2863cca8cba13dd", + "0xea57019cc85f7cece4cea7eadda96dc9e464df2689957ebfe8d817b6996b2e43", + "0xb40e930b31dc1508480ffba351b102c8cab53c6603a0dd88bfed1b0da5347153", + "0xf51ceb070d8e7cb998cf4979ac985b4850949b4456980f523d8b9d72604a43da", + "0xddd28627f5c7bd213149bc4886bf4bcb8304f86068694fc743ac81ed749aec3c", + "0x9ef2b3df587caf086f4a9838a829491d1ef45db132ea71c6bc96a4a40d833e92", + "0xc9f7d4e19501c48dda5b0012cd93564898ad080a653e29f3563ecd40d36de84b", + "0x0565db36e6fb7b881eae309fef6fcdcace7c92a7ff148476b627c012aaefe4b9", + "0x08912abab10f16b92ddaa3663375f6e2b656e4ed89f2285aab6e410fc59e650a", + "0xefe9e68ca3bea929722bcccb5150884eb23c32153b14644b1c7f4e033dc3f718", + "0x4b33e0e078056d9efd857f909d1e409516f23da68105463167e23d71c90f6366", + "0x63cd4d1c69c4168798a3d9f15388207ea10ee4dc6be3681b0c7dbce5649d8f90", + "0xc8e7c25854d49022e9a0ae2eda8e7835a6db9ef7d612312e9deae23621ba240f", + "0x22c05e50f27e8bdaf4abb0a045d0639bd7f80057dfea638df6a7184ac49b738b", + "0x4a34356b5a447591ac66c51370fb6539bdf50fda9600082dadd91d33713a74e1", + "0x7147d53533ae40e886f6bc1c3b65c51570d72398f46e3266f2eba7b707b46b3b", + "0x1e49f75a30695e9bef14b036bd1c0f2b322042b2a02ca56604484e913b284c1b", + "0xf2445d48e823bfa77776234356ae0d3c1a850db236b3d2a95e5b00c4d7e687af", + "0x7034246c6342c26f5ae974576358f993d0e5e3c577e6aecdcc182c78082ab181", + "0x965067896ebcb2628ff10127508df1c811087f45ae258a0d8179d576c21e4891", + "0x384ebc34021ebdaf95e1bf0d8d61777b96a1ae65163cd3bd9b4311970a7918b7", + "0x1ca6e203cf1e058f20f5a8b1e33464801bcbbe04c79a7201ad6036bb8aa54101", + "0xf5aaa21a85fa9d502ef278262acf71789a3755d36dd8b3794becab7fb2d338e7", + "0xdeb7dec7ec133b6ac05c3bc0fea3b0002c8ffe58b135f4ae85b71fe0350dc7ce", + "0xd5773586ddb40d4c772541f743f7a4b08e9b419fe5b5b3536afa0b3b888725bc", + "0xeaff5bc016770c7cce7be21952cd8759a8d0eeb1bd849732c15dbbb82c613a74", + "0xb1a6a6acd39b4428accf9120a46d74cca6451ea4a182206425a8a64c6d6be5b2", + "0xfff27e5023fa1fc365db1e79cf3283bee2f51333059bfff47df39f12875e5fc0", + "0xadf1ce203b0acd4cdaf1d9a91cc158a21c823dcfb0740f089ce0830102b1cdef", + "0xcf20c92fcfa22d6fe7a60d1aab2d5a942db39d447d4ba1e9e76888a64694f1e7", + "0x210a684182ea379b50d641aed1baae3bf3752fd84feac4b3dd4e110c5cfc4ce7", + "0x220c5460803cc8db7a2b645dd5a4525b0703182cce173324d20e1c865a157811", + "0xba87b487bfae148239b44f3ad7663fd66cde8e21aac9e1a50bbca7bb7334aeff", + "0x2728161f9f040b4d92ba838d841404604d4d838157fc66f20d6c4c61034fdbda", + "0x3f8a6c7198528e5084b3e8d52d3101c27c5bed8721beb831ff921eaaca4c4282", + "0x2cc2574320b3c7252404db7c67b462fbc8d87bdbeb782ab1bbd257ee634a35c2", + "0x13aae0ecdc6a70d85412178ec12e971b2c4476d5e624938ca0284ccfa611d11f", + "0x6af7161831c3442db94cbe28ee9385fe79339d533b9c0fd3266213c2a5024a14", + "0x06185136927e5bc26ecfbf2299a0fc13cb447df6ca4a60e968be8c2b7ba1c2e3", + "0x70ccc84931d910a2489d50becf82383a836309bb90dddb21026d9e4e4368c85a", + "0x400ae9e4da0f847dcd4bb65e8f9f661a3b0deb78346b4f1f84fc712fd34410f0", + "0x57aacedf503300888fcd8db2138badbfcd663c63c3cf5b3e35979dad635c24d9", + "0x8fea6cc2da76b7cc7062af870cfacf4952b81f09c3c15d31145fbbfe1c0806c1", + "0x5125434cc5d4137ee31b51ed8306b4d665b8dc66504661b46c227e62a9ef1abf", + "0x254bc0b61211e0a57755d73ac618012938472912f855972b7ce62677f5d0e64d", + "0x2d231389c849ea459a7530ac1bdffa4d84908e2c61125a70bfcda932cc8e5efd", + "0x671ae73d4739bcd4841fdff266803117c5684c61031fff16e831a3bffb4bae4e", + "0x64c4db66cae82a96f29296b481619d79a739e2dfce0ac1f659d45f526ae58ee5", + "0x3f2f08ce2f21253f8c9a3fd650a885ca0e77f720a21ad5b4c0867150a0274efe", + "0x98c48268710592ee4c26620375968f2b8730a1bd1777239e6ffb9f116c6e1284", + "0xdc7a5c095c255e1984b4a5fa75c7a1d95d98097fc4eba898e644ff66951d8dcb", + "0xeee7579812ef09ae31068e8087536362a967b2893b709a458822449ea89a48fa", + "0x296e707796c0b9f9a2f55ad06c42d03625dab94af71c2e1c7016a7ef6645bf5a", + "0xd9a3eb363d4a36300dc4d1903a83447c89ec286f8d219f1156335da283992d60", + "0x039adf5a0cfbc394847d8014d64700ac4b6e78b531a1e0328bab256f7c407116", + "0xf9a92c6b1f0b0b3d7ae33cf5ddfddad516bfd7b21842d76098737533efd4f7a8", + "0x5a5d1fa3b8e05a81173e627f14e689c166776b93df401593db8035a65fba58f5", + "0x34f7fda3053b9d06e217223ee06fd194e2962c4a381482429e596df1fe319686", + "0xb4cfd9a71a98ad52c7705d55e96f04cb9064b1c32d3c346be51370b56ebb0f8e", + "0xd46a93765af68d238b776b240afd464a24d8c8bc869280ad618fd0fb6360e878", + "0xf3c622a4ee05d1ce27d59e7b9b3748547f4efdb1d6ff72a58fa93dccb7b76de1", + "0x6cb017c4bd8bb5186590cc4559fd9600399485ca917b10556b98cd7fb61441dd", + "0x7188f59c892b8754845d73f534587f27b7da67f42dcc1c73390fe2970bf0ad28", + "0xb4b17c93af08b9f587963e42703379c5e4f760502870b8096917b09b3950ee35", + "0x03165bf9bc20c87412a41209901d2bf3c8bc03a8586a1706fe1499641cbc4775", + "0x9ef57b2126a38c2dc456c13c272de53366dd1bf1fe768185a93f3562d064fa8d", + "0xbc3660089065220589409f7063dde34aa080179b3f22464fd9df9eed98d88b0f", + "0xbf1cf6eed0e0270d6be602040a97600ca7e1279db4279a9fb7ee643345a264b3", + "0x4cc471987bfae3b32179aac7018ba574c0315b9832915b5d0b804b38e9def6c8", + "0x51351557582b1d821adfdad36536b59b28f9a1f1243115486ce44d4b22d3952e", + "0x66d6b02183b9def37dce37b66ba4e9939241732b49dbc8addd147a89dd9e0517", + "0x47261859ce169e56d4e7dd75c5e2648597c7906f9264710c7e4dff74f353f739", + "0x38edbf1db358c82d0c945a7fc024f7fdc1165331cc19caf6b8943d3ce76b721a", + "0x5231560201678a39175187469f7e36c1c729ae060225012ff4f679f3fabb8237", + "0x763bfbeeab624de07a6e758368f8f61c0fcfc8cda088d2dfcbeb47a5eea9648a", + "0xce910446cce07477d424f791a71a375830ac26a2543b8bd1343e0d775d161e5f", + "0x950ba34133aea3c2947a5e5fc1836375e81c042ee999b60dd4a27e6492fb41fe", + "0xdc24f20fda563bf74ff7540a06f3631af8ab3b3722874a6b383714f463f5fb43", + "0xf2250ef512d3a11144370747f2c86efc73abaa81152bc6083f87aa217d16ee67", + "0x8760d0bc8f28eb2504f3bde3e429a47f0aed1dc2c7abbaf01c68033c07ad368e", + "0x7ef1c11b1f025f7e2aca2624aa9a11781cd860f24ce3fb525e7196e590fc5ff0", + "0x7c4e717fe77c8f9e742e312081d51418614031745b182746c7ceb4ff54deab6e", + "0x56c82f80b8d52128275529fffb3ccf7376f411d7cf9464a15fdecf617b4e7571", + "0x46f7d3ecd09c29d36a62a1a65bd3c59a14c82687b5466c9c130df14c286c2a95", + "0x1d04deaadcfdc7a1e5e612df6eb836f55caafb4f9bf4f1200fdfef4f14229f26", + "0xa0f5e65e99a22e14ebafc71f093dadc96c68883609a7460f904eb15360e3dd6d", + "0x8ea6c444466d4b6916a1b6dadafb87d75e2fa1ddd1836425dbaaad6e99f4d68a", + "0xd53d052bb709813e6dfe218dc4bd99c5ae83b6f5993b182c36a386502713c7b6", + "0x2e0cc1dfae87825d1a1d8946e021dc514dea384241e0a6cb66d5daee570c72fc", + "0xa419612e2bca19a3a8dc7fac4da86c2df4edcc2989e10d3e9050323011676b1d", + "0xe41649d9af504bd273b9da0fde578dc126afb55feb8b3c31a0d4eeaa9c7b83f9", + "0x0121be707b5666d5a78949b2ee263bbfbd013b69caa9566864711bda4c7ed0f5", + "0x788538d654618bcef0a63e31576e19a0872a92733ef7930ef50f8afd6caf110e", + "0x7777a3a4930828cc158f696e6ddcb87696115f473f219ac5582d8a38e0645430", + "0xe15a9f42ce5964358f862fa7a40bff0c8e8d7429a5ca923c9f0d4d0d574378a5", + "0x187bd59945e1cc6a877fb324b1d7ebdf661383ae7e22c56913f2e920de73dd68", + "0x938f100308d20611bd14372b16da0dcbc888868f8bd183d667064dfa8e67a161", + "0x5e61540787c83bfacbb58967280163f55f5ed00e733d6295099588557ef2dcec", + "0xe6625082f4039ef9dccdbeb9488baedf75fcec616ed9d5009deb4eba95cc680f", + "0xd01542aefe234567f106a4f057173b4f6eb5733e0ab9537af2db309edf38763c", + "0xee0174f3f9218a3418b8dd2bcd4132821eb91b31391b7c2c6e5a84d067d21497", + "0xbe26c679aafdea135aa493bab8ee348b255f50bc69592bbe017dd96b0da58b1c", + "0x297e6634c06193ed4725942cec32ccc9b4e77b5d02fce2ec9fbf580e3dfce248", + "0x820d98bcfbc008480ea32b162d15701357f094b1d7c99a1ff92fc0afd9708a06", + "0x82bce2be0a2d468b2fe0d3ba4ec1e5e8eac2d83f8b2e402b3043119a59cafd51", + "0x63ff3569d9a5661b6773a1a5fc10a522ea12a22399cd337ffef75a0d36735ab1", + "0x8431746d8239126bedde7d5c58aaf7f733dd1542c942d415d876ebf8a062f032", + "0x6bfdf119b93ef4da6f48265f4c526f0837a10c8db9c518d0dfe1edf40ae5fcdc", + "0x55aaba1f40c9089c65623f67eef8cdb827282a39cd0778f26e2f73106d3eee3e", + "0x0022a0b29d8188251bf5c6f37c76368dc9c7ed9e00376901162d1fff111273b6", + "0xf4bda8d3cb5b7ad50dfcf2668253e44b98e87d563ce17720dd1eb1a4e1c32628", + "0x994315a889329452a3e08ef029e7d902308022b74aa5a4eb2178929425c90a84", + "0x86a962d1d436f43f6fcad5b61b615f2bd32f10fe8c62428854ce98f4289707b6", + "0x3ce476498f26fd1d0b276ea639d438d7efd3c10451949efee1c91f279ef15ed9", + "0x199b2fef89c1edbe547e8c0b666b7b138d6f94fcfb2f09f26edc429ac163b127", + "0xdf3fd62e7dd0133ffa23a0da13d720373b57e85c28ee97890c355c44323ad592", + "0x92e0cc3bc262330ed8a1f42ad40a2db6c4e75e2d39e24a6ed5eac0855c12dd05", + "0x5b46f058c21b9447f8faaf78b2549f7f1459fa5ddb4211150bc26dd718f8361d", + "0x316b4f0e5b50cea376307236de36f3a1ebad3c59ae28dcf7838339d8711047e6", + "0x2b72ece0cbeaf94140b99cd9312eb891a1264a4d31fd839017e22cd4cdef058a", + "0x0c86b9b2da38f00150d49ac53ccb43a88a44181c90b492e886c54b0d6a93de22", + "0xba5a671174dfd7f877bffd7fb3179b1f3f8444ab14eaa9a0488207141bda26e8", + "0xecf73cee14b1a8fa5c2de5d78c058bd04772666ff455ca4225ac419606041f2c", + "0x1947b6adf9abeeeb55a66cad4afd016f6522faa641c4e14af94cf6e610959ad0", + "0x5467aaeb96dbe111a0d36fa66a71f489fb33ab8d95692695c09f4680086daff2", + "0xa21fd9195eaf856bd048bdb258507351e9a2c168920fd0c550a2340b5176ba26", + "0x9b0cf5690d3c3764f5c102fe1d5139202a1f982bd5afc8967eddaa6bcfb3af42", + "0x32bb410896733f9f6080a5b574b07c0af3e5ecaf69e995751e392c3905c11d20", + "0x5e98b3dbf58bf5adc0ccc9269aa10f9921afd44283837e7cb419ac4fb89f6164", + "0x051cd6e01ef3ebac9f27e1d473b0abc00d870a78cf894cfa8222d00976948b39", + "0x500edc8298fb83a103f5bf779d1df507644e054ef27ae61ccf31d883d85c2a0c", + "0x80c8fd7e50aaa14da3af3ec622adcf89eea9760ddbd5232a49ba55837be5805a", + "0xbb828dd031299bfd428c22110ff5d9f5612447e346e98401ab4a01278834e476", + "0xe2c5f408029af25cb9c130fc8fb5118660d08da399dbec0fa1709d1c0583de57", + "0x1be80d06b4ec5ef612e16bd8d842484039ca5663234174441f0722ca521958ee", + "0x21d755042a542493e44e92b4355af2f06f161c0e2583aaf6862730be7e9976b2", + "0x49b993b77606eb939ae485e82243e530e392af6d68be4ece5ace66a675a7a70e", + "0x954823b80bea8f2007503ebda5a6ae4610f94cc2c9a6ca22088a52468a960524", + "0x2693662c6c0961a92566deaa4a59204a0c436aadc0581b799e6255fe97d26331", + "0x4e80abe082c0b8ae0602c232ab0f766aefa702e744ff142cb9e101a6050acfbd", + "0x9c47c762c73836210a6bd78e5ddf9f2e817951d52b9fea0c823596c3df2a1fc0", + "0xe86094c8da0212cb0cd96f54c9f1b22c11feadc5599f6aa63285971651f11278", + "0x3031451f37f3e0288d61580e5b20e008a2ef5975e5d12345056949dca2c1d421", + "0xbdf90347d794ab3b41da6fb75b5d8d1f426ca2c4923216393e055dcbc89f3cba", + "0x4f7a0c9ebaa4833e7fd0ae0f3ac8dbecf3d97d0036a41ef30230e634142247e0", + "0xd1cdfbbf34bfcabe4a0eb90fb4d8592738203d245d68b753d418c4bfab8ae4e4", + "0xaa56db3fe5b2edc2ed277656deb51e15f86182de49836b4dfe2636de5488a86f", + "0xf67b05c233797d61eaff641e5bd35ee830bc1a8440e06f85e034902bd1023ede", + "0x49bb9be0064ff46c4b7820e7dd08002f3914fbf9250c96873bb3dcc7bddbe3de", + "0x594efbc23c0a371e3e5478c599466ff3a8d985444583b70f275afda13cc05c9b", + "0xd1dc59771492ee0881398f87a7c90db42874d720812c1e105b1512531d9fb1f3", + "0x7462bfbf8457d1df1288cbaf339861dc91c02d772f3c1ff8c215965e555d6905", + "0xee62a752465879dd62d08d7a15a54af1e813a1bbf2035384289bd634e2e99524", + "0xc7c66334011807d017e0df794df5f2f36c4cf496ce0a3589465662f8aa5433c7", + "0x839af48e65e3e1fd3d177d90f1dafcbb0209b107bf882cfe2fd514be625c1396", + "0xfb4eeb8514ede5bc952beee0e7e78c6d7ae544e6c4d935a6c92375b224e40c3d", + "0x38576e990356b7c44eb1dd531fe28420d01d80130e0ef0a42b9a8b01d2687822", + "0x434bb4312789b8cd93c5f930f4305760f86c54ab225b35bec70954aaf2fb4c2d", + "0x19ae08dadbf2f7da90ce777913d59e74592cacf6f385600f7d50cbbf7c4137a9", + "0xfc9a8ba8d7eff3a582725f8fd1539c4f77a87ecf23505de8a321ec6d568cab5f", + "0x20fb269b1a7908ccae92532424cc94604ca9a0908bd7c5e446a687cb3be9e0d1", + "0x9fe0a0e3511056762698573eee8ee2b0b87a8b6daad2141a9ad00c5b159521f4", + "0x3630751af37fd3ae22e78198868341e86735b03432879fb159628937c6bc28da", + "0x427789cffa2250d89b99d50969d8dd9917b5f4c721ed9de79cf81dc59f94d81f", + "0x5ad7e16bd42e35671230458f8f97c18baa5a1f81b675df259c9d2d7cbb09fb77", + "0x3d58c8ee704a934f6de776ef8373c653140e089b85aedd53219dc0b46ff03b58", + "0xa5a0719b16d8771b34e050660ba965b0ebfaa06bad1973033cbe2fd69fac5886", + "0xcd66e1ce23416fb4662d2b29dd72d9f8f981c66098820058451441213f2947aa", + "0xc7eb6f1df45136c9adeacb03eada4557326aa0a22f9ac0d73df25e21beb6bc0e", + "0x890eb4c610c7036e1494514e1f7ff72f414c51143fbf13cf2cd03d8d37a03662", + "0xa54328a1d2ffd9aa3f38a9e6a0539ad2517c4f6129f01768891acc0a2b2a721f", + "0x147644decd98b450b284d05d7332629e3c6444846f7c71dbcc892d3191f2efdb", + "0x1a19c1a8fc7f9d838cbd736243e66b1f637f49b1d8734c2af417227a11623b30", + "0xa8c14722a6f7e7efe695be4e6a21f2d1c8b8d71e2cf69e7645ecc5cdc7b6355a", + "0x8eb33cc1490499aba376f581b68766c4fd40e7d6027f223eb46e27199acc8d67", + "0x1b6a906a5321b057f453624693d4ae6abe79a5b8fcd63a777dffb8b2ea4184ab", + "0x7185ec1f19e7a84c9f914dd223b382ff56464b01a1b88dabda415a01e1d0a1c8", + "0xa172df0cb06617eeb95d362bb36d5e5ac52cbdb2e5f3c2cf3d9b78ef28fad82b", + "0xa11941ce1c866d077fdc995acf3ff2ee0ea0481eddd142f9b343c8403ed606a2", + "0x1958ac9a77c5b9825c401b204001dea8ee2520983fb3e738a467980a7bf9defb", + "0x6b24d043eab24359787ed7e93543967c9f9b7ccf99894c1ee7768f6235cb0cfe", + "0x6ab8c28ddda71b937d1a6feaa67b071f78ff7ead3a192ae63dac34ff24b8d929", + "0xf101e3da7546249b5b6d4dbe960c713cf152627a7482fc3377aa31f430c54530", + "0x22628e903ea9eb3eda9c93ac92d77b1b8a5ee62706dc5ddbcd079c57d5b721eb", + "0x0050467a543fbf0a232c8ce9f66eaec6c38c3c31b8ce3d590d1b07586374c1ed", + "0x4235a1330a45838b2d2aa9873dfbd59cfc0f0cd16e13ca9292f8342eec255fa3", + "0x2049ff9cebd379b51308220449b3568c6d7843f5b49f61b85808287f3d60441c", + "0x50c2ef0e832df29297dc524fcf3af4cd0988fbfea71987f3ac5cba8d4ec34102", + "0xe7260880b2d822d18c9ac2224d09fa18f5c324fb421470aad5af6c2605b40985", + "0xdf51e1b441b9809b26cd7cbdc4df27eb9c7fbb3bf764971684aab6c63e282a75", + "0x597b5c48840a25294feb135e0318ba6d6ca09aac476b1041748738963136a0a4", + "0xc710bd4b45a991f7f1387c25db70a1964ca4fbab32b738424d35a6e06e2483b3", + "0xd67460a50ec79c90a97e25d4cebdeafed6c897593fe8b24afe47a71c818a55b5", + "0x0ac1f2282e4491fdc8d28f1697026b7fa88f46204610cbaf8811d38dc84539f2", + "0xc3352ebc532273e4224dc0e94ec4cbb83afc2b5c364d71534344793032441006", + "0x42f3d39c81e118a7d515d82b6880104909a7915aeaca8ad64fe74d9fe88a7f45", + "0xac6fa42771e9cd6ba31dcff2455d2234c53c282251ca2399c727fd5521eeff0a", + "0x83ae44822213f59d34543a6d4fcf76b4e22cbe5a90674755072613550d348551", + "0x99cdb65200f9d1c602c5c2ded67a8cf2722cd7c1ae3f11d29a2c1b702923df93", + "0x2adda7cfa12bf5ecbc74ed4f4ea419ad7cd3e7cd03a0e2b32e924aa2ab98ec42", + "0x3da7434a58c60b7fc7fee8e30b3073ff4d3c381288fe6ba791f68d74d24ed19a", + "0x9dbe78f9121e6c0d99fa6d441f6aedf54be14fb39a277cbb5f19fd0b846305c3", + "0x2ded5acc49e2e1fcb57a66a81f59405febb50edb6b41d0fa8e445477028f422c", + "0xa46310f11937ce81ebe8d4c60de1a5c8787a1aac35ff3b6e2f0cc793112b7df2", + "0xfa693856fd1867458c335c6e903e5745a950ddf8a43cd9ee76ce8d0b3070bcbd", + "0xb374a194d9edb55d2946d40a16ac4617e4d0674630c6a970f58db17f21d22c12", + "0x651032646288a0b6fb5322626bbbc5b6b87dc5a5d59f5f39073f2f9574646c41", + "0x7f4346336c95c7fcfc1f849cfa63afd46dde8e346ae0801aaaffa9069f989e99", + "0x8bedf8e9f5095b4275635525fea6169c5afedff2ae434e42c5cde973de77ae3f", + "0xf92ac4f6fdd7801f15c8e0ee163241542d1359372d2189d8cd2a33f925933cd5", + "0x806d437ddf966fc6631a8f81a54eb82080fb2ade64a2b715872d8f648d23b57d", + "0x2151451d68f912b58bb510002407943ef6f2cc87a992e6df0765a4c239e63779", + "0x6a02bab7734d8549be10373e6395c368492b8518df793821962a940d5cf93654", + "0x4de627f1d096c86c1c1dcde2a314ba65700b1ac47b9db95e9ae68f8d28f52b16", + "0xeae202c747b699171115bb56652ed534d9ca6de0e8c3d947d63c6d60b5d658de", + "0x7bddba4a7c160445653f62d27c1622323c784461d52aba5a6f19964194a063c5", + "0xddfcf0c5ff899f19c4ed0604e7b4cc645ce5bdb7b7c7d6bcecfe7f2cfa3bdc0b", + "0x7d27d279f52b83afc9a115c71910d06a054fdc2e20625cd05fe35ecb03734f5b", + "0x415f6bcb216ad524eebd7bf177bce80cc3d5fb3e920ed65a8ba6c02f59fa88ba", + "0x570daa81ed1b593529a07396784c2996d5703f4124f941e99e8f9cf6b608b1f5", + "0xb9da28526fe8300989e16c83c4bfe418c74878be1bf3af12ff3b9a098a4c92b0", + "0x691938f83dd63e39be2fb03422682ee8dae8e0a95bf4d09b4727f8162b2da11a", + "0xde168c58358db826c9c953895b7a0419066e65eec0b7fa479c328719cf70df6b", + "0x65a7b2207932e96c427a6c01efd0c3f01a37e02e7dd98b18ea559c2a6c83c8d2", + "0xfe54ee65b1b8e21292fde2eed9ddda163036cd6745254bc7cb9f3dea737832fd", + "0x543d64c2a6b763cabbdc1a9316f37115fd572d96b5c75184c155e68532fdc8a2", + "0x31b41a4f481a786bcf4029b19e84729c699a8d742fef50040221ddf6785d7335", + "0xa383494d908727fc6198035c24afb3f352a16b29b0c1639062e7169618bcb38e", + "0x3da745966ebad677a703f5db94777fdc307f6e3e66a7c3c5ca24f35cff3f43bd", + "0x32fbcb24d42beb2128d95055706b767f7df7ce16c1613e3195342db84dc9955e", + "0x1723ae6147425f5b01b68de9847d79b918ca0f85a800d981029dcb5e3c62eb8d", + "0x997f18b9977469cbeeddaa1bb31472be3806c03ae77973c857e32d6fe2c4d740", + "0x6c27575f33b1d85fdf9643c9ddd27085f4241518cbd5b776e0d2bce19b152ef0", + "0xacb86fb3209fbf57c42eb86d2617eb631e0ba36da7de5b2c7ed63f168a7b112b", + "0xae02559f4868fbe4f114eb320ff0f3a38086f364a2ee537e6051cedfcee76d6a", + "0xc96e439aaa996d4ea4c276d1592fcc06e829d5f3cebf163aeb75f590896a2648", + "0x87debf5b6912717ec3c0846fcfb5b459a15254660cd5064180c0c514b4b15f59", + "0x37587d340df2b40b3f14746b72c5a72c5f51963d208b02c9671d6c623079b584", + "0xdff2805c029c4e3c249de3aa9f5cb3b48daae4f4496deefc91ebe3251c18629d", + "0xa84f66a457869dfc95d625d40496250ff33894be23a43e53ec892481f1eb4fa5", + "0xf8fb34bf78ad6d52be6fbb5472f13322b506f594ad3b585c04f56ed8d0d9afa1", + "0x546937b89a4d3b59817377b9c2ffe9579d4650cce71aa26bf2c76c571ec495b3", + "0x5ac921894e98005d03aa42e8fbde7ad0af0401e350c8ba98c01543a93b37dda9", + "0x3cc76dc057c73f0e0fdff28d484a092747ca42bc10989c599d0f597ead6024d9", + "0x1992cd7e94e9ecfaaebbd08d91519d6b67857db87e2e67c546371738ae0d2d0a", + "0x3604be694574c05c63d69cbfbbddbafe3cb425d75a13e69d61b50fd8d9c947a7", + "0xd1c82e40206d2a89e3a1a40c4a1b63c62ea6fa0847ddc2b25f63cb9bbb4a55b5", + "0x66ba114d5bf45d50e9ab9beaa879ce18d02a8b4f989c29ea7e9ae604593e860a", + "0x94f74c09ce5fd1c8fcb9cbbcc476af20fcfd9cf01c7ea65c14917da7b9560ffb", + "0xa4e154ebf83215c3843ecbff1dc8f646f221505c21d2a76f47d55466d895f1a9", + "0x28c20a0e95e23a023678443d7bf5b2421975b827dbd617239dcf26bf6db9b255", + "0x55d8ddf586d61e137482e3f4bfc1904ce4e04d21c6e7ac4d8c7d29b1483c8c0a", + "0xa9e1aed191a7a1a92bc99604e3b24c02356ea378b16de109362aefa2fa978451", + "0xd543ad635db78b2518681654f98a32d227fa6a1fa9b7043ad12cf58c91e8f729", + "0x102fb87da8b57948fcb763d7b797233f21523545f78388d8d05c6d7f2a4b388d", + "0x4e7273e2a92e897590988f38f8b899879aa1aea754fd5165364e8b98a66e0d62", + "0x5a06544527f88d9fbbc5905742863d873367d99e574d75496c59caa041e2b612", + "0x6a8957954db14594746daa61f907e4694e2a749ff53ea6b1dbe77d7d1f378d22", + "0x0debcd48486aa0d33a783caec0d6fb1256ffcca39071041fed7f047eecde8640", + "0x9d0a9b13dab1888bf0eedda217c501d76f587ee9a8765bb455cebcca0b705599", + "0x30693bf8c9bcb6bb4187606f98e138700e999d8824cada72d3d07f8c104fd263", + "0x494ef870dff64d1d65b4ae4b49ff13c145a6058876eb657751d58c06f62b5032", + "0xee4150e64f9ead8124d50d56fa4b6e6d185fe8ac385bd2a9db7ee991f6e34c02", + "0xb859d7db7abe48cbb9420d008d94e8d47753cc78962e5dabdded9438bed56b1b", + "0xf8b1fb734c345111704d73fe6944d0a274964a347d7dc5c7cb8677104829f5ce", + "0x5dc002623d9b3b872900b0b313ae8520009de730577b6eb2e2de18ae5cd4ac94", + "0x4d63e346ce7e654db6f067e8348c539ccf622d84020812724b936c19ff4f86af", + "0x2ed43f4e5d6889f5379e42d4a06de7c343080da74ff353960e4cf980f750fb90", + "0xfc61d0c90ecb073c022c87098045b6ca3f2b66c94f3723c679d81ac652b16f72", + "0x7e69914b56984b8c7cc9db1732c3d2d32969a58d6662509846e6faeb1305586c", + "0x0ec9b1b68efc96fc7d831ac7316e0ac0d908bac31be330d905f87b136556c241", + "0x32fdf6c25f6c741dfe468289cd7f019ec3a40c5d8fe882ef662b798491c0dc34", + "0x1ffbc6b29826aa58595d1a412fb90050f2bc3cf0ebc5462f308d4c8d85a1eb59", + "0xf0fc93cc2868cb9828ce16463e4cbd59637672d5815dff03aec7f3e1424eb204", + "0xe404321694894ab375f5a65c339f2cd2a53fb5a10f312082ce019681f6ed64e5", + "0x81ab1f93747c4804a85f56b0c6eb61491b958504ef7b898fb1362eda9b394e1e", + "0x1535d439d0043d1436de963e3eba47335bd7afcabeac4d3fc3f342396d3538be", + "0x42da1b95481bfab6cfec59884bb1ac7572636c8f489df2768fe2140cd2702766", + "0xbc3fd861f6e09efac1782d9d383c4ddb9b4268216fbdf3c25689162628e36cec", + "0xcc74c3d8b44a8cd23676babb4efb0e67871582cd5686fde9de6a052c5bf91ad2", + "0xbcd7fe80e95bbbb5ac93b1df5ff0b8e921e7ebc4960877acc1a95c478c65d64c", + "0x045e5918fa69606b9546f5fe83cd9212000828c54f9cab856f85d3a22536a751", + "0xc0f74dbb5a42bf1656698c37aeb904a33e969099f215a7efeeae0024c3a409d4", + "0x36d537998634f2dcab43b387edb63119c0f4cc68b1979a2ceb373089c531ecf9", + "0x87c20426fccdd225bd3b961c7adc1de3f9ac9640f6d26bd183f6e528089922fa", + "0x195ee1daad5c3d0052d6d633eda1c9f7160d488d4bc54f4ac3babdbb678eeec9", + "0xf9a5e6735f9c5577283e8cd717b56f69dc8306b23781755f2e513d15e6738cea", + "0x3e5bc3e78ae33367ce7450c5da7436f1faf3b1a62d238208df207307762688be", + "0x123e7b4f7e6b9338df2827a238a266376a20a1fd065e9f8a4446fcac4c6c92fa", + "0xf4eb14bfd197d49c42daa919322f18228d2d9ae2dac6dd7113c5e7d12d2ef866", + "0x78836678c20a40fbe09849fe190a9e74ee070f2056d7bef85d0f124676a93130", + "0x7986f7321971519933aa5dd507074c7b007328a7dadb8734eb4aecf732703fed", + "0x14485d24b7e90fc39d91ad6051b7f596d320b1f88f54fee132e032753e59a766", + "0xa80a9a5db758bfacf831a54022c85a838e30c8611ab4b17bda0641994302b59f", + "0xedf1814fb78abf675f3c5671c3618e5e51105647997d6dea6a0cfd1f0330bf6d", + "0xa91e9fcdc4f2b5e029abdc6b2523079bb4a2f5346d8a5a674e3d5582b8871d1e", + "0x3dbe468159a8c068285c92360cab488a4c1ec37487dd54cdc0b70e6d7cf074dd", + "0x69877439effb3388639ef6e1cfa132bc605bd8a0da053bcca23d82aa453d0040", + "0x6751d32ee3a1244532e6698ce57cdd0a59f99130e1e7e004c2751bc49d10b355", + "0xd1760a4f6e5a7967985125d2deae8bc783e47b1b85e19fc273e33eb2ef88d271", + "0xfa934c087923cc16f636615657477c48c082623d7cdd35508571655dc14efe57", + "0xb6b1e4387e04c4ddf88ada0aaa162345cd43e54482fddb4297e1eb6f8ba1ce74", + "0x3988089edd46b57c0bc83b1bfeb0050b503cbefdca83e96f1c12e7ea80688a79", + "0xedcb1bd8b522ba5155965cf18c25a090be2f8d7871ce60f0f371cd033d5a31d2", + "0x2f887b56b317e9896698ec9059d36aad63d54d95a01d389aa196ae12e562ca2e", + "0xe6d6b89e1d851fd24cf54f6b60c6c93a8b014ae30906c156374d73605aab3028", + "0x177928968fef8c6da017b177f6be85851616775be043b64f72925e6b8a4eeab2", + "0x71a3de323d9a600e15c25a5a6e05089d849defc3830fd69738f548fa4c57aff2", + "0x8e7d92f316f96b491e4831f52a799846810dd032bd720dc891195739192f3955", + "0x12a3433e8cadc005ac35da334d557c8cdad63576613f07df8c3ec9f528e846d9", + "0x1406da1f5efe9d3de6a829f1219f731f3ac875c7795f72b5a9ad25a57970b9d8", + "0x15a849a0ea56a777e00325b4af4d9996747486cc9893c08b0773210306193521", + "0x6178e69be88e7e93878b731d062b29a34bf2951082b947f35f60fba2c8de62b7", + "0xc4142d4fe01091e82626178b66c13243c9b35de0f07a49e3c5f2ddc15b39feb6", + "0x8abda6239557236af27a2cdfbb4fb91a6b136931c53067739578ed13e1b0a2ff", + "0xf85615d9337092e25080430cfa0b7a24c97effd422a1947a4c07239d5221418c", + "0xf9534d7db3b5fc1bcd7033ade59fd66bbb94a5bae91c4acebbb1540fc8bd3b67", + "0x5ed0f8035d3920d6e94b881cafac324ce5688f8c97668715733e0d00733b0fe7", + "0xeb6c474a0adfd84c79b86090c793697c0bb39d6cb007c725c2ae7afdc98df5a6", + "0xfbfce3e019b0b29ad03fd9146fa368f9965050b40733ce297bce6acefc4668fe", + "0xeda9ed65fbb1c7fcccc91de519f69933ae66c8ed59fb65f64751ca8aa06030c8", + "0x359ea9df33d466b5dc210ef0e99f3b4416ce03a5439f49b4cc4c1b98b22a21b8", + "0x14b2e8729b70abac62120541229182264b78c7ba1a1a379ac8a582aa0bb0d739", + "0xcec0dbdb55f92191974c2c8ed716578c5ba04c4584a0770fc0d7d5cfbdcb2717", + "0x07334b05a08cab079354cc1f7a945caa3c633de89a89c18244de81ed56da850b", + "0xc58e0bb71287fe92564d00b5094ce36b7899c346679011e52b73eae45bace19a", + "0x9dbef45ce9abb762bb9b30b61456a90b74b0b6f5b41af9500699542d933f9535", + "0x3cf848f770e15e7f682075c77f7e980da6750d3d4cb038479983e341eea3c354", + "0x608a4c5958ef3b0a324a7cdeebcc3abae89c1371c949d6b269b2d3936d9fbdb2", + "0x66422fbb9044305317d900702c2f99702317a8a83ccae0911a2832f623356c8f", + "0xe977f86ae4c5b350b350a3d6af7fffdc9baa96d9a7cb24834e5dc4797fe39fa8", + "0x6f56fc66544e099797cc3b0879dd20b21796ace01a0029e0d8464a3764d1e858", + "0xcaef7878c703facf29fde1467dcd08b03761872f598f42f5c56b4cb367b97255", + "0x9055cc0c11cbbe8477c7dd35b37a57e7994248c6bde9ac05e85717cebd2b970d", + "0xd7b08c0ca8abb9f07e3df1c4ebdcb03b0ac2018a905d1c78e6825d2bb5ea1ffc", + "0x0184cb109267e58d5bc0193a04548f0c2b87286ab6b03a1ff7b6d88a725662ef", + "0x3005e0af1ac0c5fd6d58328c06cc7f5d89c8c4ad173106fee1a7e37c9f2dcb95", + "0x8f7f8800d29c66b4fb12334b622fabe1cc4ef06e4ded44e4315efc381987cd56", + "0xdf74e3be6d22159e0e02ce3b8f0b405e6469557ecbd12e4432d52f4ae4637bfe", + "0x2fa9a889f958ddc41bae5916657f946273447add502464674658bcc257f1af15", + "0xbfbdf04ab62a35b2f7b038b02d8c37ee946cfee18e10ef8a4cd5409a5fe81d19", + "0xc4e834510182950161a75a843352b5b46e246a05b7c7e47240b6cdf7e18b4de7", + "0x2534be362fcc238c530f2ce8f64a3366d4003a21e6f32493a082b7efa1d413d3", + "0x628e5f76af96e64ff34c52cc5d07562e72c53e7bd4b7585cbc83b7c9951d0d2f", + "0x41687c81b22f67e4ab6ba0163da6d58c81d94c5db20569b4a42fb58b7321a442", + "0x50f55f58cd9768b611fce3ff13e8da9195b1eef5d0a618fd27f7052f88c8fd84", + "0x1b64cdcbfc12c42e9dbc7a62a1f8eeb0baaab8ccc867f7a7308c88e4968eb9a9", + "0x77e9fd9a5d64b66cb901c5795b9f66424638b24e457024b5e71ffbb79ed8a863", + "0x35644de61c2108bf9d49efef164414cd2594ad4cca6bc421699458c9bace5491", + "0x172ded87912492ee521f79c1ef22e42b1d22f17c3286575a5d419fc00d928199", + "0x3c8fdc337338b107ff5879b3e95cf285b5128ae395c4b89ccfd05a3d942887d3", + "0xf4b22643ebb6d46cf292531792543f9699a99674978045b0c911818211be6017", + "0x783fdc538e4505d4187a0f341b066007caff8030c3bcc4bf49ebd31a8f6b4794", + "0x38e11f176844f680e75b65d5225533639eb522f39495b9ee426135097e5e8fab", + "0xc5e0da94d4dd6e29c8bf3684177a62051e7555ee87007fb07581c885be598edd", + "0x317dc456dd095f9eef53781c214806beb31351cf78cb1854be257b4039324b8c", + "0x5bbf954741e453e3157dada0a69bafb9ebc63c3dbfc0cf6e3fc937a1b14b7356", + "0x56a5354de5acff2b904c5b6b976c473277ac2364571c54583bd682e76bb3f43d", + "0xc37f17385f4e6015cdc8083fc750499ec8c9063544102eb0e3e3b7e0b5046946", + "0xd616c205adf0ecf00c7563fda837e94a4f48be8560ddd15d93988cfd3242b40f", + "0x1ecefd5cb0c61b120c227274dd60b42e6d25229517b20dc3e37a7c3b436f0e92", + "0xcd447982c518db12b8aeba63b68d8caf1eda6bcc44400c9d83c4e4d64b4e949a", + "0x3763ef2d96a89a302260ea66e22e3255001ba2f003770c03905d4f39d8ef6501", + "0x2fcc41e9b574af5402cdce8dc66d79488cbd5cf960209918863ac9526bcb6a70", + "0x17b71848876a6e0a8857f1e5d04762734678ed1a8addb7e378915a7c3f37c981", + "0xcac9e4641f50d52d77e0e77b1a1b5fdd25cae239864367b3d99026d3fb973610", + "0x55eabf50cf101f65e51dd3a54321c1897a67c50512c534ee9398a716a790ffba", + "0x49101d5719e4de5e4e88645de3c22cb3ab794df815555d4f22d54ac6a59f73f5", + "0x509cd8530c28cc098b0aa80d3006a8f71ac7ad56101b880288658917173b8c8d", + "0xdc0e15e6d321519f34d40c6b2cf5f6955c15af815dbe02d84606ed76a01fdbb8", + "0x0b8e107e7abcf80e85b3288786dd79f949449225315c9125730d7d42f0ab9cb6", + "0x07ba997ea28711f221ba26d724a09a52b2737b8aa8532e890490ad811ffa792c", + "0x713775500194ec8691fb540d63e99a70cd443e5539b5f8e2a993266bb58266ef", + "0x3b2ccbf35ac833e845f00329c1f8d130a3f804c55aa83c35421adb83749213bc", + "0xee82c15eb18a075b00de8fd610621683dcad88a19c1c507351b5be0de0c6c4bb", + "0xf874298782be23045971092d8305c469a309a1a33f6cfde7604e6499d2384cdc", + "0x1a9d88cd641f6468fceb32eced3710569d511848f393c2114ae33d7f36c12f3d", + "0x5b2b8c2ba5d3aa8a0503d14e759154d1f2f46d819b363025a77d4cf5e3d83586", + "0x0082bad01acd43bc2c504f66ae28056ce352257b7ba7e2c27dd36d256c079561", + "0x9c6e4e01a831348ce64da4e4bf04cad5f58749573e54f1062b0e2921bacafe74", + "0x600e1b0101161721066952d71401f8fe6e689b66b26e2e74cc924f5e914e8eec", + "0x8720d215255e4d5e2a688096506d5b25c3a79c511d8c0b3dd7ad3ccf542e9abb", + "0x48baaec9724cadc4f7cb8f10549b8daf87b2572151cdf9308b3e96f02b048f23", + "0x2adf0f56fb9bcdbae394025ae949e694e01599887e50c355c90c3ee5ff32eac2", + "0xcf78410476d781bae1567f3d763af732d2ecf56e741cffd1bd3906af83de1f2f", + "0x4e7e223f6881065ee722d6ff9603f1786e4e99292e9caaa75b7b1fe9aef00109", + "0xfdf0b390b0395f007b1b342065096e0a8da957b26ed4cdcaba432a202ec12b65", + "0xcd40d2df140abc1228b2e1f45b5d65a0f3e2ab8b7e740dfb5376b036f63c1c2c", + "0xa491347f128d31f68cd1ae536d8f982fbfa5b58d855a95219f104db741d3d2ad", + "0xaa91fef9cecb842de4df61fd1650267420c8336758fa450f87ee867ff1520905", + "0x75d1574bf7b23319a7c8ff6a0a7cae649313aca8893ccd223f1f77fd71c9b8e1", + "0xc72491916b25756e3f505081b7f63e32f3289b86cbe0181ac9d33d29f666b9e4", + "0xd446465131b34f091673736f70fa0508ee7065c4011359c302a603b6159cb52d", + "0x1380689a50696e1cf0c19869b9773528f01cdf20b8f8a6c6a7165fda31ea49af", + "0x01cac6d9deb56473681c02dc753351feda402a1a1cc2b4cc8beeb23884f40760", + "0x3f622e134dc529c5cfbf58a3ce91d57850578f45b77c4683b2dfe4530ba0826c", + "0x016c95fc875baa0a5d1ae22c8772eaf574a6c918510875f1000d65f3a779dd04", + "0x86e5f579f42ea54a96e622f4a6becdc5ae85e0d0af87997fae87b6707abc8d28", + "0x53d403f0d0f1f30d919ad7212cc5e2e73cb4870c4fb4e6d260d2573e9bc5575e", + "0x961cad0d17fbec30a8f614ff3565d12698af096e61836cbf1f0ea125ae3ed72d", + "0xc9dcfe7844bb4ea845125bc3674f326c0f178c5cba4349b9461e40bd6ec68c3d", + "0x894243ff80e90c4c4676583b4e428f13e077008d225790a234ae215dc53d33a4", + "0xe5fddd80d3cdbafb53e0cf3c095d33904ac8db83bdeef9816111d20384aed444", + "0x5c7ce294d82fe6502045664f7d13d02063ef24f0f4960e4fb62bb6abf08c63eb", + "0xb33a5699ac121a51c0074b4783545a86a428fb239b4307f1e45108c85af88617", + "0x37168f3f0220f50ba3cad0a558cd8b01a7a435b6c3c5cde98b420ba3b54a1cbb", + "0xd50928e60d00c23adfc916e7f9a5363fc8c94c8edb3aef41ac1dc719041f92be", + "0xa08b27f437ade4d527d883194f79927053ac55a3293487a65060aeaf4c4e5147", + "0x326e2d1f45438741b63d346f0da55066dfe0284382f1b4ee54b1d5552c4f7d83", + "0xbd96baee5835d9d6007b0b5957e452d71d1ee31aa6fde99796cce59b17dab703", + "0x1cbe90df49f8929ce1052049bde7d6169efe0b289ad4e05414a8e7bd61788900", + "0xa0b914df37895be6f5341f3f4013ce5c61f108203dbac4ff205d5f1a581712cc", + "0x1582e61974c0bb5f9f2622d70e772f3e9ce145be97eaf5a87ad794268cf352ab", + "0xe946dda774c96c7878a0daa686e4a22e0d9d36a88dd9c93b1776432adbfd68a1", + "0xf88a07db8c0fd2a1354c38617c16b4d2e4f8bb43d9049321ce47a8c03c8430d9", + "0x2adb489b34c480267927daf3ba3ca7567d542edb83fa82e8040ec57e25e3e6d7", + "0xf1c28c6daa3e97466d50d9780bd3335f3dd096c3389b906bcc12426ae4862a99", + "0x4457a8686a3839b7d3b592a1751c25b216bc64e9d0b8a81eec55601ab8d8a98d", + "0x0ea5d5606c5e81f92d31b49b2e54ce6c6314b13ac223c83094280d0196e003b1", + "0x33a91da49deed50914d998615077c5192be56e482ab230bdb3d480d283502e2b", + "0x5385496abf2e351c0cbd7f6fcb5bf5b5345783b4e512bdfa23b9736e77ea43f7", + "0x98f808b18e5778a1bbdefa3f19991a3d008c27e9976db0ce77ddf9e4e21a0feb", + "0x5381dab139fbb0ad6b61afa35c541aba559e2ac25c4ab1cf8a756c2f27c6bba8", + "0xf4bea5f3ab0bc9ba3ad00ad79402d1d62da125d311884f225ad8abe9fc36d56c", + "0x6018a9f7edb5ee7ada70c3e85f22ac88924d06031cff3f61104ef52bf0baa2f1", + "0x01cc4300f1cd2bb4948329d42e17a277c7da52696d46a60442b6f5600d869faf", + "0x330240c95bec1ac1a476cd202aa74e85db562750f860a9fbd76e813f16cbb639", + "0x0809c487d45161c3b85cda014603ba7efd6b67a8c7aaf314cf20c880ec623a7f", + "0x653f53065726f9a7c1b96ce7d836acca515f563a47c9d7d47aa8c5c030a9fe6f", + "0x37b8dd7b2a844e519f9eadab305efa5d112266cbbc76bcd5afc119e0dd337ae5", + "0x385b7031eafc345ed353d9b35dc53010496db172cd906f8e0b7b891b84a65e4b", + "0x38259038fbf1ab3f0ffac98e6b312457f6b2631f68ae477b9302fe740cfb8e50", + "0x5a963aaeadd708291b41bd419cf2ce0585e162e0d46635902b58ee85e317adc3", + "0x881004f4fabe3e7642c8cb5e99dc3909da28451ec442a299f331790c8065e049", + "0x3c721f828959782052312d30d8256c9351a141923a9c2e2ca5b605f3a92cb27a", + "0x3429b149f860e963ed3819ddf19164977d637489eae313331c71165c7eb8f824", + "0x44e291345b79ff4116797899da20baf28fb9d4d2a5d6b1661a0c83b8952e481c", + "0x00078c007b6c0b3b6603b0838b03ee9e8944fe16f99f0a35eda286a288594806", + "0xbcd3506338253f0df5abf0c2866cdd319fe75bad7ac6f18d1f8201164e0b9986", + "0xc047f5f06cc54e4bb54c8e3bf22245d68c18b4787a01d324deb2139d7405814a", + "0x77ec49a04762af36eb63e2bb5c5cbbf15b580020117639ed5546749e34285195", + "0xfce516ae95eaee4067e95a5752494974ebdd182fa47deab70fadc5afb5ea8648", + "0x2ee54548e56d2cecc3e6cff4e60a7664e55d9b1c1c9a61be74bfff7635078cb3", + "0xa79dce8f10567e060638cb2f09ead0b191e59d972c532a7e91b33d27151cc23e", + "0x436b4cf10f5cdbde72be02ca16602190a56c77f1686533e643c885351d4657e1", + "0x9070c78384138f5e17cc9e6148c7cb7591eb9864f042b82ad38ee263383496c6", + "0x12a8d5285c871a0b05e370a337834458ae2159b5d8cb4bc93b6cc83bf7351b68", + "0x3c07d35ea209492f4aa811c51202f081a3bfd6e31705ffec497d70bd59b7a6f2", + "0xc0a99b851e0fc4655cb3cb43547f4ae6c36c350aa71626b61ed3ad3492f04600", + "0x064404380c5969d8e43d759ef990658d7cf5bcb7b4f8512fe58a7e994e199707", + "0x3d3a61c95ffdd3c7f05b3574370bf4cf0eec605ca27cde051b5d77e062315f36", + "0x9259e0113f1e009fad7454eebb238e0c7f4b7aee8118b63b6c05aaa2f0bc39df", + "0x76ff9818e62b25fbd698ea021e200ac9314090b801e000ecddb71bf4829aec8a", + "0xdf0031d6e1c55717102ca1b3a0bd389cc0d227f0f804396d4b84b5dd26abb1ea", + "0xd0220e77632c2353d51b92b1638e909c1f41a7ab0e6801b65e344ab594f48881", + "0xb15fccf30f298101d5ca0034cb8585cf14ddd76d58f3a8ca71a60aff0d0438f8", + "0x5dcb3817ae05b8c8490e197cfdd3f0b701e61d83b8f6423b3f24f27ba0f4c668", + "0xf3bbdc6651a4ba011443f6c6542b3f45b8aa2ba8bc719e7220578d6362cc441d", + "0x1edc95bab3c88a66246393058ad1a9557b371e726adaf261a5faa535cb8fab76", + "0xe02975b5ecb9fb8abecab35298704ecc476d2e6205c2df900312359d5aebdf9d", + "0x2a5c9b033738fe9e7ba6949df526b5a735753464b746e7d1faa29491a8e5f57b", + "0x46ac373df276af8af25aa1407659a8e85ae12b51ea6ae0150ee2b80a76ea6d9a", + "0xe85513a38b54114f4b6cda2bc81a4dcedbec22749cab6676c061d95c7f38258d", + "0xacfba9967af17aa94f0bf73c3b1cfff113e14625742a7398a25a01aa29bf02e3", + "0xd589df920ebfb3c3c1660a16f74213dd6d487ee577bdaf18f6279eefb9252c57", + "0xb2b66c26bd139976ffc2471f8ec71e353108828bad5094a324d1e4762f5547e5", + "0xeac126eb94bb1ba443373fb2556753d95804891d4763a2cdd1d297f1eba0fe6b", + "0xfcb52c727793003a70941fb01bf6c184890a691b70c0aac3b11feb3987de8628", + "0x1c1b6aeaea826ed0cc776a322454663ef555adb0d3c6f50480957ac4ab7f0672", + "0x187affcea64fb6195ee27cdca1096142898be0fb8f216f10913a744f2005f7ab", + "0xb4e42e3a4c94477a6d5d7f3de429edee7d92cff93b647c71d7a20c1e07a35117", + "0xf960751197118967fcea65f10b51d9568c184a8bc968c609d093a0f6c15a71b5", + "0x0bb9ca3521abf8fe971d371749e5c2258b1fd4c681ded047d6dc7820d303fa9b", + "0x52354e8e99ecb5c2dcc1214c08901d715ba62a7463d56c76a6bd1287a74f5c38", + "0x8768dc0cb22a0ea9fde00170783fe3741501d958c186e2c636d03fdf8a995129", + "0xb4204eddcc9c75372de503645bddaffd3f71e8554c3bca09ec700d928a9664aa", + "0x97c94c63bd30754d51abf48aa830bac3724cf77e366965e9f61a100cd0136714", + "0x60dff72f08506ac9ddabe3f957f88a1ef4935f187b6c536643500d65512fd393", + "0xa94f4c353581e474a091655c78c491c38315e93e287f848c17843d807aae3527", + "0x09d90469c97087fd45cf1a2c5471c6e81e0ec1e7850dd76b0d0cfa9fd49aa13b", + "0x298d03c60b8dfca9ecac182b5c0f6818a4c3d84e55314c083f8913a8746fe335", + "0xbfa7ba8daa97bc681bc6ce413494b85ccfbc10e2bc96e148713e0325e21b3b60", + "0xe61dde9cf0c1c6fb0a37993df24dec2f221f97bdd34f607de13fb1f947e7f284", + "0x91e9a9e65d5076819146b246647b9698954bcf55e7f059db32854f93b325d35a", + "0x7bb2fb25b881772f318a10b6ce8896712c93cc85ce9c7c371337020e86817a3f", + "0xbfdda2258ccd28dfc81f83ad7cba81967120257392279c7412f0bb116605a21e", + "0x0a626f29328872380ebf6a10468307abda5a02c3a7b9e04763c0c8c83f903df7", + "0xaa8ee86e9446a125356a96f8ed47c3821da54b003558f68c823c4ac1ab966c81", + "0xe26f3cbd95e0a26683c26adfb71b6d4fc82b034171f29836cb9bf391cf172376", + "0x7cb80eb383da7d8c1120fbe79cf3bff3e5bf19b9f57aebe11f79ee23dd82e611", + "0xc9b85149830b7a2dcc1f613f40ae232bf5cce7770780bfa7c77ecd25ae0bca6e", + "0x859dc28f93d2f3b17e176aa8248d6720be498fc85017491c68d6af5f4798b437", + "0xdcc4dc79cf88601caf6e038bea275a98208d221ac8d3efdd5db3d2181c14c947", + "0xe1bd63a920d45b05efe5d2fb99437a26bb7049ea5b183e99866d6dae947ff724", + "0x4aa94bfe1501f4d37b0c55d77add7bee9bc7f24d444a3ed1c6cf27d67026bb62", + "0x10931498b823a9784c4aa3ece5e88b477050927fe4016e4b10de7e2e0eadbdb9", + "0x7f30cca2119b5a4107cddca59a88f10ad95cfaa879d97bd1e50ae6a347e71b1d", + "0xcd8a0dd7a4fa9b97641d5288375105273c9025a2c9f3d7d9d04179fe3f55143b", + "0x6c8ec850db640544b7e5b22c19253dd1595899a7663d40c4fe13de4258cd60ca", + "0x06ec895b6dd7f299edab3e2e3a65322fb7f8fa8c9a6182b7af4f0fa25acdc45f", + "0x45f6d74f05f7b366770428b49630e836c2fbcc72133ef03a1bcf9953209e693f", + "0x3d868a3921aede543f2bd8ccbe3b51468e7a87f8278e4601c4a8e740e8c339cb", + "0xc808c8fa7b02023e5c64999a141edf6e0ce0239e37656e0fa7c5156443f555c0", + "0x82c273cc2afd955663515932357f19d657eaaed2824551814706ae3843fa1739", + "0x5785f16929a6a73b4621e75d31958e2e9b00dcbf3a6b38bf3ed59672918b68b7", + "0xc8f84b888e55070682103999cfc315ea3d157d0771f0f035cf2ba03f6fe1b1f1", + "0x343a05e1a5e75e09528f194394caf6ca8caf94904d54d89c9d22abd5cae0d83e", + "0xddca7f95c2d9cfdc9efd9158d29045ba92a71d45488c40d28b257425c1c56bfa", + "0x008a2b681c4691d7e0de476180c969aa511467f27755d0d498eb22c9b5333835", + "0xe33fb40ffd6253b5701d24c59a4e217197f9eb7caf7c2223722734f4c74fca4b", + "0x650e8f1c6c4dbc76ace7d6c29b9a659d520af9b291b389bfe3812c1ccbd07c58", + "0xf88c36b8042df77734f99395eb68aa9f4b67a21891c42350e4d5e3e6d8fdf168", + "0x882c68aaa8d1f6acf005ce2ad3a6fef7ec1212ce610dfb8a7bea9417d87431fb", + "0xda73d75513895d5bd5174814da25cddac9a633507960e78ae6884b92e48ee699", + "0xf07d98594c0ecb16cfed18adb9f7b5b1055630b43444c70e6357cd18ebc09392", + "0xd70c5886426c55dda997d615d325b5cb5b652f5673601a045a113d94a17715c1", + "0x3e8dbda1f53c55fa4de65efc7d294a02d78c69a98d59049dcfcdfff6b7eaa521", + "0x67b14249f9c987298fb00e0bf560a976dcaa7fc0d02e816f84c3bf7a4e7c6901", + "0x4f8affa83492afa72e95a36f23356b46e58a0a19ecfff6960d4d6e5b9877b1d9", + "0x09cd2a17655988d2d8cd5fbe44965a6c15c3f123b75e1229621b9ab74d030e53", + "0x30693dcabd19e89bdefff4753cbc64d00c65a4af98f782e6e67b4e84f6b015a9", + "0xf67db822aaef8bdf7967c0dbe25015ff6cf88ce21e8bdd25feb764828ee64951", + "0x9a587510721ee914cf8b9c863859629ca0c8ed22b0aa023e9efb0756d3f9ee5a", + "0x5d00c0a840b96a19679736a7ba555f3e9bc5263b4b8437d6c3779191eda0a7c4", + "0x3e01cf22757510938a5aeb2ec6cf5046b7d3c186bafad7d57b81c7d2a99415db", + "0x0ff2d3ed3c5acfa5db9f9820a1a314865e266a823ab42f40bef6b0276af0a108", + "0xd3207e322207667c614e50be784f6b4d9c3f48362dbb65b17c62f5f33e631ce8", + "0xc7d5e81b23b741a772af6263a7c5894d13033001fd96898f749050f6b856c94d", + "0x7c40099f6b0bc7f0d54650a56531b2cdefa990d3356c79a9c6bd78033a0aa1b4", + "0xd35ffc6c8de3c7f5d939c8476758c99201113336a6fea177c312ff1cb4f6d7cf", + "0xd6c9ea18bb47feb446998cf2e1374aff33e1282167318c5e5104657a69291797", + "0x66251f4b977561f1fa9906b2a26d31a8b7a6aa62f4b7b901220c44acb93bee11", + "0x1ce1b8ea8492cff1eb95135084d3334bb45394eef0dd3d87aa8b68fa9e950683", + "0xc3b226cc60b5af90984f3a98a55c1d608afef326e0bc504869723d545f633196", + "0x63f93d6ffd8e9c5779721a53d38b754faf582cccb8f5dba6f952ee079a08d8ef", + "0xc4dff799018abe40f08586ecf23fe06afca1791cb7968218c93eb8d70a8956d7", + "0x3231b329c24ca1b8e3610d8a2b5fcd0eb962f04e93bafc554c24d047cf130ba2", + "0xc7b393970a7126afead537405174b2146bd3b1a1e4eeff0508fc8d79b9233a4b", + "0x73ec83b51241245c9ba70d1c5026a226ea2b690d05a01e392225821f6cbc76a3", + "0x8a69ed7b352026316a74f566d9eef099341bef9afe05eab1f85d1bbcbc3499be", + "0xb7e26c2cc9d43bf91577fd258cb3dc7a4ff1819e69aa425d48a31c909742c78b", + "0x7578d8319252e136dac5b721e377463565f545a9786db38cdf048d27a6c7c8cd", + "0xa9136889bf85b078301ce670c54928ef29fcd6a268ded07a08becb440915cdf4", + "0xa5a4b8468a5aa50a2afdd44e2515faf1fe0e7ddd0456372da0db232e00d47d9f", + "0xf433f4018378147994bdee5603e4990f728a1838213c81e655b8b9c224f54517", + "0x1b387891f9ae757f62f9ce1e2f8e8a9a5c8dec29a5d045e41c924b5d3dbbc5dd", + "0x47b8b6748b07b33eb0237d2726325415dcecb2d038be9872834cb5278a5eadda", + "0x131cf8b68d0c779df85e51dbbec3f768903a3ab289a7d39b72602ee3ea7104de", + "0x9b6ab213619ae96805a754947644c7465274c7f686b5ae16e54f90ac0c78526a", + "0x2e34a90151060fc2ebc58f830a87cf33b705b4e3fedb2c5880c0f900656a9436", + "0x092cbefaaa923be1541c221aee81cff83650d8c5fc2503c7cf9f8ea2e7fac0f7", + "0x0b7b1e280b8ea2e59a8f322aa05f7c9b7e717cc21e05abb35f62432a480f1277", + "0xc82f74348b03897beb7c622f63976b700a2e031d0c380b3577a5ac69ce3eab25", + "0x232b12662086b16480d650b7ebd1fb0e5de4e7d6dfe1cca34be044456159f0b4", + "0x2a51e7ff6379e6ec9c3bdb4f7c867f7ba272315d5577f542738db1a4e986b219", + "0x09319ad108934876330c0e72e626eefa5a3d768487a90dfebac5de9df578d5c3", + "0x4dd72eab12d9183ac4c3692cafd33b929cbcfc6c8abf56a9fdda21fa0ae90bba", + "0x014c07ab6f5628be304140dbc98f639ee69914bc47eec73741c3ece25fbdb186", + "0x77c1f0d2effbfca82dc1c3af80124666830f84f1ae9a61399a7df9a7ee9ead8e", + "0xde29aa3faba8e8d7cccd3d64152d787e0957e2e02b85f8b598e27a64f85be92b", + "0x7c86c19f0f598c5972729b14a4a2d89490be2a5aeb9f09fbc47ae11d6e9e5589", + "0x58f4fe437e049d73c3a384856d7c4249d0f9084ae8a1d33e268567f7cfc1d843", + "0x679054ddfda36d5694034de0d9159204f67fba8dcd64ea27ae481751a6a042d9", + "0x00550f8a90888c1266ed3d43558087bbd255de842bb5c7ce5a0ffd7501e217ac", + "0x99f3cfd2d9dcab86723c6c5dde5342e3b0570c26f7f4d497054971c9e0c79714", + "0xb23c9a8cdf75d08c55d42dc9b5a4937c7a2ae389269921da4b0f3824f2fa4ac9", + "0xedb69805d643bc999dc8f42c82fda5c86dbcdeb97f8ca614ecc442b0096ce0a4", + "0x9732275603d65d92f1a2731e4e7f822d504175aacb333b3f011ab12c25c16e24", + "0x74895f04ab02583a72695faaea930e965fe5cf127e78048ee7b6fd931252ff60", + "0xccade78490ce81bda38fc7246986bcaa159ff4210c78a818908e7929b5d5e214", + "0x0f83b40f4169d073918acf1388b052b238748d6c5aeda235800403194da65756", + "0x2e0fc727f8fa2cc3e815eb0cdfb8fc73a8bba70c281c78a77bbe7247a1757b9a", + "0xca6fbe2344aab3a18e8ba3b18dcae9624c995175d77f6d9783cb73a6779d4953", + "0xf93234aadf9c1c1da370bc2e58dec3e40840ffc4456b7ddf7b9147ddfa5c87aa", + "0x7217d998d17977983d7973155777b694997ba1fd9b84c3f723917628a14a8bd3", + "0x81e99babe840021f79c09988425bf91745116970fff4889eac90f4d948617b45", + "0x6028f39dda3291724550ed9d5186328de53b442deaf1e37a01bd1e37746c2d7d", + "0x202131d5985bb64c2cd745f8c57ae870358a66d915fcf64322afc3e907f57a77", + "0xb242517abc3fce2b275d4a88a1689f836c9556ad589be1bf62e6978c042eaf93", + "0xa4e70eaa95e779b934269dd10085060923d9191eaae34a75fb537832140eb1ad", + "0x9f21679b001c396ecfe339f57c798c706c1567547f19f0390154a3419448c8e0", + "0x85ed1f333690e69275ce513e2d633192b0aaccc8e0b912196a154dd0ade30f72", + "0xdae9e867f112bff48300cabda2626cd9de0dcb249aa3ee2a7365f90541bc08ec", + "0x2acb02e30384ad2364b1f83784b5a785820e07ed7a7b51afdb9249d671ee6ddb", + "0xdf7679b1e10f8bc3191e6dbfeb777ec3d27f9bc1b6a46c146cba9a923881d9e9", + "0x744f20162facbc66a246476d4a8ecd50922b5d2b16823b5df599945aeb8014da", + "0x44b7f3359f92e5a2b6c42a443065a3f819d9c381e69bf236aa71b2f9c49631dd", + "0xb1a63564b8f7f9b17aac6b5f5639d9323e6df5080aad9ad0381d3cf2c8985337", + "0xf35537961a22dfd460b78626fdc79cb696e7c2b670e27368836e8c7d698b1ff3", + "0x206a5433880de275cdba7a9bdb5f4ce8ec5eee0115b793bde8071512e593731d", + "0x200ee9535bb4b7e8fd3e7733de7b0aa376e8c837c2955f1fce3310b147d33473", + "0x005bea89fd624ad0b9dad43bca25748eac78d33e786374903665081d7f7b7391", + "0x41f5ddfc45630fdbd7358ab65d38f14b71faec3a1ecab9ae2fd9fc685f527ade", + "0x7ebee909bd7ccd1ec9aefdc1b6abb98f326daf66f5b1bccc05c740f03c362268", + "0x8bccda1bb4f9d06b1f4ac17fb13504ba94edc3c9c833aa6400b3f003f430576d", + "0xc9f4d7be6782ca8377e3290ede54d3d99364173c00cc4f44b3af20d4f297d4ce", + "0x397db0e2df773dab48ad8b207bdecba5677cf38c460cfe3bbada407e392fc0c0", + "0xa3c1612387b2b51fe87bdc4d57e54fde0785fc2c7095f4343bb71b4041cce47f", + "0x43e9ea7beeda42d33658042f72b5e7cb33478df7b0cbe34bb424239e8ed7c695", + "0xeb523d35f5cbf920364d97df1129aa1aec48b0e49ec2121ff9965c34a9b1659c", + "0xd99698427684f0db6c0de0e18fc14136711e38cb65cbbde722d55e05105db03e", + "0x079e80fa24f5059276e3512debb09c453df0c957e06e42f645227622e83ecf7a", + "0xe8cf948ccc07327ce3fa321c5371deb0237d51f147993256246b619b75f9379a", + "0xbf3418e0a245da4ada0849d2fe9c934e95609e344cf4734a20d23a86466138d5", + "0x9c3620d280ea8e6d04f460756fd7e5d7947b15ab87b2a24e31d96384aedef5cc", + "0x0467892273772abede0e7efd081058c5242dc0f474c90405f987c19056d4cae7", + "0x432592be748af66d3b43264e00d46119f65ddff1cebe8d3853f072f21145eef1", + "0xb98a1dbee5daf6f25dbdf731efb0c233470eb4b44126ad8dad31b89794130bb4", + "0x68c7b6c356f3fdf82cff0e4b693bcd2239d72b77f08c587e9f611aa38c6cb67f", + "0x2b3b7b113b17f69188e71507bf5cd66685b976b5ec23ed8c9f70cfbef5b3a641", + "0x360b08f1be4a53a1db2ec1e068da659c3b693d956dd37c5c3ad04c935081f732", + "0x4f220d5102592db62c3ca6bec42a304ba2108fff69d39fb740ede163a7667df2", + "0xb12b9aa1524ed587b6857d0f847a22d2e0b726a253e3dcd5375411263144fa60", + "0x77d7006a8eccc9426be6d0d4e99d2f75db18902d4dc8bbc2a2f651b7737adee6", + "0x711cfeb0c16df71b7140ec86c221f08a4aac7295ef990834cb0c4c6586fcb952", + "0xd0ea4ee8acc3746d4949b9aea555ee8f7dad81cac48c6188526cc8a3fdca0674", + "0x17a460691acd145b00658639b51c9467325b02b0b0552b68111e9bc70f713963", + "0x3ee66ecf3c8622ccc48bff5f77ec7b6ba9bb9ae7162ab99869f4476d786750f0", + "0xf846ff968d826c20e10c1248121d4af6fb6e2cd86d0f8c1d2a6088cdb23c2ded", + "0xedd84b8243b3fe742052a421d9f3e990ba31e3ceab24f2bb5ec2d8f9d7594378", + "0x92cd6c59cd631f02a52434feba99dcc550f2567156a4669a5d2d98077aff7e05", + "0xf3557a61071097dfac3cfb0bdd8871fc759500d6aefb555292128ad785fc7d3b", + "0x3985a6dacd96834a54d581b38690efd4dbd50f6354e238a551aace59610c300f", + "0x194575b6ab2aed3d99269301408b8b9bdc765870fa312c4ecb6771b29d667398", + "0x0c6aca1dc3670f27093e5e3d8397d58cef4c77009c22be3524bd6c9a691ecad8", + "0x1b97718888aa3fbbf8c2d3159f204ad0f646b27bb18973452b9ca4ecd056fceb", + "0x22f223e74b95ac311f3747e410397420297ad63d5e6e7e6259345546af349bed", + "0x0fc0e95d219c422d2eb0bf38f28ed200f4f725a904c5bf85db7b31f609d56b43", + "0x74544c1e115514858a62461584e02fcde29f89ca783b3f73a55cb2d0bfe199a2", + "0x6f75971fd8a9d7d4518d2c3edd580643e148afd67e7c135cab6890a53cea390e", + "0x32ea02d2647e1e02a3a08fb4369cce33d5d7b857ba66ed9ac69411a42c8c384d", + "0xa2c0271cd9c3538ad012ae5c631bf8aae0f36d1c4be4c99e8b0c7dfc3777dbef", + "0xc7d4ae7347249377f473bfee60525031ab18e7818bf7c047dbf78fc6bf178536", + "0x0682d4bc9423be1aa3f07fc7d307d63243383a265e59d8fb963151046579f1d8", + "0x67dd80cee212ae46069b1af2ad98ebcd5a12c5ca23effb34ef48145b867f9a51", + "0xbdacbccb5511ffccba4ad93461ead16697944dd61820f19c88468f142ef81b36", + "0x078ab49dbb49bee1b70eed80685179c484e65f7999fc7f79fe3a711ffd931318", + "0x22a8907100fd6f6b0e3e47410aab0947091465188c3895852f849716033be524", + "0x6a784e15b8b309bfde5743c6b4b5006c86aee4cb56a7cba8c25a7909efc56720", + "0x48f1dcba97a055f366175a40966c01ee499936ebf5602117d547ea99384f3b48", + "0x8e1fb0be5bbfe825b57c5aaef6866794634e42a28e25df77a38348656b57020f", + "0xb3845ce8c6a1e1779f085f409821af631276cb413739c2412a37eda3d260200a", + "0x2230e2aac91929625cc9b7ecac5b84680d2978405db1565a4522d7a895ee7290", + "0x8c23ad236c0fb61af08b665b655313466eaf04433335130945586f8993041b58", + "0xdc9a50633e3b12d420663e6ea9c79c5785fd333ea0feb53567980afc1de70a05", + "0x6c1929f3669d42477844f993387ae6cbc37b7831bba146028ed81e5490dc758f", + "0x9059daec481d4ce8e2dc66c815172933e3e012a8593882a249f78056ad4b50f2", + "0xf9dfb03a341aaf57dff8ccb571735fa07bee708190e98ec0be1065fd66b89373", + "0x15a02a41a22ef5b01754bc9795e04974bcca9a3f2ae168de0c6136cf0aa2548f", + "0x494d825348d46c5bcaee447991111b0aa9e93657c90e268da1d9c901d4e4840a", + "0x3b817750bc438728bcc0b7f8252b33432cfc5453d50907ae45c62c338d2ebcd8", + "0xd529b68e9cfc3482d5be812a8ed91cbb55135bb25cfa9d036183deafc8e460a9", + "0xd6b77501125e0a57f0c0e91905debb2d024d6df612d66cc09174586b1e02bafa", + "0x4e0a88a3a74f58bab4f534c2545689b37548b4616ffd393f2267db8c691f88d9", + "0x17c75e3edf1a030852b274159fa85a77092714e370aa2f0b0127937dcd6660e6", + "0xb6fa7da4857701b71ecfb278cac489abbffffdabc6aa671fbade2d2efac41859", + "0xe8ef5fd31b9673c39399db90bce23c9ec89123aaaa1ce6015ff793d8306afe1f", + "0x3ffbc8309fe01232021798dde65fb6a4635bddaed77d08213203b1c65dbabac0", + "0x2966ce3428110d587f2d9e9809316852813e6bdb69f0a66515c8f36edc054eb9", + "0xcaeb39151adde827f09cdd4ac1d75f73a4b3dfa4c8608937c13f53db96aa7142", + "0x354b88ecead2b00b2bb215168460c2cbafec22a9ccfb84cc969ab497f9f69816", + "0xecff61575ffba36e15d742d45698a669febdf5f47d1677fab4a65cc3427cf01b", + "0x95f96355773843e7104efcfc1dffd6f298fb0a65b2c24791b9e392054f880ea3", + "0xb44ef0452bae93cf91664024e27170818bdcd7b6b5a181ca6959c919f8fe7cb8", + "0xce2a82cb562e0fa81f41ea271274d1f02eed4ea11ae750cc410fe6742be33cbf", + "0xd6a26e0f490eef7443b8dc8221745a02d4003f6a218997c6b796925b999b6ec5", + "0x8a387b6684eee474d241c1c6163a249155495da62aa52ca29aef549acb998112", + "0x72cea28da88a6e131ef42f2a9f757864534cc34c4136217f233e18f1eb3db4fd", + "0x70206a53faa4f230c5f86c891ca4337007ed930e3a7bec26209be8a13bfbc2c8", + "0x2f6bb3d5ab4be435fd07aaee9c2420080309526a70f52341194b7297a0456c0f", + "0x92b3cb4373bf691b83ab02ca22770130bd5f8bb830fa349e55692cb3b96d5107", + "0xceb646228b176e71f96dade90e7d21f2c7db94461b18434c7fb61502a814424e", + "0x1dc9aed27813fd95a2a2793073ce8572b37e18f0431e95172e6f1fc49f9cc69a", + "0x024b753479521357a211ceb85b78f4c3f635bb5c5b77e15bd2092b6b7fa6b0a4", + "0xae547ac87a1ac7be258bf1cccf3bb1e7dbb1b6db37c78e04422353421fdc83fc", + "0x38ddf517c3975783bdeedf862084e8f90ba3ad2df9470321b8b881cd7530738e", + "0xbdf262fd61c1c3bf6d5b3643b48082f57485dfd933a85cf60f6df85a38ea7701", + "0x828e793a6ee29d08f08263b8556468b5d0a7925e8865813628dc28928d5bf731", + "0xdc2f4d695b8e21df1faccaa26d3d8e1495ef7b52300903737d7ba49ad6c5fcf3", + "0xf0cd111e3ce41ce9fcffb27cdd58ce456574635e997751fb6fa1cfee26fddfc1", + "0xc9b303881045a0c4910407bbd58a9af222dba35ef790e6d3b188f3cbc04d0349", + "0xfb2fad6c0000e72f51a853a98cef9037339817c6d84e8cf4b067c1ad1f4221fa", + "0xe1414f1f8a7edfe0427ab063c0ce631ba06d5a3d9cc8dcde071f6302cb45b1e1", + "0x6ad5eeae009879cf0e0a3381041f25828266055220b8214928fedd2effb2801b", + "0x2ef44f7c5bcfc0856d215f380e8792c2bfe5c10736ef0bd0aa0ba7cacc4ed7f2", + "0xb5d7a0fd9101534bd504246c5ac161befdbddac49381327234a1162a7adf2391", + "0xafea64b36067c325fd4d884c79a9728d342cc2f756054739cdeef4ecd6dc1896", + "0xf2937ffe604ae91ec475b70a044ef165d2f61c0953daae90e63992cb5493a1bb", + "0x69a5ea452550bc85b6fd733561946b0ea8be6a1167ef6806d993c4553e02f027", + "0x3f99bfd16beaac4ab3a910dbf79c746ef702b745e0ba46e76332e5f64df83fb3", + "0x871d8703b4a1d6d946b23af9254bca992b31dbd52a54c89dc2dd3d4d9c5c61c5", + "0x908fd554e2e5e426772e774fc832d4b4117377d8fd1ff3f55453405b9d257128", + "0xac6fb9261c0b245f4dc6e7a7ce626c1c69fc57e0c29a223637a99da146e04ab0", + "0x9a03df9fb7a01223780b7cd27e2285102ebef4b9c087f6f32cb1f63016991764", + "0x5330a917aa2c137659a5ecedcd9c0f1621349cbd1ae11562f8ca4cbcfbcf5792", + "0xbe0c26211359510e5ab47e8fec850535e89d03301f5e083487aa421450b3e70c", + "0xaddfee931251ec4df67c6c5c19bf27c57e8a7a60fd6569f62681e32a50a85862", + "0xa1206c42a578a4088ec677eb6454a24aa4ebd427939216c4550fb7d12d51be7a", + "0x6c81c0799d4dd6983cf1065222dcb8c6d3bfd3ce236e3c57417a68e86defa0a8", + "0xc356b1cf9d36bb4e2f8bf64b03869ec7a1bd2c82d407d4df4c0a582cff5ba6e5", + "0xf900240cd95f9685deeaffa1b2e92e6f2211093ba83a4a6ec7c0819d04b53c17", + "0xcf10e728ff9ba17bd1031e4d4976127e6d2b383ee06581c57f22272ebf34e4ce", + "0x7aaa9304c2cfc79d2ed28aa855cf2b6f64f162e47935cfaacb83ed8f4e78fc93", + "0x45b6eae599001b455b5cdc82e83aa8d9ae0900e444a11e212e1a6ea39418e38a", + "0x57259a8fd16a85b0106bf94e360b33406305df5f93b3503d6ba5a17802ab9d31", + "0x59041feb40e4e0561512491b14d250fb6752092a024b70c91af3f1cab358fb9f", + "0xfd6047a708a0b7f7ac20d2bf38ca8873182ec6b55e4615d69073b1e839874364", + "0x6f0c025c2df8deae6c20f94e618d0c29caf5618503d3355fed14b8b26058757b", + "0xf9f5bd47da201f438fb3291b50952a9af0a4c5db743a8fb4015197cfc87793ba", + "0x4921ba6242c5532a45d6cfd87abc9a2f34f3ff103dd0437a26fe01e0854c3400", + "0xc407023695a845165b809bd12ed30227efa885faaa3a0c37633b5cf0ab83f519", + "0x52d0c065f1982e204d03964b362d89ec231d03c740591dff6355faf2860ebb14", + "0x6e2b510edb6032b08823aa67d82e7a7495fbed8b7a1c3afa5c3f901925ca785a", + "0xf56c13b9f11ef46043dccf99b1c40c412bf3fed6ab1c1b02106237891894d747", + "0x838cd04b046dc3ee6102bdd535468a10721d8be7d8dc072c6ac0c08c99124280", + "0x535a1d6a7354fc3d51e07ff67bbf0715ce73600fb6a4d5a966d2879ece256fee", + "0x07ece2732d471cf54f6388cdb24814f68e18b43536d4c0668366952c9cbe9e09", + "0xfca111ce286eed8ceb0aff30c8167fbbe464d528cc46c82a302d751b07367389", + "0x80c131302b043a3c9f03f153c262ab5fc99c1ed690d425ab842db059e820461e", + "0xcdf5f53634cb958038740b5c31811fbe2dff04917926750473e23396faf8651e", + "0x0b251bf674c097a1f6084b7d4f8f9e5fb208cc97c504e4af1c22df24b2bf8aba", + "0x49af2a38ab378c2d611d6142d22721341ffd4c7e4ea77208a6154f5badae0e8a", + "0x497c31900ea5a46025a159d2d005a6a0065f2a954f936f4163ea559a3194fcb6", + "0x6e11a069d89e3f9d8c606fed7666e60ca25e7abd3eb06021dc4cb98528cf5f08", + "0xb0a21c8206796f2f589fc76c220957da326b0ca87c26ee3bd0ec818602be6827", + "0x1c52c95455cc49a789ad9c91ff0fbfc080d01c44508c4f7183c5b52cd8d2a67c", + "0x226e0fdd735620794316a6171ee930629f51b952310b460bb9ad1af8db4c2ea9", + "0xf279db0c181c473379f076b3e9c1b934609983ffff2e4af4bf6bbd5e8b702db9", + "0x346f7dd1b2befc4f2e2394c8f260ed0b4f32e4af43c164c4ea09e96b7477ebdd", + "0x1e84e296acfcace1226ae4bcc983ede21c69d0783403e9c7c584ae72d6718d52", + "0x28afa2327f10d052012d7079d7071b56cefde51f440f82ffca9a54c25e49ca1f", + "0x07115beba550a7120910046697865c321ae7affe0d5eb24d4ee14c5427cfca0c", + "0x01d5cefc62ba9bcd1b7d07e48ac1d2cf9760a2ac4fc3d69f93c7ed347c0c3b13", + "0x954bba3b9e47d949d0879961e4e3c7f199d4952fbd8ac6189e2ef34362f6a42f", + "0x35ef992a7bf7a2b2b0acdb49cab4b9321506cda95130750f28067f04033052a0", + "0x7daf0ada3ad44ac8d78c311b74c664ba36af509b9440e276cc1cd115217dfb58", + "0x8138a1e442554341f20ae16a0f791bf562bb11bdea235ff089faea5b33ddaaf3", + "0x65ea5c69209e6896dba728c2409098b543f807243c9376f51eac4856c64f0487", + "0xfe67020e8b5d36b616c2e8a40517109b6fd06410f7168318a15c7096159910af", + "0xc7aebd89e64d6cb4a3a0688dd84ebf3f448a2e1814402b8391194d15208a17d5", + "0x81e0a798aa0a6ca4ad54a830edfe5e2e78492e5346c58c7763891818ad47b20a", + "0xd6f211f6248bad1e5d52013da24d79226a8e914b899fad73fc39ad9e42c103b9", + "0x341ad9c5497c3f930331137a5d081cdb134fcc055f85a6d50e7d03e44a593a44", + "0x9e2c09b2009f0ad546bcf12deb943c0936307e2d0c5c7d40c096a438a8320862", + "0x652e2126bf65168127ab0f92c480ff8705243bde90206096d1cd2dcd3d1e46b3", + "0x20be65ada96b76f93c0cb556151cee0785d7338b094f6b6f2c8a7f22f9799d49", + "0xfba2ed75cc2d93496e10419ad9d9ce0b33383f03465584340d5a3d1a6a90a577", + "0x16609893c9789ab20196bb30a19ab2bcedf47142e663a713535907ca6daf3e86", + "0xf0a300a152e1f3dd993dec6ff0911b8d92c67958bb0c56c4e499aff48bba3e92", + "0xb77b19d3b07bc7efc626f9ceb73d2f4d324902edab4aae4413250748fcdd96ba", + "0xe85e86b1f9f60661147aeb7df3bc40e1bf200ff1ce57f61c22c916a3203524d7", + "0x6bb9119c972939e3e1fae48d42527ba5dffd8833cd670113a979ef039b623499", + "0x0afc5ce9ac66d41de52b568dd1108727bbc4717a2f04ffeeb74ffb63bc737c82", + "0xe08075d030de513603957add9a27b8e76d3df7d2ef65f42fde161b0de1ee937f", + "0x10c0279bce16c255e8a106e0d3a0dc56981791b6214993f67316649525c85544", + "0x4996458c81f145a6a718cdecef773946b97e3d0c81907d3478f5516637c0fdb6", + "0x845c9b3662816e8c8deb911c6062a31c5296b4ec9e5e507fdd250f1b0ab45a52", + "0x5b5c22c142bebee8d99660e9485a54d8aa42d0c0f6cd5d870d006b0be3a24230", + "0x65a87e4303ad18afbe8528f7a6510ea6a7d2d9caa350a31b501db02867e3cbf4", + "0xb98ce6fc35c269d7cac7769db519d0219d44cce7bcf7075ef9c81878da0b0828", + "0x4c85a8a986de3b492aea89536dfd5312757ff01ba5dfbe51018d97b11429dc6f", + "0xe1822a4a922b0ac1dd66c06069f80f5c3c3a12f6ebd92f07fcdd424b2603c12e", + "0x0de2099a5c47c3442fcf4f294e517d3318e181e23972bfeeecaa3f0066d09206", + "0x0d18960691f8b4834f008832a028e84341daaa69e24ca35fcd3d4b83c10429db", + "0xa84ffca22d21c426548458aa96f0ac16372d5a2e91c1bd15173dab4045214b07", + "0x6fbb13b65eb2b1cdab20c23c627bee73f2f8ee6b1dcd4feafbc54a421c341bac", + "0x9fb42defaa9926a71ca5ada26aab3a0cd9f23b8c36bf542ad69ee7e7a2c139bb", + "0x8558a1f0a23e656c8762af69fe385ba2a4cce72119399945d60dfe7f2b1c79c2", + "0xa9d3f4f851a03f9fe4b1a1c85f42a07b7d7756660ced3bf43242f7750f03e374", + "0xa4b1e0d91f09765bb5bec63f90f3902b06b29efd9272a3248464473e9a07ab95", + "0xe881daae7e35e21a2add885735e54e6e847bcc8fd429a20be45ac749a15ae81f", + "0xc25c69e8c0a61e8103f0f952adc5c49d24368253be6e4a9e3277b9e02a2c0fc9", + "0xa39fc2e497a7efd9e6b0ad2775518e9d01c584cd134900e8a796056e8280330a", + "0xcef1c3a1ebace0a6e7ab1e402dc20ea3917c38f88f2d305cd6939e380a40f603", + "0xbf3bc7cbc84203db96a973047b2f4db2ad204b4c48abf5076fc8f2a0ba049c68", + "0xf4550102b8bc55969f17c47165605996713799aae54b4953ea539fc38a5c4055", + "0x852d591591504b86580e1193a4d2d6f30f1404d64cf5a53dc200b768151ee0db", + "0x26495cbbd2983bdb5a41d5a1b5b186dfcfbddc53e3955f2947269a50634e966e", + "0xd623f346b2f6aa11a73012577728a1b71ca74e3c9458da8e0ce9affb0a927b0b", + "0x6d2a19b145e354d56928ab1960565ab48c0fc487610f1043ad078623d606c343", + "0x5c612211df07f1a91909d1fe8e6cea9a2196e7c95c27445ae66649995e491fca", + "0xe7bea84b4850a2b7bd170c61a699f857c9685f3125c4902e9a21d2292ff926f0", + "0xf7c44f95c701df6a93f15ce8de008ea3c7e087d9faf437613166f226ac433254", + "0xdd7c4c343931c6a3c7bd49e6698e791d6dede3234075a5eb5674df621545d6b7", + "0xba668334a45a2c5393b4ae3feda289818ea261634e6dd277f7a9c284d4b6514c", + "0x019717a5c3fe560bcb9a7df209a156efe550075313c38ed8331ea4117b14987a", + "0xdbdb821a7354c2d64067300221a47c4936307f1a918ac4fdc716eec9b5421217", + "0x94500b9c93da559d73a918faf0cdc9f9cb3a90b0dc219b63bc4ef84634325aa8", + "0x50b4ba5b95eee9bfbbd94c71696395c3cfbac865b11a294349f1f0b57f70ddb0", + "0x61c4e5aa02c5b13bd7c7f8ea3c2fad8814568e822200062f88df9e87b321aadb", + "0xf98a11584eac3ce8032ee5617616da3a8bd897ef5b0c780eb36b4f3005636ff3", + "0x13b2479c0d0d452ade1ccd27f7581a257f4e21fbe7adf16b4041e4b4001af070", + "0x6c58a1f54b7160b42b06fd42da605d8576b82e586bc53fffa424a6ad51d5de5c", + "0x6be95b15b26ad33ea46f8a3d2b6f6770513ca0b315c686c86cc4e87f83257ee5", + "0xe9c8510f7a288699a5558f0b7a0808e568fe0093695bde1e2c7eece351d979ef", + "0x9822e17cbb24d2eef601ccbc3c4e9383b5189a92257159918bea131a41ae9a8d", + "0xfa0a7f7e8d554c6e75aa1d562406feb962394b514fbe96deb27d035219b70efa", + "0xbb4b62a1ebcc8f41e42ca70d570708bbc9a57bf08d5fc4287bc94729d2d391e8", + "0xbb949bed075fa35a9452fc76c09e600d2aa02444db336625420b61302c5b1d2b", + "0x9f1cf8520fdfb59122c3d8ab6e8ee9851b9e852e3ebb1ab940d7d22d1f0fd60b", + "0x11ef3c742cf06dfca2ddec7911e5ceca3362036177368bd15e9d4a7cd11648f6", + "0x9eee5f42a36978479d55632d8d86e57de7cb73c9b1961511cfe9b3bb70cb8d3b", + "0x7ee17dba9f383b15682beb87ab797dbb0ff002d21c898704ef92edaf7049f9da", + "0x5751e43effe6b2a2ab9414d732ba34acb7a7599862fcac4c8335b1e53e98fdf0", + "0x7f476aa4ed7c48da093dc85084df751a00dbdc6e89eeead918a0513879f7a47f", + "0x792ad74f008a7c2dc0b50acea37d0d9805324d7c80efd1754b0e07bc47008390", + "0x48653017bbc645a99e5264c4d5f781655abe4c417a9a6dc1a3e56684dcd01844", + "0xed182e2bc223cf015d21f540c280e9e49469e08d840fa00989dadf68ba643df4", + "0x7a56560bdff2aac53f0cf9c5979ccede352e1ec0f3200cd1cdea5d704e61eb04", + "0x37cdcc0b9f310f7f681b4d044a03d97cc09f7512399dd99b8a43a6fa80769414", + "0x75b7711099ba266a168f5534685ad829c011ca79c79eae892f859fbd9d5a76b1", + "0x1e7739d74174ffe0dc6284f046f73618eb1f854dea28aff87b18f09ad720b7e4", + "0xd695ff00975f61bcc48456903c764afd0ada99460f1ecc65171be258cb164115", + "0xe38746dc9d2544171763b0480939c1c8377102b4125f7d27d05f48d0e434a712", + "0x8ac00f72334ae5b017926bef6f94b5551f17a2373f0f7ac9d225651683fa5457", + "0x7dea798accd9318d2d92e1abdbabfaa902ec40f6c63d3ffaa78e81a5eeca2f06", + "0x5ff02bf62f47617330f64d1c845d5732737cbc397fd54d4167e727533dc81f65", + "0x0c7688c23adee0d14383cabf150933ba9cb448473feef696b4fc740840629b0e", + "0x2c2a277b1513d5446429068213180b0de19599b35fb6448da84dddc8c7676bcd", + "0xefb57782f278582d9d11c6b1972f2ce5799ba3383bffe507922052f09e6056e6", + "0xe308b75bc8f39250d4e02f090076c6f6e200f30904e3147e7cc57be2d8d81a5e", + "0x86b99886fbd1b58295709017cbe9c2143e932f8577a24f31528ffc025a7e44c2", + "0x643118e6e01e1311ec5b12696b59cf2ef6ac531f028b6e23f4a3025235ade454", + "0xe0deaf6d9c1a4da0c5e60fb586c550e30b04ef33b1aff61f9bb7491949e2ad15", + "0xe3ba800c9905ea8556dbb2298bec7009f633772f55f3ef5810ecfc1a391bd3db", + "0x06406d3f51ab5ba9096b76702130f3f27aa5890597996ec8a48954d16f4e29e9", + "0xc1fcb87d9c0c29b70aceefe3ed5b3608d05dde30b6d995dbd7bb7154146e8853", + "0xf65e31030188f5ccffe39cdcb4b847f4547924971aab5780fb446b1f08ddcdb6", + "0x662513354a8b56413cdfaa0b56fa031a0ab1c58b16077162174c4c8b814cb4c1", + "0xc1ca59f2eec9ab3839f85e742ee26e9597febd648df1a4ceb1134211bcc0ff9d", + "0xa454920090cd3907d585781adb9af550e4d927ab83ed88856dfba1bcb4dbdafc", + "0x5472afc931e445cb261e4d13cfc84e04d1c2c2a8c00120c73e055c5e8c0950cc", + "0x9bdd7291f4e3b0b34c20e183c8129eb4e9cdd3430cfeb3fd0047a2fad815c797", + "0x99959d3aa3de615b1d68e236786358a48b0b1c52ba3017a8f9545e97402ab090", + "0xc2a6d1dea0a6091a9f5441e1edb2c99e5a4a4bd07238662da8ffe3845d526b4a", + "0xe1d7948ea5adb5d7dabcef081801606b1c74230e9b7745862b2072434700050f", + "0xba15f27b7f2a19dffddd7f0d72285ebab40edf0fb9035336be6912d72ab5cf4b", + "0x61f06104ee5488bec408aca22be90b37d7b2f76abace5d8e1d9daf8488c10dca", + "0xa601ad3010bb154479bb7f04b3118da08ce7aa66afbb65d5700380566f7dd04d", + "0x87eb8b49206435fb7a6983d6d7ff92fe0cbb173c7be1c2542d6402760f98dee3", + "0xe1c8d190243bc91eb6012c79103d2f91e3c652fe09936b0d194a024a8ec01f1e", + "0x0752aaebb4b1c381e4d9747d5045cde49d99011784c0919329c81ce7d99bbc98", + "0xe74f74673b076b9761a10e98c8ddd456391a2216e9e658cba548ff094192ee92", + "0x840203d6cc8e414dca34b4736501bae836a1febc9f84589b673bc55c2ee05ad6", + "0xf61b094ff4320abb822307cb6501a76ca6ceddd81661531751782feeebf7cde4", + "0x4dda3a80f7d02dcfeb4630ad9680c37f7ea01f0ab9e5d506417f0fe4a1c82e9c", + "0x142f83abc309cc5bdaff2a385bd18dd96340b4d14a472c3ff64b280835b30587", + "0x6bee7fe1f7cf8faa01d094bec19cc20004d11d1f9408473ffde658d087999f67", + "0xd811c2011327ef0c434ba199fb016d491cbd7dbb8ad647967fb6427d7f72cc9c", + "0x4c9a5ec5e2e002c73f8e04c7eb8fa2e4c54188b71b824872234872b44f820568", + "0xb1520f14f6e9acee16c52de5e36d52ec19a0f90a90e8bb0e7d54f3b52c0a9398", + "0x52f8ebb0ab694f94d2f0baab9740b8410f581373bc4ce4bf6e7fd3e3f64685d4", + "0x1a9d0c5df31ecef11e6a1bb402e36fd51ac62c296ec51d1cb4612581112fe940", + "0xb1533ddcb0dadc809b166867c9c06c4983ad794a38014bdcd4eeedd3473dda61", + "0xf4a202576a94c983de3aa2ac0bf6cf403b8f22fdc39c184c702ca9a6503995c1", + "0x8ee1285025696b8908790fdb8fb1e06afbccc29841ff3ce9fe3bf7cd307bff09", + "0xe396c7b228e54e3002b042372a95debef7e9d346bc660f4c00ee5964978042e2", + "0x721acb1e7c918b232ecc98bff0297db492c57bb356b6a8da2673286f241c2b74", + "0xa4fb8ab31c31986031d223b3dbcd0a903c37173113c90da029998ff0f8031db4", + "0x225d7478fc19068a839b44ea477db46b6e044af11278567db75686c007ff96b3", + "0xab3aaa9e46b07d86a4771de32a6f4516543f0e7c8e25aaa78508c9e736b85abf", + "0xe16b1c4f4d0fd76588abec3c00c444c658d74cae60ea1a74c56cdc727e1b7001", + "0x27b8247c8d21156cfcc17d7616e218a41ea1597dfaee951dfae6ecb612140d10", + "0xb7930ab63a5bf124d615b21070f24ff0cd6ce807b9eacbf4f3d681f7725a4b7c", + "0x4811fd297a2c2731e35396886868ca3b3162f144ff4adbeae8804554d2a28de2", + "0xb1afd5fec04effdca7ff5801cb197eebb13d65652c641bfdc4719ceed05f70f7", + "0x7472cecf0bc3728c0f0ee7141ff0513395d012d3c3e1453fe01e17f44e491d6c", + "0x6af7dd9ef565e01df7771db29033dbe061046079886f798fa789707004f61af9", + "0xb0023e5e5b28da4a83187d053fc1d1cd90406f5f058c19ffe3f120cf040aa529", + "0x1f0cf67a9250d1ee3a9a05e3587c8c87961111b9bf10b94dc13e896c701cffc8", + "0x77f16085517da13e00b449abbbd217731fa12beb4364b8a7d650e44930cc16c1", + "0xac630ef3130001a6a6805ba5a00ae763f1f5169e32d50f8e2461e9b53ee1f37a", + "0xc9472d0ef3a22e37a5b5b333173ab18b5d01550cb239d47354b85f85a3dc8b39", + "0x10995cc8a94ed2a5ce0aba717ab0c3598a46634627ac38aeb9142f1fc04f6333", + "0x88f6533bb9efca7f80b6680221f2bf21ea7e8a21d798c8a461e0e8cff55ddddc", + "0xf342f6a8aa3b4deedb9cb461e601fb6d7f57378495f5eb3e489dbf54db3b0f59", + "0x7835d8c68f16abaab0abda4b6e3088a03c9426a838594cf99295bc270e6f648d", + "0x4ef4750a1d701da04680c6b04bd580aa189330bb83241aeed55fb55dd2cee52e", + "0x9f7cd9e7de4c6deb36156b37a73ea8c6dd068c3efa733be7aed94a1a801a7095", + "0xfe0af324ef5a44e7967bbd6de6b916e3291cbd67127356294bebd18b164388e6", + "0xffef694495a0c487f654af6891b9a5f585264ff3f3df7a8ea6438aec56185031", + "0x0c186c1b9ac25ee05118b7fc0627966136ed97e42dd5b433b4a6e732a29eba9a", + "0x8a13dc929b97d7861647c70e2d95546ec10c248ea2a3971e282157d1b1803ef9", + "0xcb332dfa5e1f0761612276bb430c84ba60a76199ebf6856c7450b3007c369d5e", + "0xaae70cacc2b426b77ca0dee01d7988975d73af89f4688d01f2141a06b6261032", + "0x6618c49567dc4b1ee6f06de4ea46f384c7f917e5353cd32910045ba2da2a2c43", + "0xf59ce02369f22c1dbc1480c2f99d7737974742754e49838adbdd95872377fb9c", + "0xa647b3029eb79001e782a6689aaffa70d0b3ad84bcd5acf6e7a0d1d1c279f854", + "0x56b4d39909a387fd5e4ced15060784b8236427cf6192295d98be51f988c47d56", + "0xa23cec0fa0bb943d9b0fe829aa0a21632328d8d67efcf507d570f170ac18200c", + "0x74496da6db136824f209eaa839036e3a7e94363b1e23ba39d1f3a74f43f065e6", + "0xfa2897c07d422fb4d81fa4b22c393ebca0cf86d03848fcef41e4f14e61d06699", + "0xee3020113cc21d2da50590ab8d700d9584e958af1c6289e9291670fbbb9086da", + "0x03121d6a6d3d46737f8010bfb658ba934bab32ae835b248b6f11cf44985b30a6", + "0x35a7206abca809ca24c3de74b82ab231747424aac530c31d1f93e9266d1c79ab", + "0x2089128abc1988f1e2ba2f294cabc7d2aae3a2be249b86fdd7cbfad5c05a3b26", + "0x31579e077a21db02601ea141fe21623899ffe195a3b947d2f55818140f5b9d59", + "0xaf1befab09595e55f83dd8a6c6722e62700ea5791211e27f5002db88bbcd806d", + "0x29242bf7c89946f11899e3425e7fa79d08a1a1b8bdedffd8dd02e823ce787890", + "0x2282493a8131f5ad82b0f5bdeb6b0f392e0f8636e50fd1ba90b09cf6ac442f02", + "0x39f63ff122022bb62c5d8c1421af47ef94991bf3a8a97e5f702de400ec5e1f28", + "0xd9f43250fc143e36f92a12a993e44674fceb81e6ac65be08361fcfe91401b3ec", + "0x88ae3a33d93e8627d827fa95aef374f9d9df8a7e821d3542c77b9bdf9e765cd8", + "0x239a22800e8b887eb6f84a1a7e09b7543e958ffaac59f226ed0b91af2afc2b09", + "0x8b5253760367d4d8c235f54c1cf85883b40c96d42a21e69e7055065dbc266b2a", + "0x48929c8d87f726ba8717a8d93e9eb0085832e900e658b5db11a0ec099915d835", + "0x735f49fd642ead8ced382ac68819104688c4610773d8301efa4f9ff1af9d6374", + "0x1473095adbdae18abd70432823099c217d15d6a394553cd6a4a20daa1867f5cd", + "0xb92e5530fee287bdd20a0985a22a0712ea61f1ec39e37029036aba475726e3e4", + "0xb16db48d134c0a4dec30f81c9f521b9fcbbce57923473d9a0a2d8ccfcd143b83", + "0xfb0e576a64b8f2cbb043c6d55cfd622735d9c2e8e1c73c7c85712a3555fd9300", + "0x0a555d959cc4c9e681ac1def25251f856b82746e568182a1802c662f8b7cf327", + "0xc65727c61aed82e4fc87810915807c5904fbd163722d783b6f9983823f425d7b", + "0x80c5689148bdac882e9b85f402f8e2ae0563f92f0e1214d706ae0f5029508145", + "0x3c81dd3a1e7094877f7ffed704a52a2e177f728e19858d21c0b46296054433d0", + "0x6e765d51cf90b7e021567584e0cdae766c20d4ea61f40d102c5b237bc831f0f3", + "0x184c2d3bc2bd2e96955ae40d7499886e46e2da0b9fdc3c55465f3023879738b7", + "0x74162a72176acab4dbc8ac904ba1ae98db539b90d6010a3f3cdd8e86f99b03a5", + "0xcb3ac6e8d74afc0c2a2908a1f248434026c99b89e1494f17f05717096dc44682", + "0xaa657accea572d043d5f4da5ddf01006748d22362d5512be8f59b849b86737b8", + "0x6165ad890727c2f2bfb07cb4f8bb5702c3b802e7b3608bd0985bef56bb6d8934", + "0xb1bf86dc2a2023f8d6664bbf47cc8f80df8bddc7c71217402d02b485fd3fd7ee", + "0x755f5584be60718fd8e846ecde5ddbf6d160602441f6ef0d688043f6b444decd", + "0xb4561e1c950702bd4248d9dbea09982512640f1fd2380be6d9274c30ad2680b2", + "0x460fe85ab763867e2d544c249da96b476dc97b0585f35efb9c5f75586690740f", + "0x3c3b9419d1d71df4469895601daf1848b25c7525ad0cf9cf84641e5dcc4013c2", + "0x31158f7120694fdb6c8ca57be4a4d55d1fd0dfacacdb1d114f5bc81cf3ad5b84", + "0x87a0735ae331643d6ee5d75ee57b8acd3c096af9fd2bdff96fe21fb2e23e4c03", + "0x86ee7cb0e0c1ce7d68c40bdf308765a91daf9098b6a2d0524e84dfa044319eed", + "0x76b78aac48f86b1698d304c27844542603f59edea7e5d4b5077bb540c4084946", + "0x3dfaa796235f91f05e80c5eeae3759d9044fa47164460afc8eb57b022cdab0f6", + "0x8c4858b78361011f7d35d81e6e5fdaff40abe6f0db70e2e7cb8b9926012b59ec", + "0xe1ca3ad88639975a3094f2d5f2bf812b91732c7e681aadfa9838d48acd2aedc5", + "0x8722628324d16f4d9d98a1c05126ed28a796927a7d92b12433f450f9dde982df", + "0x969ee350352d2b966a70f3ba7209d9eccd11900225f05a894c682db9e91eac37", + "0xa652d00076d380708fdcf9a8af53307f7e8ce8be0895a620305d2ab694a41081", + "0x9126ef241ef900f6eae95ea7fd48b9759fab56486dda0e847705bdea850a156f", + "0x545ca4cae7541ecab49f31fa795974ac2aea0a80faf71feae0a7c778490215a4", + "0x28507604ea28e064be5da5f6fc5fc35d9b19866cc8b349bd97791fd36319b982", + "0x4d81d0d091b500eb8e207c7ae8cec63c32f766b55a4193b5ba0aa505d8828ec2", + "0x472cdd8da3753653dc90e408bc2931296d0c96872770400754f79f63cd42dbc2", + "0x6bffc19062f0d63fcc842db4fb492553335d0340a329bf4b6877e1135fc87c8f", + "0x3bdd494804e2af4270a11defb4f90591a61722d9ab9f8e9ffa36eb2b38f31edf", + "0xd51e3a94dd3a847b40b81550428dc73ffc00ec66aac2751accf904355054046d", + "0x1d52de027023c8a53e186179c90653ad6e72816e3b5f2549776844157538d567", + "0x683a282516a4c1ed3f8964d616570138c545e00d1ef58e3eabaf2b5cb4017670", + "0xa066a6910e96e6ffda5553ec6611ea52a6dc244b4575fec2d0d294240c169173", + "0xce30711f7ed1859d2f9408577ad316b810e48d78f1e9500993eb89b7cef6ec4d", + "0x998c0d9a44997597bba2c9c9f0cf04d0b752b7c3981dbd31a37b433d559aaea4", + "0xe4775536fc7c8a2e15793443c9f81eb32800d339a4e54d12b621b5c3eac69c9b", + "0x30d47f77828169c8831dad3a5af4f59db161c8c639f9647c03af7f88fdf6a0d2", + "0x0d9cb6ae0f5b05ae03eae9f71fa10d8cc4a11d1b33ab4229941062a20979d2fc", + "0xec4b532649c0d685c05d0de3a652f3a395412bf4a67c813c573f2c261a5e143b", + "0x9b105824aa129d95a45c9ae21e83e89bc73f1cec89b4cacbdf81c6754e44978d", + "0xd4f7656af32242c24483894450a6c9a4dc39eebb7702228279a918c831bb4fcd", + "0xdf7d66dc72b157a57b7db88bd90cd61e7c581624847585088ab0d70fefb5be07", + "0xd94cb3d9320157336ebc825a669ebada765ae8d985ed3cb94b2f9344f49b5bd2", + "0xc92f6a9417507c04501e469189bf38dc7de37d2acb9b4b9ab444c9f7eddce74c", + "0x1d69f2b12610020ba4cfbdae081aa2dfd740319dd9afbe523d8885f9ea535f32", + "0xc931317a01775e3549639948b79d2643ba4974f46ba5da05d3a65a5276a62e75", + "0x7a7392150380ae3152ead78a897780eec8f20ebc3fb58c552b49b6fee307cf7e", + "0xd9c6a9c4e19d8d5020894b78dac2b019f53b0c5a906242a538fd105a539771e8", + "0x0d59d2947332b0bc87470704c4dbba5613df8c9233ee7b4810bd0c11e521c784", + "0x4e1e3bd3b80672e7f6ea8a9dad8faffcac275466cc3b09a409928a6c2f6c4054", + "0xf2ce305c9c72f5d02df8c072f1b41ac49a9f991b660a3a0ebb3884ca6e38ccfa", + "0xe53859f4e1ceb58901c9395e71001768d096a355d2fae64b4429889ae60d88b2", + "0x84ee091c71eb9406957f377d9690f2b6b74703da3798cfb801fcc404a22dac74", + "0x386ef8f6c5d07fe658167dfb1aa408b0f51b865e93faeba22571f981a87b4c6e", + "0x5e5f828788586e30ff1b6b62475b5b4510f1730d61a1774cf209be25940b85c9", + "0xb6b0a202ab4224f4050d6685ad2ae7eff550eadb59c34e65e551b428b2b762b1", + "0x1bc0293120588411e41448eed6436d52389fe915de5d99c133caea02abc1d6b9", + "0x8fb61c67f5dfa0bcded55375847f5e94a875a0d0d7f2522de0d0fb064ffcc31d", + "0x6247750212b8158b45ebea4d4e8361b0cd66fe40ce07ab208b46bcf89797be74", + "0x536f1586f67abd4833e3796ced30c1ecd742f9b705ab736321f96e8bd9314341", + "0x379a7f7c3897e4c8545d268d4f786fc92799a50652bb8c3cd60416493c9043bb", + "0x0593835a986174225dcb5d12b9f006e551935714d56dd639928153cd752e37cb", + "0x25b4a18c4e41dd881635e78261120840c9141bf0d98f23cbccdaf3704a9a8682", + "0xc55f91278be72dd3a066ba1b9efb1d39d011a723d5b123cf5ada81637c6279f8", + "0xa17e5f021b8511bb74054fc8cde1583762d36dc706612dae90d326712077af5d", + "0x5723f1ebe3c09c4751b843d091ec3fb2bcc6e5247eb6c9dce7fb0cac1d571a2c", + "0x5ad78014b5d8d35d114c0037a03e3adc7d11435d94319d078d4f8f844eb9689d", + "0x6e85d730f8c4c54280eef864b3c3033ba64c59331eb55ddf3486b0b54f327bae", + "0xa70f92be372e114b08f5e611a5de003a3f8c2f08a131bb54f45310783cf0877d", + "0xc6704e4b5f2344c8dcabc9885ad3eccb4db940478d33c8ab9fa44286588f2476", + "0x1c23d2841154a346fbd28abe3e2276dc83ebc84da8073ec82fdfa414372609cd", + "0x2ed8f84b7eb32b7f290c6a2363ef8d9cbd7c624440a8bc00b1adbe3f378f5619", + "0xf2c91d3ed1c6aa7f736ab4b936081fcaef6654a37aa28fe8b7e1b7795fcf3752", + "0x4275145e36f5873e14fdbaab462d3442d40a132b3975a2432cfb9a08ee083d9c", + "0xde5a4fc0bc197894296f63a7cee228c049e6aeb1a28f892dfca342fb35346bbb", + "0xf92ebf124db0be2296859cf79bbd14263db4bf5206b7dc36b63b786de7b64ab9", + "0x16eacba74f74c808a9902d789337826eaf445e9a131d8ccabe3bde22321c54c5", + "0xcafeef8dd957b566ee6f9673c81107fe9ccb499dee211345593194ad3de2b3e2", + "0x85ff213e7a9dd6c021ee307e6374c76dc08237ea0c08e3f2acdf94fa46a6c09c", + "0x4e4de2fb8adc658065aa6e54d888ada05ebaec39714bd466e1e35742c14b89db", + "0xb443b982f0945e0963f1cd43d85af46864f420bc47c75c59ebd515227a1a8f1d", + "0x5f2493aab4585f81bfef5a113985dca819c5e34693152c191ceb35e747e2141e", + "0x6d30f0784e1edb21a23f634ef2a2da79734ce86e84db6a201c2ea13262ff9074", + "0x266f276556b8b3f90c00212933c9ed2b0336d8abbc2cd8b544cf132aa516e814", + "0x88100121c595cde6a22f901bf8dae321fe8b12ba7a3b67b4fbaf3ca2f8b045b3", + "0x26350d866afab7c488f36b2b97cd252c01a9ca7daabd3932d7e6ae1ec87977df", + "0x7392586c92ef2eada65ef219f34c0fe65bf9042d46923dbcaac02cc3ec7704bb", + "0xe5bfd7a884d8a984993f6f35e4ec626883b473df444de5cb15ad9fbafaf872d8", + "0x6207ef43c9b95c289353d40728d56d323f99d7e815d4e8a8f20d621e4b47a0c5", + "0x4a757a8d31f2ab1176c4f6ce7d9f39fa882c0bac80af99cccffb5acc0b416c39", + "0x1aaa9fb56c4a89d19db5b71ca66f74d1dae1d3aa516f3d8971f3fe5796d4293d", + "0x83297fb846b8e3e76cd8a5de225b0d763b5ea7e713868d80306566fec3990852", + "0x018a26b285d6baf120e00091ce27f1695c58952b23020cc798b227a44bded5d7", + "0x1bdd73cb3f78d8d4f008345290ae5b73007ccc000574929b60007572b9105ce5", + "0xf3f8d1db0c6282e8359bfc61683416eb683c4a69b930b7c653ade0606a91b8e7", + "0xba4788f36ab573953242cfcd98b17c19eec15c25759007d8c56a3790f14f4d7c", + "0x351dca68df8b8386e6efdd4c9b52c00c59bce95ba4f74a851927f256d93c202f", + "0x91aaabedcb0e0b2a838d62f05d9856e69f6df8b417770b8ad8bebe608e327448", + "0x5cc4d0e86aa63c5afdb0c5b1af99354404c99139f59242ddaaab78b8795e4aaa", + "0x763277f6e08bc3339289d15e70fdc74ec3a7690ff0aaefc791108b4da440937a", + "0xde254d61b26f3a7b54e16a7b265d42874815783866151333af03f6bbfe6e7f5b", + "0x8bc4e31e8d5ec897751a54b914c61485bf96e6c1fc87c4b9bc0b19f935423dc5", + "0xf20e609f7df30958c85399402dca144944c5eed049b35b2300ee1ebb56e50077", + "0x7085a365683933d31e6b6b5208974a893da182c6c9ada13abd806e03d506d0dc", + "0x9a80b9d0aa3288bca9613ac41372f675401c5d3d230ca1b2a6add2ec68cb85e8", + "0x82e6d8e7b19c30fe2a651ae7729cc406d49f339f2d43766f973b9d97a25857bd", + "0x646ccccadee90279cfbb56b158944b553db8d9bc725258876b8a78de748f73ad", + "0x94cdc4f42628fdf76b0005121574a33d02a3202e6172a62dbebba6bf62c42d9b", + "0xa75e9362d131b54af8295567d15e8be510572e6453e25db128f74be8d85d30cd", + "0x5772c596993a6667dd424bb5e6666ce2625a3e1bd8e9817dfa77f7f6f3d12d07", + "0x19a40af4d283c39bbf558b8ca585167ec699705d2bd3c4ec407ea30cc5ad923c", + "0x38ad933e8bc4f3da73b32053b6fcf3b6c71ae4bc4f69a517c664ea228aef4409", + "0xfabd9776f037f9da5c80c4c88a160e6f139b08bef321e49c73bfd741a0654fd7", + "0xb072bad767d789f424ad028d5802a0a57116ed39aa831dd7831d70bb7165ece8", + "0x673cf8961606da36c2721d0536b8a3156860eeb08f664305e7a622104548859e", + "0x6c9eefefff1da960879563dae8f724144a96415e75e8a0dc54386db7d43cef7d", + "0xfe4be619b6f8239049e57938e5e1a3cb51bb449aacc71ed4f0d6e37976aeea93", + "0x98e94e7d559eeee117526394013c05745833c7effb89ef544740d775998e2611", + "0x442fa6baeff05720c957a896d00b60d75d7ce84bf688087a0b2a8fe3a3e1e97e", + "0x72789471d2b83f99b78fdf098f3567173301baeb07b5cf6ffe55acda8f9369ea", + "0x80fec35949e332105c99d631157f4b47f43de8bd10e45c9ad92a4acbf236029f", + "0x5baa59d727f7e4ea83cf23efa88110e8191cf5a89c68aba70b642c96c0b72458", + "0xda33eec2a35ff5ebd8ddc2541343e097320b99fb8ae2cc24d055253d3bde22ee", + "0x2daeb33494c6b567e787afa19f46c3573ab7896880ac064cc30c24b582099758", + "0xc72e07ec23ce92a0e602c03daead89176ef52171f5229ea97777e69dab16d348", + "0x3348c37d4fe2b489f7ba29f775c87ca8fa775c2de95dbf7c87498a78a620d76e", + "0x261c881f9be7b5ed77e82db8e834e7c341d942217264d7b0dac1ac29c94d8f34", + "0x6762ff4f6f3d5635156a3eb07f5b259c50566d7d5e42cdf52ca11549574abdff", + "0x4034ab592ada763d4b5e32cfc3714316a599f0949288b9aea686f5d246749197", + "0x40a9eaee7dcba2fc78f5435bf5051f1d9a84026206f47ef02acbb204c34038e5", + "0x26770fc1dd664253579e16671974104ee00835e80ae15d164ffcdd5b194fc676", + "0x8b8fdf4424dba145b4fa00ee2e72dd1f2950120bdcf9768d1b6b19024055807f", + "0x0324a4d2fd82de6bd6dd459d19b2f02a7d97755ea5dbd010be3b108b0072ba7d", + "0x20f243e1c374b7f7729e875af2198eaec2debcacdd513863f86e5597a5608e05", + "0x0b9d49c34b9ee53774fe8dc1643b59d69273b21837a720763285cecd09222186", + "0xc10756e8639cf67571eb0a80946e4ca859cdbc5761fb6aa5ab46cff2dedf74d5", + "0x390f9b716cbd49681056b9e1fca49530e51472c10c2df9397210cee0dbf7cb73", + "0x6bf8f1ad4d14e98e50c4e327acadf8b22002285f06d22c61ed0a574e64e6b540", + "0x9487c95b903f6d33e8ddac0604167fab06bf6f1a62fcfd8b38083ea15712bb7e", + "0xbc0a6f9f5cb5ce4727803f0a6269f14a8f267e7a3cc221f36c3ea6053ab06692", + "0x93de0978f4a5277ff9cc8d5d538a938a7813d1116f6f473333b7417837863cb4", + "0x5e2f071c171923d561fefb8353ea7029f03d0b61f443970177206e8e93e51842", + "0xe3008f65fa98e6231cd4cd619cdd90e613637f2a1f424ec4163efdf11bd03426", + "0x4f065201faf5eedac4c014b27677d00c6b0325aeb75ad5b8ed716dd0f772c774", + "0x077e03f083a4827da5321edc220f6b96695f7bc47212a7a0982d0215d0115308", + "0x21a9cf94043d38a61471a5204a4fc6967587c970632a6683fab048ea27ec54e1", + "0x2ec179d196277a51271fbb2d8a24597f8cb39ecd0746a32bc509187ede47dfe8", + "0x68ed1279809702f81463e8230122eecaf48cfc5c0eec75498985d261755c076e", + "0xdc3fadf8293aefe9b9b95ae2643b48e874e19d47bde7fad6f12723e1e2c9dacc", + "0xf861a8077feb273d45d934549b07e846a16ebb2c6555ebb7e57dd9027e6eb343", + "0x3fb3c7ee945d5782cdcb2f8062148f8335023a42f8a1d94ef19578df3923ae84", + "0xd9d6149c09826a82d19bbc0efe396629ec5265bfc6639bf49f977b971cfe11fe", + "0x856316f73229995d3abcb1d7c760fbfaa8ed4a824a1de6faa2adb62dea2bbf3b", + "0x7695527d9fbb1dd9b3d1d95f2c102937b36c69edb0ac0949895a29cb0eecd3b0", + "0xebd39a0511e64daf095960f4612cc97b92a98319f9c5dae9d13f56c3cabf3456", + "0x862aac10df3f3f8486d07015ec829f4ad2a4ebfc96d9a4c1878b9c17fcc85a43", + "0x921ae497e7cf40b3578d172a373c39b8cc7c05414e2a706741147b3eaa23e8c2", + "0xeba8def627cb48ac443fa362017cb5ce06625252475dd30e7731b94651f41975", + "0x8f9e9090036f690f546d90cb1f74db3804304791947603d2460e2c83e439acaa", + "0xc5fff2c4f0f1847a6e20f1a93e2ffcb305a2b9b34b850532623899b3d450eb57", + "0x4f360b307b8761f87f46e1ad725998e0f94343967cb82bbf415c11bdf81ed1d4", + "0xd6604a5c1de0557b6288ed612da8f3311ded595be696331abda1a121aaeec31d", + "0x80e9135f9f5f0ab84828493327a1f76e22abd9b47bcd765174f99a03a1330b92", + "0xad1896959b309904c28415c9349746a47365172ba2a9f64338b7ef27edb13bae", + "0xdc13ec27d5d5a9799216e01ac08f08f87f0fe27a3ded97f0c79a14490417f05d", + "0x131aa3e6f9de242ff71a78e411a7eac79a6388d93162030fd3e5cbe7ed94b36f", + "0xa2defd1306fbce126ac3fca31f72daca408160b2a8c9f1e1b333fb4735471e90", + "0x565c329d62c9e15a58c00f273ac372431e0948bc1085d1f867bb9d1da5584e5f", + "0xddee498c84407a18f7172931527b6033fe72a76a0c1da15552e83d4f8111d81e", + "0x21e8ad6c7085ad6d9684a6d0cb649ce7cf736aee2a5f0b000deb0562b405df42", + "0x45cd4e94e94e418f254673365013611ced27961529ab90ebea1bf22866ab8f98", + "0x21641687a64d6bb2aeb1fcd1dd6820e8a3263e8dfe1ab16cc28aefd81ef33f03", + "0xd5653e5636d08dcfa9eec120562dacb88362164c1e6cbf22b50b1ed763be783f", + "0x799d28262dd44d6edc81fb2d8ce0537bde7f17c553a793ce0339dc41ffe81604", + "0x056c40b65418757a9faef6e79781d952d4d7faa87f9ab8b543fce95335ce5661", + "0xb25dc95e4495eb262af93a71cc7d7f8c3894949564e00eba64a09393381e2308", + "0x2a117faab32173593c369a077551cf32a4f2ad5ff47db09b02a9c01fc9231a81", + "0xb97263788519d2404cd3e87b3c5f1f60bdafdcd66f90cd7f1cc6e48c91e41386", + "0x81cdfcd9d33a1187be2d48d01700f650a3cb5ad9015be43e5e346f1e74ac0910", + "0xc8def1ee952bd7c6d8e7104ed03afe3b2c3524ab0309d675e6a8440a8d30c707", + "0x510f4396b7b49c7a9d22030ddf7f9ba9028e48a17ff4c528aed714e77f5eaea2", + "0xcd498eccfbc75b2f53fa83e69ccd9609cb5b2b7776593b08b215c341814633f7", + "0x968f34b1265f018a2d654665176690c9a7f9c734bea5647aeeaeb30b79bdc35e", + "0xcc7df5e5ce5e0466d1984bd0dd141bad375efb95955f642588d6dbbca7ccf6d3", + "0xff24c0d896be86bf5b7a634246a697b71034b78a30f1c7180a38806e1666bc6c", + "0x5c7638a57f6d0719176a165f1cf0b9660dc115f1a988450148d52b8ceae47bd1", + "0x8f2dcb63926c2011dd70a5d4232896ddde9c484ed5c79619c1d38bbd8aa3a9ab", + "0xa48817b418c2f53a1df14fefd5df47d5d7d7665bbf479d8cadae010a0089c10e", + "0x1e0c61b8c4e6620e226de19941ba161063993af6cab00368ee08225bb197c609", + "0xb42e3cc1fab01739cbae6297d20d364a9dffa1c90b8090622a004036e956ee65", + "0x8675a534d124fa5f2aa0743ea5e7dfac1364e808e194f2b47a3be40596007fa6", + "0x5e6e41af664b6b76da9c492b590f135213f899cfa71f46e4817dd1e8f4825379", + "0xa3137844d37a0211ca70df2542ddb0515167ac2f9e8730b3f78ddd185ca1f71f", + "0x2c45f83c26e711693b1238e74ef925ea7ca62f8ae87a0bb56be658f50bb85f8d", + "0x57efda2e100f86e0cfad773efedc6b94e8433660b5505bf51a2fcfbf36693d62", + "0xdbddfcf9ee62dd2df5bbe3570593d35ae11174c75fdd2d9fa2a036603617bfd2", + "0xc1426b30576b1cdf484839e173b623bc7fb8e44512add04ae4cf09171bf287a6", + "0x63769d98a465a6d52457f5abd4f981335c68681277a665e5c69670c794e22048", + "0x84ded21d627443ce058449f621be8945fddb90126b0dc4013e020c6587e7e5fe", + "0xbbb52eb6ec5aac2d9ccbcb76244c6fef09ce7da0b4bd082a63f71cb904debe1a", + "0xbf8a7d1fe769344c7a4c1ce30ed1078d430f9b829c91eeeeffe4c512aa3d7bd4", + "0x8f955aa1566d88bcc72c5dc44298c7be8615cd16880551af0d5e85e1e75fc9e7", + "0xf13a984aed4e995a89f46f9e59ad2a0a9e6a35a366a11993e80d5409448010de", + "0x5f2f9addccac7a68888d9a75281a97270eace816acf9a66eb571f0b528a974b4", + "0xfdae3b48b794022a96168d280f966c46f27518ac2871ef5be4cded911d8c3468", + "0x09381a1113a9e8d4e17087b0bad6cdfe178e91b8846be88380a42b68d6c92955", + "0xaa0be3afcf3440d0be507bf2d7709c90dc6de0f9cf60f360996c31d9f0777a64", + "0x897481932de8dd0ac4d50687174fc274bba7f00def2654754c53d6a86a0cc056", + "0x674d3e4625ccfa18dfd8ea715f6ee536501e6935d0acdb962f5d36d185e795b9", + "0x2c4d74a35d981b3ac8481e9b2318b3c8f76c82fa9132d5a0df7e3003d1f56c56", + "0x457d591254d2f393c4c5a586dddc7ec840f27b3725a9e3d966c440e61eb1da1f", + "0x3bef7d4aa7d5fe18678f5cac053db4ee36f2273ec5fb11f2158777fc601311fb", + "0x96aade6ad2e2c5fc13a08c19986739c8c93d6107e3083c24a009728259c97f49", + "0x9be928c4604ecee2797c583f89d3cb730390ef41dc6a71273b051daa783c5443", + "0x5f0f6828a3d60a0d1fc8fce5ae884700c8b68f5ae339aed49740f44d81f3421d", + "0x1bebc8b98f2399e3731930a61e547e073c8e74d09c36017d88c52865240c1a93", + "0x89e58b2f46b86a595e0394bcf99c87f1abb1e3880b16a3eebc50a98fdb558e38", + "0xe9e853f496019d39b542e6d4923abd961514c75a35f1489070e8c058179ecd6e", + "0xc45895680db653abcee58043c646a97271e68ea6be5e440020b763814e76d8a7", + "0x7a9b8cc39c454fdf2c2f338bad6399f47af580d914c0529c3c78eef9c42a279e", + "0xfda0c1a4de2e6ab3aa415a3c0c54dfa72f8e5973f31246dc40932e5dcd2a8186", + "0x590f73f3733a7ad889cc51efb29cf73aab601af049e4ed42f70fb62d663ff4c7", + "0x9ddf5288ddc8cb7f770a9c87d3f3b7bba42b1acabc115bfdf8a210a3677a6e5c", + "0xdbe759f16648b0bb9cecadbfd18bf035f00908db82ea5eb89c92089fba99d20d", + "0xe780ce464772573bf46c8c763f15d0d3efa00f13eb046590a535683327e4d660", + "0x1e1a6eb209d12c4ecb97c5b0b6d4cb40ec6c48718e7f66381e6e70a070f4ecbf", + "0x20956a87f5127d80bf43f94c5b5e201768de55eb49eeafed759ffa93cc99e60a", + "0xb95002df40ab16bab3b6697b1683cca0f40f5a8a87f9cc209a7af5b2d833efdc", + "0x4a1dfee0a96f440c25957d4212a962c8bd105d8fda0136337a534137c84871b4", + "0x3706772e4b873e4901d46b9d1e3c4d47907643b9ea66c2c4a00769c379d9480b", + "0x54bbdab103586d5726c0fc06f4d37073d11d6643a08a7f4383fd2dbea805b22c", + "0x71fade35df17079aa40692fa1f4b0c06ccc923b5fbd352137fec2bc6de163766", + "0x6e68f8681269a5670f017489e5518c305f223d79ab8b7c0c0d8123decebb135f", + "0x6b2738c79521ed4aca1e2d1d1d064c9ceb7976ea419c00c1abdfc1fde2f1198d", + "0x768fddc96428bc51d2da8c29f0382a88ada02fad2c0722c3415e5f0124437cf9", + "0x073b3604346c6ab886df9a256e087fab99bddd2b63993a18d19c2f792d5d7ef9", + "0x0d4fd974576faff3e2b7143c7b9dd497a82fdb40cf6dc7daeb0edb92c04dcdd4", + "0xff968d9401495c2e6498651ded58cfd877ac2cd39a4ee76ed2d38a9df9237f48", + "0x941ede6edb4066a0fab64e43d32b914275bdb99d9260ccf13abac4721664a49b", + "0x74369258816347fc00ad9044cc978b081bff27ac93017017089eedc9d6bc0572", + "0xc4da7669db1532966236b6bb91efe50f8e49b0ba763eaf0edf7da01ba7403c64", + "0xe1f544ae2dda3252861a0a40bbdaee2e07a4853f0f769e2de4f591781b26d8b4", + "0xd96de0aa1e5d38c3a99207eebe8bf6a441bab660a1eae7e2f9740566e2b26624", + "0xe594f15b5572d594fd2d6e04c85700b2a54920a538fc46da1f435278b797026f", + "0x36c7f38d700166af4950cd092a7dafc0f858991cd756ba6e488cbad5733df81f", + "0x188ea063d9741276d6577815ad32078286c0e5935e9a4641ee6fabe86fdd261b", + "0xe83266d0dfe0465169535e16a6329b94334ca26a71ca8a6228bcdc5d6d9e5e3e", + "0x4f72f32b995c669ae359e35f853b32d78c9c10ded0090afeba135342e024c284", + "0xf0c349b2c53ae8922dba6635d5ad6c815cd41a18e80091fb53af888dce73fc5b", + "0x449c94f382b39268f70e7cd127b2e983164f4efa3a1ae7ae0457f18cc903e783", + "0xc2187c3ebf507e7ba02d0e9fc489742b07d5d1c6e56e952dc999543f46906bb4", + "0x55451070dc027493822eb1e25dacd66b4885f6e5d7696fe76054d700ba8fd7f2", + "0xb918488b2d6b2bbbf97132d8627b1e90644d0167b4ece38bfc72ebc59cac068e", + "0x8bff7b7f47013f71703b45acc6967777662d08052df955f51321539e58b9ee21", + "0xc588704ec672fea0cca9a37795c7beceaf977f60ef505d021cbc232e6281ac34", + "0xe70023b5d66c749625852e12b1716484b407d277968ae5668cc19654ff970c5d", + "0x9406fb501b38ac94bddf9c53299e856c4fa043971f56fa728cf02980d0053057", + "0xc472250a88b80bb35bafa79ad16f351c0effd4d529a0885bf308923058459d59", + "0xad80c5dcd33345da4dc627ab0f4db7468b7342a75153de55e527f77383d8f6e1", + "0x4b5a6e47d3d6e9b3e7fd72e0e8075556896415ee1bd4b5e5a803f08217f63727", + "0x689205df58a74261976513827cf5bda9798098a2da603990bc8ab3be295e107e", + "0x5e5f44891634df25e9396bac7ae80f632ce05cc717a27469c0ec3450bd86b8ef", + "0x45c8922e585a3ade1d9692ff7fb632ae93c887e63367e7b8719532a019c214ab", + "0x5656f71b6ac8a82539bb2b50e5355bc31549870f7e950c9f45443d53e5bad4b5", + "0x8fcb0de18049a1d68cdbd7a9986cfe683c0bfbb42cda187709fd1f657ee38305", + "0x3e74faf49aff89e3c73240dd61b2aaef3e9055212ab2a20bb0755cfc4e9a596d", + "0xe93a158e733f4c2d51407dc1cb83023df0ad632e49d1b12c6270cbf945e09559", + "0x7f283b0278e6e84ecd8f66bd6e0d1cd340c586a9fe0785ba454f5cc238f88b78", + "0xf367446836096eaa9ab4ba421edb8f0af0ef73a1fd958ad36e52fe4a98d67084", + "0xbc2caa4dfc803ac078b934e0fa4486438ab5d64eda0be84ac82d12782c68d3e3", + "0x444f24147dc65109475cd063e4a37e6c79d0facbf672e716128a48e313e44fbb", + "0xa6c1765069f2e38e2e3c1f40c90b674e8bf6f5e64a518a966dd158258e57b9b6", + "0xb5071af90877914cc565d5b76ebbde651ed6f5db76b9940ae4176cbb9fd92d18", + "0x29f88ef40f89c3889e159d632c941308ed5085188527a36e23606c50ebfba2a8", + "0xc0c02a3ddf3ad0939fc9df4d3aa48f81cf3771dacf62afc956f5faacb1bde118", + "0x84ec18194d7ae7654da7b1999a019bfa75f2f69e1cb2fb0fecc8f4f61e5c0b9f", + "0x2803dcc01f327f40d67094a16d7991defa101d8ddcef31b6d1357e11c06fa940", + "0x2aefb88c2671c3f2042fb93d022847b60d536a8fa14b5e7c52e9cf62fdefe486", + "0x83b06ea5e66be9d159d28b5851ead921d856aa64e84050ba7644218d8ea616af", + "0x3d00b3dce583ef2c73e8787230f3661c7a6ac2f17478d209e7eca9ef1f2421c2", + "0xe74bbdaf8fc7dd39d06b420393dfe0eb6de555fead817d87477a56ab0bd5c8b9", + "0x51ca229e7e529d7dd9278d174380d75fb7b9597e52f9ccda28c2a9563b0eca16", + "0xfc9c58aa8e07fdfbf2007f7cce4fd620215ac4c027da65dc2fcb173f0bd6ad5e", + "0x334c50b0ec398053d7b87d80d08c2c74acbdc61a3055e04856a70cac680dbc1c", + "0xf4913e603c18910e3058b5f65737aedcee7866b393ee319db746334e2a3efa8f", + "0xe9e6aac42b0fe25a9649ec83326123e05adb51cf7ab1049e984bf4e28d56cdc1", + "0xc8a375c04f6845b72cbaa84d22d393c7e744041495c0589850baf86a824b58c6", + "0x5aa08a6a75c4bf9c356a8853f30a625be8ebaa452d3686070bd9e32a70376f5c", + "0xf5fb959c5b65d44152e61d1b3721f286fac2eb64d5f43367dd8d81533230dbb0", + "0x513e2626d5ed52ec89ff88583ad765ffd9b4ffde79645c90ad2928516306f8d6", + "0x69319f3bf63ce64ce910f9ca90374d56f4a1a0afae4c56d0609dbcdd65570da9", + "0x9b1e05ed52a705140484c879821901dff8972b4fec4c8cf8b5a8ac3af20a062a", + "0x6e926b50a300af65a0da8fc6b36ecb6dbc0f36a322477d496bd2ae9d242e36a1", + "0x5a0c0243305b8258bfeb1910533b90bde09d7294de26ea1dd2c815a262dafb57", + "0x8f8da16c726284c5c8c773af62104728558f4c6a3fccac42226fdd381935c256", + "0xafeffba3c64595e4e202fa144c247f9afac6a1e8aac25628bc31628cc8b884d3", + "0x27c414ca1714c88451fb7ca6dcf5801a42fe6b50488986d31f4d33c8af60fbcb", + "0x9804e738c5d2a417b8234ca7ea552add4541c578cceeeb521f1d539d50d4277c", + "0x227b9cedcb8a98a8bec8429d0b6c32c1cb68ce931efa940a66b4b9a5e6e96b51", + "0xf6123c95f854e21044df359cff00f110dcbd86ce9784b8d428601a7755a86dd2", + "0x8e365936727e87c1816f427fd7f07be72d39111a51c5ff6752aad55c00cf3649", + "0x2ef4a4858a36b00d793bf2a207b1a952b730c3d618fc88bf797f0175b7307532", + "0xc577af7060fe80099f26956e63baaa34f2951b38ffe80804217b7eba2d6c441e", + "0x83241d8159b3b5920206dfdb5428d3dd4a4017d77b3cf1da12b68fb922ef026a", + "0x52532815abe951b5b1c29b31d8525aba3357441d2e7dc434666b750da5f6cb31", + "0xa55855e40293e6127d035383ff4a06009521d1e51ef6c3d4183f278b5209a47d", + "0x291825150b3582dec421ec50cb68e5121d672e353d49ad15b241e50d48f317c4", + "0x1ea01b3f106de9453f76c5da0ed054370ff3e09830f1537c99bbe5180bfa865f", + "0x97712de570a93fb5f4a65edb440ae8d40df884f1632b49cf2a2d677c23854075", + "0xd12d14d9dee8a1511ae6acc678264540efbfe3e0bc680d3753073bfa86237f20", + "0xf3babbc9ed75b5cf6237509bedcf1c5e3c4893533bb491ede3e7c0b794e6e6d2", + "0xe9604ce3ec312a4fa0919c3cb93974cf45b82fb58000cc35f0a9aff8640e6307", + "0x063aeb5ae400d73bc55b33bc48e2360e1cff6634c2a9a8282821e656f1ac186f", + "0x19eb4fc202d084bde1d280ffa2d47cbe13f875d131011e0efbcad50bc56510b5", + "0x025d0406da1470c4f4619d06f68029001e77f32c996c65a64dd19c22f5914187", + "0x439f8ac9ed20bb2f9e93d9ecdfa860a8728aa7f5ad3672aad0960d22ecc4990b", + "0x6d4e93a5cb9132f0504757531822b78552dad48e5760a28037c3160fd19f18b3", + "0x7b4e2fb316f3ac96382f086d9b58cc6f34d924799ddd1526b240789d7207fa25", + "0x206be12aafa8622da5f7073eac42c6f6a706623f771ff5f8e14c32383b256e17", + "0xd7bca9e89221da42f54f184dcfe3dd93705eae29844824bb73601cfcc51b5405", + "0xe931dfc9838059409b959382cd8fef53c26d08a509fec1672b5ae32d36a4f642", + "0xdfc59b76afd96f42ca5299b7d83daeb7bd99515a15fa714348d2dd737bf4123a", + "0x2b80ea34e8f3f334a3935aa27e7990753e0a75cc0f6d66335c449143457a9130", + "0x8f681bb84f9402cd3231472d3103a5fd73a0b00bdf98610a1bfa64ec3a3716bd", + "0x9ae86d50dedb89f36bf6ea98bdf6feac997934d0335e4d576501167624807a02", + "0xd610522f6bc35189643b7ca313d308bd09362310c3c242ab054cd689e9a3ceac", + "0x2639ec5c2d1e74d769f0dd9cebf9f97cf3f8bb7237e2557782fbef69fa289a3e", + "0xc3a1bf00517da2707dbf4a77254326dc7560618df58f3299b971de163cf30b5c", + "0x6ab2f1cce24656ed209dfbd63c50289e5314a8ab4d9a9883d94aafa90e5457a6", + "0xaaeefaa934fcbcde6f7d8d551bb04c59ef02044382ccffc0d391602d54bb08dc", + "0x1219f82ec65424420025c517665acb975e844d2e194dc2865d00b57d9c9bf6bc", + "0xd4a4f53312be916eb3f403246f4dc33025cbcb47932601e43f0634991198191a", + "0xb291089807f2361218966d187216a57e7da75a90affda3ffb9ea9686f200db48", + "0x495c6e323696bfbed94b7b141a412ffca903266294cdd609f9a3919a2e56106a", + "0x55e53a382bef3540ef569b9c4e2c4554ecea88e7f02954b5f553813b0f723f2b", + "0x243c3c576d45baede693313cd297000fb029ed43edef95aecf7870b807defefe", + "0x18605e184cfc5c1fd6deb89e469c541953921b69a1a6d60ce96a9b38477ebf87", + "0xb235315517748d459d6220cbe386c18b4c28afbb3ea4f0dc269def49d84c836b", + "0x0f92014b08ee5286e7158fdeda3e1ec128d75a454cd5377cef82dd605b85b23c", + "0xcc197018d000dcbb535b4d7dcaee1895613aa913910873be4dd18eb8db4d84e1", + "0x5272bd28803e27471c8b74c73501deead26b088337d4d108774bcd20a16e474d", + "0x95994b45cdd5e24d0d62ade16622a2df256b7c34bb6fc3ee1d82c8bd9c9ccaca", + "0xf3540d14e991c1f41f0da0752aa6beafa52b3d2dbed31b11a037fdcf95a91cb8", + "0x1e3f2d520c3c8a5a6a5f4dfc98e34e41b00c7f2373e77c894d2138ddaa4c48f1", + "0x73a32af3ff4f5e32cae216a58ce5806b2ef2c2138fc661626ead2f3594281975", + "0x24c7750911b78aafd028a9bfb8723c23709229228b55cecbec2be3a85e4048c7", + "0x6687c041b158f93684a86d7d2ad32b8fc1a2a189cc84b458acec35f421213186", + "0x7be2d7b949ea309c3edd3aee1df035b3b007394d508371db07e1fe7050b8fd92", + "0xa93cc5b8160519159b0aca9de5e3ba73df420773c43faf77aae11e808cd31444", + "0x48da7fe896d8a7190b88493c007446d7e45b01ec9336196fe590eb7104296890", + "0x00b562260930d36e8ff01819603a1fa7e47defc9afca6f694ac80e258b2259cf", + "0x634774d7f08b45b0a5eb7f6366cfc3d587652280e67e5530c19a59b5e3608e56", + "0x71210aa1bb90f98be4b5d3624aa434794ebef0036317d0ac0c81aa5989bfbc23", + "0x08d73574c11609a5c0d8011d88985770c7a9f6c6b13241a60e97208e70bcd8dc", + "0xaa8f2649733da5542c5ebd9093f6385403e54893cd20159c1904b8a65a93b0fd", + "0xba2b8890f1068d0814e7b9f4ec96122b2f054d9d9a00de7be6f1376588668c7e", + "0xdbcebb99aa1320ba6a73bbf03d0c3a6f6a5a0f448fd82f66684132f466005730", + "0x1bc13dbb79db619549e48b2aff6bd287770dada84871eba6cc3ada263f1fead8", + "0x34bd6250079d5450494313d82d55b6d67b5c88b9c327c12ccd1dc26229fec85a", + "0x9bb7f357e6c2fb16a1785ed1d8329dfdd1a0e153eef63a28426da32c6b3c4f21", + "0xa400305a3b3c3a43cf19db3a8c3bdd798bee0b3823794909c99ad169aaacb5c5", + "0x70e2a9779681594fa2c5134479753290cda06e381eb694b733ddef6f7d68c196", + "0x5310ecb256d7c062e314d3efe63c8e4aeabeb8a28deefb7082932bce1bb0ea2d", + "0xdb31f093dbe2d74e97f89d9d4ee90ce620b10516bb2f67f0f72083ef95a08533", + "0x194435831533350741d784baacfbb72bf29607cd156262b1850ccff9066b1dcb", + "0x34e908f1794a6b6b62cd390af76426dedccc25146ce1ed9655a419eef19ab593", + "0x9ebd77d7838567ecbcb9bf6e01470a6504e1d11b72ac7cfee1252a38b6fa22f5", + "0x890acef390032fcb941b497d0a8d9143f24a2ed38320e563f4cb00aad423f945", + "0x476f91830e89ca1326ecfc1aa170638f69d85ebd2d2e6925a28686ffed118269", + "0x05b82272e619631be587e2e9576651efa30f4aa606a602fde6ba6612c96b0204", + "0xbe52d8c0da80709a0f9f74733514aa89f0803a1c3d6318548db8591f04d5cb50", + "0x505c6cae331c6545e52479084689cc05e9402afa29c39dd2db6929b8c0f343ab", + "0x67a97852d6f51efe6d6936b4b46913e3155706b8bcd5cb84a2e5b4345a0c2319", + "0x38235c94758cbcf5f87801f7fd971307e0c0575f0fdcdb01507c3dadcd866196", + "0x8c8374cde00dc3c8d981e85c7abd861cba034740b088c3b3d0d902e49718fb73", + "0x00d8ef455db3b3176ee73881da23eec72aada4ba69d99e2e9e8854689036f719", + "0xf449e78106ff9feac43cd39874c96b283796703d95f3cc2310eb0891a847f5c3", + "0x59a55088e2bd944ccb6c765c1736680ace188ed3cb4426e7883d6a9b13fa3566", + "0x61a70e0b86bf6c918a7ba9e5cee5ab1b1778ee8bb0c6d95a22fd3b316cc49318", + "0xe76e9eae05121a7297046ce013cb15f9f9f4948f75b11080e8624d8db4c72fc6", + "0xe4e0fe04b626bbf1a4a3c07d83879fa431624a2379d96876d0660aa11558833e", + "0x4669abdd5a4414d5c3477ffbf117282ce30e3f7eb53d51a4558a53a6a218ead2", + "0x9047a215e32e7cfb8cd0f8ed9ee511b97ce6c6d958932f9a69de675fa40be3f5", + "0xe843ad9c00989e64bbc628bcd94ec33d9fb7cab7da04414bd5a8836abf3d77e0", + "0xf74a439fefb92fe2f4a5cbc00b5d0aab98b123ac35ce5b721c822e3f01abe919", + "0x2a180beafbe97688ee4776ea146b7a04e1277f34c6f590a36e757713b8fbd162", + "0x7e6b2b0e1f5ca1710beb9679e9a76198e8c46cd7f78e708f8a221c1b0cf8706c", + "0xd81eeaf24e581409b240f4c939eef367a1202a67b0f3f9624ad2b65320a5b1d8", + "0x0785cb4877a081b0ffe0969659e31e0cdc107e074e0f50441efd0d605e24ba50", + "0xd940ad268d241a3816953423ef21b00accee9ff8ecaa568b9f07d450c83b23ec", + "0xe9cacf9f26f9285a92d9de458f0da70df4865fa339257b9194170e47b1b8508b", + "0x0a609857a03ee4a9a12d4ca433dcf4b1dcce562eb8eaf680246c5677592792fb", + "0xdf39272007002deaf6e3e08d39c301acb019fae9fc1604045970b24ee811ff5e", + "0xbfdcb2fbcda60f56f4894c363616d0b618e69a65d99a28e7a97e7a3e994ffea4", + "0x1911b497e25ac33f47d17a3375a48429f2ed8ddaceaef5d87833200d177abdd3", + "0xcb567fbf2368e282fcce5eb91de6d63978ddd81fcf708a7bf72dbfc67507cc70", + "0x389cf86c4724fed48eb07c84ddc9eb57f6ee7f1289ff784b40b0583adbe17258", + "0xe4df95ab6106b76317b98743c8502f542e4c938c4bf6e7ff8333a806e5b7ce10", + "0x5d6011ffd07ed24f53c89f8e0b7bcbfc9d61bbc7bbf4c75b2d016ccf0ffba894", + "0xaf73a81601a6966ef20a3144f78b58dee5a11dcc62d9c8571bffcf47590f8390", + "0x0f2c2e6f8709204b16e1150113a3c21dee41e07e05c02d2a267db5ba790b9fdb", + "0x413625e84a39b66a76f367e93e7540ba19e449da99b20027bee22ee43d951b91", + "0x8c1d212a9981956be03bbeb02cc9481f49e2dc7771adf2528db022a566c1e0c5", + "0x931f8f9b774998cac650e051437ae2a3e283649c70c99bded3f782590507be50", + "0x3c921258cb54fd6749333647bad45ec2e370e6ea1717378c5c220707057489ef", + "0x4199f7bfa2612d7b55ef0866222e826360ac55c331bb224e1172b23b908e63bb", + "0xb031554c6174037e0e653c770748fe0fef7c2e07878641fd8b6172d407c96f36", + "0x80a29a2e5e0fbbe548688162bbe896e4779c14cc36d2cc8d79625f4e900e2e29", + "0xaeeb107069aabd8f5a493d4eabf07269ba8b138de2c6fc2e45c1cc51b16cd47e", + "0x693796fef4816ac117709bb0897f04f7a7839a63553480c58cc9c9e84819977e", + "0x1f7799d1703c941c22d508c77b9c675b41fc9b3458676f8b68e61bc6f782ab51", + "0xb77b822d6bf3c564e85a5fb807a6f2c327c8e9878f1a8bef5efcfc2b42683ccd", + "0xa7a18f0dfb0ea0fb324e44e3e8f4b0855909243c4d9033c049308c1b5b0230ae", + "0xa0510d0ea833b196befe7e7306d032dcf7118f6441b08c5368446585c2eecd6d", + "0x9a147ae2c6e144acb568987fd0bee3217f3b9b3e93c8838e61456bf8b86a22c4", + "0xe9f1a8278a5ae525ed2a36fd215c8c32d829a7d33d8b304ae5e3b1be87bc2a71", + "0x0b72bb9e24280b927c53ca9e0b5881692a512f5364aac34d7fcd3a74e7afd48c", + "0x769739b3852616af794e5da01fd9c82d4f18ba2cd83e3f4cb91abf373af2fd01", + "0xa08efd521c783110f8bcbd6b10e0fe88589b86cce52e74b79fcac0c2d9c0622d", + "0x2a92ad845e5248c29dde55744617fb89da6274b00ab81b39ca5165e7889f7c84", + "0x97a39e46bfa06d65b82267322c932eb47fd300c9c3ee39317490d5b2cfbefaad", + "0x2b069b2073de7bdd72362c3d660006c887a202455fff0a5ec829dac09317ab95", + "0xc589b08560639f3cf40f7ed21ae23cdb4fc6926b8107bf1c5d43bceba8b73b72", + "0x7e60eedd8908ae15c145697fe52bb5583450cc3823e022ffe99f6b339e26144e", + "0xa9aee5b233f7be5937c774181bfeb00eb1f6ddcfb15c75f32ea8ac25e8b27afa", + "0x3b61b38d28bfa8aa927b5bfba2eb720c458e381081ddeb272f5468e0e337127a", + "0x81a3e1d1085962a90b26d069802a3a222b7514c976cdaecb17991dd14c39abe1", + "0x1f323a73660c294067febfee61dd3ba79e6b6e44b56f3643e6abb46bf23e59f9", + "0xbebd2e901a90f7d00ebfa0a37d6c30fb82df35277bad3fd361bd996aab04e76f", + "0x540045b3dca70445378bd7a5e99e7401a6a34852178617c224070ad6168c68f6", + "0xbfb24b0f324aeb1ddc9896d84243304e7904a5877c2d3905e9dec916aeffb833", + "0xd35e90e38c97392ffd3b18f6fa3355cfe7cafa1fb42a679341d120dcbb00cfb6", + "0xa45d268b64eacba83a08e071a70238f6a09268d93f9ace0239f98b9b480054dd", + "0xf3811936dd4e523e92bece26a6ae9757d082b0c90db890d29dd6db748532146e", + "0xd2f0acc18ea883e914643230ded3c14ac41530a207891a60cc115788603cae9a", + "0x1bacd3ba7d6ede3600338ec74c93a544b53e79607706c78ab8c3628abf086000", + "0x84ed140ab09aea7bb06b372079cee2c55014ccdd7a86256de4203b3edb395d7f", + "0x1eb7929230ceae1a1eb2ad2e621ed4d96fb7519519d67690a0a02028354f5b44", + "0x6ea5e84a1e0044b4ebb4c9889c0f0cb8366067e83b41549fc0b566f8af18f373", + "0xc0a31489bec0a05ebdef2d85f63ec978c7732cd7f85363b5c0adbbc24f8b8bee", + "0xb411b35100cb2e46514f4cb38fbafba9b5d08deb69dd04f5f1d6242092256ad3", + "0xda4f3602b5186ba05a36c6801f9671bd81c0f7bab2958f92f23b53428c6d7d20", + "0x192955fb0de4dc5683143b58cee39643b8dbe650ffaabffaf1901c36f66c2206", + "0x01e6ffda8040936ecf0fb9bcb7ade2c111a1ea60d865eef26e64cf2b61c60e64", + "0x0f65e8a8a15d7dfa88138209a07882256d0fa29598c80565d25031fd9c457a1a", + "0x8d271c3e2b1f46c781d3e0b78a3e32ba6cc4a34dfa64beb67000adff81082a3a", + "0x1797d9d3f8ef921578e44c12e89a3603a1834979f4cb095ff97d587e3ad0fef0", + "0x43b8576ff5188a17105986358fd46476fadc8b012c2b5ebca1a6e2c7ed99c672", + "0x9cb12e9bd8ead00e00267b9059c27805d8f1183e38e77062d6e8596f3aaede4a", + "0x487a0d1136629756c07b721524706153dd3b6b30a99ad21524c6ad7bd1fb68cd", + "0x585e4e9bbec3b503e9febaf2fd948dc570a68a7d00869efec0696ee734793188", + "0xcd6687ecd3a89f6148ad3649b533e6bf73693c3dbc7ac8786346c28b31d46045", + "0x6d84a80a92c4f0e46814b781c9bf810e8951b42a3b4ffdbd069af8cf5df68e6c", + "0xa665dbc194d98bd3241df0a0c3a6ad0840f26b6516d7acacfb14d762dce7332c", + "0xe4be31ef78d1da2809a8893e184c8dfec02c9cc6cb6cf9766b24f5c751ffbdba", + "0xf627f2f2abba302c369d9ef1440fccb76dfe929da867e990cc0849abbbcee381", + "0xa0c92bf12232f1382eb20abc27d456348bed2968498b1f50af47b4ffee978dff", + "0x6f785f8c8ee41dee4919d36a6b93bc79358bad7c6526406572d8322d2c4caeae", + "0x956663cff06f54baef4916c5c1cf2fe2f74ed3adc3d037675e5f560f20fb40c3", + "0x254f23c420ee39fdd9a9855232983dc72ae2732df41a9f5a6f706605aeecd1b0", + "0x9f506bfbca58d8a3c1537223b508ab1a73fa305115d567799887ad3fa358dfd4", + "0x45130075968c58cbb9ff62dcf24720665cd0445b07bfcb48f258e774b7afa696", + "0xc82b3616bbdb734206081ffda98c7ad52c25d6e319e128db9805d47d4c0c91d3", + "0x5514a3752fc41d6fde6efbedc5819451b5f5c447da3165424c0b45eb45b7e05d", + "0xd43b0a7a8004bad15520484cbef390383d383f92fdfff2b565d9c3cce843701d", + "0xff3c2c98321126f95c78489407a7c1f740d91d1097a9db6e7c2956daee4ec037", + "0xae6f03d13a9484763007bb1747aec64fb8af07a6d2b75e4f0ca92b1e5b5cabb0", + "0x77c0de0b69d598bf861d6202a9aff1bf969ac530bc4ea29821f3906786bd5033", + "0xe5304ed9e69f36201a17a15a52b0d55172ded72e43930d07d0031f6d7930982e", + "0xe4d4f0914e9da6ec689721953fa6434b7a6df1ae96d5fbeeae58be9bbbafe91d", + "0x4ca8aa5164de5e03129e0c0fd1b25f8edc0be0095880c1be92f559c9e41088ec", + "0x10c0cfc83a0ce9cd01847cd6608d0d5f1e9556bd601e00daa76df36a5478b4a9", + "0xd3dfa0401755d52369eb3420d9f11faa30642f96ac47cd6df647832885e45255", + "0xc5f3e2ab30f2c04663785ebe8616d721fed26f3b0682978d8d293b71c6e679db", + "0x5d3a3771e375cfa767bb2f79f4eb524e24cc75edc18280f45e9b5684feb8cc21", + "0x5f75a61d6cc535180f4866f131a6b3765f8f887bbcbad8c2341d0f3639f670ab", + "0xaa92f9beedcfb4a89c40c175aae2ab7d714b9e08514521026c04c394b8e691df", + "0x3c308a2526b380b770b440e597ab93a9890a93aeeb0f7358e0d718b8525fd83b", + "0x72d99722cae34e5e98024633450eec36b5c5f210ad8d926e706130b668ed652f", + "0xf355aa777e1d6eb54079aadb9e01f90019f2152867ffcdcd9370890e52f78f00", + "0xece9a8bb68f51b68b1af494c1f9f939852f8b5f02bd8ea7d5ed6184826e53fea", + "0x175ce65c526df144931678b31a52c0482cae8c7c5fc257af2b67db4d3b911eed", + "0xbd08d3f0448c85b347293e37521be9cd023020d5f0dae65a58685c9b38b0d72d", + "0x7ce531279c7237fc6a5cedd136859d2dda2994798573eea5e16c9c4c1f8dd2ed", + "0xb9af8108c38f749245886a5c739a8a27ea4374f1e4f1f80f7cf5d75ca24388ca", + "0xb47fd0ca734229e031302c21e9cf9e722313af7687a017be4cfd7a126d3e3a0a", + "0x535c450febff97088cc5b9a2dc53322464d30ee1e1a4b637eb0af6fd9cedfc4e", + "0xa96eec2bbf07a5a721757c5f822cad5eccfc109ab625f60637640b593fed6e33", + "0x1dc48b9654e75fb0469f31920208cfb8daadc29e474c2ddea26a84e41192b7f6", + "0x4eaa4710b6f59a32654b551e6e6831962244adf7cfde3bcca1eb23f3fa5fd6dc", + "0x974fc45c5d0f29e9a435be9801216e821528d63085f91c8f32926fea6f2fe33a", + "0xae9258fcd4e24377f6575b1372d93c8e1f3f182d69e1dce0f34e5323bb564c40", + "0x936f73a8db5d27ac246628d916076f210512193fb0ed07b177f88f38f1d9f93c", + "0xb1d9add4e81f7e31cdcf939e96aec52343f0fcd1c3945a06fc373582cac5e3b8", + "0x715b33556e8d2c731a3a9f82d62de5fd888406275ee48b0aa1e667c500853f89", + "0xbb069b2facb78c576d0b5ac5b60cb5fd93086c8b2a8f8cc3de93b5ee0a8047c6", + "0x139c62086e489a6dd8df1879e40d3efbfee2a5a9a18a20be0d278eb5b6342a24", + "0x0ec77a5043d047ef4790229df9a6420c40bbb12591100292f7ad1cf01a1b26fd", + "0x3bac40b81c8200311f142b21e74e878bde0741063625f8a88255f618aa7cd33a", + "0x0f40ba7924103e076c023a324cdbe7a066af460e628fdae93c6cad2644af9838", + "0x9e78a97556487bdef14755b016b70ed5ac02de3bb49570dc43c30f356df6b659", + "0x3471964bafe51086c307c784b38cc06ab61f5303aee7aee894df2e7a759c40b8", + "0x0a3f66714a6a0b2a1d5f534be95a510f44d8d238744412a532dddaa49ffe8d7b", + "0x7bec733ae41397642f1f5c3d8c1ccf49b6bc9c1a518223fcf01b5f7cbf6f3705", + "0xb9963b533ac1898cc8bd7ec202395b1a84ffc9f2f170727db472a957404ba377", + "0xeeca7419303169bf94ab4b5387582f8512929e9d3987f14a6917be06195b76cc", + "0xcdf32b3f676c7f972fc32235c8aca016c467a67a441575d473add2ff67c101f4", + "0xbec739da4ef3aef4e7a8d40a58f8343fb692d9d19e5c4c6ed2e1f01910123483", + "0x9ca224e1f36aad793dec4eaee936330bbef547282038de374fa8f812b6ac2731", + "0xd8cebaf48d29db6b9bb818fe2d8e959c40d16ae328292f679bf719fba9eba43d", + "0xfb91283b8e72f2b65fed21efb13841cc1e845ad312275a55590f0114b2118bdc", + "0xd6708f204a771a6f77be76e7b7275bd10cb43bc141dee5219574e14298665087", + "0xcf4684a5a211f183a8ebe5ccbab97419f3cba8e9d060e7842d4d9128db5f82a4", + "0xd4964b9f2546dbd080b764645cfda3a5b24e30c76d30089b3da7f93793830699", + "0x3fde509e67bc090d74da01cfbec10c03bc456e63fad6a57593a5f534beed113c", + "0x70612230eb6bf9bea267f83c3bf62d0f2decd1f43653bdd00a0c7b89b0d32b59", + "0x40803fa27145e3e16373032c2512214f35bd7b5dfe06aea4a42104e43a58fb4b", + "0x0d78c2b135f282debd581c77572eac67618a27a2e72928b531d8c550a83ca95e", + "0x1ff6f0966557746d1dead627307711e35e21125c5356183ba6a7fe67a33dd1f7", + "0x2d0e54e705b6b48a0ecb260421b1b320ec6332f2326b570fc2671119c889fc83", + "0x931569040ddadfcfa6ebd7264a58b6d3a7200819fd83d5be3d107e8fca662fbb", + "0xa152c1e663ceb96c2fb4d3fe992a8df968dafe840c41171ae1115ee4c3f2189d", + "0xe0eaa06be11e49629e893be21e3485edf1c2d1c4e10a2ebd56771bd9c8c43128", + "0x4cef1726c40c846ea4b89412d0959e0c60c2d7d09aea7260c450e65b6959cd0b", + "0x03d60eddaf920b24db0cb177b3e87febf7ff42c70b01f19165811c02e934bac1", + "0x20237d9a59b4c8d7bc324055ed2c09106c5a83f80e3faf9a519ab7fe7dfda4e4", + "0xdeba273b77f09eef6383e543f144981ab2b0a8cf5458d53cd7b62f2f4620b5ca", + "0x792ca8b535585e17448d5961a53d48478f5ff3ad780b4cd5ce400155f99d47df", + "0x9562462d4c50af030ddc1eea7afb2daf174d37e87331012ae7809675977d19dc", + "0x534126a5a45d07b97f8530683387aa7b7d3c542791a591c999a3147120c9df66", + "0x395866222f4b9eda175fad2b5c03d8edaf7dfa8c231e1f63b50a8f7ba8ea768e", + "0x3b7c90bbb4c1d512f3b32c52c11df90362395458b9e5036fc115cf8c7e1fe8db", + "0x1b83d9a38e749c331b456700d809d2fa4d44183ac7931a5bfcc270710db5d9e6", + "0x0d219f3be7def7fdf0a6a4fc7b9d801fb7f82bda18480f5de4bd144b5a07699d", + "0x8b239ffbade64752b0753f0455f80f48bbf1759b578877b4cd633120640e368b", + "0x4952033d5a714fc9f00d6cf86cab40961d6f65f41cea32969015eda8bcd86d12", + "0x9337c08af2b8a8109fee2b5d5760dbbe0ebef717276c4e0ec366a7fbbf089133", + "0xf8b5d552c23243c2388cee3d830353d2617058e2564ea735f9266650e0b384b9", + "0x998403af8da153a188078874fd7733a4975985e478e0bffb88d32f9f73165859", + "0xda6b8575198343fb5e0c383c71c3237e22d8907c732324adad6a1c9a7094b364", + "0x6c4089d09fca65f0e08065fe76fc808da298d15c1be524faa7127bdab491bc0b", + "0x6a5d8d5b0d7ed439bb5794e4a9851ced8dca4b62af2c65adeeb6de85fff25ad4", + "0x26268391661872d1c42f455f4607ad6235e8d4d37228d6f6e68d58cb7757ee3b", + "0xf47c821ff8ef71b25afae26a0e7032830af23663ec7c7eaf9541215bbd0ac318", + "0x660e9ecae596fdbe31d4321e902e723744b036af20acfc7b07af33de3c03426e", + "0xc068e5ef9b354646c4c196b8f4b76f90c653de3bfe5d731b9af6a38f7e22e5bd", + "0x855f15c630f2779849f380f9b72f3eee4188786a14609f4523199b5674eadc90", + "0x184d0cf7f3411e67039040c211b63ccf65e12a34807b2adfccc6a96f2958f10c", + "0x100553b7852201b4cfef0c0b0e3bc9b85973570c9a15d494172f372de2f4c3b3", + "0x316e8756e1e2937c91e38a8dbbba3c9a8306542b2ddea63b38ac987b7cf17880", + "0x86d773822b5bd5a74bfeba611793bffd6b10c44ed6dc1fce06bc69b274fce579", + "0x70260f95b4eec1171c8b46f9a19b83ff561c0e776948f79d0c57326f622d045c", + "0xd2860b14214a368f32c68f4ae7deea94ea239ee0099d26c41932ce0218148271", + "0xeeee56e8202b193a51f2858e5d6d98eea1120343c5a9fdb6b419c732f39ccfe6", + "0xab9fa4a69e08fe455b209c841d02d724e6afcbc051d8c4fcf0f76e7a99baa728", + "0xd6cf37977456356252e1e1aab71b518d4be08713c6a4ead6e1a30f7b07b799b6", + "0xf5ac688debe75fa0064a5a9135fd287a5bebb62a7cf803fd6382e29b008e7ae1", + "0x969119e969f9c55261957f605b579e96f7e9f7ea6002466c70d08c3d72893569", + "0xa07f93f5a103d361989a48acece650873164d1e5f99dadc2ae72cbe8f752ebf7", + "0xbe03f1432dc8b8fde8107328794dbb10075acbb835a9ff9876574bd54e6fcbde", + "0xde96c70df84aa83b2c7c467486fba87df3e1794f48ace7ab2a58120057bbeb44", + "0x98c963171be9bc3cd0e851b1e925021a41ae96425bed1c9171a9806836876722", + "0x4ee4973b6ad260367ec2e85de7c9c488eb237386d8c0af4538480a07bbac6362", + "0xe55e62e4da77ff26e1b74b9cd88a4fb9f6bb09ecbf70748079ee98fd1b29e9b3", + "0x5668d865ec045e0caaea9173ab2e0bc243279cca9889b554bf8fb74be7edc8db", + "0xee0219965a896de8fbd02a9e392e41511dc01b32adc879f47e840fb16748e0ec", + "0x067de7534f4c63eabf619d1a723fbbaa940f59ee92100df80aeec1868cff40a6", + "0x701ffa3418f9232a4902df7668b1fc87ac1d9b685cce9f5d820f626540a0f89c", + "0x16eb30bb64ffa9ad25b579f2f019c7886184631abd0a40e82313fed29eee31ed", + "0x5aa8361d42f511c5a3691bb64308da2796244075e829767386f4cc70f8c2a70f", + "0x85eaef383b0baf4533683496c7f749cff3b07bef1bc971ea64ea3f1b8ec97ae3", + "0x0977f99e26f96fb31d04dbcbce8967118b51398b6f0712cdf55ada5928b5ab5c", + "0xf321eac1b43d232c612e059be9e98d24bab395de5406f9b514d39a614a4a143c", + "0x9e3e81a1e0823b9a166cfa8105d3def2789fbd4d3a2ca9871b75a05cf252f8cd", + "0xfed3f3d4d86bdbda79fb9c9935c65d3e980bde5e9f599ee73071cc4bb0571ada", + "0x864268476104f0de0dcf8a024d808a4170158e74c6ef681910e3497bdceb27c9", + "0xf48691090f8661e5baa46f0025730a30cf57d186fc1458628d61e8c1a847bd72", + "0x41656453dee2ddd1694362eae0b6b741a7ba33cdbcde666b4f7e21b087ef79eb", + "0x48c7cacec3e2161bc35642f96f207bf65561f8c944e2cea48651cddb8a4548ee", + "0x5522526dd64584467b416086a92d9e9736fa07d25d524a0dfddab3694eae37dc", + "0xa73f2a4d69c6cbb2426956019d86e0e278913c613bc241c20e7a04fd46475e7c", + "0x3828ba052d46e2cb9db1e6284d7b57af1234b19ef57e95414f76af00588f5736", + "0x05beff29352d466ceb0fd835239ff491da78baf0c4a49e7e86702e5ba8d9938c", + "0xfd1e5c44abc25920639f0d3323c7a37e187e9c3523f1bdc2f5316f58e0de3277", + "0x5b6e17ac5e43079e136fdf088eb0667f2ae1f3d8d74853271f6450ebf10e5f87", + "0x93eee544e2bfa4b257962690614d6e3b6559a30e1fdc99e2d5c9438e3ef5294e", + "0xa1ac97bb27493dc07b4f9c74c5cc51b06a990a016f4ae8b7b175145c49e5e8d1", + "0x347b031d899061ff61328052398bcd237f611fc737eb3c89a644a0f0583df6a9", + "0x6a21e50a143263badfc63c3558681b8dff02edb87e49cdb4ccd6dd22ee640a84", + "0x72a1fbd845ae2f93570b95899b5604431557b40ceb3bcea49f3a601c7dde8fc7", + "0x7736fa9605d1d96b1e60bc80357b42e1bc1af7ee93fd677510788986b271d8db", + "0x76f89a85221739882eb8868e64bf4cb5bf148c1676f40ae8c21d593448f3c35c", + "0x87e9ca31389a42d0333fa723cd93a414baa8785d4e1adbd60803c642ccef4354", + "0xdb85ecbe1e60b2b7323bfd8b9052ef598c9a3978d434587de7b0acb4e5ddfa7b", + "0x74ecc5544a2022d9ef644e07ab4e7bd2fbaa091a0602378e797a79fd23a39a65", + "0x25875438959aef4b9439837aeef040eb22182fd2eceeebd3164b0e171a4f07b6", + "0x7b02a31c30e1aaaadcbadffa16b5d5b726bd6e7ce69e46f131a2e2ae9028e3aa", + "0x4da810150fe04769897a9dcbc762e57e3143f53b988fa384e9d1e975a10daa1d", + "0x02e8c7c864c9099c9de03ef799ae67538e27d4e5986c2b43f24dbb1e22bf215a", + "0x3a2549524a0542211c9caf8d7c50bd9be376839a7835b671999ee13d16ab2a23", + "0xb797387ea54fd787d5f2f7422929d3fee3380752f4e6f72d8f7c3ca1c18aee53", + "0x591126651f4ae3f82def63d62c3f5006d274951b7d0df241f69e5531441c865d", + "0x25e2bce70b31419aea946dbc890957a718a09cdd51bede651135181220eb2ada", + "0x072e249c21a440f387ebb121db0167e690cf227afad7a79b4dabe13535dbdc3b", + "0xac20848b30eeb59f0e86b913a50a0bf5d16ef48294b5753a78392472d5b821f5", + "0x1b264fcdf4c4664716e5d15f37d30036bfabb7dde156156af0d9a3427587d946", + "0xd1f6eeb6648fcf7bfe2a529a1cd95397dd5637f40446d478102cf77c1b4a0a36", + "0xbc61fb25e983a4e72c8f0b1de3c0ce64af6f81e991a3d2503dd9cd378b307830", + "0xd1e5c22b81c1c97704acc88ea4defd20e38fcd33d172d2e10c88b9e61e42186a", + "0x62429704d8365056cd9200d4b75043c1ed888978f59cacdf4df78a77f241958c", + "0xc75f2eb3ae96a0cdf4bf343998acb1ceeb1698de850be9739345db110c4547d4", + "0x293f31fb7885b5a8b56a806ed39fd4ce21da2b2f2aa3d53ba64ebb69ad3894f5", + "0x25789ebc42d9fce453435b830febbdc9d96b169e58fbf123ddb4c250be46e186", + "0x22374e1bf486955234966e8d5749a12d3fc8f3757deb03635588ba4cbb3b6d05", + "0x5ef1c59731d07948379cb8a2f69bb6c85831dbf4877bcd15dbef2203c466f08b", + "0xc8a399261d6fb17dc44542966b6f747dd9bb79ffd9ffaa4057cab7005add231b", + "0xe86ae035915ddd476aa6ae8b0a5d7efe1b12299749fe26572432e9de84667b9d", + "0x63ad0c23be328e42265531a35cbdc4ce0cb54466c4df2d7c06cc78996cf59359", + "0x9f7a76b739a2c83b3707878f96d738c75339187d18692df863a3080622e521c4", + "0x9de463b7adc2645388e7d304e8fc3dbd41792feb3acac6df07a7e7b738f18918", + "0x91dde10aa2843b61d1ec9698695b2b98e36e4256f89149efa80f05c783a46703", + "0xd5b8ade80a8e8c0a6d3409d1487a75261c7fa09b12f42d688ec3caf2ed3fb845", + "0x928c920abbf2e979b8e083b2126a9e57dd32e9dee159e872132bde12572fbabe", + "0x0df9a734740e8e43a7a609dd1a572b34d03fb6ca0ca2bedc4156dee372d8f031", + "0x687bbc3fafd974f8acc6cf950602684f4dd6c18aeaa0810ba8379c69f1f93e69", + "0xdd0758b5ce6846d130a2a510915cd269e5bfc32190cc192c52014e8ec1152daa", + "0x6cb72a48fc6e2fabf87a168e068da7f2a2e2b6f283bce30ce89225da1a7c7fa0", + "0xc69e84506b768224407215792c4eaeef4e2637c49a3c780529263dcd06008e8a", + "0x3d1c651e092a51426c336aea9d67e24e539b164a6328d3e1dcfd682e308d5b57", + "0xce28ebe86f5c68349465570c4734e67de9077042700cb022f50a1692f86c5ac1", + "0xe1c0f3403dba2a0252851d0de326a77b45bd6348aa77f1fbf50ea400291b7369", + "0x33e8ca0dec08e4926eb078713b29f0b5e3a149c72665fc118a1b390645597872", + "0xa7b1db9f872acba007a3d289bb9fe6a344a598484f05b3d09f86fd8937e4a7e5", + "0xa167cd03858447b05f4b04c7a00dfa47ef401a591c0cd6e21dedc31c6317dd88", + "0x7a36596e1d467bf69fdcf89020961fe226a7a74caf3f6a301a93bb62ae04da64", + "0x6df1255e8d0f1dd26b4d8c2074f6fd6ebd19c63ba8d4f018981fb3c5143869be", + "0x405a94ca8487db8a2848ddb2626780be4d708a524333f337d3a70388911dbaaf", + "0xfcb3c2a50e7b705e9bac79bc767dea39a72453b624f376f2f443cca4d71fd27d", + "0x0df59a47ddc76021493c451a150e89a5feeadb9c0d7eaca5735adda83beeed81", + "0xbcbc312916bcc4384c311770513a6e25966ab0bf4c603abc2e76341bb5e0861e", + "0x6bdcbb81e9ccf9c3ced0b046190510b50ea39dd6f4ac7bcf93ce9460d26b1a85", + "0x2fcd38c30ff75f79b7ae8cea289a994c2818b182f7a717c4e00d955e94c0e4ea", + "0x626aa23fe71966ae5d0ebd2b243ba26a0251221db8dc72ca75128cf8496c397d", + "0x3bd021853dcfb8c802bea2a6fe5bf9e0d9eef8dde8ea427923d373e68690edef", + "0x9185a0aa01c251e8e66bcbdffab85e08beab296e611d32eac6e1df89716b65d4", + "0x3110ce921cde1d11185e96c7202e59557bcd0289404b5daafac3eb0c3369769b", + "0x48dd13aaba98e0b9fbc5bf9e7fb4fb4c2399d6c43d348e7d9bce63d552ba4b16", + "0x949c894608158f17b860305ec50ccb9c261bd91698b4e74d90bfdc2e6eb7f6b4", + "0x03a54f8f490fbb7337edc852ce4db855c23d63952b680f0c7b0b4929ac32b53a", + "0x1772c66225597523609caa0809b52de4a0d23986c2a5f9a10c72138fa0da513f", + "0xc0ebd7935a25a1562f1ee993805e91239ef0e1677c6cb193399c69489aee3372", + "0x92c04fe853c0b20b8818e74353f02ab732277570d53a316009197463159aa998", + "0xd7748a6066710d8cbfb62716bb707d70d2aa35718b0162eadf28efa167bf4247", + "0x40c764559b23340611f6e586c5b3ca3e34109f39e55c1013444e5fb46b6e4ae8", + "0x664f106f2b63400e49e27d642888c2af5c90601ac3421b16d28acffb81980552", + "0x94bbccc56c838a7144f550125bcb6a78239e17186986bdca310b3b567bc04eb2", + "0x50769670c148c4bfd4a439dcd4a439f5a3c562eeb1486beccd5e47bc7ffe7e62", + "0x1dd32b9d03d7db815564a3eaebe223077329a00bfa1b2fb95ce5c3e28e7e1e7b", + "0xda75f4e1904c0046f8b932e15f1ee75ba5b18d619c03c313f91fc67352663dee", + "0x26b8523d80f4b02b48e90aa144aec7b3e8dd2904ddf98026da16785411e650c4", + "0x3d632940e2cb210bae6c004fba156ff936ed5b899cfb8113c3fe81aff90a9d31", + "0x5afbc6c18455b8616f6946c0eb86e25a5958d4ee43aba602d73ddb51f95a120a", + "0x638a5c1e22c63a56923b20094499f7bc341a24977e2da4330b4ccfa7cbb2133f", + "0xd03566f2a41fa9b73dd3008e00290cce8c0b606790dd4eba6954718087b035ff", + "0x044eb0cdab90661aab26ccc50dcedf16bae98e1dc64eb0b3efc0823acbd9189a", + "0x87b06dad58a4570e111b8fca431eed1194c7d6a3d2ddde4c03af3d5dcaa73c1a", + "0xa4a7a4bd57d4df07fd7f724f877f1809ce58267f4cdd6e01b6ebd74a51ba4f1f", + "0x5a677ca1f995ff347a445b19adbc95458ff467fd6e54bc5daac6631965b0682c", + "0x66d2db95f8a2dd6ca5e35dd98e48d65566cd7b49295206503979e1aafd2efec8", + "0x2a084704906271f7b6bf58dc814947bcd7bbbfe946073ab8ed93130442c28547", + "0x009fedea5e258716c82c202710581078c93e5fbbfc6d309f4060b883bdcff7f2", + "0xd05dbac18603ec1410626621f1b9b678139131af740c7bf913e5596b4ab50afc", + "0xee459c9425dc5db61b17204a8f16c7e30ac2d4e0e25dbcb966b8105bb696cabe", + "0x4e5d309f715ece7e3cd39322b70295087a1e4aecfa09935cb1c02f11e9c0b0d5", + "0xf205313bcfdb532ded0a5e3449510915cb951e8b39538295bfde1529f0c8e76c", + "0x425af7920153f9145c21f7596856855d55a985ea3b86007641cc648f721e55d1", + "0x4b7e0997fae4aa62129dc7542dd9c8759b3dc83b295edea0c301c3e5d0c7047e", + "0x66ddd8fb6fd5eaeaca4ab30997078089fe12c23538b263b6a30bad2de240de70", + "0x2aae904d495d75e755879d332388e3ffb794506f7636140d5996d198f7d595d1", + "0x57715fbce48b3eeda882ff4795eafc9e8a78a005c7f9fe29aef34e76c532aa62", + "0x7e292ed2cb56a5d088454c304405ca92357048b1a2b59558cca938868a489e41", + "0xf7d14a8e386b97e0a1bda779de74cca484c7ba777f434e40bfaa38898816325f", + "0xcb97729d67e7af8af5aa450e419ddf517bc5201719c081abea25b7c1b3fd4b94", + "0x8ea13b5666929e667b161611016990588465731f409f27bdc594295ea18f053d", + "0x515ffa2fa1d02fa812ef6cf9accda980ed3de8734cb0e6b0ca779642bb9b821e", + "0xc0f4f27af937f1ca108a68964b99eb1ec541433fa4ed7736ccef44cb34a2e220", + "0xa6ba9d246099cd4ac98171014867ba2099f8af6d5960d4dba2d02ac3519d5417", + "0x576ceb5dcba6fd0abb933edf52c56ab1de4bcc233d84b3335abc106dee26a979", + "0x02756b443a7d7c0147685d3bebae7c6b8ca41e08a420ced3cf96954d35b8f8e6", + "0x76b256b0f219de31672ca96ef25df475cb4cd886714dfcf86ab5f583c6831cbb", + "0xa8b06de1a5e939f400cc040d97023593d94bd6677f775344dd7fbee523e37793", + "0xc7ab90bb0ad571c16f4cf04f5231bee6461bc8ad8d3341022dfec1fa4683008b", + "0xe5dc898a5611a5641e5668498bacad7bcbe8f2f56f5749f108e3e2edc936d612", + "0x3ee0715724eb91abcc8e410bd2dd62329494cb806531a50406bedc790db70163", + "0x2adf081b1f48b98041163816ac7cc1e3d553b90cf2f25957f18d78dbedd28e78", + "0x55ff274524876c6bbeb9cd741a09205be57818692d7bd1f44dbd00fd4c987167", + "0x5bac9d22d8224cb5aa6dcb1d1d0b8e7a19a7920f9c1d60e907dab4ed1de56030", + "0xcb040f8185956dca644d263514f8df9e880ee9e840d41ffebcf2b330c95e084c", + "0x01654829da5415a428777ad66890afa49a9f5c018e9183e75ed5e9ce33edc6f6", + "0x1f5c6aebbfa4a5eaa31e37a2d9e1bda3903d1e60fb9b116ba108d1e728f8d1d6", + "0x2e1285d3632ee31f39c213cf9ff4dd0f8f71e02f6d9e208ea1da72f17ca2efde", + "0xbaf1ea78d8a7059dc640aa88c834a709430a58dbf0000b008598e50c0a918d5d", + "0x1cf4601e3b0455845ff1bd5a69a11ba9b1cb3766552250413ab05d23031d5ddc", + "0x24cbe63ee67f5e46571dee67ce5231d91d37ac9e7db876fa203dd6b711f9468f", + "0x40a40d3e099c678b41ccc96fa40d58176c78fed3a277244296104ad34fe672b3", + "0x5fa9756bfeb3a1b959fa9e0eeb4be5d610d21dfe79b01da9629678a57792f785", + "0x831d02f9bc15c3a107fc0d02af6986e90a4e10c337173e2c694049668494d6d3", + "0x0dea5d14f6b970008d4c568fcaa012c666997c4403003e071398091a4430fb3f", + "0x55ebf8cb23fc19be6f1bc81c01d22a9d68b33ea72057088fa218f5b823d62190", + "0x22c432494ec0fbf4b86deaf9e315f2fe303475954dd7fb334e970f075c836d18", + "0xeb7c33063357ed449a7057975fba7f1534859bc7a2b0a325675c0aca06d498b6", + "0xd1b4c264a6b1a6c5b29053536c94f9212a5361a59ba6c347bb293e2e5f4ac3c1", + "0x1248e24c5585593adbe274c96b6085c27af8d9109bb9e029c990ef8fc05b7de7", + "0x62e71fa6bfd51005525f7022aaed1dff888b494e33811bb8ee093528d22c8e46", + "0x452dec3f2d5aa670be7c63495b5380dd48a740088cb0c83bf3177d95070d30de", + "0xd4a684ac6f08f8ddc950b2fedee72f43fd68e1e9b5c90c49d628975933b0e6fc", + "0x13304a80344874cfd8d3473b3417bcb0125cb51bca1b0c17b1abd273ebdb76e2", + "0x119725b4c9f238e1afec7a1de2486d83659078410088239d0b2dcbb2229ab4ee", + "0x84d0632697d03d038465c69cf09897f590f2c54d4b489cda0933ee78b305159d", + "0x9cb911ea27c7b78d83cd213bf51bb1e704c6f2d3301cf21f7d556461ab4b4547", + "0x916fcca360f78a1cc254ca6a9cc813fbab69ddceda7e2a9d9f50a6efa3807c96", + "0x5e372a3c9a8a9a7152e85f6daf47501c22160873f656e9cfb44f1403ddf1a33c", + "0x3903ee5968ff71b55b8231a2293bb77a62116de299024b237c8008f9fed354dc", + "0x6a06a0e8a57406f09f8491f72a65440a7e8af76f1c94944cbe4431419009a286", + "0x718f21ef626dc8c5d1cdc673b180f83236964a04d65c2fd920ea4ee1292f03c2", + "0x266f181b66322be4694ca2d29334a93cf048a55461d5ea522e3f993b10c11da5", + "0x1329d0ca2ea012dee3c12c1eaff3764ac129b39439f0ab31c99315b845930b7f", + "0x148590d22c32801674a59d19057fa7c4fc2887f8526ae1c4f115c11a94343669", + "0x750be336395c6f4de6ed11ea0b9b021ccba8fc06d24acb28184dbcdc1c2440dc", + "0x13bc3e338a318feed2536031cbb5b0b7598b943f32dc2c88fda0f388688d496d", + "0xa0c0dc51049562f22afdd6c7c09d742c1faa1abfb72d6f1d1af01d90c61c0e00", + "0x62582df180bd65aa98acaf1b92c6bc454ce1ed19839752abcda3c19e6d33d374", + "0xcc86df4a115333f19819b493d17cba26a43bfdbb2223e4931ee6b5eba5f38191", + "0xf2704da9f0b3e4323651948714f738bcd1b98b375c206047b7191e78120e7cc1", + "0x9b7b5c587abff319712424711c2283c63eaff7b6b612c3c3af3db2e49efdf4e8", + "0xf048e6ffa41ec43d6754c3d0aa4b348b8cba9c694dd642101e89bdc60f851acb", + "0xd54a3922322ca33d14d7a76f9112351561af5cdf6938190a9f72dbc743821d93", + "0x224fee97a81d25039af7bb9933154ddcaf3ec019e15e9d8b3faca76e97f5f456", + "0xd05af3e61e93ab21bc4acb5f5a7f5b1c65cb62a0f66418989a33cf5a022b1303", + "0x0b4d26d13aa33c3f18815ee500ff94e50b07744ed653e1730505f34807171fee", + "0x042c4d57c11f67351185f8da9d13a4eaa81c16a0562168f3bdb5dba67695ad3f", + "0xed23904d7f34fda2feaf767b4a159f4bffed7262e5fc6e57134fb9f9e1537179", + "0x86150cce44f1cbc0d70faf4a9a8ef43d4cb379502c3f093edbb23b29da7d69f8", + "0x8dfd33acc56528a2305927a1ee8ad4e6aeb2ad62c1617dab0e433f0349e23d68", + "0xb0265b1a9e0b4329e58dbd4c7330334b89f62208b564d34a36adf63b0a1edbed", + "0x449ad314b97b04a8fe27b49c3ceaf4f48ef4da32ebc838ec92e760cfc69ccc60", + "0xf8f709094f667677a51e6cbea7d80111b3dc605fe85eaa89149db75daff572f2", + "0x958dcbc8aaed9d26e1471decc11f45002248aa3b319474a4476c3ec3c56156a5", + "0x3ff1d72bddba150d37ac533d8cbc79fa0df9dced62d63788ead1f7f0e2f908d3", + "0x1dfd517bacff0cbed6ee00e1aa0860e1132ae0357f1c04cc7fcb3cb6c4b576af", + "0xf7fe6f99b1d498ed42147d0569a367453b43393383bc6766b799041f539f11b8", + "0xbdcf4453234b219089ff1319929db364d41acae2a6852c59324fee210f4648cf", + "0xdc96015b8b607582a66112acacceb00436ae99b1457738b2aaf2d4607b902bc6", + "0xf94d38138af0896d0a5d982d8d2f579ba22602edac3e197d955fc3fc08a1d66e", + "0x69905142ab72223097855fb3948f08820464acb8648d9f17889dfc4fb53f5119", + "0xd5f6eb135b118a63959276d91ab9a243cafad92a5224c1607ac23627459af522", + "0xc648f20006811f74a283f809e7870136493a922f73a570ad183c52460583be52", + "0xdf9ad900f0078907865fa24a2cfa43cfe463414ed730deeefd3346bacc3af191", + "0x4982f194d6c379706f34ce3662c88ffba3e01ad4b1531ddc06bdae8205443f1c", + "0x7b7711b498ba7fd9e409ffff12fb4ca0bb7a35b0a7a52fbd9f4e891fea5e19d9", + "0x7483501ff50750143e8c6105d110ca22e04b47fea2f52e5fe78288093126fc8f", + "0xfe7f95c1819c9aeea3b825223370a12198d83e9e5ea8afe3d7989576b4769207", + "0x7720c14c730ab8e13cc2b6210fd357f580c96fce65432b04ec787089658eec6e", + "0x37597a0cb5f115fbae5304cf0951633845b60c8456f0a8015d7920aa5cc4789a", + "0xe9e6ee709139afeb0f9b18742f10c444d982560ead60430bb6b0c7b21b823fc9", + "0x6b1e527db7795acbc6ab1d62a449d5df9f958ce2cce62bc75ac3c4851f30bde8", + "0x36934bef6115f8524890d77f087e49c6b95d832f7e5c15dd40a99e12c27a7c25", + "0x828f90bdc68ab754862b11e2794284b0a79130c4f9dfabf743eee463dd138210", + "0xc74307172a17ffe3f2b22c397fc16499af6c772c1ca4012504085304af6cb1eb", + "0x3ec72268a78671c0027a5d72d14ca5441a65c385961aba9d79a8b5c60f06e7a7", + "0xd85c033362ec66336cb685af11a577aa8c58f6970c396c1c3d01b373e28bd83d", + "0x4236db4114a216aa3db4ee43dabf042a4fa142f506671db79271e5e87d43dcc1", + "0x0994b83392c79c039ddb3a7a39af10944f9c8d110db91ac6cdd3901fd6162e3f", + "0x05dd8ad9cad24784c538826662c60a5b7793cce0c9b0e516d302c74caf4fbad3", + "0x90ff9715b49ffa4ecde93076fbb26263d5cbbb5cf1da7d733c7969a323a5efc9", + "0x9cdbe11208234c59c0c2d9eacdbaf71ffaa35abddb770a9173b5161aa12822c6", + "0x52508554b3c1774feb39569f3f1d750de3c6378ac1a00dde8d7937499a01aafd", + "0xb1f8172ca90c9de72134885a07e72e8fc586f15cdd939751556e1b1569827fb6", + "0x62c6c1cd398899b1788741c5d38b6d7e5b87ca6d7df9adebb3a7ede15773ae16", + "0x69f98686ed693fb4bd9c559d06cb36b1ca0049b89224a0d0989afaab75f63a73", + "0x922df7c6782fd8d09f8151de65da4a661888a547ea7606bd0bbcff76da9460af", + "0x92fe7525ac7654d9c1afaecd305bf49797c8f170c18a989fade3261859b09c90", + "0x9c6840e8deabcf6a4f9b6d455cce40e507bacf1d2ea21e7be5e886a7fcfca41e", + "0xadc0de536e5084837e63c4c9307f43d483faa0517703461198dbf6fd9d45985f", + "0x96cd5b306365675610295293bd8c85f131fcbe98da01d65b02d586fd0deff6db", + "0xf64265c5166d3e4c7b43a44e1d342ec17573f8914c890a7844b97276c1f4e9d6", + "0xf57e23fc51b49caee68a24cd0a44c1751e453c305559c4c5e962481960920b13", + "0x2a79bac7e52352c86db3d30dd2b30f9e971812e7b90524259052e4dee002022c", + "0xa34ce80d02bce67476c9884650e9c364b18701df17b98eb626ec8a8b8ff94c41", + "0x3d33046ef8bf3c6ac74809bd647125cb3649c50a683d81d189d5a3a1697d5c12", + "0xa9b71e759c32de96cc2e60eabb3babb2fc54ab03b0919710d0991dd96054658e", + "0x03943f2696bf2827b5b185273736a9f196b6b9876f872cfda33a6287a5d8b52d", + "0x64c3155f299850c3dd2af09764526fd1fd66441f9c9e6f5cb0a2e2301584c175", + "0xea2e486290caa2832e51111a84028c6e048cb75b518c01b036c10414f42f8f15", + "0x50a1d1408a591f87d4d68836e1000be260842c29ee01e9f7d4aac7e7d979e9de", + "0xacefd24443c1df58c5eeaef883152021cb4c6fc97b48ace81eea57800bef42ea", + "0xeb6d6aacefa2588be8c725af0e96a54ef419b955873818e7157ec33b4111122a", + "0xc8a041eeb0059a5471425f16584246cbd82599d149cc482c5a5f33deb8a4b51d", + "0x57133965ef6ea219184e9c4f2cc5dd36b06aac56c232db9f13612f29cf7452c6", + "0xe12e43a37f7c8af5993380c9f9d52dbc079cf6a15dfe6d5bef674bb9095522a3", + "0x872f41b87598ac8bd9db28030b619e821f55388e1dbde3fff91b978273dbd2c6", + "0x35da6ae783f5551e7db1afab49ba65064b9d498c90b020efbfd8d3bde4d9149b", + "0x79ca7bb0eaaaadf841b7c439347c8dd3c25eeebe59184cde665774fffdcd9d83", + "0x7e8fe47fffdcc9497c04c84db14ac49876bf67f343e1a86d932fd82a34fb03d2", + "0xf04393e39f1c99b43526b1cf831777bf45cb5bed023ffe01ce649aced0755406", + "0x119f7202cb5e5f6418744e3548577ea718d0cfc4af84ca2ba163932e79a74dba", + "0xe943792863c593b9d12ba8362ac3949f3f4d956a0ced7d36db39d08d0d6554fb", + "0x89374b8ba8638b278f957dde6caa5854e615e95c56f817b4b4d5d8b7578bcacd", + "0x5beaee31eddaaa076512f20314d86c022cb4343960c1a124a14c09d346ab1b49", + "0xe68cf25266b943db13b5d99c978d9a959a52a63e179b45b38abe3b75b1940dd0", + "0xd046209b2ac88f4a900023f47a3965e9621943365bc67398ee83d8e7f5bb9392", + "0x9c2129baf9e5d8ec70aa3d7fd749ecdf2a6a8176e5507e2b63cf435db7969106", + "0xe54d9583e0d28492f2a55a5616e1d116036ff5c79ef18d75f84330cfbc5a94c5", + "0x217bf1f6b520b06cd61fe846ae6238f07e2ce5b164cd0afcd300a072438d35d1", + "0x38c5656521ab8f20c1e3d76b16c1907c6f085d7483e65c677d5772c42f733196", + "0xa41794dac6ba96bf22822c510df1a6185f0091c42bb5f3d42ee52a3b0e819706", + "0x7a35c8be930d2cb2714a313527d0e7adef99ef4769a0923df79e4da0c7735fe7", + "0x641c1160852152427f30b1aa357b38e8d324383e4691ef2341aad1a804bc6ea2", + "0xfbaee404480be652ce473ce8373dc1ee4f0115ef3428965076308f4030663f7e", + "0x40c26cddaddcde3306faaaa204a7f04868701b0b257a69a0d99bd89d6d8b0af8", + "0x72de7931dc0fd19b44424f402956d53e640308d8161fcad541a6298c4e176a30", + "0x66e6aa59bf00b9816cbfa7f890af9982533786c0f79c410aaa6b4584a4fda270", + "0x6fb2113654b31d029496fac61ac915d6f6cf51da90e70a34afd72e8b404f8225", + "0xbb79f6186b2a12597e9ba6f96282c581391bcfa71c74d14d945ce47f5f630a64", + "0x18ef3a7a66c4287f250ae9310fe19c5331ad9b8078417c601dbe38a5f0fb151f", + "0xf5a098a71b8520b687d9f1901ee49d2e4930ac60b8e7d86bbef467cdfcb17600", + "0x295f0734697e04b2ddd7eba80401340e6f1ffb92ffdb4c419b21dfe1743d9c94", + "0x46ff4895f55e08564a01019056b0b8de3a125c281fb73c8d83eb33d4289721f7", + "0xce3b9b708997480c042a02c7c7b7743eeadc948b8d8479d39a561a2447026137", + "0x754977681746a986f52c71baec741978357a29fa85bf450085f048c919f90b8a", + "0xeb57ec1308b1a5df2d2030b42161a1614f0793637c39803951366cbfb47aacf2", + "0x4415343da1a3844f15e5760837e98d3429fded7bc33b994ef40937745bffbb3b", + "0x8518da414093c6dc7e967501e48c6f0f851c5db9fb9a766592be80bc92356a71", + "0x4b4336daf2468eb8268d05f15aebb687b0a93e332967af722c849dabdf8c8983", + "0x9744bd3239db2321672d3fad68813855cd3fbe242e8ef36055242fc38ccb46d3", + "0x83fd1838bf22241cd133ec22143e73f9ab6cc5d60679f069a5ecd8e1a349dfdc", + "0x5a49226a79fe77472836dbb1ebc3438b84913042976d50d420c61e59fca2e895", + "0x1ed763438ad1e3928fa0ce385e38bd686041062c28afe1ab41820ce1f3866fbf", + "0xe052728bdf265d0ee32484db15e1ca727bb138726d728d1b4ca192c0603b8f13", + "0xc80890e61f7f53b78ee423c1b9722af2b6dfdbbbad942a3108eb313a06da160d", + "0xf295b732773ec1a19577ca63bc1dbf6477b252cb86afd562ab95000aa9f27a5c", + "0x32d1c01805a2139bd8754c20ec9ebcb7bec07d2cb77e9ecca6960ebbd7f630fd", + "0x856165ce956f4995e1135eabf21fd9c9a3d1e8ad0acdf654dff5e08f27d74b40", + "0x27574b2df854573a4d349745a137df0f16ce959e6bf7d2f9d5e35a8f81393f89", + "0x8f473f340bc991cf773664e842168192a591f81d6878b8bafcb3a85e9853d670", + "0x634b934693704cbc13397f9e5dd40c290c1993ba21ba072061f67d8419374fe7", + "0x9e368b89eb53fa0c6957bd212caee6fb83cb3c0f3f5e2d7bf0d5e6d40c52f1be", + "0x666ed8a2afd6e3592ca5dc9875364d79ad998a155cc1be9f79b8531ec47be04b", + "0xcc5a705fc30d157b449fbca19f4c3fd090752f01a25c79398e4db09e5d608e36", + "0xac46b4e5fec1a5420e4225d0a06d1835878e99d608ee7dc664f0ed02aa969a26", + "0x75fd6803ea7ef4b76b2efa5d759a18b389808be7c77bd07855704062a409486a", + "0x4eac0f01ce006b9caf205d9d69ea4b7f2588c35d0d4391cd28eb2874d193060d", + "0xc9d114846a34430d25c3ee2787f249fb5d5c48927b0b9088b51a157d4070f1ed", + "0xf855abfa802a2218c6cf6ee9b83e460a10b99d9e4bb00caf401fd255e8ea84b1", + "0x745eaa0ab1a88ab969adbe465cbfe083cd6d9a0e16388afd55a078d319199c1c", + "0xd1385cceb4e842335fd43a11679a1651f5839624d6de72a6fcf62a701aeef71f", + "0x8ca6643f362f14de97c52daedebe7b534c3f9848e47dfbc74ff35ea22eb34509", + "0xa3e33679cbb620d2423ad0cf7ca0fa2392bfcabb3523e43a60768034b435671a", + "0xbaeef325583ddd0d70225158c339a39cae656394d8838f7366abe1e6fa92fd83", + "0x0fd99fd738d3ded6ca70051989b30e5b5fb4885e3250e3cacf13c8fe1a617f70", + "0xaa70c56b85627949399f2c6ce910b901057e27dbb3376e2ac97f5a21eb336452", + "0x70860c214c0902bebb4d2b63e56de710f3f64197fab1db24a55bfa76781be7b0", + "0x1220df73d96074db0b6c565126b1d1f34fe9aa37ea915463e3265610d92e7cef", + "0x30b5f6badd7a1f14f328dcbf4719a25a53c88121a7954b1bf86bdd32ebc10bae", + "0xb3740510fefdf78178071e675e983f50c697bf425329b6fb3d67897cb9abd956", + "0xbd3e1c3a296b038b039944258cc7d9fadd16e9880da82e950dbf0aa9eae1b661", + "0xd10c706488a87c66f225532092138f5da46a66ce2f2f033506474df57c4f6251", + "0x1eb08842fedec4305541a174b5f2f3a1648b51764a8a5a68abb3c3c309ee98e7", + "0x17ea3c35342139775b39c97b8ba3626a9db11be861b201ac3ce65077e4465510", + "0x2f2ad51f712bda042707f5546ae2a4780d8892092babd629100890e4b32485e6", + "0x3699482aca1e43c46ac13b28cddfb7d2e04fa66322b127b1e33e35a14c1ffc59", + "0x1a16b64e41bf3d0cb59318dd8a9860721f4165e1ad4794bbf5049a91ebe8e482", + "0xb0d19db2493f48c4899c88f5d3b4beaac17246ce12c3c3875db8ee3014324b8f", + "0x4a1563d90acfc44fc636c2d65b0064cdb066e5ecb96617f8537f42ebde87eb2d", + "0xa9b3aacf11bb1765cb1f8f5a0059a8620d81833f351dda8d070abcd8d31cc9e4", + "0x553bc48ef25bb01f179b94ee681eb3fe01cade86733cc2a329f73e9225323239", + "0x7f69a7ea675555481f5b48a4f257fc053000cbf11ddca208cdcd3e50b5a2c30b", + "0xf52022fd47313165f2155652d0df83f1144dc466828617fd66ea72e47dc45e28", + "0xb77889379380a01dd6297254d1aeda969ff8f77db141b4df6235b95a850d4fd2", + "0x017c341b5c24a304fc401abf7c4e2e35d1814549d31cc7a7e935437df5e4a0d8", + "0xe07f6dd48974e7eae5bfc5d61419f43cbcee5da15a5cb3562cbbcdb27109c725", + "0xf95c4ff89df473cd0620050518ad21437b3f68ad7ea1f5d80221b5c279d52a05", + "0x09fe043efac912c5ebe8b936ca7a0bbe0878e75a6397048628d0859788488664", + "0x821a1b9fc32182d57edeeeaa0c3e2756bdf40238f6172df71bb570b71ccbaf31", + "0xd550f297c4ab333e2348da72410d5e228ede1054d97619ec3f8d3daabb26cd5b", + "0x968ee9e7837c7f4db9eb845c0cf81e7df775dee47ffb9a78aadbd29749500adb", + "0x9eae40666da91873a377751549e72001b02fcd908104a8a8409920752b870015", + "0x4fb1d2641fa31caba1faed883f8798079010d04630dfa1b4168b0cca1d71fd04", + "0x4a222181b4a19b58a26d2da292e4b47a912c18b96ec276f1cab4cfd33ce17acf", + "0xa2b65494badf68a52576c151fb20ede37b03bd08b6b5be7c59667da48da31701", + "0xca9523d3c6b00be58ec473cb663263939807a4718975acbe4e818d93f5563354", + "0xae67a66d295c82e30b6af1c2175c6d4682c545d1d99f148569e0852915af9d2c", + "0x4cbb8e4c46ffb937beed22468ec09ea68d065262d4126b5f603ff4580d4f06f4", + "0x89d56e23737196666e3b11067f17489ea385293b6510e34343601e5eea536154", + "0x59656043c6c15d02709adbd4b374fd72d429494fb0fbb2d30dc50b45e832f6b3", + "0xe6ccb1c41796a8f25627f1c581b49609bfc0b4618e7c6b56e4ce60ef2e99723e", + "0x87188b1bc21774d9a6fdbf3bb31a40ce50ed6ad04f2c8bb4f68ba5b4bb0db85d", + "0xbcd37880bfaff5fbac65abd7ac269eb91fcacd32a718a727c1f451712975b2df", + "0xd356c7aee30f9a046f13081bf8cf7bd5cdef7dcdcea98ce72b8fef1bc5e18de0", + "0xbb58b6798bb9f141f4a2cf078ddb228e120e0bdb921238a4f55fb5d06d62d949", + "0x0ea0138e4e061b8c7a26235aecc4106b084f2f0a225855d01e0a0e535128f147", + "0xd0509b0e82ec1a686ee4ec2d234e86c2351a4da629d0dd4fa63ea8acb5c75615", + "0xc1dcd1f056f5f091761816a586efc14223c16eb111373fe09340a10bca313646", + "0xf8603b03f239bee22d6080fd4dff7247f3c4c5b840fe6550d726f9dea89d23a2", + "0x11aaf239138e5a91a023ad33b925051a7bef3a047ded716358a9ea37fcdfcf11", + "0xaf5fb28c6363585f0a9e6e07b1ca8abe25a7377c419e92e941fecb988bdd2bdb", + "0x97e6612b804b56899a6352721946f731307ff10ef3a3374902246b79cfe2a39e", + "0x1a188d5c06ce92cb047fe44b365134690d8b0f9d48bdb7c7d0b2144551f879ce", + "0x08326e6d088fb427d567e5f48f9bf2723273194476ab7b1f3fdbd1173da2934a", + "0x5d41ee7fc86758eaeaf7d2f89e129368c87d489833af34bdf6468d97aca71daf", + "0x6276b413f2429de12acc3891e0d6d8d6f84a0222076968ddcd1510c7e4f6360f", + "0x5179b0d269ac7822edd60c2433e14d0ca080e0cc69ca25160f2815b7a9dfced4", + "0x682a7c8e055d651718b96381a44623d3c0cd5482d5abdeb40d5240a662892721", + "0xb0378542ae8eca6b4c62e06bef747cf878ddc3fa02e65a6d2058b59b7346ce88", + "0x8d9f94b18f733b111c595d078ba1b39ea5f497493c0764946b7dc56eeb5a9cf8", + "0x3672c07d311f84f8cc7d3d455dd06e8329a0674158083c69b6947444d844cf4b", + "0x167d0eb0384565323dccba9faaf5afdf8ee69002f00cd865fbc218c3ec5c2f96", + "0x14a307b41d547659a9f9ad0cc99997acd148a0c93a35cb68d6b05380e15ff692", + "0x8ada7de0c892e08e0d77f4df240477611721555e10e57e5ce88f635baa96b1b8", + "0xb2ea07f4d247acd95b4c1bb3fb511100078ca8dbda6a986c5bd57baa45af8c5e", + "0xe7ca9d79e07576fedfcbdb57b33cadf91ae88eed90e49db4fce73ec6307e07e8", + "0xb29e9e28d2d1cf7192b228e0fa47b3164758a595a425493799a6e15c64197ff1", + "0x27108b3a76a21ca696f0e4a8cd9a3088d8f4e9aff87699d6a5f24ac599ce2c57", + "0x07d8bd50d0fd5072d93bb8bf577eab11abc000a7f82e7bc610b57d37d841a355", + "0xda6a6792b382a199336cf02e21941ddc692d37cd9d140313bb991a61e106bc39", + "0xdba10b67be085101d9e64fefaa961c2fb7ce88a8755600c11f36b639bcad5a6b", + "0x89d5fab1659e4260e1b900a051a6388eaffdb3d51c3320a275d8734cf5760f9d", + "0x11e25965923214834c02f7decb81d5ddfabf2b7dae609dcca8ebce3bc521edef", + "0x07ef19ee3a02c7d6fbabbbd446b93a2d6157a130c72a2e70fa464dd22090072d", + "0xc2d114d1d7c92230fda4961e566d6bbf79c59d5f6d834659d0ce541988246e9b", + "0xa806ae811f29b017ef1ab204ea2690cdc0b092fb44ff902d2a2eae98fca66144", + "0xc5d53fc3c5250443fce19ef19e7d3f8ed2846877334e2c9c6fbf6efbec646197", + "0x7638f3a6807181c76c2eac2f5d4121f8ff7fd9af43cd05c761229001f64426e9", + "0xfffa2fe996dde2034f6655108aad0d9b3c203cc165203d2e09912211b0ea45d9", + "0x7ad6d2fe456d57c95342ae28757e73ce3d82b780dc003f29ab49c1ed40904b95", + "0x0594f6bae93b268aec2cf274e02eaa31c050f9e5c83c1dfa0f57b45a92aa6429", + "0x390fb08a7f18f5e4b968ad5d8ea80b5344487c493797c4f244e78e40da3eff6d", + "0xaaa73882ad2e8871bb226de36ffb89ddb4edc83dbc03203adc30f240ccae0a1d", + "0xcb4f1aa82966978efb447b00adbb73bb02966991de7198b0348ab9e1d1263346", + "0xb6b4b5be9659ba7d846cff73a90ef523eb90debb01c09c16cacb7f12ae54d89c", + "0x63f763356f684e6636f3c0d756c04f431014124ab22ea6ecc3b4dc9f19f2798b", + "0xa540c05e13ee03659e7f4793913b17b8223a57e2a06955471abbff55d498d192", + "0xb495ba5f56bb27d3c3474b193d85bd940fb6817185a1e3fece930f95f7e8361e", + "0xec15c20e65bc42edae809d6482b9ff9833e1da3b8356dd85cc859c6cdbc9c12e", + "0x5d3c94aad26e00ba29f32b74f3ad1f98d37417d8e6ffd463aad71e94c2fa5af3", + "0x2625d4e56a57e21806600454a2f302aff282502219bae68bc46cfae2c124367e", + "0xb069c1ed8c1bb38e4e3f7c9b341acdaad8325ca730896f8aecf61cb90caeedac", + "0xa96a8794f83e8be206609673adb252ff36c73fb4b0d4fede4578a56948d7b730", + "0xa67c8fcd63ec561b1ea81a7c33a099ea1ae1df4763717bfc47ec373e29acccd0", + "0x0636616d377f1cc6e0d137dc540d8c1f4524b39c4d06c55fed4f97c5b8e84fae", + "0x72e9ef9eb6e09180f9138bded4cea00d4b498a678345a86b70660f965385ddb4", + "0xbc3934b7bce3c55baac4ca784e71647940fe55644015607a9ce7fab0271c11d0", + "0xdd342fde86e1eabc6454dc64855ea302ac867d6428894e864c44c0de96cfae75", + "0xead66979a3fd9591de9a53d9c6b72b2196e1194bf41570053086bff526101b27", + "0x6188160f02cb74a611ab553aabbdef66dacc06e066dc03a9b2d2fbe535a9638e", + "0x83f28a56f6024056ff8d1721e15a6e64b974b9eccee06b173d60317de96d1025", + "0xfbae5724ebff4fe9f795c9ffc082bafcc1cafadbd87c1c7f41d8a97dd7c57ee7", + "0x66a41f7b13f43920dc32e4331e032c25b40421ac9b76d0fafa473a6903c140ba", + "0x4543e01ac5f747fbb1dafe627833f6b1f7876286fa09e57f9ce4cc0dd90e3286", + "0xa9df713c6914563663a319e911a2345cd14093b6a06612217a474ee83113d1c7", + "0x171785288cad15c71818ad96b7d70aa08d245f27b681945a460fc9150436260b", + "0x45213365acd35d54c504bc05c94edc435601c3fb79616827ade4bef8f6146966", + "0x7b68dda953680a8489afcbee464c57883bb1dba89498a156085e964c0126daa6", + "0x56b9c263ec26fbcfcdc8aca55afd0f108fad308d97d9f1b4ecae25648a119969", + "0xb4a617718b2840e7304084458ed3d31472d1b17943524506b87ba373ae611e64", + "0xee206776b921a0b17f7e66a46d3f46bc59efd3a3d416b9baed26146392b13f2d", + "0x54c16e665f2a06737566a16e4e8d27f1c74bb86e4f515eff33b599d256bea030", + "0x9d3aa984d3593a67ecad729e9d9fabde7e083201c79248dd2b877430f32970a6", + "0x560c8421e918623e2e9efabebbefa77ef47cf2bfb728069a996e493b8de78648", + "0xc2436d5acfa0652ed88cfd6ec03644fa57892124031bd81c769b1260536641f4", + "0xcb5b68284216400fd63fb771dda5f0549b09543ebc2e412f715087db4ae2ca09", + "0xf362505d802d231bb749367d0393c76591c4ade3dd04bf0724ef661f21a24ad9", + "0xe6dd045892e791f52e389fd460ef342af231d2fa9a887167d8ebd099dd4c4829", + "0xaf8144ffe03357b30b52e9bb43221cd5180915338a41dea010d5e2069e9bcbb7", + "0x3b7647787ec9f714bd054673f2372083ca7e0de1538fd12119df6b2b5f72e2e3", + "0x632a04950b5ad2626701a0b0937116e128cd26a36725abcb40c1b847b1fc22eb", + "0xcc132fe637af129e51216fe39cfbe3fa2ea1ef493f9df625383d72165082026e", + "0x3f1af50536229e2c6b19da6e3aa711c0563dddd07e004b6cb7fbea915e3b2f96", + "0xe63a35f258460a52f644ae126adbc97eb267b1ec7bb40b8913ac95637cdc0bd7", + "0x771fc4006b7495f302d8d59d62d4f348701512465c7bcf483288b4a3cf1df544", + "0x00686653ddd2aa48e2982c26217a7f1428cb8df6eafbda49f44b9bceb5282ebd", + "0xf5d2a69a5c1700170ccf4820e7787057a0bb410e2011a835953558e69b3593c6", + "0x6e8c179171ff913dbb36bccfd0e37094d7684be3b3b550b95451de9a2573a337", + "0x21d0f292d3ace367c98d3879515f860687f9a1ddd3f736e9329b10b9566a5314", + "0x9a6723877470597e1c846f0fb1bb881ccfd16784e5b97f7ced6a858bde277d63", + "0x2379e99e79b024a882b95dd020732d620cde340eddc17e506d05a1c86b4eb953", + "0xc2061dcdfe6b0440dbb0b51e0165c02064ae544f5dbfe2fb6461c426982dbf38", + "0x63bff10713da0453a6672d489dded72ccf4526ab6c42d6fa8e94a7d1c2e83cdc", + "0x9b999c4c7e0ab1e6c2e4dcf90b08dc27074ff9c0e4e65e4760a314611cac06cc", + "0x338dd4c1a4bb139a2d7bf1fc5cbf4a5e6a0509f9883ed48989cc4cda508ca92f", + "0xed1c0c0a31e7d387e367d2578d9526adf0e7a95ba8bb78c917ec19e333195fc7", + "0xdefb920d6c97fd9deb9e253bdb0c47e973c10a6ea2e54736907abf2ff87451f1", + "0x2f4356e08d091074eee77a08f8151ca1cfca1b9c3fc0fe3424ec7e282c135c39", + "0xed00aeabd96140d2058352c5b54904033dcce4d7e674eeb70f89b36d3a6d2b82", + "0x0bf77f382f84de47f5d701ea8ad1162853f8fa05474a54ff5a742118a4aedfdd", + "0x772d24608a38fd3bca25493ed12821ed7a99eb6a79fae2e8f8fa59874c2cb1e0", + "0xc593c4ad7f4799665944170c88709d67b32479f0f36e82b0405745984697fad1", + "0xaa69e889ebd6fb54ecbc137487f6e65f9084d1586a2d4d561b03d707e15a4cfb", + "0x388d9dd700717aa8c19afb6e6ad6ed322271199ec9f4ba5795e612ba466a7a62", + "0x68df4c472e669a2477bd123a135d3e1e9fc1454ef9c4001b75041037910c6e0b", + "0x0f71b9f338fbdab556c5e33603f29c011f9dd3c00038e7adba9da28fa606e3e7", + "0x246550ae6ad91f25dc504667e98c12f076fdfc405382aa2af86708e28f011f37", + "0xc8e8f6e387ff32fc1a290bb5882fa4f56bccc716392fb8985cdc40a6f8145918", + "0xde56c970cc97055f75b49be9359cbcc1e815e1b771c51095872aa5538548d4af", + "0x011a5479a5192cb0c5cf2a2e58680ed771ff7d0d3128d1e4e58c7ee8684c12f1", + "0x6b975fe3351ef01d8e88e16ee96aadcf28aea0730eaf3a7d382d4c5b6ecc3cf4", + "0x66e8a35a06eedd293c10a61f79c00c2da418d372d7a41923b49aa269ed90f187", + "0x1ab5924225ec646903e2cc3befa65ed480e07e4bfc7b23a8112e69a898514940", + "0x42aae89f47915704db5614d2427bafe17d4c89f3b2f9a54af75788b0a465b581", + "0x6116b3cf781b5399ff85b53cdb73c8a691768b68691ce6b28f1e3814ceb67e29", + "0x789e62df669a8accf7fced4a94c4af70b1f99105d2fd46d1e7852737408696fd", + "0xf0e0efb701bd33a9cf46285439498ea610fb9fd7e497fc67a12076aae786c858", + "0x4b37c504b97bac7e683060f6bd731675c9a425dd1fdef61f49098fdc3a20d5ab", + "0x10f0cc3ea407f13c912a02f28e9a3175565d3fe3512e21ebe75c419282e609b8", + "0x48e24dbab06428401206805fcf50e533e596ac7f06dcc1ca78145306957ea2d9", + "0x43fc043bfaf30e479b15099995bbdd637678a7545318a8506257eaede34ad5c3", + "0x1ce6e0293bd8a48a6d65894ad0aa814bb1e220f88271d0478a1d35fdccc4368e", + "0x8798a23cc8be0306074e7da374760dd95ed6b3e85f7d3e1b7e08a9403738c7c9", + "0x05a534efd715fbdecfeb19391efb948fba524fdeb7fe5415379328cb92ee0e7a", + "0x8f13ed4eb277b6d570428a320918e2cbf309252a6c677dd63afbd777170cd766", + "0xd95418ce8a701035ca94cc2fcb44161cd1669e75d2f1912103ca52f83433c92f", + "0x681be568f2b05e562134aa60f5a8173cd5b49ac27645aaf3d742b11ae60cda78", + "0x0ead88dd38d9b21c7551fa6927e65551e491f93e17a23f05cf5ef49aff4424f8", + "0xde4fc8cd734fd01fe291c39ed36a3b4a51f448527d90e4bb0eee6a06dde0b976", + "0x95598d98d26fe0fc0b1e3b703e649386dfa52f892b176a862791c49ff1b8ee87", + "0xcc756753a08234dad53004649a1cbcb00a4b5582355bc072569225f8a49c1f2c", + "0x957aef285d8a880b736c4ea2f14d6274dde065ccc8e9c2ff674477f53d4a44a9", + "0xba94da4c4e497aeffbd0d0a2aeadc9e5084ef32528197dcc89c2ed9cde555c6b", + "0xd212db212c103136ee2e69a44e2ad8d3bcb3155170de7896cb68756aa546d5ed", + "0xdc61234e477321b6e7269d24b8c2b8411c7d94260961e88f5e897e534f82f8f0", + "0xdae46238c68e67e1dfded286230787eef026c98fadf9d29be98e0c3b74bd9541", + "0xdbdc6cf4b55526560ce2d4b47fff4a63b46a6f91d3f7af8711c0c2d5fe7a3a16", + "0x8498bb5772d8ec37456aa75752b5efcb92262fd3dc67a74ad62b0f9ea2a34bd1", + "0x4caf29e606a840a3f2678b145d28a29de65e4db25b5e6a7d407745a11afd9e0e", + "0xa422bacad4b0fc07ac3e4917fb4d86e40575b6ee59b4dc1aa22c550ddaaa4072", + "0x09ef8f935683b1c33a49158fca5d9e8c7521da28991ecc7b4a43d15a7f3e8179", + "0x868e02a322001c542de6b8874ae28c6b242d008980651fc8ec165dc26d1325f6", + "0x4ac2ee1b915a6a3fb22c031bf4b869785bb07af260d4aab107e4a2abf58bada5", + "0x9906fe76b1cb5187dab28a1e5b4ba5e3405305e937f1c88c6876ad53ec1b6c1b", + "0x9d6a2109384f7c9dd76271506ef0c4702e4385addfa5268e9a934b0bf4522ba2", + "0x899eb72af76569530958ec1f8725567a26ade27a89294b16ef4f87e8f12c051f", + "0xbbb2ed5029c368ce8cb34e52f36ddd99c2486b026094a9f935a04b106e1133cd", + "0x7835cacb5e7d39db682b8b16acf95504ae70ad08c64f205ba45b6f43998be66d", + "0x79c9dec734826ec7c43b8d37cd56f2a8886474b71244c0b913eeb652e2588b4c", + "0x574ea94ecebcdb9420c5d576a2bf4220b7cf8362ae7f92a0f5268792bb49880a", + "0xffdfe73b6b47fcfaf6b26c12956f96cb80505bdcfce5302d67683c5fd62197c8", + "0xd0cd4977c4fb430f09cd338f5df66e67a7fabce709fcec371ae13819a375b49b", + "0x6eafe501f49d14d093691c5f7948b53b59f38a80624440bcafa0d0308282401a", + "0x2b7ac65ed137696fc2ee8dbd1cb6a5fc9de6cee9748617ed436fffae6f0d9eed", + "0x0329936be953a4850cd53d84333e8f801906f9d5f17068faf8d2c99ed29308fe", + "0xf09ad47fe7e45c9e10266bfc452fa8e15ee1de2842502af44d08043899d39545", + "0x99166364cffd02a748be5a0a7de4590e5238b94640f68ea7c07bb0d9e0473877", + "0x8d37c6a259ac724cc67e8cad78c463d3505d11a14a7ffb30594918307f53deb8", + "0xcebfc571f69509d40dc3f15e872fcb72929245e8e66808f9cb7ae52e1c847214", + "0x1ac22d558b9e4a82008360050940ff6516a0f942810eae028fa4dd087d16d66c", + "0x8b2d70b5463cf663b2bfcf04811f6a29425de37d0fe4ddd64a5420c557a9779a", + "0x192a7331749e24299fa79d33b3c3bbba166d5bc9b955a3c79cba28f1a39f92e9", + "0x500bdd246d9d9a3376e9fef8d02d30d7b0a0950a6714a1310bd4de624b06e7dc", + "0x444e8465fecde8bdd1b53efaf118b3251bd4f2a65296383bbf25550fff8d36dd", + "0x63cd477c06e10cd5f645b93af2368cd151707051ba1e6d921d386b867efd76f6", + "0x6ec5468c3b201931725dab24ed6e72f89cac5dbe49a25041458c25d0d5966785", + "0x2b03d1bd439513feeef7697d4a58e21c5715e863e5d27a748153419a604d9fa5", + "0xdcf64485fe42fb0b483b81124758b61ba27b3f7d6561d449e17febeda6a01cc6", + "0xb557797848147314de5b34965c8756d3e797775edf51be2814b5545603b1f659", + "0xb3f1dbffdf4320e5fec0725cea7b3c98c8dcbccde0f1e032696e0c14d0bea7bd", + "0x3ffe56934a6f659f59aa128ec13c2db95a2b0df18d1a37840db869e914fdd361", + "0x14a51cd6559a2a6f12e903179547e3b76a10b339e978d7aba19222d7a8995e39", + "0xf55f41fc193413eb8dea30afb910f46536c4d2e0087101cc7a1d1945bf3f9d82", + "0x9afdc6e8253c623ff633f4efdbb3109d1f81468222a7de77fbf216c4b2d46734", + "0x2bfcb3ed3c68ac68546cb704695a479a0c15c45047e98b027a43be8c3756da80", + "0x65675b82c05d41a86fb8ddab438dcd0973e7d1044044542d36641ae387e6f9ef", + "0xe56fdcc41be235203967f4ede3bce76cb0f8e078e68ed9bf6e867bd695864c79", + "0xd42dab74de64242fb5eef9b4c239e4d5bde4c58d838c07dc728b3613c929deb4", + "0x8d52b0dc5de4452809aa787e83f76a2a650e7675aefdcc89b8e6ff34114c2a51", + "0xca438b0b85381752e1a066e5235e0d9838fcb375aabaef6e859888018a4557a2", + "0xdfab1e3a231c959d8d154f5509a167272cb647bc368413c74e411b7f35ad32da", + "0xae1d00fd3cd778188bd5df7627b2a02c69a612873bac8df6ba96816be0929b08", + "0x2dbec9851e37b9a54f0cbbdef72cde39a4368a5bfa0537b96d7ce584c5589292", + "0xfe67d721575913df5f0c69ad9e362462db169beb8f7277e15a09861817f0ae47", + "0x7d6b8267bcaede21401ebf6841f7e95a80136c41f5876a680f28e94fa89bd673", + "0xecbb62951ceeb9b49792afdf3323bd8607c8e0c019983babd997cd3df1f2dfe0", + "0x6b6a945705b609715f9e6e222e0e8145118bf97d29f3f331aac194a054a99c9c", + "0x56a7c6b7d616e3806452d6e8a2540f94410ef10c8b57f7f21cdc2df799bb0a02", + "0x73f6f889fe9d8276f2942cfccd3781e8e326e29ccd033a8273041451c9065ef4", + "0xec84330677c2311e85d76dffc692ed3e2d194e90fef2423609c53afe03b10a2f", + "0xa63916671ed57cfc053a4595a854b26aa31a84e775fd3a9d3e3b4763b6f23625", + "0x44e3a21e4b5b1ef0636e0e4e4775b16d4722838c3eac7062e963d46bc2946d92", + "0x910eb99fbd1e3afc013a5f50b475fb324d20c7aad82c602b8e9c21c7bb914d26", + "0xe66fe50308eae671e265d6985c346cb23594746b2c7470a0d3bc8018f3e89abb", + "0x68c0706f4a903432bc423c7b11ed2fd685b0c11cfcc9c7da4b17ea9fe77ea628", + "0x2eadf540de899a1b71827e8cecd8efe280b6f5a9e96cbd3fbdca10ecfa8c18af", + "0xb67b79aee1d96e626a92864a92d0e1536e4c79d1f7980c83ef53506c3795d4c5", + "0xf8b79fa4dcc8b6943c76a1a48ccedcabffe2a309f38682bc7dcfb6cc71900dbd", + "0xaba4ea033adf6944ecec4d49b886d5cf8be86576a2c30a9609292cb087bf2f30", + "0xa38e14dc7b081b096b93a5588e13c18156dfe90a1b0c3f294568f8fb43a1679b", + "0x796373232dc5595162f632d5c169ee186c48fe7c33be7e9d69af68b836e38399", + "0x612c5be74f0bc72c953546a6a2f70d0e7c05bb3e9806218867ebc29924b7e9f5", + "0x9fad004bd232cd89ce84777a1480893821a29718e464cdb662c5dd9c5a276c6e", + "0x4c0a8776183994e83cdd7816ae3dbff33da6754f6a4dd16405d7c44823266c5e", + "0xbeef52ba26b24e9c34a630fb5bceaf97f5d56577855b409bc8b27e5e25b3b870", + "0x020fe496c09044dffdeaccc2a90ded49031829cf75a747c7a27aca06f489283b", + "0xbcd6208f1eb03d16f20fe1cc19fa2992d1e0def9ba1e3c3e95f26a413153a7a6", + "0x45c09c2c26bf73116b2bfb8762d7837815d2ffda196517b7fe9ed23165b49eb6", + "0x99314aaff566a187f89b9634bb9d28325bd368e29b7a42e73653731a1fa42522", + "0x519db26bae12d9b532d541db13dd74c1e19b6390029f3091e99b76f85e74e33f", + "0xd3c0b7413873d883efdf1c42e0de66cd78a9c0a8b614dd88a2e84947a1bd0869", + "0xc087342fc0e8df4176bea79dae4d6b4f33ca9b398fbd357c877c7680ae39d9f0", + "0xce5714dc42019277e8170fa097ab567ccd88cd4e24ce511fa6e93f85ed8c3302", + "0x68e1064b5077861bd9839539a5529a63bc0e4df68e875e6197f6fc9616fc1c2a", + "0xa898f156e8de5f588480a79ee5448f6a1c3f482cbaed2ac2659459cfce08ae34", + "0xcdd2f9e50fbb0eea3058d3341cbe39a7274cdcb3f10df0cb5803fe1bdeba3713", + "0x7eee48ac933e7cafa8cabd7b2868d92f27b0210bc0810e5a1337ea32daf3ab8f", + "0x99e2e041e1b178b8538594e356ac7c7133f24cba67083192dd2bc30fdb3d0d69", + "0xa4f4e1777b831cd05440067982b48aca3b89b9c2b19ab82c788be5301856f7c4", + "0xa44b761db0a2a19eaa9d2086a594290eb48f8fddc3e9209f3ed8c82de35d5fe9", + "0x189fb24a706ede989db9a587e205b66cc4e2ca5329c4726f5cfc72dc0df4563b", + "0x9104e63319bd2ba428a47c170e0a310a67bd90ceab2d232dfacdfb72bee09f0d", + "0x219779e07435f4b4458ea8a5131e796cc79d47a30692798eeabee8c8a47a2405", + "0x2a946612c3dcb2da23fd7696d4d30acc3ec25e292d239f3c01b0923f62ee51c1", + "0x7a244c94d76d458be7acc6c885c357496a77daa119e49a3ae168908bc73bb569", + "0x274139b3f78e5193cf35b7f28439dc4f74e6927a795234a00262175971b99fc6", + "0xd138526ac6cef7792d3dc1993f364f1b0985b9dfa3db1847d785ecb81a70eefe", + "0x1ce8e07f1350000599c342adb2557d8ccf3fa1d4752b6cf2cc71c42fd62a7e8d", + "0xab8f97c1e9a65dcaaac53f799f844d831da02dcbd372b796375115ab19a32eb1", + "0x53a3a62994cb0391e81167207b1a25604f25dc08240666072b0f0eec0311feaf", + "0x786797a4a478d15b758067c82e2ebe1d0ab2240e8db29e050e6765777b2aae3e", + "0xf096ab958bfba2f4aaab3e1bca5bdedf276bec61516ab7602a8a54ec6219920e", + "0x25ae9275d83e34866d66f4896167de7e04aa6fd8070554b11ee847fff73d9e27", + "0x871e675b37b2ebb4f3a7ffeaa0fa6f4a47db92f517b66fda5bea400f13528071", + "0xe706cb07d3f90e7c4f7c9cf09401b9b82a063fec369514247db76efca5e2c640", + "0x0eeab1ee0c30812b9de778016821a933efd94129b13524b9558a74ae84906380", + "0x7f86033772f4b5265042b6ec7f3b14570415db9a148617e63b84331d0decfa25", + "0xd916a6a70300faea19447bde63491ebc21d8447e5a5225f18618cd44d9d25fe2", + "0xe5e632370370812351165ad2d82a6be86e9a2ea0a134cf0b2d92e481a282506f", + "0x48d4ede9a70efe12d9f21bbeccae2857dc5859d4d155da96806cbb392194aed0", + "0x6def1fa1beb67760b1a94ac9da22a7df6a3d3b9722c2e9c2cd503dfb14340c2a", + "0x0b6493b5a5798dd98ebf99f12fe714d11f78eed5800d892f50f6c80d5f9b916a", + "0xce7bd3ceb24946842e452057021e80b7909ab4326fb43725923f5447da7566a7", + "0x3d2bb2934beb966aaff7629a346cdf19c4e3671116d7e202e2fc9be7d1fa4fb3", + "0x07e58703bfd562eaacef11363c7f70b0609ed6d628ee58e06b11122a8254f0ef", + "0x26cc012c66068fa47616f5f1d9bf45751102e99519bc5cbf0b7da14eb0ecb1cc", + "0xcd736566d5d6c8ff5bff349d3a932b94c19f9765193c3e41f70f0345521038bf", + "0x1f400b109e0773845f75f99d107e6146c97172799351597abd435af18b9faa46", + "0x0009b529ec164e1686276b6b1dade0a82f76963c43f27919b193348bf9372bfb", + "0x180b4008aa291f371615cb3e2975b2b29b3db58d2ad61593a52dd9a9bd963319", + "0x86b7aa3798243667c0001cb9a97a7660145b3582fc2232b4625b001e4babe622", + "0x823312d5231a8db9211b141b2483fcb1b6d311e482efff347c9dd17a74c611d0", + "0xcd0e83e63db1c4a6f2638dce68677bea55e9d4b84feaadb1bb085f485318c627", + "0x3f34cb62b347f4930005e39a102d08d506fcf9ee1418c372dc64a70f86b7e02a", + "0xd03e1359280033fe74fff780447b29397894a811859929eefd4d52cf6ca40521", + "0xa6fb9b05db2dfbd6ff4414b5f03633b46f5db77c198e6aaf9ffb366b9bdd3af9", + "0x87af91f40f569df2c64e20accbd3cb7fa21c2cd24a1f9eeb1dea7a39f11ba3f9", + "0x20d35104742d776aee3cfbf6dc1e36a172bfbd2a8ec14f9fd016eea15e480c19", + "0xa388892adcd0c0109f09a3bca25c6d49f2295dac3c61c6d6cca03b8e92d253bd", + "0xc7189645b5cfab9cb71e3d1c671bb439e8c14eb2971bbc21fd5da08158ca07c7", + "0x72f695f9d98843fc4950f8ae78c2bf48c09c92660483bfcf270c2a633f05e852", + "0x866f028434caaf3cbe032ce693c2628295daa219b0462dcd3ae14df71fe746f2", + "0x5d3d16c2f16c48a442e44fcc0a04700c40c1033bb0276a1f27d264ad2fc91b6e", + "0x4bf7678c9db62bf4f8aa92098ff39619b2484f75fae80f6438742c3c5702c652", + "0x8200e4ab04b42c901a2965aa2243976e553c555ecc811ecbdf9bc470ca32351d", + "0x1676a43cfbf10d344c6837d1a139de56085b88acfceb3cbef0056c11ee6cfa28", + "0xfb3ee392b6c300a8be67d4eba8093471c77a6c6ca5682644b16bafb749d9c995", + "0x4887db0505d7f3c7017374a482367ecbe9b69de429d2d0965fc9a4e37093787d", + "0xcc00e39c22808934bc034c2ac322643668711279b300ccc561dd7381bbf094e4", + "0x2d906acbcfae462edd246ce62e07f29e1cc0a0cd23b510b61f4ee523a2061ba8", + "0xe61769fa90b6df16bab14466afc63cb1efcbe46fa54594e8c7c114ece565250b", + "0xae6085d35aac3488d871bee66119d05c889acb428cd5c6a2a673d85a45932ca0", + "0x17c004024e663872c0ba979e00490587977f2237bfd11639c4abe5e4eefd3fc6", + "0xe5ef57a117bec639b4885e6941aea12a6dd96aaa7849f29f000654a2c29c6b7c", + "0x00dee21ac9b8eec2b22982645edf796dd65fe1cc68629bf7f79ba4910b41c8f6", + "0x8c42ca1d5ecd86e445b0c01da6d60202b1371495ff1a3990fa880c43c4681de0", + "0x234e64d7baecc3e4ab3ac0982ee93dd426f8b0313e59d40be4707c40540f0c91", + "0xd7f8b45da51184e9ac15b373991b0c46d48c7cb5776967953e57f9e85f7880b7", + "0x1d895c0700d2db688ce79e987e3b35b5c0d0bf17ea5432cb1db245592054b484", + "0xb12cb54a7f50711f7bfbf03d57c5c1262191019ef9ce69485cdc41d7745411da", + "0x2f54a275e01adc7e6cd5b464f8d033007ef09a0a3ae29f9bdf179ee985d5f29b", + "0xc21039510b8dcbfbacfe8794826b79d3ad3c839287015857d780fb57a1ea4ea6", + "0xb18484c56bf516dba0e6a2b31c0b6f93cd38957a60c588e9e7fb1859d8ad18e8", + "0xbaceef26e6b8a5bdf0a21cda677f71239736a0544bcac5f3d9a90696b8a7b15c", + "0x97838a53f6996d5dff68c3439689d2f87c7e97ea6be519cf8dd70a47b023f2ea", + "0x882be66e5ac63dfa0f5c31789b24f6a25f6c8751ff609f86977dbd0cae890df7", + "0xe462a0b007f8029cc65f40ae1f42abe47f160afaf92da8470990bd94443165c4", + "0x37a46df02258c5965454e0374d08f3650d16f05b083190b787e7d514409daead", + "0x55604327bf00775ed3b2d121acd86563883f597628a76e5f1abc66309fcb09cf", + "0xd893ebd9fad9973e616de074827b3af3a0387fd3b9a7cd4d59f1bf98d8426027", + "0x2e8c05fc5ffede3b58cfbcaf62cdf334357e3786764c715c2a6980f0569aab2d", + "0xa50933e55e80764035403224fef71248bd1bd3c0fa3b40b485113c203ea1197c", + "0xed34b281864aa711320b075dad853fd035aff039490bbf3d029b647bc7ca6943", + "0x0d29603bcdeab05abb491caaab151e0c4fd2e3d7b9dfbb1f3f37d0869ff09862", + "0x49f2318fe7347589b1b0444d98dc79b31ce22225ebd2c463a29bbeb1b65d45e8", + "0x7cd03259ec36ececd895da05e4490770e4a354e0f84a821de440a05562220a0e", + "0x0bceae0593be03526c84e8979522408d01f8b553bb4e18ed9dc81ca62ec058b9", + "0xc4f885819cf0f8a398b59040acab517ab10d3380bd8ac69645ce27836dc19ffd", + "0xd3bbc4fa9b2136118179fe8eb0bd79c113a725bf6cf7c7e4f8b5f59398dc44ab", + "0x73e21d02abd45dc1689e24b9d25141698b683a8add128122ac3e245e23958d70", + "0x4b6814ba380b801a62c4a3d3e8ade70c48cc7e7a5a4d5f6a0a7e8c5d7b8ecaf4", + "0xacce6845fbb4ea44e2b3f81225437c7eda438029557a26419c6d76755cfaa9ca", + "0x8ab24bd5c8ac2081b713634b56f459db67ccd48f833cd9ff170fbf1baa476e3d", + "0x817faf7f5bc035d2c3684ea95ebf27a7c3048e85f0595d4cf8318192b532d2d0", + "0xdb867eba31c6f0b191784bb7ee4858d2db1bf3fec19dedbd08e5fbdd4e1b3559", + "0x4c28527c58ae5e6f29102bc5711d39e25af511bbcb02d9a87f52f76eed517f07", + "0xc0b8bfa43b9544a635ca96d3fafd9747d24680c81af43234dd30b65fb304322d", + "0xe26c80fdcca6e61411fff3991dbc44c4f3725aae057a81770fd8def73f0ce024", + "0x5f044013409beced775746d721dd78b45591e20d3d85dd6c9361aaf47a0ceb65", + "0x71e3284644d22af77474a93e268d0dd265c0c42d94c4ad9fd62430461cf3efb9", + "0xe2487c02ef5a9cd04fcc5544243fb7dfdf90b559bcc8277f7ad6d892753df2f3", + "0x09808d08c0e358c29603f83d201938377a45b543816b079f889c1fbbcb4847f8", + "0xb5f97d9ea4e92b9884d70bd1b0dc301b33690e64f648c770d4f9fc16e3e6fbc7", + "0xe7fdb278d471461a7adf3496eac82bf323a0faf62b2a4d634f56468ede626322", + "0xa9f79b0f2e8e7b8ec5224773f1cb2762078430d8b131a6f22cf7973252212e72", + "0x5cf0e6a30df29b2ad982b1db7283cc4c671488a43602b0d768177af61684124e", + "0x11fd4ff8d42811d05bbde1bb0769cf4cbcd03b6c99048aeee9bd1b608c3927c3", + "0x92b6d6e27443525cc63111623c69b46c3bbfbd9e528d876a6de043d7f82b3a50", + "0xd1a398f4b33acc132e854b49eb51773abf1846cde2dbacff9c4527b466bc8a26", + "0x95628b62aa0fa59b2b49fc6fc7e6fdcc416b59ee5229edd425b1a607e9998153", + "0x82f479a7ab8e6db85296f8cd3df13279ee899e1bd8df95b357ded43d4baffd6a", + "0xd193576f1bd139a319e1493c075e33f317a05308b93ff3ecaf5249c20e025755", + "0x7ad318979fbca17b06a968c11be03713d3d46c8287477723a0c97374f5ce4986", + "0xdd52a80097dbabfb0979368e56fb93087cf9aa1e5e3047faaf6ba475c5d3adfd", + "0x3f54e8d5b1ea24ef7fd8e5df54ab472b1611925df5c8431336ad647687d942e9", + "0x13602b947455a57cec85f485f3b06bef3268ef99f5d0d80ec3278948354dbc78", + "0xb6d186e6caa9662af33cb661605d18cdd96d54a62fddf40a8b59957c95794009", + "0xf26e692ac554a77ca5f56aa4f49dcf03a7b9706f6814f0d8e09007f81d8a79ca", + "0x31fbcf8df989b08262cd60f604edf8149974245f020acdedb10d274f59bf77d2", + "0xcb796442847e9eae7bd397c45394fca256f885c921d9757c3eb3ac6a7c4d21d4", + "0x29643bac94a2c041e6bac56bec1cc46acb340ed5ab34606b2fe088a804a3459e", + "0x4204834ffbd39aefc2a735c2f9ddd312104481866d1e7cf169eaa1d95528085c", + "0x86de4f25fa0c49fd019141a1386cc52e296651684d13679f4f67a814155eb215", + "0xcf32d0cf2c694df53580cfdbec9a6b54eb8e83c7403d3359c61ce85eb5418ce5", + "0xe081edea49229b8f7b276b2e3bdfd2b8ad12afbd071997a0e5443949d1f5fd7b", + "0xd43f8f081c96f2639add57b7d7a112106de124b7d9c504f792cd422358aeb7c5", + "0xec11b96266eb477f0b998ced2832efb936ca3ebc1da4146342627d9657f9d31a", + "0x89927e87d7b5522802f654da80dc70b8a14a3db83a8ba1c0e162d5bdd6327a00", + "0x052526cc801a21f0bc0b145d45be93d500f48127a6fc1970bf10ee2d5aac34ce", + "0x07f53db511f45a428f6508c51fc608730a53e1ab0d425c8b44196507c3288f76", + "0x380ff3fc61929d4297b598c725a1bfdb651e878ef0e26049648a622c126a19da", + "0xeb9b3e7bfc792d6ab85d00d45fee76cc84f81692d5554bee8f1790f027bc615b", + "0x10ef177a4d3610f9105e6b35318f2d12df4f7c248e639999961feda96a5f2f30", + "0xedb17228c2bde8e124c0fa9dd99e9af6bdb920b30e71ce55c3aefe30740ff377", + "0xcc110bc17f21ae92054bf94b3109efa6df3240fd54d7a22a87492590e5fa7c21", + "0xd946e901eed5e8f0ab584258f78e76436f6aeb5c16f49d0bdd5c7b1ecaaf62ea", + "0xc7fa65c5e8c48d4ea354f3900623950a0f6a319572381624258b5cf6b757a4af", + "0x262f129de130f709b4c98a31c208c2edf21b10d005507762dafdadf0195f61ab", + "0xb71ac11bffc2f2085699142bf75c7723624454cc3f3f44390e21c50a43918ed7", + "0xd0fc736551e28fef1816584f4e80fbff2b92dbbef3c6b33de9fff624c9f30050", + "0x423f396ef11a9100a30ad47e0953efad3014797c97b468d68e9da1cbff620ed5", + "0x819259e80f60bbd32cbab7027ff4ec134778f9254bd5c12020dc743b31a4ea49", + "0xe3306484604c7e73f844720524303484126db195e3bfa429feb6189a1685b018", + "0xdf1cc368134b50f3a2cfd8660e1fc8cc27e12f58c979e0416b391c140baea6c1", + "0xbda9fee3730f730df0ffa9c0051ce991d88e9b97106de6429d125b0b477d61ec", + "0x3d2fa3a51f1cc993baf397ae89fd9153e7842ff613e7b96b5e572b5a3558394d", + "0x3ba82a36da3d9732daa74bf593207b49a071cc4db8a1327ae0d5ef9534181697", + "0x19b4b261ddc43476412c8b8c537d9e26014c6c632ba98466003591cc947a5805", + "0x568f44291c13efc908db42d2473bc91ebb16e062e9b4368bcb770a3033d67741", + "0xe5ecad510448855ff0aafb92a8c7aa54aca0fb390bec3c14ad5d2ba200380aec", + "0xa40aa7655c1458b76c04ea5934ae171fb01c72c8c375bb61a0c27b0ebd70f21f", + "0x770ad5107ac47fd983979b016553ca8f340a13e2647b9140e65c980dcf349cff" + ] + }, "nodes": [ - "enode://efe4f2493f4aff2d641b1db8366b96ddacfe13e7a6e9c8f8f8cf49f9cdba0fdf3258d8c8f8d0c5db529f8123c8f1d95f36d54d590ca1bb366a5818b9a4ba521c@163.172.187.252:30303", + "enode://6a868ced2dec399c53f730261173638a93a40214cf299ccf4d42a76e3fa54701db410669e8006347a4b3a74fa090bb35af0320e4bc8d04cf5b7f582b1db285f5@163.172.131.191:30303", + "enode://66a483383882a518fcc59db6c017f9cd13c71261f13c8d7e67ed43adbbc82a932d88d2291f59be577e9425181fc08828dc916fdd053af935a9491edf9d6006ba@212.47.247.103:30303", "enode://cd6611461840543d5b9c56fbf088736154c699c43973b3a1a32390cf27106f87e58a818a606ccb05f3866de95a4fe860786fea71bf891ea95f234480d3022aa3@163.172.157.114:30303", - "enode://bcc7240543fe2cf86f5e9093d05753dd83343f8fda7bf0e833f65985c73afccf8f981301e13ef49c4804491eab043647374df1c4adf85766af88a624ecc3330e@136.243.154.244:30303", - "enode://ed4227681ca8c70beb2277b9e870353a9693f12e7c548c35df6bca6a956934d6f659999c2decb31f75ce217822eefca149ace914f1cbe461ed5a2ebaf9501455@88.212.206.70:30303", - "enode://cadc6e573b6bc2a9128f2f635ac0db3353e360b56deef239e9be7e7fce039502e0ec670b595f6288c0d2116812516ad6b6ff8d5728ff45eba176989e40dead1e@37.128.191.230:30303", - "enode://595a9a06f8b9bc9835c8723b6a82105aea5d55c66b029b6d44f229d6d135ac3ecdd3e9309360a961ea39d7bee7bac5d03564077a4e08823acc723370aace65ec@46.20.235.22:30303", - "enode://029178d6d6f9f8026fc0bc17d5d1401aac76ec9d86633bba2320b5eed7b312980c0a210b74b20c4f9a8b0b2bf884b111fa9ea5c5f916bb9bbc0e0c8640a0f56c@216.158.85.185:30303", - "enode://fdd1b9bb613cfbc200bba17ce199a9490edc752a833f88d4134bf52bb0d858aa5524cb3ec9366c7a4ef4637754b8b15b5dc913e4ed9fdb6022f7512d7b63f181@212.47.247.103:30303", + "enode://78b094cb27ceeecbe311bc278f4fde8b9a265db42d268c88484c94d7a2d19b82a1bd22dfd6c2bd4d90f9b05e6d42255e6eb85de15f73848ff82ed0be9cdf5202@52.233.198.218:30303", + "enode://00526537cb7e1aa6cf49714f0635fd0f608904d8d0693b949eea2dcdfdb0abbe4c794003a5fe57aa662d0a9215e8dfa4d2deb6ef0101c5e185e2617721813d43@40.65.122.44:30303", + "enode://4a456b4b6e6ee1f51389763e51b80fe04782c762445d96c32a96ebd34bd9178c1894924d5101123eacfd4f0fc4da25b5e1ee7f18832ac0bf4c6d6ac81442d698@40.71.6.49:3030", + "enode://68f85e7403976aa92318eff804cbe9bc988e0f5230d9d07ae4def030cbae16603262638e272d19875b7e5c54e296ba88ab6ec6e98face9e2537346c4dce78882@52.243.47.211:30303", + "enode://dc72806c3aa8fda207c8c018aba8d6cf143728b3628b6ded8d5e8cdeb8aa05cbd53f710ecd014c9a8f0d1e98f2874bff8afb15a229202f510a9c0258d1f6d109@159.203.210.80:30303", + "enode://5a62f19d35c0da8b576c9414568c728d4744e6e9d436c0f9db27456400011414f515871f13a6b8e0468534b5116cfe765d7630f680f1707a38467940a9f62511@45.55.33.62:30303", + "enode://605e04a43b1156966b3a3b66b980c87b7f18522f7f712035f84576016be909a2798a438b2b17b1a8c58db314d88539a77419ca4be36148c086900fba487c9d39@188.166.255.12:30303", + "enode://1d1f7bcb159d308eb2f3d5e32dc5f8786d714ec696bb2f7e3d982f9bcd04c938c139432f13aadcaf5128304a8005e8606aebf5eebd9ec192a1471c13b5e31d49@138.201.223.35:30303", "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", + "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", + "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", + "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", + "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", + "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", + "enode://0cc5f5ffb5d9098c8b8c62325f3797f56509bff942704687b6530992ac706e2cb946b90a34f1f19548cd3c7baccbcaea354531e5983c7d1bc0dee16ce4b6440b@40.118.3.223:30305", + "enode://1c7a64d76c0334b0418c004af2f67c50e36a3be60b5e4790bdac0439d21603469a85fad36f2473c9a80eb043ae60936df905fa28f1ff614c3e5dc34f15dcd2dc@40.118.3.223:30308", + "enode://85c85d7143ae8bb96924f2b54f1b3e70d8c4d367af305325d30a61385a432f247d2c75c45c6b4a60335060d072d7f5b35dd1d4c45f76941f62a4f83b6e75daaf@40.118.3.223:30309", "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://2c9059f05c352b29d559192fe6bca272d965c9f2290632a2cfda7f83da7d2634f3ec45ae3a72c54dd4204926fb8082dcf9686e0d7504257541c86fc8569bcf4b@163.172.171.38:30303", + "enode://efe4f2493f4aff2d641b1db8366b96ddacfe13e7a6e9c8f8f8cf49f9cdba0fdf3258d8c8f8d0c5db529f8123c8f1d95f36d54d590ca1bb366a5818b9a4ba521c@163.172.187.252:30303", + "enode://bcc7240543fe2cf86f5e9093d05753dd83343f8fda7bf0e833f65985c73afccf8f981301e13ef49c4804491eab043647374df1c4adf85766af88a624ecc3330e@136.243.154.244:30303", + "enode://ed4227681ca8c70beb2277b9e870353a9693f12e7c548c35df6bca6a956934d6f659999c2decb31f75ce217822eefca149ace914f1cbe461ed5a2ebaf9501455@88.212.206.70:30303", + "enode://cadc6e573b6bc2a9128f2f635ac0db3353e360b56deef239e9be7e7fce039502e0ec670b595f6288c0d2116812516ad6b6ff8d5728ff45eba176989e40dead1e@37.128.191.230:30303", + "enode://595a9a06f8b9bc9835c8723b6a82105aea5d55c66b029b6d44f229d6d135ac3ecdd3e9309360a961ea39d7bee7bac5d03564077a4e08823acc723370aace65ec@46.20.235.22:30303", + "enode://029178d6d6f9f8026fc0bc17d5d1401aac76ec9d86633bba2320b5eed7b312980c0a210b74b20c4f9a8b0b2bf884b111fa9ea5c5f916bb9bbc0e0c8640a0f56c@216.158.85.185:30303", + "enode://fdd1b9bb613cfbc200bba17ce199a9490edc752a833f88d4134bf52bb0d858aa5524cb3ec9366c7a4ef4637754b8b15b5dc913e4ed9fdb6022f7512d7b63f181@212.47.247.103:30303" ], "accounts": { "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x7fffffffffffff", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "bn128_pairing", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 4370000, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 4370000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 4370000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 4370000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 0f4b8850fd6be4803282bd1ad030f67e669fac68..6d2ea3693df017294ba1b54e0897c24d2c21d270 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -6,6 +6,7 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x118c30", "daoHardforkTransition": "0x1d4c00", "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", @@ -136,7 +137,6 @@ }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 802a77f8da218d8b25a77bede47f21229b189a83..aae59cb071e4ae574f3b07a7bdfe9e5805eec0e4 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -6,6 +6,7 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x7fffffffffffffff", "eip150Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", @@ -16,7 +17,6 @@ }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index 557a48a64034e7373a399e862b76d3cff452535a..c6d49b5455604566fca593e6b09130e327246a27 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -6,6 +6,7 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": "0x0", "eip150Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", @@ -16,7 +17,6 @@ }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index ca7638e338c56508964127f1ff269f153c71396d..0d00478c599dd8c3c9b502813dc652e2d87023ba 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -1,63 +1,76 @@ { - "name": "Kovan", - "dataDir": "kovan", - "engine": { - "authorityRound": { - "params": { - "stepDuration": "4", - "validators" : { - "list": [ - "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", - "0x00427feae2419c15b89d1c21af10d1b6650a4d3d", - "0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c", - "0x0020ee4Be0e2027d76603cB751eE069519bA81A1", - - "0x0010f94b296a852aaac52ea6c5ac72e03afd032d", - - "0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A", - "0x00E6d2b931F55a3f1701c7389d592a7778897879", - "0x00e4a10650e5a6D6001C38ff8E64F97016a1645c", - - "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" - ] - }, - "validateScoreTransition": 1000000, - "validateStepTransition": 1500000 - } - } - }, - "params": { - "gasLimitBoundDivisor": "0x400", - "registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3", - "blockReward": "0x4563918244F40000", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID" : "0x2A", - "validateReceiptsTransition" : 1000000, - "eip155Transition": 1000000 - }, - "genesis": { - "seal": { - "authorityRound": { - "step": "0x0", - "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - }, - "difficulty": "0x20000", - "gasLimit": "0x5B8D80" - }, - "accounts": { - "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "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 } } } }, - "0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } - }, - "nodes": [ - "enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303", - "enode://dcf984764db421fa0cd8dc7fc02ae378545723abb94d179f55325514cc30185eaea3dcefde6e358b7cdbe970c50b7c49e841618713a9a72d6f3f59ad9949ec6b@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" - ] + "name": "Kovan", + "dataDir": "kovan", + "engine": { + "authorityRound": { + "params": { + "stepDuration": "4", + "blockReward": "0x4563918244F40000", + "validators" : { + "list": [ + "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", + "0x00427feae2419c15b89d1c21af10d1b6650a4d3d", + "0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c", + "0x0020ee4Be0e2027d76603cB751eE069519bA81A1", + "0x0010f94b296a852aaac52ea6c5ac72e03afd032d", + "0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A", + "0x00E6d2b931F55a3f1701c7389d592a7778897879", + "0x00e4a10650e5a6D6001C38ff8E64F97016a1645c", + "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" + ] + }, + "validateScoreTransition": 1000000, + "validateStepTransition": 1500000, + "maximumUncleCountTransition": 5067000, + "maximumUncleCount": 0 + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x400", + "registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2A", + "forkBlock": 4297256, + "forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f", + "eip155Transition": 1000000, + "maxCodeSize": 24576, + "maxCodeSizeTransition": 6600000, + "validateChainIdTransition": 1000000, + "validateReceiptsTransition" : 1000000, + "eip140Transition": 5067000, + "eip211Transition": 5067000, + "eip214Transition": 5067000, + "eip658Transition": 5067000, + "wasmActivationTransition": 6600000 + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x5B8D80" + }, + "accounts": { + "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "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://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://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303" + ] } diff --git a/ethcore/res/ethereum/kovan_wasm_test.json b/ethcore/res/ethereum/kovan_wasm_test.json new file mode 100644 index 0000000000000000000000000000000000000000..9be03a769082544f329847d55c18b21de6d25de2 --- /dev/null +++ b/ethcore/res/ethereum/kovan_wasm_test.json @@ -0,0 +1,74 @@ +{ + "name": "Kovan (Test)", + "dataDir": "kovan-test", + "engine": { + "authorityRound": { + "params": { + "stepDuration": "4", + "blockReward": "0x4563918244F40000", + "validators" : { + "list": [ + "0x00D6Cc1BA9cf89BD2e58009741f4F7325BAdc0ED", + "0x00427feae2419c15b89d1c21af10d1b6650a4d3d", + "0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c", + "0x0020ee4Be0e2027d76603cB751eE069519bA81A1", + "0x0010f94b296a852aaac52ea6c5ac72e03afd032d", + "0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A", + "0x00E6d2b931F55a3f1701c7389d592a7778897879", + "0x00e4a10650e5a6D6001C38ff8E64F97016a1645c", + "0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de" + ] + }, + "validateScoreTransition": 1000000, + "validateStepTransition": 1500000, + "maximumUncleCountTransition": 5067000, + "maximumUncleCount": 0 + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x400", + "registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2A", + "forkBlock": 4297256, + "forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f", + "validateReceiptsTransition" : 1000000, + "eip155Transition": 1000000, + "validateChainIdTransition": 1000000, + "eip140Transition": 5067000, + "eip211Transition": 5067000, + "eip214Transition": 5067000, + "eip658Transition": 5067000, + "wasmActivationTransition": 10 + }, + "genesis": { + "seal": { + "authorityRound": { + "step": "0x0", + "signature": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x20000", + "gasLimit": "0x5B8D80" + }, + "accounts": { + "0x0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "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://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://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303" + ] +} diff --git a/ethcore/res/ethereum/mcip3_test.json b/ethcore/res/ethereum/mcip3_test.json new file mode 100644 index 0000000000000000000000000000000000000000..d2e5ec8b6bceddde13ba10c7dba043e14c810548 --- /dev/null +++ b/ethcore/res/ethereum/mcip3_test.json @@ -0,0 +1,168 @@ +{ + "name":"MCIP3 Test", + "dataDir":"mcip3test", + "engine":{ + "Ethash":{ + "params":{ + "minimumDifficulty":"0x020000", + "difficultyBoundDivisor":"0x0800", + "durationLimit":"0x0d", + "homesteadTransition":"0x118c30", + "eip100bTransition":"0x7fffffffffffff", + "eip150Transition":"0x7fffffffffffff", + "eip160Transition":"0x7fffffffffffff", + "eip161abcTransition":"0x7fffffffffffff", + "eip161dTransition":"0x7fffffffffffff", + "eip649Transition":"0x7fffffffffffff", + "blockReward":"0x1105a0185b50a80000", + "mcip3Transition":"0x00", + "mcip3MinerReward":"0xd8d726b7177a80000", + "mcip3UbiReward":"0x2b5e3af16b1880000", + "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", + "mcip3DevReward":"0xc249fdd327780000", + "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" + } + } + }, + "params":{ + "gasLimitBoundDivisor":"0x0400", + "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", + "accountStartNonce":"0x00", + "maximumExtraDataSize":"0x20", + "minGasLimit":"0x1388", + "networkID":"0x76740b", + "forkBlock":"0x5b6", + "forkCanonHash":"0xa5e88ad9e34d113e264e307bc27e8471452c8fc13780324bb3abb96fd0558343", + "eip86Transition":"0x7fffffffffffff", + "eip98Transition":"0x7fffffffffffff", + "eip140Transition":"0x7fffffffffffff", + "eip155Transition":"0x7fffffffffffff", + "eip211Transition":"0x7fffffffffffff", + "eip214Transition":"0x7fffffffffffff", + "eip658Transition":"0x7fffffffffffff", + "maxCodeSize":"0x6000", + "maxCodeSizeTransition": "0x7fffffffffffff" + }, + "genesis":{ + "seal":{ + "ethereum":{ + "nonce":"0x000000000000002a", + "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty":"0x3d0900", + "author":"0x0000000000000000000000000000000000000000", + "timestamp":"0x00", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData":"", + "gasLimit":"0x7a1200" + }, + "nodes":[ + "enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303", + "enode://3f1d12044546b76342d59d4a05532c14b85aa669704bfe1f864fe079415aa2c02d743e03218e57a33fb94523adb54032871a6c51b2cc5514cb7c7e35b3ed0a99@13.93.211.84:30303", + "enode://78de8a0916848093c73790ead81d1928bec737d565119932b98c6b100d944b7a95e94f847f689fc723399d2e31129d182f7ef3863f2b4c820abbf3ab2722344d@191.235.84.50:30303", + "enode://158f8aab45f6d19c6cbf4a089c2670541a8da11978a2f90dbf6a502a4a3bab80d288afdbeb7ec0ef6d92de563767f3b1ea9e8e334ca711e9f8e2df5a0385e8e6@13.75.154.138:30303", + "enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303", + "enode://979b7fa28feeb35a4741660a16076f1943202cb72b6af70d327f053e248bab9ba81760f39d0701ef1d8f89cc1fbd2cacba0710a12cd5314d5e0c9021aa3637f9@5.1.83.226:30303", + "enode://d302f52c8789ad87ee528f1431a67f1aa646c9bec17babb4665dfb3d61de5b9119a70aa77b2147a5f28854092ba09769323c1c552a6ac6f6a34cbcf767e2d2fe@158.69.248.48:30303", + "enode://c72564bce8331ae298fb8ece113a456e3927d7e5989c2be3e445678b3600579f722410ef9bbfe339335d676af77343cb21b5b1703b7bebc32be85fce937a2220@191.252.185.71:30303", + "enode://e3ae4d25ee64791ff98bf17c37acf90933359f2505c00f65c84f6863231a32a94153cadb0a462e428f18f35ded6bd91cd91033d26576a28558c22678be9cfaee@5.63.158.137:35555" + ], + "accounts":{ + "0000000000000000000000000000000000000001":{ + "balance":"1", + "builtin":{ + "name":"ecrecover", + "pricing":{ + "linear":{ + "base":3000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000002":{ + "balance":"1", + "builtin":{ + "name":"sha256", + "pricing":{ + "linear":{ + "base":60, + "word":12 + } + } + } + }, + "0000000000000000000000000000000000000003":{ + "balance":"1", + "builtin":{ + "name":"ripemd160", + "pricing":{ + "linear":{ + "base":600, + "word":120 + } + } + } + }, + "0000000000000000000000000000000000000004":{ + "balance":"1", + "builtin":{ + "name":"identity", + "pricing":{ + "linear":{ + "base":15, + "word":3 + } + } + } + }, + "0000000000000000000000000000000000000005":{ + "builtin":{ + "name":"modexp", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "modexp":{ + "divisor":20 + } + } + } + }, + "0000000000000000000000000000000000000006":{ + "builtin":{ + "name":"alt_bn128_add", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "linear":{ + "base":500, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000007":{ + "builtin":{ + "name":"alt_bn128_mul", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "linear":{ + "base":40000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000008":{ + "builtin":{ + "name":"alt_bn128_pairing", + "activate_at":"0x7fffffffffffff", + "pricing":{ + "alt_bn128_pairing":{ + "base":100000, + "pair":80000 + } + } + } + } + } +} diff --git a/ethcore/res/ethereum/mcip6_byz.json b/ethcore/res/ethereum/mcip6_byz.json new file mode 100644 index 0000000000000000000000000000000000000000..8028e6b1bbbb52370bb7a2c765a3697c4fc08af6 --- /dev/null +++ b/ethcore/res/ethereum/mcip6_byz.json @@ -0,0 +1,161 @@ +{ + "name":"Musicoin Byzantium Test", + "dataDir":"mcip6test", + "engine":{ + "Ethash":{ + "params":{ + "minimumDifficulty":"0x020000", + "difficultyBoundDivisor":"0x0800", + "durationLimit":"0x0d", + "homesteadTransition":"0x17", + "eip100bTransition":"0x2a", + "eip150Transition":"0x2a", + "eip160Transition":"0x7fffffffffffff", + "eip161abcTransition":"0x7fffffffffffff", + "eip161dTransition":"0x7fffffffffffff", + "eip649Transition":"0x2a", + "blockReward":"0x1105a0185b50a80000", + "mcip3Transition":"0x17", + "mcip3MinerReward":"0xd8d726b7177a80000", + "mcip3UbiReward":"0x2b5e3af16b1880000", + "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", + "mcip3DevReward":"0xc249fdd327780000", + "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" + } + } + }, + "params":{ + "gasLimitBoundDivisor":"0x0400", + "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", + "accountStartNonce":"0x00", + "maximumExtraDataSize":"0x20", + "minGasLimit":"0x1388", + "networkID":"0x76740c", + "forkBlock":"0x2b", + "forkCanonHash":"0x23c3171e864a5d513a3ef85e4cf86dac4cc36b89e5b8e63bf0ebcca68b9e43c9", + "eip86Transition":"0x7fffffffffffff", + "eip98Transition":"0x7fffffffffffff", + "eip140Transition":"0x2a", + "eip155Transition":"0x2a", + "eip211Transition":"0x2a", + "eip214Transition":"0x2a", + "eip658Transition":"0x2a", + "maxCodeSize":"0x6000", + "maxCodeSizeTransition": "0x7fffffffffffff" + }, + "genesis":{ + "seal":{ + "ethereum":{ + "nonce":"0x000000000000002a", + "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty":"0x3d0900", + "author":"0x0000000000000000000000000000000000000000", + "timestamp":"0x00", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData":"", + "gasLimit":"0x7a1200" + }, + "nodes":[ + "enode://5ddc110733f6d34101973cdef3f9b43484159acf6f816d3b1ee92bc3c98ea453e857bb1207edf0ec0242008ab3a0f9f05eeaee99d47bd414c08a5bdf4847de13@176.9.3.148:30303", + "enode://38f074f4db8e64dfbaf87984bf290eef67772a901a7113d1b62f36216be152b8450c393d6fc562a5e38f04f99bc8f439a99010a230b1d92dc1df43bf0bd00615@176.9.3.148:30403" + ], + "accounts":{ + "0000000000000000000000000000000000000001":{ + "balance":"1", + "builtin":{ + "name":"ecrecover", + "pricing":{ + "linear":{ + "base":3000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000002":{ + "balance":"1", + "builtin":{ + "name":"sha256", + "pricing":{ + "linear":{ + "base":60, + "word":12 + } + } + } + }, + "0000000000000000000000000000000000000003":{ + "balance":"1", + "builtin":{ + "name":"ripemd160", + "pricing":{ + "linear":{ + "base":600, + "word":120 + } + } + } + }, + "0000000000000000000000000000000000000004":{ + "balance":"1", + "builtin":{ + "name":"identity", + "pricing":{ + "linear":{ + "base":15, + "word":3 + } + } + } + }, + "0000000000000000000000000000000000000005":{ + "builtin":{ + "name":"modexp", + "activate_at":"0x2a", + "pricing":{ + "modexp":{ + "divisor":20 + } + } + } + }, + "0000000000000000000000000000000000000006":{ + "builtin":{ + "name":"alt_bn128_add", + "activate_at":"0x2a", + "pricing":{ + "linear":{ + "base":500, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000007":{ + "builtin":{ + "name":"alt_bn128_mul", + "activate_at":"0x2a", + "pricing":{ + "linear":{ + "base":40000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000008":{ + "builtin":{ + "name":"alt_bn128_pairing", + "activate_at":"0x2a", + "pricing":{ + "alt_bn128_pairing":{ + "base":100000, + "pair":80000 + } + } + } + } + } +} diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index f316fdf5f950f85f054043ec37dc7307942cc061..04c5a1244418101943ed94a07cccf898d410334d 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -7,20 +7,21 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": 494000, "eip150Transition": 1783000, "eip160Transition": 1915000, "ecip1010PauseTransition": 1915000, "ecip1010ContinueTransition": 3415000, - + "ecip1017EraRounds": 2000000, "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", + "bombDefuseTransition": 2300000 } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d", "accountStartNonce": "0x0100000", "maximumExtraDataSize": "0x20", @@ -30,7 +31,6 @@ "forkBlock": "0x1b34d8", "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145", "eip155Transition": 1915000, - "eip98Transition": "0x7fffffffffffff", "eip86Transition": "0x7fffffffffffff" }, @@ -49,11 +49,13 @@ "gasLimit": "0x2fefd8" }, "nodes": [ - "enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303", - "enode://ceb5c0f85eb994dbe9693bf46d99b03f6b838d17cc74e68d5eb003171ff39e5f120b17f965b267c319303f94d80b9d994b77062fb1486d76ce95d9f3d8fe1cb4@46.101.122.141:30303", "enode://fb28713820e718066a2f5df6250ae9d07cff22f672dbf26be6c75d088f821a9ad230138ba492c533a80407d054b1436ef18e951bb65e6901553516c8dffe8ff0@104.155.176.151:30304", "enode://afdc6076b9bf3e7d3d01442d6841071e84c76c73a7016cb4f35c0437df219db38565766234448f1592a07ba5295a867f0ce87b359bf50311ed0b830a2361392d@104.154.136.117:30403", - "enode://21101a9597b79e933e17bc94ef3506fe99a137808907aa8fefa67eea4b789792ad11fb391f38b00087f8800a2d3dff011572b62a31232133dd1591ac2d1502c8@104.198.71.200:30403" + "enode://21101a9597b79e933e17bc94ef3506fe99a137808907aa8fefa67eea4b789792ad11fb391f38b00087f8800a2d3dff011572b62a31232133dd1591ac2d1502c8@104.198.71.200:30403", + "enode://fd008499e9c4662f384b3cff23438879d31ced24e2d19504c6389bc6da6c882f9c2f8dbed972f7058d7650337f54e4ba17bb49c7d11882dd1731d26a6e62e3cb@35.187.57.94:30304", + "enode://30a1fd71f28aa6f66fe662af9ecc75f0a6980f06b71598f2b19d3dda04223fc0e53b47e40c9171d5014e9f5b59d9954de125782da592f5d95ea39066e2591d5d@104.237.131.102:30304", + "enode://7909d51011d8a153351169f21d3a7bbedb3be1e17d38c1f2fad06504dd5aa07a00f00845835d535fe702bf379c4d7209a51f4d1b723e0ca8b8732bd21fba3b30@139.162.133.42:30303", + "enode://a088dfb2f5305be9232e8071c5535f13718a4017e247a0b35074b807d43d99e022880c27302cdb5b1e98ad34c083dbbb483f2b17bdc66149bad037154d6ace96@139.162.127.72:30303" ], "accounts": { "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, diff --git a/ethcore/res/ethereum/musicoin.json b/ethcore/res/ethereum/musicoin.json new file mode 100644 index 0000000000000000000000000000000000000000..efe81c58821e9c050353dfd1ff1347f71dda3503 --- /dev/null +++ b/ethcore/res/ethereum/musicoin.json @@ -0,0 +1,165 @@ +{ + "name":"Musicoin", + "dataDir":"musicoin", + "engine":{ + "Ethash":{ + "params":{ + "minimumDifficulty":"0x020000", + "difficultyBoundDivisor":"0x0800", + "durationLimit":"0x0d", + "homesteadTransition":"0x118c30", + "eip100bTransition":"0x21e88e", + "eip150Transition":"0x21e88e", + "eip160Transition":"0x7fffffffffffff", + "eip161abcTransition":"0x7fffffffffffff", + "eip161dTransition":"0x7fffffffffffff", + "eip649Transition":"0x21e88e", + "blockReward":"0x1105a0185b50a80000", + "mcip3Transition":"0x124f81", + "mcip3MinerReward":"0xd8d726b7177a80000", + "mcip3UbiReward":"0x2b5e3af16b1880000", + "mcip3UbiContract":"0x00efdd5883ec628983e9063c7d969fe268bbf310", + "mcip3DevReward":"0xc249fdd327780000", + "mcip3DevContract":"0x00756cf8159095948496617f5fb17ed95059f536" + } + } + }, + "params":{ + "gasLimitBoundDivisor":"0x0400", + "registrar":"0x5C271c4C9A67E7D73b7b3669d47504741354f21D", + "accountStartNonce":"0x00", + "maximumExtraDataSize":"0x20", + "minGasLimit":"0x1388", + "networkID":"0x76740f", + "forkBlock":"0x1d8015", + "forkCanonHash":"0x380602acf82b629a0be6b5adb2b4a801e960a07dc8261bf196d21befdbb8f2f9", + "eip86Transition":"0x7fffffffffffff", + "eip98Transition":"0x7fffffffffffff", + "eip140Transition":"0x21e88e", + "eip155Transition":"0x21e88e", + "eip211Transition":"0x21e88e", + "eip214Transition":"0x21e88e", + "eip658Transition":"0x21e88e", + "maxCodeSize":"0x6000", + "maxCodeSizeTransition": "0x7fffffffffffff" + }, + "genesis":{ + "seal":{ + "ethereum":{ + "nonce":"0x000000000000002a", + "mixHash":"0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty":"0x3d0900", + "author":"0x0000000000000000000000000000000000000000", + "timestamp":"0x00", + "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData":"", + "gasLimit":"0x7a1200" + }, + "nodes":[ + "enode://09fcd36d553044c8b499b9b9e13a228ffd99572c513f77073d41f009717c464cd4399c0e665d6aff1590324254ee4e698b2b2533b1998dd04d896b9d6aff7895@35.185.67.35:30303", + "enode://89e51a34770a0badf8ea18c4c4d2c361cde707abd60031d99b1ab3010363e1898230a516ddb37d974af8d8db1b322779d7fe0caae0617bed4924d1b4968cf92b@35.231.48.142:30303", + "enode://b58c0c71f08864c0cf7fa9dea2c4cbefae5ae7a36cc30d286603b24982d25f3ccc056b589119324c51768fc2054b8c529ecf682e06e1e9980170b93ff194ed7a@132.148.132.9:30303", + "enode://d302f52c8789ad87ee528f1431a67f1aa646c9bec17babb4665dfb3d61de5b9119a70aa77b2147a5f28854092ba09769323c1c552a6ac6f6a34cbcf767e2d2fe@158.69.248.48:30303", + "enode://c72564bce8331ae298fb8ece113a456e3927d7e5989c2be3e445678b3600579f722410ef9bbfe339335d676af77343cb21b5b1703b7bebc32be85fce937a2220@191.252.185.71:30303", + "enode://e3ae4d25ee64791ff98bf17c37acf90933359f2505c00f65c84f6863231a32a94153cadb0a462e428f18f35ded6bd91cd91033d26576a28558c22678be9cfaee@5.63.158.137:35555" + ], + "accounts":{ + "0000000000000000000000000000000000000001":{ + "balance":"1", + "builtin":{ + "name":"ecrecover", + "pricing":{ + "linear":{ + "base":3000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000002":{ + "balance":"1", + "builtin":{ + "name":"sha256", + "pricing":{ + "linear":{ + "base":60, + "word":12 + } + } + } + }, + "0000000000000000000000000000000000000003":{ + "balance":"1", + "builtin":{ + "name":"ripemd160", + "pricing":{ + "linear":{ + "base":600, + "word":120 + } + } + } + }, + "0000000000000000000000000000000000000004":{ + "balance":"1", + "builtin":{ + "name":"identity", + "pricing":{ + "linear":{ + "base":15, + "word":3 + } + } + } + }, + "0000000000000000000000000000000000000005":{ + "builtin":{ + "name":"modexp", + "activate_at":"0x21e88e", + "pricing":{ + "modexp":{ + "divisor":20 + } + } + } + }, + "0000000000000000000000000000000000000006":{ + "builtin":{ + "name":"alt_bn128_add", + "activate_at":"0x21e88e", + "pricing":{ + "linear":{ + "base":500, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000007":{ + "builtin":{ + "name":"alt_bn128_mul", + "activate_at":"0x21e88e", + "pricing":{ + "linear":{ + "base":40000, + "word":0 + } + } + } + }, + "0000000000000000000000000000000000000008":{ + "builtin":{ + "name":"alt_bn128_pairing", + "activate_at":"0x21e88e", + "pricing":{ + "alt_bn128_pairing":{ + "base":100000, + "pair":80000 + } + } + } + } + } +} diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index c73dcb815c53b3d82c6be3072e8fb69393e55898..6854f2b78a94ac33c6dc207dd3dac87f72253afb 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -6,6 +6,7 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x08", + "blockReward": "0x14D1120D7B160000", "homesteadTransition": "0x7fffffffffffffff", "eip150Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", @@ -16,7 +17,6 @@ }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x14D1120D7B160000", "registrar": "5e70c0bbcd5636e0f9f9316e9f8633feb64d4050", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x0400", diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 1706c433b38904fe44cbaf7f96626d83d01cae51..6aad92505d973f2e6c41cf68e41626caf68a60f2 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -7,18 +7,20 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", "homesteadTransition": 0, "eip150Transition": 0, "eip160Transition": 10, "eip161abcTransition": 10, "eip161dTransition": 10, - "maxCodeSize": 24576 + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": 1700000, + "eip649Transition": 1700000 } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar": "0x81a4b044831c4f12ba601adb9274516939e9b8a2", "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", @@ -26,10 +28,15 @@ "networkID" : "0x3", "forkBlock": 641350, "forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb", + "maxCodeSize": 24576, + "maxCodeSizeTransition": 10, "eip155Transition": 10, - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip86Transition": "0x7fffffffffffff", + "eip140Transition": 1700000, + "eip211Transition": 1700000, + "eip214Transition": 1700000, + "eip658Transition": 1700000 }, "genesis": { "seal": { @@ -46,19 +53,21 @@ "gasLimit": "0x1000000" }, "nodes": [ - "enode://20c9ad97c081d63397d7b685a412227a40e23c8bdc6688c6f37e97cfbc22d2b4d1db1510d8f61e6a8866ad7f0e17c02b14182d37ea7c3c8b9c2683aeb6b733a1@52.169.14.227:30303", - "enode://6ce05930c72abc632c58e2e4324f7c7ea478cec0ed4fa2528982cf34483094e9cbc9216e7aa349691242576d552a2a56aaeae426c5303ded677ce455ba1acd9d@13.84.180.240:30303" + "enode://6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f@52.232.243.152:30303", + "enode://94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09@192.81.208.223:30303", + "enode://30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606@52.176.7.10:30303", + "enode://865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c@52.176.100.77:30303" ], "accounts": { + "0000000000000000000000000000000000000000": { "balance": "1" }, "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "0", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "0", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "0", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "0", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000000": { "balance": "1" }, - "0000000000000000000000000000000000000005": { "balance": "1" }, - "0000000000000000000000000000000000000006": { "balance": "1" }, - "0000000000000000000000000000000000000007": { "balance": "1" }, - "0000000000000000000000000000000000000008": { "balance": "1" }, + "0000000000000000000000000000000000000005": { "balance": "1", "nonce": "0", "builtin": { "name": "modexp", "activate_at": 1700000, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "nonce": "0", "builtin": { "name": "alt_bn128_add", "activate_at": 1700000, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "nonce": "0", "builtin": { "name": "alt_bn128_mul", "activate_at": 1700000, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "nonce": "0", "builtin": { "name": "alt_bn128_pairing", "activate_at": 1700000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "0000000000000000000000000000000000000009": { "balance": "1" }, "000000000000000000000000000000000000000a": { "balance": "0" }, "000000000000000000000000000000000000000b": { "balance": "0" }, diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index ef191fdc61cf76cdb9cdc147465fb447304b0ed2..b6011c3fb567d7178915574de0a8d4b5331fe725 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit ef191fdc61cf76cdb9cdc147465fb447304b0ed2 +Subproject commit b6011c3fb567d7178915574de0a8d4b5331fe725 diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index 409210a7694d22831adcb780f83fa045827f1305..7c18fce4e544d08576df823f0153e45169d60ccd 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -1,150 +1,38 @@ { - "name": "EIP150.1b hard-fork consensus test", + "name": "Transition consensus test spec template", "engine": { "Ethash": { "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "homesteadTransition": "0x5", - "daoHardforkTransition": "0x8", - "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", - "daoHardforkAccounts": [ - "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728", - "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425", - "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f", - "0xecd135fa4f61a655311e86238c92adcd779555d2", - "0x1975bd06d486162d5dc297798dfc41edd5d160a7", - "0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6", - "0x319f70bab6845585f412ec7724b744fec6095c85", - "0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936", - "0x5c8536898fbb74fc7445814902fd08422eac56d0", - "0x6966ab0d485353095148a2155858910e0965b6f9", - "0x779543a0491a837ca36ce8c635d6154e3c4911a6", - "0x2a5ed960395e2a49b1c758cef4aa15213cfd874c", - "0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5", - "0x9c50426be05db97f5d64fc54bf89eff947f0a321", - "0x200450f06520bdd6c527622a273333384d870efb", - "0xbe8539bfe837b67d1282b2b1d61c3f723966f049", - "0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb", - "0xf1385fb24aad0cd7432824085e42aff90886fef5", - "0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091", - "0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd", - "0x51e0ddd9998364a2eb38588679f0d2c42653e4a6", - "0x627a0a960c079c21c34f7612d5d230e01b4ad4c7", - "0xf0b1aa0eb660754448a7937c022e30aa692fe0c5", - "0x24c4d950dfd4dd1902bbed3508144a54542bba94", - "0x9f27daea7aca0aa0446220b98d028715e3bc803d", - "0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90", - "0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b", - "0x63ed5a272de2f6d968408b4acb9024f4cc208ebf", - "0x6f6704e5a10332af6672e50b3d9754dc460dfa4d", - "0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6", - "0x492ea3bb0f3315521c31f273e565b868fc090f17", - "0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00", - "0x9ea779f907f0b315b364b0cfc39a0fde5b02a416", - "0xceaeb481747ca6c540a000c1f3641f8cef161fa7", - "0xcc34673c6c40e791051898567a1222daf90be287", - "0x579a80d909f346fbfb1189493f521d7f48d52238", - "0xe308bd1ac5fda103967359b2712dd89deffb7973", - "0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c", - "0xac1ecab32727358dba8962a0f3b261731aad9723", - "0x4fd6ace747f06ece9c49699c7cabc62d02211f75", - "0x440c59b325d2997a134c2c7c60a8c61611212bad", - "0x4486a3d68fac6967006d7a517b889fd3f98c102b", - "0x9c15b54878ba618f494b38f0ae7443db6af648ba", - "0x27b137a85656544b1ccb5a0f2e561a5703c6a68f", - "0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241", - "0x23b75c2f6791eef49c69684db4c6c1f93bf49a50", - "0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b", - "0xb9637156d330c0d605a791f1c31ba5890582fe1c", - "0x6131c42fa982e56929107413a9d526fd99405560", - "0x1591fc0f688c81fbeb17f5426a162a7024d430c2", - "0x542a9515200d14b68e934e9830d91645a980dd7a", - "0xc4bbd073882dd2add2424cf47d35213405b01324", - "0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4", - "0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb", - "0x3ba4d81db016dc2890c81f3acec2454bff5aada5", - "0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab", - "0xe4ae1efdfc53b73893af49113d8694a057b9c0d1", - "0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5", - "0x0737a6b837f97f46ebade41b9bc3e1c509c85c53", - "0x97f43a37f595ab5dd318fb46e7a155eae057317a", - "0x52c5317c848ba20c7504cb2c8052abd1fde29d03", - "0x4863226780fe7c0356454236d3b1c8792785748d", - "0x5d2b2e6fcbe3b11d26b525e085ff818dae332479", - "0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c", - "0x057b56736d32b86616a10f619859c6cd6f59092a", - "0x9aa008f65de0b923a2a4f02012ad034a5e2e2192", - "0x304a554a310c7e546dfe434669c62820b7d83490", - "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79", - "0x4deb0033bb26bc534b197e61d19e0733e5679784", - "0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a", - "0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b", - "0x4fa802324e929786dbda3b8820dc7834e9134a2a", - "0x9da397b9e80755301a3b32173283a91c0ef6c87e", - "0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6", - "0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9", - "0x5dc28b15dffed94048d73806ce4b7a4612a1d48f", - "0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76", - "0x12e626b0eebfe86a56d633b9864e389b45dcb260", - "0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7", - "0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5", - "0xd164b088bd9108b60d0ca3751da4bceb207b0782", - "0x6231b6d0d5e77fe001c2a460bd9584fee60d409b", - "0x1cba23d343a983e9b5cfd19496b9a9701ada385f", - "0xa82f360a8d3455c5c41366975bde739c37bfeb8a", - "0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339", - "0x005f5cee7a43331d5a3d3eec71305925a62f34b6", - "0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d", - "0xd131637d5275fd1a68a3200f4ad25c71a2a9522e", - "0xbc07118b9ac290e4622f5e77a0853539789effbe", - "0x47e7aa56d6bdf3f36be34619660de61275420af8", - "0xacd87e28b0c9d1254e868b81cba4cc20d9a32225", - "0xadf80daec7ba8dcf15392f1ac611fff65d94f880", - "0x5524c55fb03cf21f549444ccbecb664d0acad706", - "0x40b803a9abce16f50f36a77ba41180eb90023925", - "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f", - "0x17802f43a0137c506ba92291391a8a8f207f487d", - "0x253488078a4edf4d6f42f113d1e62836a942cf1a", - "0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915", - "0xb136707642a4ea12fb4bae820f03d2562ebff487", - "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940", - "0xf14c14075d6c4ed84b86798af0956deef67365b5", - "0xca544e5c4687d109611d0f8f928b53a25af72448", - "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c", - "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7", - "0x6d87578288b6cb5549d5076a207456a1f6a63dc0", - "0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e", - "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6", - "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2", - "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a", - "0xd343b217de44030afaa275f54d31a9317c7f441e", - "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106", - "0xda2fef9e4a3230988ff17df2165440f37e8b1708", - "0xf4c64518ea10f995918a454158c6b61407ea345c", - "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97", - "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "0x807640a13483f8ac783c557fcdf27be11ea4ac7a" - ], - "eip150Transition": "0xa", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "blockReward": "0x4563918244F40000", + "homesteadTransition": "0", + "eip150Transition": "0", + "eip160Transition": "0", + "eip161abcTransition": "0", + "eip161dTransition": "0", + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": "5", + "eip649Transition": "5" } } }, "params": { "gasLimitBoundDivisor": "0x0400", - "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", - "eip155Transition": "0x7fffffffffffffff" + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0", + "eip98Transition": "5", + "eip140Transition": "5", + "eip211Transition": "5", + "eip214Transition": "5", + "eip155Transition": "5", + "eip658Transition": "5" }, "genesis": { "seal": { @@ -161,9 +49,13 @@ "gasLimit": "0x1388" }, "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 } } } } + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "5", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "5", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "5", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "5", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/res/instant_seal.json b/ethcore/res/instant_seal.json index f59feb0bda464c06e3a3612bb147ec09ceeee7ae..e01c927ffdc39e9dd8d88ef475aac1496df8e4ba 100644 --- a/ethcore/res/instant_seal.json +++ b/ethcore/res/instant_seal.json @@ -8,7 +8,12 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x11" + "networkID" : "0x11", + "registrar" : "0x0000000000000000000000000000000000001337", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -26,7 +31,11 @@ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "balance": "1", "constructor": "0x606060405233600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550670de0b6b3a764000060035534610000575b612904806100666000396000f3006060604052361561013c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306b2ff471461014157806313af40351461018c57806319362a28146101bf5780633f3935d114610248578063432ced04146102b75780634f39ca59146102eb5780636795dbcd1461032457806369fe0e2d146103c857806379ce9fac146103fd5780638da5cb5b1461045557806390b97fc1146104a457806392698814146105245780639890220b1461055d578063ac4e73f914610584578063ac72c12014610612578063c3a358251461064b578063ddca3f43146106c3578063deb931a2146106e6578063df57b74214610747578063e30bd740146107a8578063eadf976014610862578063ef5454d6146108e7578063f25eb5c114610975578063f6d339e414610984575b610000565b3461000057610172600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a1f565b604051808215151515815260200191505060405180910390f35b34610000576101bd600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a81565b005b346100005761022e60048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803560001916906020019091905050610ba2565b604051808215151515815260200191505060405180910390f35b346100005761029d600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610dc9565b604051808215151515815260200191505060405180910390f35b6102d1600480803560001916906020019091905050611035565b604051808215151515815260200191505060405180910390f35b346100005761030a60048080356000191690602001909190505061115f565b604051808215151515815260200191505060405180910390f35b346100005761038660048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611378565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576103e3600480803590602001909190505061140d565b604051808215151515815260200191505060405180910390f35b346100005761043b60048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114b4565b604051808215151515815260200191505060405180910390f35b34610000576104626115fb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b346100005761050660048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611621565b60405180826000191660001916815260200191505060405180910390f35b34610000576105436004808035600019169060200190919050506116b2565b604051808215151515815260200191505060405180910390f35b346100005761056a611715565b604051808215151515815260200191505060405180910390f35b34610000576105f8600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611824565b604051808215151515815260200191505060405180910390f35b3461000057610631600480803560001916906020019091905050611d8b565b604051808215151515815260200191505060405180910390f35b34610000576106ad60048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611dee565b6040518082815260200191505060405180910390f35b34610000576106d0611e83565b6040518082815260200191505060405180910390f35b3461000057610705600480803560001916906020019091905050611e89565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3461000057610766600480803560001916906020019091905050611ed2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576107d9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611f1b565b6040518080602001828103825283818151815260200191508051906020019080838360008314610828575b80518252602083111561082857602082019150602081019050602083039250610804565b505050905090810190601f1680156108545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576108cd60048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803590602001909190505061200c565b604051808215151515815260200191505060405180910390f35b346100005761095b600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612236565b604051808215151515815260200191505060405180910390f35b3461000057610982612425565b005b3461000057610a0560048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612698565b604051808215151515815260200191505060405180910390f35b60006000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290049050141590505b919050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610add57610b9f565b8073ffffffffffffffffffffffffffffffffffffffff16600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236460405180905060405180910390a380600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b50565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610c1d57610dc1565b82600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b60208310610c705780518252602082019150602081019050602083039250610c4d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b60208310610cdf5780518252602082019150602081019050602083039250610cbc565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea866040518080602001828103825283818151815260200191508051906020019080838360008314610d82575b805182526020831115610d8257602082019150602081019050602083039250610d5e565b505050905090810190601f168015610dae5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000813373ffffffffffffffffffffffffffffffffffffffff1660016000836040518082805190602001908083835b60208310610e1b5780518252602082019150602081019050602083039250610df8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610ea45761102f565b82600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f2d57805160ff1916838001178555610f5b565b82800160010185558215610f5b579182015b82811115610f5a578251825591602001919060010190610f3f565b5b509050610f8091905b80821115610f7c576000816000905550600101610f64565b5090565b50503373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b60208310610fcd5780518252602082019150602081019050602083039250610faa565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192060405180905060405180910390a3600191505b5b50919050565b600081600060016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561109b57611159565b6003543410156110aa57611158565b3360016000856000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff1683600019167f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a22160405180905060405180910390a3600191505b5b5b50919050565b6000813373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156111da57611372565b6002600060016000866000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f1061127c57506112b3565b601f0160209004906000526020600020908101906112b291905b808211156112ae576000816000905550600101611296565b5090565b5b5060016000846000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550503373ffffffffffffffffffffffffffffffffffffffff1683600019167fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af360405180905060405180910390a3600191505b5b50919050565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b602083106113cc57805182526020820191506020810190506020830392506113a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001900490505b92915050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561146b576114af565b816003819055507f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c3826040518082815260200191505060405180910390a1600190505b5b919050565b6000823373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561152f576115f4565b8260016000866000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1685600019167f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779460405180905060405180910390a4600191505b5b5092915050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b602083106116755780518252602082019150602081019050602083039250611652565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205490505b92915050565b6000600060016000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561177357611821565b7fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca073073ffffffffffffffffffffffffffffffffffffffff16316040518082815260200191505060405180910390a13373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050151561181b57610000565b600190505b5b90565b60006000836040518082805190602001908083835b6020831061185c5780518252602082019150602081019050602083039250611839565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390203373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561190157611d83565b846040518082805190602001908083835b602083106119355780518252602082019150602081019050602083039250611912565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150600060016000846000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015611ab4575081600019166002600060016000866000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518082805460018160011615610100020316600290048015611aa15780601f10611a7f576101008083540402835291820191611aa1565b820191906000526020600020905b815481529060010190602001808311611a8d575b5050915050604051809103902060001916145b15611c79576002600060016000856000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f10611b5b5750611b92565b601f016020900490600052602060002090810190611b9191905b80821115611b8d576000816000905550600101611b75565b5090565b5b5060016000836000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b60208310611c1c5780518252602082019150602081019050602083039250611bf9565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd60405180905060405180910390a35b8360016000846000191660001916815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b60208310611d215780518252602082019150602081019050602083039250611cfe565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df60405180905060405180910390a3600192505b5b505092915050565b6000600060016000846000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b60208310611e425780518252602082019150602081019050602083039250611e1f565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001900490505b92915050565b60035481565b600060016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b600060016000836000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b6020604051908101604052806000815250600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611fff5780601f10611fd457610100808354040283529160200191611fff565b820191906000526020600020905b815481529060010190602001808311611fe257829003601f168201915b505050505090505b919050565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156120875761222e565b82600102600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b602083106120dd57805182526020820191506020810190506020830392506120ba565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b6020831061214c5780518252602082019150602081019050602083039250612129565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea8660405180806020018281038252838181518152602001915080519060200190808383600083146121ef575b8051825260208311156121ef576020820191506020810190506020830392506121cb565b505050905090810190601f16801561221b5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156122945761241f565b82600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061231d57805160ff191683800117855561234b565b8280016001018555821561234b579182015b8281111561234a57825182559160200191906001019061232f565b5b50905061237091905b8082111561236c576000816000905550600101612354565b5090565b50508173ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106123bd578051825260208201915060208101905060208303925061239a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192060405180905060405180910390a3600190505b5b92915050565b3373ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156124d65780601f106124b45761010080835404028352918201916124d6565b820191906000526020600020905b8154815290600101906020018083116124c2575b505091505060405180910390207f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd60405180905060405180910390a360016000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156125b05780601f1061258e5761010080835404028352918201916125b0565b820191906000526020600020905b81548152906001019060200180831161259c575b505091505060405180910390206000191660001916815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f1061265d5750612694565b601f01602090049060005260206000209081019061269391905b8082111561268f576000816000905550600101612677565b5090565b5b505b565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515612713576128d0565b8273ffffffffffffffffffffffffffffffffffffffff16600102600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b6020831061277f578051825260208201915060208101905060208303925061275c565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b602083106127ee57805182526020820191506020810190506020830392506127cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea866040518080602001828103825283818151815260200191508051906020019080838360008314612891575b8051825260208311156128915760208201915060208101905060208303925061286d565b505050905090810190601f1680156128bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5093925050505600a165627a7a7230582066b2da4773a0f1d81efe071c66b51c46868a871661efd18c0f629353ff4c1f9b0029" }, - "0x00a329c0648769a73afac7f9381e08fb43dbea72": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, + "0000000000000000000000000000000000001337": { "balance": "1", "constructor": "0x606060405233600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550670de0b6b3a764000060035534610000575b612904806100666000396000f3006060604052361561013c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306b2ff471461014157806313af40351461018c57806319362a28146101bf5780633f3935d114610248578063432ced04146102b75780634f39ca59146102eb5780636795dbcd1461032457806369fe0e2d146103c857806379ce9fac146103fd5780638da5cb5b1461045557806390b97fc1146104a457806392698814146105245780639890220b1461055d578063ac4e73f914610584578063ac72c12014610612578063c3a358251461064b578063ddca3f43146106c3578063deb931a2146106e6578063df57b74214610747578063e30bd740146107a8578063eadf976014610862578063ef5454d6146108e7578063f25eb5c114610975578063f6d339e414610984575b610000565b3461000057610172600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a1f565b604051808215151515815260200191505060405180910390f35b34610000576101bd600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610a81565b005b346100005761022e60048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803560001916906020019091905050610ba2565b604051808215151515815260200191505060405180910390f35b346100005761029d600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610dc9565b604051808215151515815260200191505060405180910390f35b6102d1600480803560001916906020019091905050611035565b604051808215151515815260200191505060405180910390f35b346100005761030a60048080356000191690602001909190505061115f565b604051808215151515815260200191505060405180910390f35b346100005761038660048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611378565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576103e3600480803590602001909190505061140d565b604051808215151515815260200191505060405180910390f35b346100005761043b60048080356000191690602001909190803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506114b4565b604051808215151515815260200191505060405180910390f35b34610000576104626115fb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b346100005761050660048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611621565b60405180826000191660001916815260200191505060405180910390f35b34610000576105436004808035600019169060200190919050506116b2565b604051808215151515815260200191505060405180910390f35b346100005761056a611715565b604051808215151515815260200191505060405180910390f35b34610000576105f8600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611824565b604051808215151515815260200191505060405180910390f35b3461000057610631600480803560001916906020019091905050611d8b565b604051808215151515815260200191505060405180910390f35b34610000576106ad60048080356000191690602001909190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050611dee565b6040518082815260200191505060405180910390f35b34610000576106d0611e83565b6040518082815260200191505060405180910390f35b3461000057610705600480803560001916906020019091905050611e89565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3461000057610766600480803560001916906020019091905050611ed2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34610000576107d9600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050611f1b565b6040518080602001828103825283818151815260200191508051906020019080838360008314610828575b80518252602083111561082857602082019150602081019050602083039250610804565b505050905090810190601f1680156108545780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34610000576108cd60048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803590602001909190505061200c565b604051808215151515815260200191505060405180910390f35b346100005761095b600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612236565b604051808215151515815260200191505060405180910390f35b3461000057610982612425565b005b3461000057610a0560048080356000191690602001909190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050612698565b604051808215151515815260200191505060405180910390f35b60006000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290049050141590505b919050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141515610add57610b9f565b8073ffffffffffffffffffffffffffffffffffffffff16600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236460405180905060405180910390a380600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b50565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610c1d57610dc1565b82600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b60208310610c705780518252602082019150602081019050602083039250610c4d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b60208310610cdf5780518252602082019150602081019050602083039250610cbc565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea866040518080602001828103825283818151815260200191508051906020019080838360008314610d82575b805182526020831115610d8257602082019150602081019050602083039250610d5e565b505050905090810190601f168015610dae5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000813373ffffffffffffffffffffffffffffffffffffffff1660016000836040518082805190602001908083835b60208310610e1b5780518252602082019150602081019050602083039250610df8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390206000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610ea45761102f565b82600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610f2d57805160ff1916838001178555610f5b565b82800160010185558215610f5b579182015b82811115610f5a578251825591602001919060010190610f3f565b5b509050610f8091905b80821115610f7c576000816000905550600101610f64565b5090565b50503373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b60208310610fcd5780518252602082019150602081019050602083039250610faa565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192060405180905060405180910390a3600191505b5b50919050565b600081600060016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561109b57611159565b6003543410156110aa57611158565b3360016000856000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff1683600019167f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a22160405180905060405180910390a3600191505b5b5b50919050565b6000813373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156111da57611372565b6002600060016000866000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f1061127c57506112b3565b601f0160209004906000526020600020908101906112b291905b808211156112ae576000816000905550600101611296565b5090565b5b5060016000846000191660001916815260200190815260200160002060006000820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550503373ffffffffffffffffffffffffffffffffffffffff1683600019167fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af360405180905060405180910390a3600191505b5b50919050565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b602083106113cc57805182526020820191506020810190506020830392506113a9565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001900490505b92915050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561146b576114af565b816003819055507f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c3826040518082815260200191505060405180910390a1600190505b5b919050565b6000823373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561152f576115f4565b8260016000866000191660001916815260200190815260200160002060000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1685600019167f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779460405180905060405180910390a4600191505b5b5092915050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b602083106116755780518252602082019150602081019050602083039250611652565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205490505b92915050565b6000600060016000846000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561177357611821565b7fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca073073ffffffffffffffffffffffffffffffffffffffff16316040518082815260200191505060405180910390a13373ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050151561181b57610000565b600190505b5b90565b60006000836040518082805190602001908083835b6020831061185c5780518252602082019150602081019050602083039250611839565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390203373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561190157611d83565b846040518082805190602001908083835b602083106119355780518252602082019150602081019050602083039250611912565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390209150600060016000846000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614158015611ab4575081600019166002600060016000866000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518082805460018160011615610100020316600290048015611aa15780601f10611a7f576101008083540402835291820191611aa1565b820191906000526020600020905b815481529060010190602001808311611a8d575b5050915050604051809103902060001916145b15611c79576002600060016000856000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f10611b5b5750611b92565b601f016020900490600052602060002090810190611b9191905b80821115611b8d576000816000905550600101611b75565b5090565b5b5060016000836000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b60208310611c1c5780518252602082019150602081019050602083039250611bf9565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd60405180905060405180910390a35b8360016000846000191660001916815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff16856040518082805190602001908083835b60208310611d215780518252602082019150602081019050602083039250611cfe565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df60405180905060405180910390a3600192505b5b505092915050565b6000600060016000846000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141590505b919050565b6000600160008460001916600019168152602001908152602001600020600201826040518082805190602001908083835b60208310611e425780518252602082019150602081019050602083039250611e1f565b6001836020036101000a0380198251168184511680821785525050505050509050019150509081526020016040518091039020546001900490505b92915050565b60035481565b600060016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b600060016000836000191660001916815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b919050565b6020604051908101604052806000815250600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611fff5780601f10611fd457610100808354040283529160200191611fff565b820191906000526020600020905b815481529060010190602001808311611fe257829003601f168201915b505050505090505b919050565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156120875761222e565b82600102600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b602083106120dd57805182526020820191506020810190506020830392506120ba565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b6020831061214c5780518252602082019150602081019050602083039250612129565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea8660405180806020018281038252838181518152602001915080519060200190808383600083146121ef575b8051825260208311156121ef576020820191506020810190506020830392506121cb565b505050905090810190601f16801561221b5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156122945761241f565b82600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061231d57805160ff191683800117855561234b565b8280016001018555821561234b579182015b8281111561234a57825182559160200191906001019061232f565b5b50905061237091905b8082111561236c576000816000905550600101612354565b5090565b50508173ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106123bd578051825260208201915060208101905060208303925061239a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192060405180905060405180910390a3600190505b5b92915050565b3373ffffffffffffffffffffffffffffffffffffffff16600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156124d65780601f106124b45761010080835404028352918201916124d6565b820191906000526020600020905b8154815290600101906020018083116124c2575b505091505060405180910390207f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd60405180905060405180910390a360016000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060405180828054600181600116156101000203166002900480156125b05780601f1061258e5761010080835404028352918201916125b0565b820191906000526020600020905b81548152906001019060200180831161259c575b505091505060405180910390206000191660001916815260200190815260200160002060010160006101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805460018160011615610100020316600290046000825580601f1061265d5750612694565b601f01602090049060005260206000209081019061269391905b8082111561268f576000816000905550600101612677565b5090565b5b505b565b6000833373ffffffffffffffffffffffffffffffffffffffff1660016000836000191660001916815260200190815260200160002060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515612713576128d0565b8273ffffffffffffffffffffffffffffffffffffffff16600102600160008760001916600019168152602001908152602001600020600201856040518082805190602001908083835b6020831061277f578051825260208201915060208101905060208303925061275c565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390208160001916905550836040518082805190602001908083835b602083106127ee57805182526020820191506020810190506020830392506127cb565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051809103902085600019167fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea866040518080602001828103825283818151815260200191508051906020019080838360008314612891575b8051825260208311156128915760208201915060208101905060208303925061286d565b505050905090810190601f1680156128bd5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5093925050505600a165627a7a7230582066b2da4773a0f1d81efe071c66b51c46868a871661efd18c0f629353ff4c1f9b0029" }, + "00a329c0648769a73afac7f9381e08fb43dbea72": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } } } diff --git a/ethcore/res/null.json b/ethcore/res/null.json index 97ce1afc5668edc478dfb80547d878a14b3ceb04..345bb02b2769a35bb6c226e3bef534ff18f1a07d 100644 --- a/ethcore/res/null.json +++ b/ethcore/res/null.json @@ -1,7 +1,9 @@ { - "name": "Morden", + "name": "Null", "engine": { - "null": null + "null": { + "params": {} + } }, "params": { "gasLimitBoundDivisor": "0x0400", @@ -9,7 +11,11 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "eip86Transition": "0x7fffffffffffff" + "eip86Transition": "0x7fffffffffffff", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -30,6 +36,10 @@ "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "0", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "0", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "0", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "0" } } } diff --git a/ethcore/res/null_morden.json b/ethcore/res/null_morden.json index b615cdc2953bff2ec94c6c457483badc074a6cc7..87dcee6fc9b1994870130ec56713e253384356ef 100644 --- a/ethcore/res/null_morden.json +++ b/ethcore/res/null_morden.json @@ -1,7 +1,9 @@ { "name": "Morden", "engine": { - "null": null + "null": { + "params": {} + } }, "params": { "gasLimitBoundDivisor": "0x0400", diff --git a/ethcore/res/null_morden_with_reward.json b/ethcore/res/null_morden_with_reward.json new file mode 100644 index 0000000000000000000000000000000000000000..03c09c8afa416afa4bfb509dcb016b4706ddd6df --- /dev/null +++ b/ethcore/res/null_morden_with_reward.json @@ -0,0 +1,38 @@ +{ + "name": "Morden", + "engine": { + "null": { + "params": { + "blockReward": "0x4563918244F40000" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x2" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x00006d6f7264656e", + "mixHash": "0x00000000000000000000000000000000000000647572616c65787365646c6578" + } + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x2fefd8" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } + } +} diff --git a/ethcore/res/tendermint.json b/ethcore/res/tendermint.json index e7fa69ea0bc02c129a404471a9f5a4a8bd016d6a..3c60097a4e4e80e3e0be9bd03d6f19cdd2b9c298 100644 --- a/ethcore/res/tendermint.json +++ b/ethcore/res/tendermint.json @@ -21,7 +21,11 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2323" + "networkID" : "0x2323", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -45,6 +49,10 @@ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "balance": "1", "builtin": { "name": "modexp", "activate_at": 0, "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "balance": "1", "builtin": { "name": "alt_bn128_add", "activate_at": 0, "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "balance": "1", "builtin": { "name": "alt_bn128_mul", "activate_at": 0, "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "balance": "1", "builtin": { "name": "alt_bn128_pairing", "activate_at": 0, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "9cce34f7ab185c7aba1b7c8140d620b4bda941d6": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } } } diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 519b0b967cffd7d1236ef21698b1e6e415a048e9..fb111c82deff8759f54a5038d07cecc77cb5a663 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 519b0b967cffd7d1236ef21698b1e6e415a048e9 +Subproject commit fb111c82deff8759f54a5038d07cecc77cb5a663 diff --git a/ethcore/service/Cargo.toml b/ethcore/service/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..634769d0b5441c7dc307013263e1a33ec56e68f9 --- /dev/null +++ b/ethcore/service/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "ethcore-service" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +ansi_term = "0.10" +ethcore = { path = ".." } +ethcore-io = { path = "../../util/io" } +kvdb = { path = "../../util/kvdb" } +kvdb-rocksdb = { path = "../../util/kvdb-rocksdb" } +log = "0.3" +stop-guard = { path = "../../util/stop-guard" } + +[dev-dependencies] +tempdir = "0.3" diff --git a/js/src/parity.js b/ethcore/service/src/lib.rs similarity index 67% rename from js/src/parity.js rename to ethcore/service/src/lib.rs index 9d414f90e7f1cf73e44be5005cee09ece84e44b7..907009ba324a253aa7182922a85f1d854c929389 100644 --- a/js/src/parity.js +++ b/ethcore/service/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// Copyright 2015-2018 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify @@ -14,18 +14,19 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import 'whatwg-fetch'; +extern crate ansi_term; +extern crate ethcore; +extern crate ethcore_io as io; +extern crate kvdb; +extern crate kvdb_rocksdb; +extern crate stop_guard; -import es6Promise from 'es6-promise'; -es6Promise.polyfill(); +#[macro_use] +extern crate log; -import Api from './api'; +#[cfg(test)] +extern crate tempdir; -import './dev.parity.html'; +mod service; -const api = new Api(new Api.Transport.Http('/rpc/')); - -window.parity = { - Api, - api -}; +pub use service::ClientService; diff --git a/ethcore/src/service.rs b/ethcore/service/src/service.rs similarity index 64% rename from ethcore/src/service.rs rename to ethcore/service/src/service.rs index 5e65a4de8ab6a65a4a09f1d426b55d902159a64e..f190d6e6ac39e7d6cd6239970ed6feb3d3103209 100644 --- a/ethcore/src/service.rs +++ b/ethcore/service/src/service.rs @@ -18,40 +18,20 @@ use std::sync::Arc; use std::path::Path; -use util::*; -use io::*; -use spec::Spec; -use error::*; -use client::{Client, ClientConfig, ChainNotify}; -use miner::Miner; - -use snapshot::ManifestData; -use snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams}; -use std::sync::atomic::AtomicBool; - -#[cfg(feature="ipc")] -use nanoipc; - -/// Message type for external and internal events -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum ClientIoMessage { - /// Best Block Hash in chain has been changed - NewChainHead, - /// A block is ready - BlockVerified, - /// New transaction RLPs are ready to be imported - NewTransactions(Vec, usize), - /// Begin snapshot restoration - BeginRestoration(ManifestData), - /// Feed a state chunk to the snapshot service - FeedStateChunk(H256, Bytes), - /// Feed a block chunk to the snapshot service - FeedBlockChunk(H256, Bytes), - /// Take a snapshot for the block with given number. - TakeSnapshot(u64), - /// New consensus message received. - NewMessage(Bytes) -} + +use ansi_term::Colour; +use io::{IoContext, TimerToken, IoHandler, IoService, IoError}; +use kvdb::KeyValueDB; +use kvdb_rocksdb::{Database, DatabaseConfig}; +use stop_guard::StopGuard; + +use ethcore::client::{self, Client, ClientConfig, ChainNotify, ClientIoMessage}; +use ethcore::db; +use ethcore::error::Error; +use ethcore::miner::Miner; +use ethcore::snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams}; +use ethcore::snapshot::{RestorationStatus}; +use ethcore::spec::Spec; /// Client service setup. Creates and registers client and network services with the IO subsystem. pub struct ClientService { @@ -59,7 +39,7 @@ pub struct ClientService { client: Arc, snapshot: Arc, database: Arc, - _stop_guard: ::devtools::StopGuard, + _stop_guard: StopGuard, } impl ClientService { @@ -69,7 +49,7 @@ impl ClientService { spec: &Spec, client_path: &Path, snapshot_path: &Path, - ipc_path: &Path, + _ipc_path: &Path, miner: Arc, ) -> Result { @@ -77,21 +57,16 @@ impl ClientService { info!("Configured for {} using {} engine", Colour::White.bold().paint(spec.name.clone()), Colour::Yellow.bold().paint(spec.engine.name())); - let mut db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - - // give all rocksdb cache to state column; everything else has its - // own caches. - if let Some(size) = config.db_cache_size { - db_config.set_cache(::db::COL_STATE, size); - } + let mut db_config = DatabaseConfig::with_columns(db::NUM_COLUMNS); + db_config.memory_budget = config.db_cache_size; db_config.compaction = config.db_compaction.compaction_profile(client_path); db_config.wal = config.db_wal; let db = Arc::new(Database::open( &db_config, &client_path.to_str().expect("DB path could not be converted to string.") - ).map_err(::client::Error::Database)?); + ).map_err(client::Error::Database)?); let pruning = config.pruning; @@ -114,10 +89,9 @@ impl ClientService { }); io_service.register_handler(client_io)?; - spec.engine.register_client(Arc::downgrade(&client)); + spec.engine.register_client(Arc::downgrade(&client) as _); - let stop_guard = ::devtools::StopGuard::new(); - run_ipc(ipc_path, client.clone(), snapshot.clone(), stop_guard.share()); + let stop_guard = StopGuard::new(); Ok(ClientService { io_service: Arc::new(io_service), @@ -177,13 +151,16 @@ impl IoHandler for ClientIoHandler { fn timeout(&self, _io: &IoContext, timer: TimerToken) { match timer { - CLIENT_TICK_TIMER => self.client.tick(), + CLIENT_TICK_TIMER => { + use ethcore::snapshot::SnapshotService; + let snapshot_restoration = if let RestorationStatus::Ongoing{..} = self.snapshot.status() { true } else { false }; + self.client.tick(snapshot_restoration) + }, SNAPSHOT_TICK_TIMER => self.snapshot.tick(), _ => warn!("IO service triggered unregistered timer '{}'", timer), } } - #[cfg_attr(feature="dev", allow(single_match))] fn message(&self, _io: &IoContext, net_message: &ClientIoMessage) { use std::thread; @@ -221,74 +198,35 @@ impl IoHandler for ClientIoHandler { } } -#[cfg(feature="ipc")] -fn run_ipc(base_path: &Path, client: Arc, snapshot_service: Arc, stop: Arc) { - let mut path = base_path.to_owned(); - path.push("parity-chain.ipc"); - let socket_addr = format!("ipc://{}", path.to_string_lossy()); - let s = stop.clone(); - ::std::thread::spawn(move || { - let mut worker = nanoipc::Worker::new(&(client as Arc)); - worker.add_reqrep(&socket_addr).expect("Ipc expected to initialize with no issues"); - - while !s.load(::std::sync::atomic::Ordering::Relaxed) { - worker.poll(); - } - }); - - let mut path = base_path.to_owned(); - path.push("parity-snapshot.ipc"); - let socket_addr = format!("ipc://{}", path.to_string_lossy()); - ::std::thread::spawn(move || { - let mut worker = nanoipc::Worker::new(&(snapshot_service as Arc<::snapshot::SnapshotService>)); - worker.add_reqrep(&socket_addr).expect("Ipc expected to initialize with no issues"); - - while !stop.load(::std::sync::atomic::Ordering::Relaxed) { - worker.poll(); - } - }); -} - -#[cfg(not(feature="ipc"))] -fn run_ipc(_base_path: &Path, _client: Arc, _snapshot_service: Arc, _stop: Arc) { -} - #[cfg(test)] mod tests { - use super::*; - use tests::helpers::*; - use devtools::*; - use client::ClientConfig; use std::sync::Arc; - use miner::Miner; + use std::{time, thread}; + + use tempdir::TempDir; + + use ethcore::client::ClientConfig; + use ethcore::miner::Miner; + use ethcore::spec::Spec; + use super::*; #[test] fn it_can_be_started() { - let temp_path = RandomTempPath::new(); - let path = temp_path.as_path().to_owned(); - let client_path = { - let mut path = path.to_owned(); - path.push("client"); - path - }; - - let snapshot_path = { - let mut path = path.to_owned(); - path.push("snapshot"); - path - }; + let tempdir = TempDir::new("").unwrap(); + let client_path = tempdir.path().join("client"); + let snapshot_path = tempdir.path().join("snapshot"); - let spec = get_test_spec(); + let spec = Spec::new_test(); let service = ClientService::start( ClientConfig::default(), &spec, &client_path, &snapshot_path, - &path, + tempdir.path(), Arc::new(Miner::with_spec(&spec)), ); assert!(service.is_ok()); drop(service.unwrap()); - ::std::thread::park_timeout(::std::time::Duration::from_millis(100)); + thread::park_timeout(time::Duration::from_millis(100)); } } diff --git a/ethcore/src/account_db.rs b/ethcore/src/account_db.rs index 5ce555aef0432998f66e7ad64c9d12a00360b3e4..4e715766d7ae66202e25feb0c0db98e46605f63a 100644 --- a/ethcore/src/account_db.rs +++ b/ethcore/src/account_db.rs @@ -16,9 +16,15 @@ //! DB backend wrapper for Account trie use std::collections::HashMap; -use util::*; +use hash::{KECCAK_NULL_RLP, keccak}; +use ethereum_types::H256; +use kvdb::DBValue; +use hashdb::HashDB; use rlp::NULL_RLP; +#[cfg(test)] +use ethereum_types::Address; + // combines a key with an address hash to ensure uniqueness. // leaves the first 96 bits untouched in order to support partial key lookup. #[inline] @@ -79,7 +85,7 @@ impl<'db> AccountDB<'db> { /// Create a new AccountDB from an address. #[cfg(test)] pub fn new(db: &'db HashDB, address: &Address) -> Self { - Self::from_hash(db, address.sha3()) + Self::from_hash(db, keccak(address)) } /// Create a new AcountDB from an address' hash. @@ -97,14 +103,14 @@ impl<'db> HashDB for AccountDB<'db>{ } fn get(&self, key: &H256) -> Option { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); } self.db.get(&combine_key(&self.address_hash, key)) } fn contains(&self, key: &H256) -> bool { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return true; } self.db.contains(&combine_key(&self.address_hash, key)) @@ -133,7 +139,7 @@ impl<'db> AccountDBMut<'db> { /// Create a new AccountDB from an address. #[cfg(test)] pub fn new(db: &'db mut HashDB, address: &Address) -> Self { - Self::from_hash(db, address.sha3()) + Self::from_hash(db, keccak(address)) } /// Create a new AcountDB from an address' hash. @@ -156,14 +162,14 @@ impl<'db> HashDB for AccountDBMut<'db>{ } fn get(&self, key: &H256) -> Option { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); } self.db.get(&combine_key(&self.address_hash, key)) } fn contains(&self, key: &H256) -> bool { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return true; } self.db.contains(&combine_key(&self.address_hash, key)) @@ -171,16 +177,16 @@ impl<'db> HashDB for AccountDBMut<'db>{ fn insert(&mut self, value: &[u8]) -> H256 { if value == &NULL_RLP { - return SHA3_NULL_RLP.clone(); + return KECCAK_NULL_RLP.clone(); } - let k = value.sha3(); + let k = keccak(value); let ak = combine_key(&self.address_hash, &k); self.db.emplace(ak, DBValue::from_slice(value)); k } fn emplace(&mut self, key: H256, value: DBValue) { - if key == SHA3_NULL_RLP { + if key == KECCAK_NULL_RLP { return; } let key = combine_key(&self.address_hash, &key); @@ -188,7 +194,7 @@ impl<'db> HashDB for AccountDBMut<'db>{ } fn remove(&mut self, key: &H256) { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return; } let key = combine_key(&self.address_hash, key); @@ -204,14 +210,14 @@ impl<'db> HashDB for Wrapping<'db> { } fn get(&self, key: &H256) -> Option { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); } self.0.get(key) } fn contains(&self, key: &H256) -> bool { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return true; } self.0.contains(key) @@ -238,14 +244,14 @@ impl<'db> HashDB for WrappingMut<'db>{ } fn get(&self, key: &H256) -> Option { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return Some(DBValue::from_slice(&NULL_RLP)); } self.0.get(key) } fn contains(&self, key: &H256) -> bool { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return true; } self.0.contains(key) @@ -253,20 +259,20 @@ impl<'db> HashDB for WrappingMut<'db>{ fn insert(&mut self, value: &[u8]) -> H256 { if value == &NULL_RLP { - return SHA3_NULL_RLP.clone(); + return KECCAK_NULL_RLP.clone(); } self.0.insert(value) } fn emplace(&mut self, key: H256, value: DBValue) { - if key == SHA3_NULL_RLP { + if key == KECCAK_NULL_RLP { return; } self.0.emplace(key, value) } fn remove(&mut self, key: &H256) { - if key == &SHA3_NULL_RLP { + if key == &KECCAK_NULL_RLP { return; } self.0.remove(key) diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index 752cec9649fb9d8311419c50a383be928ed816ca..74d24e7f50e95eb23c470bc7ac66e648412d851c 100755 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -23,15 +23,16 @@ use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy}; use std::fmt; use std::collections::{HashMap, HashSet}; use std::time::{Instant, Duration}; -use util::{RwLock}; +use parking_lot::RwLock; use ethstore::{ SimpleSecretStore, SecretStore, Error as SSError, EthStore, EthMultiStore, random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret, }; -use ethstore::dir::MemoryDirectory; +use ethstore::accounts_dir::MemoryDirectory; use ethstore::ethkey::{Address, Message, Public, Secret, Random, Generator}; use ethjson::misc::AccountMeta; -use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath}; +use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo}; +use super::transaction::{Action, Transaction}; pub use ethstore::ethkey::Signature; pub use ethstore::{Derivation, IndexDerivation, KeyFile}; @@ -177,6 +178,13 @@ impl AccountProvider { } } + if let Ok(accounts) = sstore.accounts() { + for account in accounts.into_iter().filter(|a| settings.blacklisted_accounts.contains(&a.address)) { + warn!("Local Account {} has a blacklisted (known to be weak) address and will be ignored", + account.address); + } + } + // Remove blacklisted accounts from address book. let mut address_book = AddressBook::new(&sstore.local_path()); for addr in &settings.blacklisted_accounts { @@ -256,9 +264,9 @@ impl AccountProvider { Ok(Address::from(account.address).into()) } - /// Import a new presale wallet. - pub fn import_wallet(&self, json: &[u8], password: &str) -> Result { - let account = self.sstore.import_wallet(SecretVaultRef::Root, json, password)?; + /// Import a new wallet. + pub fn import_wallet(&self, json: &[u8], password: &str, gen_id: bool) -> Result { + let account = self.sstore.import_wallet(SecretVaultRef::Root, json, password, gen_id)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; return Err(SSError::InvalidAccount.into()); @@ -268,7 +276,7 @@ impl AccountProvider { /// Checks whether an account with a given address is present. pub fn has_account(&self, address: Address) -> Result { - Ok(self.accounts()?.iter().any(|&a| a == address)) + Ok(self.sstore.account_ref(&address).is_ok() && !self.blacklisted_accounts.contains(&address)) } /// Returns addresses of all accounts. @@ -288,6 +296,24 @@ impl AccountProvider { Ok(accounts.into_iter().map(|a| a.address).collect()) } + /// Get a list of paths to locked hardware wallets + pub fn locked_hardware_accounts(&self) -> Result, SignError> { + match self.hardware_store.as_ref().map(|h| h.list_locked_wallets()) { + None => Err(SignError::NotFound), + Some(Err(e)) => Err(SignError::Hardware(e)), + Some(Ok(s)) => Ok(s), + } + } + + /// Provide a pin to a locked hardware wallet on USB path to unlock it + pub fn hardware_pin_matrix_ack(&self, path: &str, pin: &str) -> Result { + match self.hardware_store.as_ref().map(|h| h.pin_matrix_ack(path, pin)) { + None => Err(SignError::NotFound), + Some(Err(e)) => Err(SignError::Hardware(e)), + Some(Ok(s)) => Ok(s), + } + } + /// Sets addresses of accounts exposed for unknown dapps. /// `None` means that all accounts will be visible. /// If not `None` or empty it will also override default account. @@ -497,8 +523,8 @@ impl AccountProvider { } /// Returns each hardware account along with name and meta. - pub fn is_hardware_address(&self, address: Address) -> bool { - self.hardware_store.as_ref().and_then(|s| s.wallet_info(&address)).is_some() + pub fn is_hardware_address(&self, address: &Address) -> bool { + self.hardware_store.as_ref().and_then(|s| s.wallet_info(address)).is_some() } /// Returns each account along with name and meta. @@ -570,7 +596,7 @@ impl AccountProvider { } } - if self.unlock_keep_secret && unlock != Unlock::OneTime { + if self.unlock_keep_secret && unlock == Unlock::Perm { // verify password and get the secret let secret = self.sstore.raw_secret(&account, &password)?; self.unlocked_secrets.write().insert(account.clone(), secret); @@ -620,14 +646,22 @@ impl AccountProvider { } /// Checks if given account is unlocked - pub fn is_unlocked(&self, address: Address) -> bool { + pub fn is_unlocked(&self, address: &Address) -> bool { let unlocked = self.unlocked.read(); let unlocked_secrets = self.unlocked_secrets.read(); - self.sstore.account_ref(&address) + self.sstore.account_ref(address) .map(|r| unlocked.get(&r).is_some() || unlocked_secrets.get(&r).is_some()) .unwrap_or(false) } + /// Checks if given account is unlocked permanently + pub fn is_unlocked_permanently(&self, address: &Address) -> bool { + let unlocked = self.unlocked.read(); + self.sstore.account_ref(address) + .map(|r| unlocked.get(&r).map_or(false, |account| account.unlock == Unlock::Perm)) + .unwrap_or(false) + } + /// Signs the message. If password is not provided the account must be unlocked. pub fn sign(&self, address: Address, password: Option, message: Message) -> Result { let account = self.sstore.account_ref(&address)?; @@ -779,8 +813,20 @@ impl AccountProvider { } /// Sign transaction with hardware wallet. - pub fn sign_with_hardware(&self, address: Address, transaction: &[u8]) -> Result { - match self.hardware_store.as_ref().map(|s| s.sign_transaction(&address, transaction)) { + pub fn sign_with_hardware(&self, address: Address, transaction: &Transaction, chain_id: Option, rlp_encoded_transaction: &[u8]) -> Result { + let t_info = TransactionInfo { + nonce: transaction.nonce, + gas_price: transaction.gas_price, + gas_limit: transaction.gas, + to: match transaction.action { + Action::Create => None, + Action::Call(ref to) => Some(to.clone()), + }, + value: transaction.value, + data: transaction.data.to_vec(), + chain_id: chain_id, + }; + match self.hardware_store.as_ref().map(|s| s.sign_transaction(&address, &t_info, rlp_encoded_transaction)) { None | Some(Err(HardwareError::KeyNotFound)) => Err(SignError::NotFound), Some(Err(e)) => Err(From::from(e)), Some(Ok(s)) => Ok(s), @@ -794,7 +840,7 @@ mod tests { use std::time::Instant; use ethstore::ethkey::{Generator, Random, Address}; use ethstore::{StoreAccountRef, Derivation}; - use util::H256; + use ethereum_types::H256; #[test] fn unlock_account_temp() { diff --git a/ethcore/src/account_provider/stores.rs b/ethcore/src/account_provider/stores.rs index 72bc04da65c6516878ef9691602212404e285920..1563d21bc6716384fbd2fedb42d4276f651cc688 100644 --- a/ethcore/src/account_provider/stores.rs +++ b/ethcore/src/account_provider/stores.rs @@ -64,7 +64,7 @@ impl AddressBook { /// Sets new name for given address. pub fn set_name(&mut self, a: Address, name: String) { { - let mut x = self.cache.entry(a) + let x = self.cache.entry(a) .or_insert_with(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None}); x.name = name; } @@ -74,7 +74,7 @@ impl AddressBook { /// Sets new meta for given address. pub fn set_meta(&mut self, a: Address, meta: String) { { - let mut x = self.cache.entry(a) + let x = self.cache.entry(a) .or_insert_with(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None}); x.meta = meta; } @@ -253,7 +253,7 @@ impl DappsSettingsStore { /// Marks recent dapp as used pub fn mark_dapp_used(&mut self, dapp: DappId) { { - let mut entry = self.history.entry(dapp).or_insert_with(|| Default::default()); + let entry = self.history.entry(dapp).or_insert_with(|| Default::default()); entry.last_accessed = self.time.get(); } // Clear extraneous entries @@ -280,7 +280,7 @@ impl DappsSettingsStore { /// Sets accounts for specific dapp. pub fn set_accounts(&mut self, id: DappId, accounts: Option>) { { - let mut settings = self.settings.entry(id).or_insert_with(DappsSettings::default); + let settings = self.settings.entry(id).or_insert_with(DappsSettings::default); settings.accounts = accounts; } self.settings.save(JsonSettings::write); @@ -289,7 +289,7 @@ impl DappsSettingsStore { /// Sets a default account for specific dapp. pub fn set_default(&mut self, id: DappId, default: Address) { { - let mut settings = self.settings.entry(id).or_insert_with(DappsSettings::default); + let settings = self.settings.entry(id).or_insert_with(DappsSettings::default); settings.default = Some(default); } self.settings.save(JsonSettings::write); @@ -370,29 +370,29 @@ mod tests { use account_provider::DappId; use std::collections::HashMap; use ethjson::misc::AccountMeta; - use devtools::RandomTempPath; + use tempdir::TempDir; #[test] fn should_save_and_reload_address_book() { - let path = RandomTempPath::create_dir(); - let mut b = AddressBook::new(&path); + let tempdir = TempDir::new("").unwrap(); + let mut b = AddressBook::new(tempdir.path()); b.set_name(1.into(), "One".to_owned()); b.set_meta(1.into(), "{1:1}".to_owned()); - let b = AddressBook::new(&path); + let b = AddressBook::new(tempdir.path()); assert_eq!(b.get(), hash_map![1.into() => AccountMeta{name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None}]); } #[test] fn should_remove_address() { - let path = RandomTempPath::create_dir(); - let mut b = AddressBook::new(&path); + let tempdir = TempDir::new("").unwrap(); + let mut b = AddressBook::new(tempdir.path()); b.set_name(1.into(), "One".to_owned()); b.set_name(2.into(), "Two".to_owned()); b.set_name(3.into(), "Three".to_owned()); b.remove(2.into()); - let b = AddressBook::new(&path); + let b = AddressBook::new(tempdir.path()); assert_eq!(b.get(), hash_map![ 1.into() => AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None}, 3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None} @@ -402,14 +402,14 @@ mod tests { #[test] fn should_save_and_reload_dapps_settings() { // given - let path = RandomTempPath::create_dir(); - let mut b = DappsSettingsStore::new(&path); + let tempdir = TempDir::new("").unwrap(); + let mut b = DappsSettingsStore::new(tempdir.path()); // when b.set_accounts("dappOne".into(), Some(vec![1.into(), 2.into()])); // then - let b = DappsSettingsStore::new(&path); + let b = DappsSettingsStore::new(tempdir.path()); assert_eq!(b.settings(), hash_map![ "dappOne".into() => DappsSettings { accounts: Some(vec![1.into(), 2.into()]), @@ -440,8 +440,8 @@ mod tests { #[test] fn should_store_dapps_policy() { // given - let path = RandomTempPath::create_dir(); - let mut store = DappsSettingsStore::new(&path); + let tempdir = TempDir::new("").unwrap(); + let mut store = DappsSettingsStore::new(tempdir.path()); // Test default policy assert_eq!(store.policy(), NewDappsPolicy::AllAccounts { @@ -452,7 +452,7 @@ mod tests { store.set_policy(NewDappsPolicy::Whitelist(vec![1.into(), 2.into()])); // then - let store = DappsSettingsStore::new(&path); + let store = DappsSettingsStore::new(tempdir.path()); assert_eq!(store.policy.clone(), hash_map![ "default".into() => NewDappsPolicy::Whitelist(vec![1.into(), 2.into()]) ]); diff --git a/ethcore/src/basic_types.rs b/ethcore/src/basic_types.rs deleted file mode 100644 index 1f07e748fe63a933a70f401685bf99a376be8dca..0000000000000000000000000000000000000000 --- a/ethcore/src/basic_types.rs +++ /dev/null @@ -1,32 +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 . - -//! Ethcore basic typenames. - -/// Type for a 2048-bit log-bloom, as used by our blocks. -pub type LogBloom = ::log_entry::LogBloom; - -/// Constant 2048-bit datum for 0. Often used as a default. -pub static ZERO_LOGBLOOM: LogBloom = ::util::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. - With, - /// The seal/signature is not included. - Without, -} diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 64958700eb24b9cc6e8e885bc2211f9c2e4d0953..a0318d3e187a3126878200b1e12c9f52dc3b7c37 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -19,22 +19,24 @@ use std::cmp; use std::sync::Arc; use std::collections::HashSet; +use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP}; +use triehash::ordered_trie_root; -use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError}; -use util::{Bytes, Address, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RLP}; -use util::error::{Mismatch, OutOfBounds}; +use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError, encode_list}; +use ethereum_types::{H256, U256, Address, Bloom}; +use bytes::Bytes; +use unexpected::{Mismatch, OutOfBounds}; -use basic_types::{LogBloom, Seal}; use vm::{EnvInfo, LastHashes}; -use engines::Engine; -use error::{Error, BlockError, TransactionError}; +use engines::EthEngine; +use error::{Error, BlockError}; use factory::Factories; -use header::Header; -use receipt::Receipt; +use header::{Header, Seal}; +use receipt::{Receipt, TransactionOutcome}; use state::State; use state_db::StateDB; -use trace::FlatTrace; -use transaction::{UnverifiedTransaction, SignedTransaction}; +use trace::Tracing; +use transaction::{UnverifiedTransaction, SignedTransaction, Error as TransactionError}; use verification::PreverifiedBlock; use views::BlockView; @@ -65,7 +67,6 @@ impl Block { } } - impl Decodable for Block { fn decode(rlp: &UntrustedRlp) -> Result { if rlp.as_raw().len() != rlp.payload_info()?.total() { @@ -91,44 +92,13 @@ pub struct ExecutedBlock { receipts: Vec, transactions_set: HashSet, state: State, - traces: Option>>, -} - -/// A set of references to `ExecutedBlock` fields that are publicly accessible. -pub struct BlockRefMut<'a> { - /// Block header. - pub header: &'a mut Header, - /// Block transactions. - pub transactions: &'a [SignedTransaction], - /// Block uncles. - pub uncles: &'a [Header], - /// Transaction receipts. - pub receipts: &'a [Receipt], - /// State. - pub state: &'a mut State, - /// Traces. - pub traces: &'a Option>>, -} - -/// A set of immutable references to `ExecutedBlock` fields that are publicly accessible. -pub struct BlockRef<'a> { - /// Block header. - pub header: &'a Header, - /// Block transactions. - pub transactions: &'a [SignedTransaction], - /// Block uncles. - pub uncles: &'a [Header], - /// Transaction receipts. - pub receipts: &'a [Receipt], - /// State. - pub state: &'a State, - /// Traces. - pub traces: &'a Option>>, + traces: Tracing, + last_hashes: Arc, } impl ExecutedBlock { /// Create a new block from the given `state`. - fn new(state: State, tracing: bool) -> ExecutedBlock { + fn new(state: State, last_hashes: Arc, tracing: bool) -> ExecutedBlock { ExecutedBlock { header: Default::default(), transactions: Default::default(), @@ -136,32 +106,37 @@ impl ExecutedBlock { receipts: Default::default(), transactions_set: Default::default(), state: state, - traces: if tracing {Some(Vec::new())} else {None}, + traces: if tracing { + Tracing::enabled() + } else { + Tracing::Disabled + }, + last_hashes: last_hashes, } } - /// Get a structure containing individual references to all public fields. - pub fn fields_mut(&mut self) -> BlockRefMut { - BlockRefMut { - header: &mut self.header, - transactions: &self.transactions, - uncles: &self.uncles, - state: &mut self.state, - receipts: &self.receipts, - traces: &self.traces, + /// Get the environment info concerning this block. + pub fn env_info(&self) -> EnvInfo { + // TODO: memoise. + EnvInfo { + number: self.header.number(), + author: self.header.author().clone(), + timestamp: self.header.timestamp(), + difficulty: self.header.difficulty().clone(), + last_hashes: self.last_hashes.clone(), + gas_used: self.receipts.last().map_or(U256::zero(), |r| r.gas_used), + gas_limit: self.header.gas_limit().clone(), } } - /// Get a structure containing individual references to all public fields. - pub fn fields(&self) -> BlockRef { - BlockRef { - header: &self.header, - transactions: &self.transactions, - uncles: &self.uncles, - state: &self.state, - receipts: &self.receipts, - traces: &self.traces, - } + /// Get mutable access to a state. + pub fn state_mut(&mut self) -> &mut State { + &mut self.state + } + + /// Get mutable reference to traces. + pub fn traces_mut(&mut self) -> &mut Tracing { + &mut self.traces } } @@ -192,10 +167,13 @@ pub trait IsBlock { fn receipts(&self) -> &[Receipt] { &self.block().receipts } /// Get all information concerning transaction tracing in this block. - fn traces(&self) -> &Option>> { &self.block().traces } + fn traces(&self) -> &Tracing { &self.block().traces } /// Get all uncles in this block. fn uncles(&self) -> &[Header] { &self.block().uncles } + + /// Get tracing enabled flag for this block. + fn tracing_enabled(&self) -> bool { self.block().traces.is_enabled() } } /// Trait for a object that has a state database. @@ -208,14 +186,33 @@ impl IsBlock for ExecutedBlock { fn block(&self) -> &ExecutedBlock { self } } +impl ::parity_machine::LiveBlock for ExecutedBlock { + type Header = Header; + + fn header(&self) -> &Header { + &self.header + } + + fn uncles(&self) -> &[Header] { + &self.uncles + } +} + +impl ::parity_machine::Transactions for ExecutedBlock { + type Transaction = SignedTransaction; + + fn transactions(&self) -> &[SignedTransaction] { + &self.transactions + } +} + /// Block that is ready for transactions to be added. /// /// It's a bit like a Vec, except that whenever a transaction is pushed, we execute it and /// maintain the system `state()`. We also archive execution receipts in preparation for later block creation. pub struct OpenBlock<'x> { block: ExecutedBlock, - engine: &'x Engine, - last_hashes: Arc, + engine: &'x EthEngine, } /// Just like `OpenBlock`, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields, @@ -226,7 +223,6 @@ pub struct OpenBlock<'x> { pub struct ClosedBlock { block: ExecutedBlock, uncle_bytes: Bytes, - last_hashes: Arc, unclosed_state: State, } @@ -248,10 +244,9 @@ 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 Engine, + engine: &'x EthEngine, factories: Factories, tracing: bool, db: StateDB, @@ -265,9 +260,8 @@ impl<'x> OpenBlock<'x> { let number = parent.number() + 1; let state = State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce(number), factories)?; let mut r = OpenBlock { - block: ExecutedBlock::new(state, tracing), + block: ExecutedBlock::new(state, last_hashes, tracing), engine: engine, - last_hashes: last_hashes.clone(), }; r.block.header.set_parent_hash(parent.hash()); @@ -279,44 +273,22 @@ impl<'x> OpenBlock<'x> { let gas_floor_target = cmp::max(gas_range_target.0, engine.params().min_gas_limit); let gas_ceil_target = cmp::max(gas_range_target.1, gas_floor_target); - engine.populate_from_parent(&mut r.block.header, parent, gas_floor_target, gas_ceil_target); - engine.on_new_block(&mut r.block, last_hashes, is_epoch_begin)?; + + engine.machine().populate_from_parent(&mut r.block.header, parent, gas_floor_target, gas_ceil_target); + engine.populate_from_parent(&mut r.block.header, parent); + + engine.machine().on_new_block(&mut r.block)?; + engine.on_new_block(&mut r.block, is_epoch_begin)?; Ok(r) } - /// Alter the author for the block. - pub fn set_author(&mut self, author: Address) { self.block.header.set_author(author); } - /// Alter the timestamp of the block. pub fn set_timestamp(&mut self, timestamp: u64) { self.block.header.set_timestamp(timestamp); } - /// Alter the difficulty for the block. - pub fn set_difficulty(&mut self, a: U256) { self.block.header.set_difficulty(a); } - - /// Alter the gas limit for the block. - pub fn set_gas_limit(&mut self, a: U256) { self.block.header.set_gas_limit(a); } - - /// Alter the gas limit for the block. - pub fn set_gas_used(&mut self, a: U256) { self.block.header.set_gas_used(a); } - - /// Alter the uncles hash the block. - pub fn set_uncles_hash(&mut self, h: H256) { self.block.header.set_uncles_hash(h); } - - /// Alter transactions root for the block. - pub fn set_transactions_root(&mut self, h: H256) { self.block.header.set_transactions_root(h); } - - /// Alter the receipts root for the block. - pub fn set_receipts_root(&mut self, h: H256) { self.block.header.set_receipts_root(h); } - - /// Alter the extra_data for the block. - pub fn set_extra_data(&mut self, extra_data: Bytes) -> Result<(), BlockError> { - if extra_data.len() > self.engine.maximum_extra_data_size() { - Err(BlockError::ExtraDataOutOfBounds(OutOfBounds{min: None, max: Some(self.engine.maximum_extra_data_size()), found: extra_data.len()})) - } else { - self.block.header.set_extra_data(extra_data); - Ok(()) - } + /// Removes block gas limit. + pub fn remove_gas_limit(&mut self) { + self.block.header.set_gas_limit(U256::max_value()); } /// Add an uncle to the block, if possible. @@ -324,8 +296,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) @@ -335,16 +312,7 @@ impl<'x> OpenBlock<'x> { /// Get the environment info concerning this block. pub fn env_info(&self) -> EnvInfo { - // TODO: memoise. - EnvInfo { - number: self.block.header.number(), - author: self.block.header.author().clone(), - timestamp: self.block.header.timestamp(), - difficulty: self.block.header.difficulty().clone(), - last_hashes: self.last_hashes.clone(), - gas_used: self.block.receipts.last().map_or(U256::zero(), |r| r.gas_used), - gas_limit: self.block.header.gas_limit().clone(), - } + self.block.env_info() } /// Push a transaction into the block. @@ -352,22 +320,19 @@ impl<'x> OpenBlock<'x> { /// If valid, it will be executed, and archived together with the receipt. pub fn push_transaction(&mut self, t: SignedTransaction, h: Option) -> Result<&Receipt, Error> { if self.block.transactions_set.contains(&t.hash()) { - return Err(From::from(TransactionError::AlreadyImported)); + return Err(TransactionError::AlreadyImported.into()); } let env_info = self.env_info(); -// info!("env_info says gas_used={}", env_info.gas_used); - match self.block.state.apply(&env_info, self.engine, &t, self.block.traces.is_some()) { - Ok(outcome) => { - self.block.transactions_set.insert(h.unwrap_or_else(||t.hash())); - self.block.transactions.push(t.into()); - let t = outcome.trace; - self.block.traces.as_mut().map(|traces| traces.push(t)); - self.block.receipts.push(outcome.receipt); - Ok(self.block.receipts.last().expect("receipt just pushed; qed")) - } - Err(x) => Err(From::from(x)) + let outcome = self.block.state.apply(&env_info, self.engine.machine(), &t, self.block.traces.is_enabled())?; + + self.block.transactions_set.insert(h.unwrap_or_else(||t.hash())); + self.block.transactions.push(t.into()); + if let Tracing::Enabled(ref mut traces) = self.block.traces { + traces.push(outcome.trace.into()); } + self.block.receipts.push(outcome.receipt); + Ok(self.block.receipts.last().expect("receipt just pushed; qed")) } /// Push transactions onto the block. @@ -376,14 +341,19 @@ impl<'x> OpenBlock<'x> { } /// Populate self from a header. - pub fn populate_from(&mut self, header: &Header) { - self.set_difficulty(*header.difficulty()); - self.set_gas_limit(*header.gas_limit()); - self.set_timestamp(header.timestamp()); - self.set_author(header.author().clone()); - self.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e)); - self.set_uncles_hash(header.uncles_hash().clone()); - self.set_transactions_root(header.transactions_root().clone()); + fn populate_from(&mut self, header: &Header) { + self.block.header.set_difficulty(*header.difficulty()); + self.block.header.set_gas_limit(*header.gas_limit()); + self.block.header.set_timestamp(header.timestamp()); + self.block.header.set_author(*header.author()); + self.block.header.set_uncles_hash(*header.uncles_hash()); + self.block.header.set_transactions_root(*header.transactions_root()); + // TODO: that's horrible. set only for backwards compatibility + if header.extra_data().len() > self.engine.maximum_extra_data_size() { + warn!("Couldn't set extradata. Ignoring."); + } else { + self.block.header.set_extra_data(header.extra_data().clone()); + } } /// Turn this into a `ClosedBlock`. @@ -395,22 +365,22 @@ impl<'x> OpenBlock<'x> { if let Err(e) = s.engine.on_close_block(&mut s.block) { warn!("Encountered error on closing the block: {}", e); } + if let Err(e) = s.block.state.commit() { warn!("Encountered error on state commit: {}", e); } - s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); - let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - s.block.header.set_uncles_hash(uncle_bytes.sha3()); + s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes()))); + let uncle_bytes = encode_list(&s.block.uncles).into_vec(); + s.block.header.set_uncles_hash(keccak(&uncle_bytes)); s.block.header.set_state_root(s.block.state.root().clone()); - s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().into_vec()))); - s.block.header.set_log_bloom(s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator + s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes()))); + s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator s.block.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used)); ClosedBlock { block: s.block, - uncle_bytes: uncle_bytes, - last_hashes: s.last_hashes, - unclosed_state: unclosed_state, + uncle_bytes, + unclosed_state, } } @@ -425,24 +395,24 @@ impl<'x> OpenBlock<'x> { if let Err(e) = s.block.state.commit() { warn!("Encountered error on state commit: {}", e); } - if s.block.header.transactions_root().is_zero() || s.block.header.transactions_root() == &SHA3_NULL_RLP { - s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes().into_vec()))); + if s.block.header.transactions_root().is_zero() || s.block.header.transactions_root() == &KECCAK_NULL_RLP { + s.block.header.set_transactions_root(ordered_trie_root(s.block.transactions.iter().map(|e| e.rlp_bytes()))); } - let uncle_bytes = s.block.uncles.iter().fold(RlpStream::new_list(s.block.uncles.len()), |mut s, u| {s.append_raw(&u.rlp(Seal::With), 1); s} ).out(); - if s.block.header.uncles_hash().is_zero() { - s.block.header.set_uncles_hash(uncle_bytes.sha3()); + let uncle_bytes = encode_list(&s.block.uncles).into_vec(); + if s.block.header.uncles_hash().is_zero() || s.block.header.uncles_hash() == &KECCAK_EMPTY_LIST_RLP { + s.block.header.set_uncles_hash(keccak(&uncle_bytes)); } - if s.block.header.receipts_root().is_zero() || s.block.header.receipts_root() == &SHA3_NULL_RLP { - s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes().into_vec()))); + if s.block.header.receipts_root().is_zero() || s.block.header.receipts_root() == &KECCAK_NULL_RLP { + s.block.header.set_receipts_root(ordered_trie_root(s.block.receipts.iter().map(|r| r.rlp_bytes()))); } s.block.header.set_state_root(s.block.state.root().clone()); - s.block.header.set_log_bloom(s.block.receipts.iter().fold(LogBloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator + s.block.header.set_log_bloom(s.block.receipts.iter().fold(Bloom::zero(), |mut b, r| {b = &b | &r.log_bloom; b})); //TODO: use |= operator s.block.header.set_gas_used(s.block.receipts.last().map_or(U256::zero(), |r| r.gas_used)); LockedBlock { block: s.block, - uncle_bytes: uncle_bytes, + uncle_bytes, } } @@ -465,7 +435,7 @@ impl<'x> IsBlock for LockedBlock { impl ClosedBlock { /// Get the hash of the header without seal arguments. - pub fn hash(&self) -> H256 { self.header().rlp_sha3(Seal::Without) } + pub fn hash(&self) -> H256 { self.header().rlp_keccak(Seal::Without) } /// Turn this into a `LockedBlock`, unable to be reopened again. pub fn lock(self) -> LockedBlock { @@ -476,29 +446,30 @@ impl ClosedBlock { } /// Given an engine reference, reopen the `ClosedBlock` into an `OpenBlock`. - pub fn reopen(self, engine: &Engine) -> OpenBlock { + pub fn reopen(self, engine: &EthEngine) -> OpenBlock { // revert rewards (i.e. set state back at last transaction's state). let mut block = self.block; block.state = self.unclosed_state; OpenBlock { block: block, engine: engine, - last_hashes: self.last_hashes, } } } impl LockedBlock { /// Get the hash of the header without seal arguments. - pub fn hash(&self) -> H256 { self.header().rlp_sha3(Seal::Without) } + pub fn hash(&self) -> H256 { self.header().rlp_keccak(Seal::Without) } /// Provide a valid seal in order to turn this into a `SealedBlock`. /// /// NOTE: This does not check the validity of `seal` with the engine. - pub fn seal(self, engine: &Engine, seal: Vec) -> Result { + pub fn seal(self, engine: &EthEngine, seal: Vec) -> Result { + let expected_seal_fields = engine.seal_fields(self.header()); let mut s = self; - if seal.len() != engine.seal_fields() { - return Err(BlockError::InvalidSealArity(Mismatch{expected: engine.seal_fields(), found: seal.len()})); + if seal.len() != expected_seal_fields { + return Err(BlockError::InvalidSealArity( + Mismatch { expected: expected_seal_fields, found: seal.len() })); } s.block.header.set_seal(seal); Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }) @@ -509,12 +480,14 @@ impl LockedBlock { /// Returns the `ClosedBlock` back again if the seal is no good. pub fn try_seal( self, - engine: &Engine, + engine: &EthEngine, seal: Vec, ) -> Result { let mut s = self; s.block.header.set_seal(seal); - match engine.verify_block_seal(&s.block.header) { + + // TODO: passing state context to avoid engines owning it? + match engine.verify_local_seal(&s.block.header) { Err(e) => Err((e, s)), _ => Ok(SealedBlock { block: s.block, uncle_bytes: s.uncle_bytes }), } @@ -524,9 +497,9 @@ impl LockedBlock { pub fn strip_receipts(self) -> LockedBlock { let mut block = self; for receipt in &mut block.block.receipts { - receipt.state_root = None; + receipt.outcome = TransactionOutcome::Unknown; } - block.block.header.set_receipts_root(ordered_trie_root(block.block.receipts.iter().map(|r| r.rlp_bytes().into_vec()))); + block.block.header.set_receipts_root(ordered_trie_root(block.block.receipts.iter().map(|r| r.rlp_bytes()))); block } } @@ -561,12 +534,11 @@ 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], uncles: &[Header], - engine: &Engine, + engine: &EthEngine, tracing: bool, db: StateDB, parent: &Header, @@ -635,10 +607,9 @@ 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: &Engine, + engine: &EthEngine, tracing: bool, db: StateDB, parent: &Header, @@ -664,24 +635,23 @@ pub fn enact_verified( #[cfg(test)] mod tests { - use tests::helpers::*; + use tests::helpers::get_temp_state_db; use super::*; - use engines::Engine; + use engines::EthEngine; use vm::LastHashes; use error::Error; use header::Header; use factory::Factories; use state_db::StateDB; use views::BlockView; - use util::Address; + use ethereum_types::Address; use std::sync::Arc; 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: &Engine, + engine: &EthEngine, tracing: bool, db: StateDB, parent: &Header, @@ -690,7 +660,12 @@ mod tests { ) -> Result { let block = BlockView::new(block_bytes); let header = block.header(); - let transactions: Result, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect(); + let transactions: Result, Error> = block + .transactions() + .into_iter() + .map(SignedTransaction::new) + .map(|r| r.map_err(Into::into)) + .collect(); let transactions = transactions?; { @@ -725,10 +700,9 @@ 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: &Engine, + engine: &EthEngine, tracing: bool, db: StateDB, parent: &Header, diff --git a/ethcore/src/blockchain/best_block.rs b/ethcore/src/blockchain/best_block.rs index e857a99b64f69dbe4c05b844b9b1e68920c3c9e6..1436ced275de9b1017aa30ce6a91536d59b49c50 100644 --- a/ethcore/src/blockchain/best_block.rs +++ b/ethcore/src/blockchain/best_block.rs @@ -14,10 +14,16 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::{Bytes, U256, H256}; +use ethereum_types::{H256, U256}; +use bytes::Bytes; use header::BlockNumber; -/// Best block info. +/// Contains information on a best block that is specific to the consensus engine. +/// +/// For GHOST fork-choice rule it would typically describe the block with highest +/// combined difficulty (usually the block with the highest block number). +/// +/// Sometimes refered as 'latest block'. #[derive(Default)] pub struct BestBlock { /// Best block hash. diff --git a/ethcore/src/blockchain/block_info.rs b/ethcore/src/blockchain/block_info.rs index e9e02de608449db6de8fc8dd108cb1cc79329b5a..ee8a50d09d9eee44fc4483447b581b7089de1f6a 100644 --- a/ethcore/src/blockchain/block_info.rs +++ b/ethcore/src/blockchain/block_info.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::{U256,H256}; +use ethereum_types::{H256, U256}; use header::BlockNumber; /// Brief info about inserted block. @@ -31,7 +31,7 @@ pub struct BlockInfo { } /// Describes location of newly inserted block. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub enum BlockLocation { /// It's part of the canon chain. CanonChain, @@ -43,7 +43,7 @@ pub enum BlockLocation { BranchBecomingCanonChain(BranchBecomingCanonChainData), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] pub struct BranchBecomingCanonChainData { /// Hash of the newest common ancestor with old canon chain. pub ancestor: H256, diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 001df861c6623005508dca9ae0269703fbcf59d4..09be1143f2ec46ad6c785b24c868e2cf7b00b604 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -16,22 +16,26 @@ //! Blockchain database. -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, hash_map}; use std::sync::Arc; use std::mem; use itertools::Itertools; use bloomchain as bc; -use util::*; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, Bloom, U256}; +use parking_lot::{Mutex, RwLock}; +use bytes::Bytes; use rlp::*; +use rlp_compress::{compress, decompress, blocks_swapper}; use header::*; -use super::extras::*; use transaction::*; use views::*; use log_entry::{LogEntry, LocalizedLogEntry}; use receipt::Receipt; -use blooms::{Bloom, BloomGroup}; -use blockchain::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData}; +use blooms::{BloomGroup, GroupPosition}; use blockchain::best_block::{BestBlock, BestAncientBlock}; +use blockchain::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData}; +use blockchain::extras::{BlockReceipts, BlockDetails, TransactionAddress, EPOCH_KEY_PREFIX, EpochTransitions}; use types::blockchain_info::BlockChainInfo; use types::tree_route::TreeRoute; use blockchain::update::ExtrasUpdate; @@ -40,6 +44,9 @@ use db::{self, Writable, Readable, CacheUpdatePolicy}; use cache_manager::CacheManager; use encoded; use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition}; +use rayon::prelude::*; +use ansi_term::Colour; +use kvdb::{DBTransaction, KeyValueDB}; const LOG_BLOOMS_LEVELS: usize = 3; const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16; @@ -143,15 +150,11 @@ pub trait BlockProvider { } /// Returns numbers of blocks containing given bloom. - fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec; + fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec; /// Returns logs matching given filter. fn logs(&self, blocks: Vec, matches: F, limit: Option) -> Vec - where F: Fn(&LogEntry) -> bool, Self: Sized; -} - -macro_rules! otry { - ($e:expr) => { match $e { Some(x) => x, None => return None } } + where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized; } #[derive(Debug, Hash, Eq, PartialEq, Clone)] @@ -161,13 +164,13 @@ enum CacheId { BlockDetails(H256), BlockHashes(BlockNumber), TransactionAddresses(H256), - BlocksBlooms(LogGroupPosition), + BlocksBlooms(GroupPosition), BlockReceipts(H256), } impl bc::group::BloomGroupDatabase for BlockChain { fn blooms_at(&self, position: &bc::group::GroupPosition) -> Option { - let position = LogGroupPosition::from(position.clone()); + let position = GroupPosition::from(position.clone()); let result = self.db.read_with_cache(db::COL_EXTRA, &self.blocks_blooms, &position).map(Into::into); self.cache_man.lock().note_used(CacheId::BlocksBlooms(position)); result @@ -197,7 +200,7 @@ pub struct BlockChain { block_details: RwLock>, block_hashes: RwLock>, transaction_addresses: RwLock>, - blocks_blooms: RwLock>, + blocks_blooms: RwLock>, block_receipts: RwLock>, db: Arc, @@ -222,7 +225,7 @@ impl BlockProvider for BlockChain { } fn best_ancient_block(&self) -> Option { - self.best_ancient_block.read().as_ref().map(|b| b.hash.clone()) + self.best_ancient_block.read().as_ref().map(|b| b.hash) } fn best_ancient_number(&self) -> Option { @@ -231,17 +234,15 @@ impl BlockProvider for BlockChain { /// Get raw block data fn block(&self, hash: &H256) -> Option { - match (self.block_header_data(hash), self.block_body(hash)) { - (Some(header), Some(body)) => { - let mut block = RlpStream::new_list(3); - let body_rlp = body.rlp(); - block.append_raw(header.rlp().as_raw(), 1); - block.append_raw(body_rlp.at(0).as_raw(), 1); - block.append_raw(body_rlp.at(1).as_raw(), 1); - Some(encoded::Block::new(block.out())) - }, - _ => None, - } + let header = self.block_header_data(hash)?; + let body = self.block_body(hash)?; + + let mut block = RlpStream::new_list(3); + let body_rlp = body.rlp(); + block.append_raw(header.rlp().as_raw(), 1); + block.append_raw(body_rlp.at(0).as_raw(), 1); + block.append_raw(body_rlp.at(1).as_raw(), 1); + Some(encoded::Block::new(block.out())) } /// Get block header data @@ -265,21 +266,15 @@ impl BlockProvider for BlockChain { } // Read from DB and populate cache - let opt = self.db.get(db::COL_HEADERS, hash) - .expect("Low level database error. Some issue with disk?"); - - let result = match opt { - Some(b) => { - let bytes: Bytes = UntrustedRlp::new(&b).decompress(RlpType::Blocks).into_vec(); - let mut write = self.block_headers.write(); - write.insert(hash.clone(), bytes.clone()); - Some(encoded::Header::new(bytes)) - }, - None => None - }; + let b = self.db.get(db::COL_HEADERS, hash) + .expect("Low level database error. Some issue with disk?")?; - self.cache_man.lock().note_used(CacheId::BlockHeader(hash.clone())); - result + let bytes = decompress(&b, blocks_swapper()).into_vec(); + let mut write = self.block_headers.write(); + write.insert(*hash, bytes.clone()); + + self.cache_man.lock().note_used(CacheId::BlockHeader(*hash)); + Some(encoded::Header::new(bytes)) } /// Get block body data @@ -301,107 +296,106 @@ impl BlockProvider for BlockChain { } // Read from DB and populate cache - let opt = self.db.get(db::COL_BODIES, hash) - .expect("Low level database error. Some issue with disk?"); - - let result = match opt { - Some(b) => { - let bytes: Bytes = UntrustedRlp::new(&b).decompress(RlpType::Blocks).into_vec(); - let mut write = self.block_bodies.write(); - write.insert(hash.clone(), bytes.clone()); - Some(encoded::Body::new(bytes)) - }, - None => None - }; + let b = self.db.get(db::COL_BODIES, hash) + .expect("Low level database error. Some issue with disk?")?; - self.cache_man.lock().note_used(CacheId::BlockBody(hash.clone())); + let bytes = decompress(&b, blocks_swapper()).into_vec(); + let mut write = self.block_bodies.write(); + write.insert(*hash, bytes.clone()); - result + self.cache_man.lock().note_used(CacheId::BlockBody(*hash)); + Some(encoded::Body::new(bytes)) } /// Get the familial details concerning a block. fn block_details(&self, hash: &H256) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_details, hash); - self.cache_man.lock().note_used(CacheId::BlockDetails(hash.clone())); - result + let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_details, hash)?; + self.cache_man.lock().note_used(CacheId::BlockDetails(*hash)); + Some(result) } /// Get the hash of given block's number. fn block_hash(&self, index: BlockNumber) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_hashes, &index); + let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_hashes, &index)?; self.cache_man.lock().note_used(CacheId::BlockHashes(index)); - result + Some(result) } /// Get the address of transaction with given hash. fn transaction_address(&self, hash: &H256) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.transaction_addresses, hash); - self.cache_man.lock().note_used(CacheId::TransactionAddresses(hash.clone())); - result + let result = self.db.read_with_cache(db::COL_EXTRA, &self.transaction_addresses, hash)?; + self.cache_man.lock().note_used(CacheId::TransactionAddresses(*hash)); + Some(result) } /// Get receipts of block with given hash. fn block_receipts(&self, hash: &H256) -> Option { - let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_receipts, hash); - self.cache_man.lock().note_used(CacheId::BlockReceipts(hash.clone())); - result + let result = self.db.read_with_cache(db::COL_EXTRA, &self.block_receipts, hash)?; + self.cache_man.lock().note_used(CacheId::BlockReceipts(*hash)); + Some(result) } /// Returns numbers of blocks containing given bloom. - fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockNumber, to_block: BlockNumber) -> Vec { + fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec { let range = from_block as bc::Number..to_block as bc::Number; let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); - chain.with_bloom(&range, &Bloom::from(bloom.clone()).into()) + chain.with_bloom(&range, bloom) .into_iter() .map(|b| b as BlockNumber) .collect() } fn logs(&self, mut blocks: Vec, matches: F, limit: Option) -> Vec - where F: Fn(&LogEntry) -> bool, Self: Sized { + where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized { // sort in reverse order blocks.sort_by(|a, b| b.cmp(a)); - let mut log_index = 0; - let mut logs = blocks.into_iter() - .filter_map(|number| self.block_hash(number).map(|hash| (number, hash))) - .filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts))) - .filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes()))) - .flat_map(|(number, hash, mut receipts, mut hashes)| { - if receipts.len() != hashes.len() { - warn!("Block {} ({}) has different number of receipts ({}) to transactions ({}). Database corrupt?", number, hash, receipts.len(), hashes.len()); - assert!(false); - } - log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.logs.len()); - - let receipts_len = receipts.len(); - hashes.reverse(); - receipts.reverse(); - receipts.into_iter() - .map(|receipt| receipt.logs) - .zip(hashes) - .enumerate() - .flat_map(move |(index, (mut logs, tx_hash))| { - let current_log_index = log_index; - let no_of_logs = logs.len(); - log_index -= no_of_logs; - - logs.reverse(); - logs.into_iter() + let mut logs = blocks + .chunks(128) + .flat_map(move |blocks_chunk| { + blocks_chunk.into_par_iter() + .filter_map(|number| self.block_hash(*number).map(|hash| (*number, hash))) + .filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts))) + .filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes()))) + .flat_map(|(number, hash, mut receipts, mut hashes)| { + if receipts.len() != hashes.len() { + warn!("Block {} ({}) has different number of receipts ({}) to transactions ({}). Database corrupt?", number, hash, receipts.len(), hashes.len()); + assert!(false); + } + let mut log_index = receipts.iter().fold(0, |sum, receipt| sum + receipt.logs.len()); + + let receipts_len = receipts.len(); + hashes.reverse(); + receipts.reverse(); + receipts.into_iter() + .map(|receipt| receipt.logs) + .zip(hashes) .enumerate() - .map(move |(i, log)| LocalizedLogEntry { - entry: log, - block_hash: hash, - block_number: number, - transaction_hash: tx_hash, - // iterating in reverse order - transaction_index: receipts_len - index - 1, - transaction_log_index: no_of_logs - i - 1, - log_index: current_log_index - i - 1, + .flat_map(move |(index, (mut logs, tx_hash))| { + let current_log_index = log_index; + let no_of_logs = logs.len(); + log_index -= no_of_logs; + + logs.reverse(); + logs.into_iter() + .enumerate() + .map(move |(i, log)| LocalizedLogEntry { + entry: log, + block_hash: hash, + block_number: number, + transaction_hash: tx_hash, + // iterating in reverse order + transaction_index: receipts_len - index - 1, + transaction_log_index: no_of_logs - i - 1, + log_index: current_log_index - i - 1, + }) }) + .filter(|log_entry| matches(&log_entry.entry)) + .take(limit.unwrap_or(::std::usize::MAX)) + .collect::>() }) + .collect::>() }) - .filter(|log_entry| matches(&log_entry.entry)) .take(limit.unwrap_or(::std::usize::MAX)) .collect::>(); logs.reverse(); @@ -440,33 +434,31 @@ impl<'a> Iterator for EpochTransitionIter<'a> { fn next(&mut self) -> Option { loop { - match self.prefix_iter.next() { - Some((key, val)) => { - // iterator may continue beyond values beginning with this - // prefix. - if !key.starts_with(&EPOCH_KEY_PREFIX[..]) { return None } - - let transitions: EpochTransitions = ::rlp::decode(&val[..]); - - // if there are multiple candidates, at most one will be on the - // canon chain. - for transition in transitions.candidates.into_iter() { - let is_in_canon_chain = self.chain.block_hash(transition.block_number) - .map_or(false, |hash| hash == transition.block_hash); - - // if the transition is within the block gap, there will only be - // one candidate, and it will be from a snapshot restored from. - let is_ancient = self.chain.first_block_number() - .map_or(false, |first| first > transition.block_number); - - if is_ancient || is_in_canon_chain { - return Some((transitions.number, transition)) - } - } + // some epochs never occurred on the main chain. + let (key, val) = self.prefix_iter.next()?; + + // iterator may continue beyond values beginning with this + // prefix. + if !key.starts_with(&EPOCH_KEY_PREFIX[..]) { + return None + } + + let transitions: EpochTransitions = ::rlp::decode(&val[..]); - // some epochs never occurred on the main chain. + // if there are multiple candidates, at most one will be on the + // canon chain. + for transition in transitions.candidates.into_iter() { + let is_in_canon_chain = self.chain.block_hash(transition.block_number) + .map_or(false, |hash| hash == transition.block_hash); + + // if the transition is within the block gap, there will only be + // one candidate, and it will be from a snapshot restored from. + let is_ancient = self.chain.first_block_number() + .map_or(false, |first| first > transition.block_number); + + if is_ancient || is_in_canon_chain { + return Some((transitions.number, transition)) } - None => return None, } } } @@ -511,7 +503,7 @@ impl BlockChain { // we need to insert genesis into the cache let block = BlockView::new(genesis); let header = block.header_view(); - let hash = block.sha3(); + let hash = block.hash(); let details = BlockDetails { number: header.number(), @@ -609,58 +601,6 @@ impl BlockChain { self.db.read_with_cache(db::COL_EXTRA, &self.block_details, parent).map_or(false, |d| d.children.contains(hash)) } - /// Rewind to a previous block - #[cfg(test)] - fn rewind(&self) -> Option { - use db::Key; - let mut batch =self.db.transaction(); - // track back to the best block we have in the blocks database - if let Some(best_block_hash) = self.db.get(db::COL_EXTRA, b"best").unwrap() { - let best_block_hash = H256::from_slice(&best_block_hash); - if best_block_hash == self.genesis_hash() { - return None; - } - if let Some(extras) = self.db.read(db::COL_EXTRA, &best_block_hash) as Option { - type DetailsKey = Key; - batch.delete(db::COL_EXTRA, &(DetailsKey::key(&best_block_hash))); - let hash = extras.parent; - let range = extras.number as bc::Number .. extras.number as bc::Number; - let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); - let changes = chain.replace(&range, vec![]); - for (k, v) in changes { - batch.write(db::COL_EXTRA, &LogGroupPosition::from(k), &BloomGroup::from(v)); - } - batch.put(db::COL_EXTRA, b"best", &hash); - - let best_block_total_difficulty = self.block_details(&hash).unwrap().total_difficulty; - let best_block_rlp = self.block(&hash).unwrap().into_inner(); - - let mut best_block = self.best_block.write(); - *best_block = BestBlock { - number: extras.number - 1, - total_difficulty: best_block_total_difficulty, - hash: hash, - timestamp: BlockView::new(&best_block_rlp).header().timestamp(), - block: best_block_rlp, - }; - // update parent extras - if let Some(mut details) = self.db.read(db::COL_EXTRA, &hash) as Option { - details.children.clear(); - batch.write(db::COL_EXTRA, &hash, &details); - } - self.db.write(batch).expect("Writing to db failed"); - self.block_details.write().clear(); - self.block_hashes.write().clear(); - self.block_headers.write().clear(); - self.block_bodies.write().clear(); - self.block_receipts.write().clear(); - return Some(hash); - } - } - - None - } - /// Returns a tree route between `from` and `to`, which is a tuple of: /// /// - a vector of hashes of all blocks, ordered from `from` to `to`. @@ -710,8 +650,8 @@ impl BlockChain { let mut from_branch = vec![]; let mut to_branch = vec![]; - let mut from_details = otry!(self.block_details(&from)); - let mut to_details = otry!(self.block_details(&to)); + let mut from_details = self.block_details(&from)?; + let mut to_details = self.block_details(&to)?; let mut current_from = from; let mut current_to = to; @@ -719,13 +659,13 @@ impl BlockChain { while from_details.number > to_details.number { from_branch.push(current_from); current_from = from_details.parent.clone(); - from_details = otry!(self.block_details(&from_details.parent)); + from_details = self.block_details(&from_details.parent)?; } while to_details.number > from_details.number { to_branch.push(current_to); current_to = to_details.parent.clone(); - to_details = otry!(self.block_details(&to_details.parent)); + to_details = self.block_details(&to_details.parent)?; } assert_eq!(from_details.number, to_details.number); @@ -734,11 +674,11 @@ impl BlockChain { while current_from != current_to { from_branch.push(current_from); current_from = from_details.parent.clone(); - from_details = otry!(self.block_details(&from_details.parent)); + from_details = self.block_details(&from_details.parent)?; to_branch.push(current_to); current_to = to_details.parent.clone(); - to_details = otry!(self.block_details(&to_details.parent)); + to_details = self.block_details(&to_details.parent)?; } let index = from_branch.len(); @@ -758,12 +698,13 @@ impl BlockChain { /// This is used by snapshot restoration and when downloading missing blocks for the chain gap. /// `is_best` forces the best block to be updated to this block. /// `is_ancient` forces the best block of the first block sequence to be updated to this block. + /// `parent_td` is a parent total diffuculty /// Supply a dummy parent total difficulty when the parent block may not be in the chain. /// Returns true if the block is disconnected. pub fn insert_unordered_block(&self, batch: &mut DBTransaction, bytes: &[u8], receipts: Vec, parent_td: Option, is_best: bool, is_ancient: bool) -> bool { let block = BlockView::new(bytes); let header = block.header_view(); - let hash = header.sha3(); + let hash = header.hash(); if self.is_known(&hash) { return false; @@ -771,9 +712,8 @@ impl BlockChain { assert!(self.pending_best_block.read().is_none()); - let block_rlp = UntrustedRlp::new(bytes); - let compressed_header = block_rlp.at(0).unwrap().compress(RlpType::Blocks); - let compressed_body = UntrustedRlp::new(&Self::block_to_body(bytes)).compress(RlpType::Blocks); + let compressed_header = compress(block.header_rlp().as_raw(), blocks_swapper()); + let compressed_body = compress(&Self::block_to_body(bytes), blocks_swapper()); // store block in db batch.put(db::COL_HEADERS, &hash, &compressed_header); @@ -784,7 +724,7 @@ impl BlockChain { if let Some(parent_details) = maybe_parent { // parent known to be in chain. let info = BlockInfo { - hash: hash.clone(), + hash: hash, number: header.number(), total_difficulty: parent_details.total_difficulty + header.difficulty(), location: BlockLocation::CanonChain, @@ -900,8 +840,8 @@ impl BlockChain { /// The block corresponding the the parent hash must be stored already. pub fn epoch_transition_for(&self, parent_hash: H256) -> Option { // slow path: loop back block by block - for hash in otry!(self.ancestry_iter(parent_hash)) { - let details = otry!(self.block_details(&hash)); + for hash in self.ancestry_iter(parent_hash)? { + let details = self.block_details(&hash)?; // look for transition in database. if let Some(transition) = self.epoch_transition(details.number, hash) { @@ -913,7 +853,7 @@ impl BlockChain { // // if `block_hash` is canonical it will only return transitions up to // the parent. - if otry!(self.block_hash(details.number)) == hash { + if self.block_hash(details.number)? == hash { return self.epoch_transitions() .map(|(_, t)| t) .take_while(|t| t.block_number <= details.number) @@ -950,14 +890,12 @@ impl BlockChain { let mut update = HashMap::new(); update.insert(block_hash, parent_details); - let mut write_details = self.block_details.write(); batch.extend_with_cache(db::COL_EXTRA, &mut *write_details, update, CacheUpdatePolicy::Overwrite); 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. @@ -965,7 +903,7 @@ impl BlockChain { // create views onto rlp let block = BlockView::new(bytes); let header = block.header_view(); - let hash = header.sha3(); + let hash = header.hash(); if self.is_known_child(&header.parent_hash(), &hash) { return ImportRoute::none(); @@ -973,9 +911,12 @@ impl BlockChain { assert!(self.pending_best_block.read().is_none()); + let compressed_header = compress(block.header_rlp().as_raw(), blocks_swapper()); + let compressed_body = compress(&Self::block_to_body(bytes), blocks_swapper()); + // store block in db - batch.put_compressed(db::COL_HEADERS, &hash, block.header_rlp().as_raw().to_vec()); - batch.put_compressed(db::COL_BODIES, &hash, Self::block_to_body(bytes)); + batch.put(db::COL_HEADERS, &hash, &compressed_header); + batch.put(db::COL_BODIES, &hash, &compressed_body); let info = self.block_info(&header); @@ -1004,7 +945,7 @@ impl BlockChain { /// Get inserted block info which is critical to prepare extras updates. fn block_info(&self, header: &HeaderView) -> BlockInfo { - let hash = header.sha3(); + let hash = header.hash(); let number = header.number(); let parent_hash = header.parent_hash(); let parent_details = self.block_details(&parent_hash).unwrap_or_else(|| panic!("Invalid parent hash: {:?}", parent_hash)); @@ -1052,27 +993,50 @@ impl BlockChain { { let mut write_blocks_blooms = self.blocks_blooms.write(); - batch.extend_with_cache(db::COL_EXTRA, &mut *write_blocks_blooms, update.blocks_blooms, CacheUpdatePolicy::Remove); + // update best block + match update.info.location { + BlockLocation::Branch => (), + BlockLocation::BranchBecomingCanonChain(_) => { + // clear all existing blooms, cause they may be created for block + // number higher than current best block + *write_blocks_blooms = update.blocks_blooms; + for (key, value) in write_blocks_blooms.iter() { + batch.write(db::COL_EXTRA, key, value); + } + }, + BlockLocation::CanonChain => { + // update all existing blooms groups + for (key, value) in update.blocks_blooms { + match write_blocks_blooms.entry(key) { + hash_map::Entry::Occupied(mut entry) => { + entry.get_mut().accrue_bloom_group(&value); + batch.write(db::COL_EXTRA, entry.key(), entry.get()); + }, + hash_map::Entry::Vacant(entry) => { + batch.write(db::COL_EXTRA, entry.key(), &value); + entry.insert(value); + }, + } + } + }, + } } // These cached values must be updated last with all four locks taken to avoid // cache decoherence { let mut best_block = self.pending_best_block.write(); - // update best block - match update.info.location { - BlockLocation::Branch => (), - _ => if is_best { - batch.put(db::COL_EXTRA, b"best", &update.info.hash); - *best_block = Some(BestBlock { - hash: update.info.hash, - number: update.info.number, - total_difficulty: update.info.total_difficulty, - timestamp: update.timestamp, - block: update.block.to_vec(), - }); - }, + if is_best && update.info.location != BlockLocation::Branch { + batch.put(db::COL_EXTRA, b"best", &update.info.hash); + *best_block = Some(BestBlock { + hash: update.info.hash, + number: update.info.number, + total_difficulty: update.info.total_difficulty, + timestamp: update.timestamp, + block: update.block.to_vec(), + }); } + let mut write_hashes = self.pending_block_hashes.write(); let mut write_details = self.pending_block_details.write(); let mut write_txs = self.pending_transaction_addresses.write(); @@ -1147,13 +1111,12 @@ impl BlockChain { /// Given a block's `parent`, find every block hash which represents a valid possible uncle. pub fn find_uncle_hashes(&self, parent: &H256, uncle_generations: usize) -> Option> { - if !self.is_known(parent) { return None; } + if !self.is_known(parent) { + return None; + } let mut excluded = HashSet::new(); - let ancestry = match self.ancestry_iter(parent.clone()) { - Some(iter) => iter, - None => return None, - }; + let ancestry = self.ancestry_iter(parent.clone())?; for a in ancestry.clone().take(uncle_generations) { if let Some(uncles) = self.uncle_hashes(&a) { @@ -1186,7 +1149,7 @@ impl BlockChain { match info.location { BlockLocation::Branch => (), BlockLocation::CanonChain => { - block_hashes.insert(number, info.hash.clone()); + block_hashes.insert(number, info.hash); }, BlockLocation::BranchBecomingCanonChain(ref data) => { let ancestor_number = self.block_number(&data.ancestor).expect("Block number of ancestor is always in DB"); @@ -1196,7 +1159,7 @@ impl BlockChain { block_hashes.insert(start_number + index as BlockNumber, hash); } - block_hashes.insert(number, info.hash.clone()); + block_hashes.insert(number, info.hash); } } @@ -1212,27 +1175,27 @@ impl BlockChain { // update parent let mut parent_details = self.block_details(&parent_hash).unwrap_or_else(|| panic!("Invalid parent hash: {:?}", parent_hash)); - parent_details.children.push(info.hash.clone()); + parent_details.children.push(info.hash); // create current block details. let details = BlockDetails { number: header.number(), total_difficulty: info.total_difficulty, - parent: parent_hash.clone(), + parent: parent_hash, children: vec![], }; // write to batch let mut block_details = HashMap::new(); block_details.insert(parent_hash, parent_details); - block_details.insert(info.hash.clone(), details); + block_details.insert(info.hash, details); block_details } /// This function returns modified block receipts. fn prepare_block_receipts_update(&self, receipts: Vec, info: &BlockInfo) -> HashMap { let mut block_receipts = HashMap::new(); - block_receipts.insert(info.hash.clone(), BlockReceipts::new(receipts)); + block_receipts.insert(info.hash, BlockReceipts::new(receipts)); block_receipts } @@ -1247,7 +1210,7 @@ impl BlockChain { .enumerate() .map(|(i ,tx_hash)| { (tx_hash, Some(TransactionAddress { - block_hash: info.hash.clone(), + block_hash: info.hash, index: i })) }) @@ -1261,7 +1224,7 @@ impl BlockChain { hashes.into_iter() .enumerate() .map(|(i, tx_hash)| (tx_hash, Some(TransactionAddress { - block_hash: hash.clone(), + block_hash: *hash, index: i, }))) .collect::>>() @@ -1271,7 +1234,7 @@ impl BlockChain { .enumerate() .map(|(i ,tx_hash)| { (tx_hash, Some(TransactionAddress { - block_hash: info.hash.clone(), + block_hash: info.hash, index: i })) }); @@ -1305,7 +1268,7 @@ impl BlockChain { /// Later, BloomIndexer is used to map bloom location on filter layer (BloomIndex) /// to bloom location in database (BlocksBloomLocation). /// - fn prepare_block_blooms_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap { + fn prepare_block_blooms_update(&self, block_bytes: &[u8], info: &BlockInfo) -> HashMap { let block = BlockView::new(block_bytes); let header = block.header_view(); @@ -1317,7 +1280,7 @@ impl BlockChain { HashMap::new() } else { let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); - chain.insert(info.number as bc::Number, Bloom::from(log_bloom).into()) + chain.insert(info.number as bc::Number, log_bloom) } }, BlockLocation::BranchBecomingCanonChain(ref data) => { @@ -1325,14 +1288,12 @@ impl BlockChain { let start_number = ancestor_number + 1; let range = start_number as bc::Number..self.best_block_number() as bc::Number; - let mut blooms: Vec = data.enacted.iter() + let mut blooms: Vec = data.enacted.iter() .map(|hash| self.block_header_data(hash).unwrap()) .map(|h| h.log_bloom()) - .map(Bloom::from) - .map(Into::into) .collect(); - blooms.push(Bloom::from(header.log_bloom()).into()); + blooms.push(header.log_bloom()); let chain = bc::group::BloomGroupChain::new(self.blooms_config, self); chain.replace(&range, blooms) @@ -1346,7 +1307,7 @@ impl BlockChain { /// Get best block hash. pub fn best_block_hash(&self) -> H256 { - self.best_block.read().hash.clone() + self.best_block.read().hash } /// Get best block number. @@ -1444,43 +1405,40 @@ impl BlockChain { total_difficulty: best_block.total_difficulty.clone(), pending_total_difficulty: best_block.total_difficulty.clone(), genesis_hash: self.genesis_hash(), - best_block_hash: best_block.hash.clone(), + best_block_hash: best_block.hash, best_block_number: best_block.number, best_block_timestamp: best_block.timestamp, first_block_hash: self.first_block(), first_block_number: From::from(self.first_block_number()), - ancient_block_hash: best_ancient_block.as_ref().map(|b| b.hash.clone()), + ancient_block_hash: best_ancient_block.as_ref().map(|b| b.hash), ancient_block_number: best_ancient_block.as_ref().map(|b| b.number), } } - - #[cfg(test)] - pub fn db(&self) -> &Arc { - &self.db - } } #[cfg(test)] mod tests { - #![cfg_attr(feature="dev", allow(similar_names))] + use std::iter; use std::sync::Arc; use rustc_hex::FromHex; - use util::kvdb::KeyValueDB; - use util::hash::*; - use util::sha3::Hashable; - use receipt::Receipt; + use hash::keccak; + use kvdb::KeyValueDB; + use kvdb_memorydb; + use ethereum_types::*; + use receipt::{Receipt, TransactionOutcome}; use blockchain::{BlockProvider, BlockChain, Config, ImportRoute}; - use tests::helpers::*; - use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer}; + use tests::helpers::{ + generate_dummy_blockchain, generate_dummy_blockchain_with_extra, + generate_dummy_empty_blockchain + }; + use blockchain::generator::{BlockGenerator, BlockBuilder, BlockOptions}; use blockchain::extras::TransactionAddress; - use views::BlockView; use transaction::{Transaction, Action}; use log_entry::{LogEntry, LocalizedLogEntry}; use ethkey::Secret; - use header::BlockNumber; fn new_db() -> Arc { - Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))) + Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) } fn new_chain(genesis: &[u8], db: Arc) -> BlockChain { @@ -1490,18 +1448,16 @@ mod tests { #[test] fn should_cache_best_block() { // given - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let first = canon_chain.generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let first = genesis.add_block(); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); assert_eq!(bc.best_block_number(), 0); // when let mut batch = db.transaction(); - bc.insert_block(&mut batch, &first, vec![]); + bc.insert_block(&mut batch, &first.last().encoded(), vec![]); assert_eq!(bc.best_block_number(), 0); bc.commit(); // NOTE no db.write here (we want to check if best block is cached) @@ -1513,117 +1469,104 @@ mod tests { #[test] fn basic_blockchain_insert() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let first = canon_chain.generate(&mut finalizer).unwrap(); - let genesis_hash = BlockView::new(&genesis).header_view().sha3(); - let first_hash = BlockView::new(&first).header_view().sha3(); + let genesis = BlockBuilder::genesis(); + let first = genesis.add_block(); + + let genesis = genesis.last(); + let first = first.last(); + let genesis_hash = genesis.hash(); + let first_hash = first.hash(); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.encoded(), db.clone()); - assert_eq!(bc.genesis_hash(), genesis_hash.clone()); - assert_eq!(bc.best_block_hash(), genesis_hash.clone()); - assert_eq!(bc.block_hash(0), Some(genesis_hash.clone())); + assert_eq!(bc.genesis_hash(), genesis_hash); + assert_eq!(bc.best_block_hash(), genesis_hash); + assert_eq!(bc.block_hash(0), Some(genesis_hash)); assert_eq!(bc.block_hash(1), None); assert_eq!(bc.block_details(&genesis_hash).unwrap().children, vec![]); let mut batch = db.transaction(); - bc.insert_block(&mut batch, &first, vec![]); + bc.insert_block(&mut batch, &first.encoded(), vec![]); db.write(batch).unwrap(); bc.commit(); - assert_eq!(bc.block_hash(0), Some(genesis_hash.clone())); + assert_eq!(bc.block_hash(0), Some(genesis_hash)); assert_eq!(bc.best_block_number(), 1); - assert_eq!(bc.best_block_hash(), first_hash.clone()); - assert_eq!(bc.block_hash(1), Some(first_hash.clone())); - assert_eq!(bc.block_details(&first_hash).unwrap().parent, genesis_hash.clone()); - assert_eq!(bc.block_details(&genesis_hash).unwrap().children, vec![first_hash.clone()]); + assert_eq!(bc.best_block_hash(), first_hash); + assert_eq!(bc.block_hash(1), Some(first_hash)); + assert_eq!(bc.block_details(&first_hash).unwrap().parent, genesis_hash); + assert_eq!(bc.block_details(&genesis_hash).unwrap().children, vec![first_hash]); assert_eq!(bc.block_hash(2), None); } #[test] fn check_ancestry_iter() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let genesis_hash = BlockView::new(&genesis).header_view().sha3(); + let genesis = BlockBuilder::genesis(); + let first_10 = genesis.add_blocks(10); + let generator = BlockGenerator::new(vec![first_10]); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut block_hashes = vec![genesis_hash.clone()]; + let mut block_hashes = vec![genesis.last().hash()]; let mut batch = db.transaction(); - for _ in 0..10 { - let block = canon_chain.generate(&mut finalizer).unwrap(); - block_hashes.push(BlockView::new(&block).header_view().sha3()); - bc.insert_block(&mut batch, &block, vec![]); + for block in generator { + block_hashes.push(block.hash()); + bc.insert_block(&mut batch, &block.encoded(), vec![]); bc.commit(); } db.write(batch).unwrap(); block_hashes.reverse(); - assert_eq!(bc.ancestry_iter(block_hashes[0].clone()).unwrap().collect::>(), block_hashes) + assert_eq!(bc.ancestry_iter(block_hashes[0].clone()).unwrap().collect::>(), block_hashes); + assert_eq!(block_hashes.len(), 11); } #[test] - #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] fn test_find_uncles() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let b1b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); - let b1a = canon_chain.generate(&mut finalizer).unwrap(); - let b2b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); - let b2a = canon_chain.generate(&mut finalizer).unwrap(); - let b3b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); - let b3a = canon_chain.generate(&mut finalizer).unwrap(); - let b4b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); - let b4a = canon_chain.generate(&mut finalizer).unwrap(); - let b5b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); - let b5a = canon_chain.generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let b1a = genesis.add_block(); + let b2a = b1a.add_block(); + let b3a = b2a.add_block(); + let b4a = b3a.add_block(); + let b5a = b4a.add_block(); + + let b1b = genesis.add_block_with_difficulty(9); + let b2b = b1a.add_block_with_difficulty(9); + let b3b = b2a.add_block_with_difficulty(9); + let b4b = b3a.add_block_with_difficulty(9); + let b5b = b4a.add_block_with_difficulty(9); + + let uncle_headers = vec![b4b.last().header(), b3b.last().header(), b2b.last().header()]; + let b4a_hash = b4a.last().hash(); + + let generator = BlockGenerator::new( + vec![b1a, b1b, b2a, b2b, b3a, b3b, b4a, b4b, b5a, b5b] + ); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); - let mut batch =db.transaction(); - for b in &[&b1a, &b1b, &b2a, &b2b, &b3a, &b3b, &b4a, &b4b, &b5a, &b5b] { - bc.insert_block(&mut batch, b, vec![]); + let mut batch = db.transaction(); + for b in generator { + bc.insert_block(&mut batch, &b.encoded(), vec![]); bc.commit(); } - bc.insert_block(&mut batch, &b1b, vec![]); - bc.insert_block(&mut batch, &b2a, vec![]); - bc.insert_block(&mut batch, &b2b, vec![]); - bc.insert_block(&mut batch, &b3a, vec![]); - bc.insert_block(&mut batch, &b3b, vec![]); - bc.insert_block(&mut batch, &b4a, vec![]); - bc.insert_block(&mut batch, &b4b, vec![]); - bc.insert_block(&mut batch, &b5a, vec![]); - bc.insert_block(&mut batch, &b5b, vec![]); - db.write(batch).unwrap(); - assert_eq!( - [&b4b, &b3b, &b2b].iter().map(|b| BlockView::new(b).header()).collect::>(), - bc.find_uncle_headers(&BlockView::new(&b4a).header_view().sha3(), 3).unwrap() - ); + db.write(batch).unwrap(); + assert_eq!(uncle_headers, bc.find_uncle_headers(&b4a_hash, 3).unwrap()); // TODO: insert block that already includes one of them as an uncle to check it's not allowed. } fn secret() -> Secret { - "".sha3().into() + keccak("").into() } #[test] fn test_fork_transaction_addresses() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let mut fork_chain = canon_chain.fork(1); - let mut fork_finalizer = finalizer.fork(); - let t1 = Transaction { nonce: 0.into(), gas_price: 0.into(), @@ -1633,42 +1576,35 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), }.sign(&secret(), None); + let t1_hash = t1.hash(); - let b1a = canon_chain - .with_transaction(t1.clone()) - .generate(&mut finalizer).unwrap(); - - // Empty block - let b1b = fork_chain - .generate(&mut fork_finalizer).unwrap(); - - let b2 = fork_chain - .generate(&mut fork_finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let b1a = genesis.add_block_with_transactions(iter::once(t1)); + let b1b = genesis.add_block_with_difficulty(9); + let b2 = b1b.add_block(); - let b1a_hash = BlockView::new(&b1a).header_view().sha3(); - let b2_hash = BlockView::new(&b2).header_view().sha3(); - - let t1_hash = t1.hash(); + let b1a_hash = b1a.last().hash(); + let b2_hash = b2.last().hash(); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b1a, vec![]); + let _ = bc.insert_block(&mut batch, &b1a.last().encoded(), vec![]); bc.commit(); - let _ = bc.insert_block(&mut batch, &b1b, vec![]); + let _ = bc.insert_block(&mut batch, &b1b.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b1a_hash); assert_eq!(bc.transaction_address(&t1_hash), Some(TransactionAddress { - block_hash: b1a_hash.clone(), + block_hash: b1a_hash, index: 0, })); // now let's make forked chain the canon chain let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b2, vec![]); + let _ = bc.insert_block(&mut batch, &b2.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1677,16 +1613,8 @@ mod tests { assert_eq!(bc.transaction_address(&t1_hash), None); } - - #[test] fn test_overwriting_transaction_addresses() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let mut fork_chain = canon_chain.fork(1); - let mut fork_finalizer = finalizer.fork(); - let t1 = Transaction { nonce: 0.into(), gas_price: 0.into(), @@ -1714,104 +1642,97 @@ mod tests { data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(), }.sign(&secret(), None); - let b1a = canon_chain - .with_transaction(t1.clone()) - .with_transaction(t2.clone()) - .generate(&mut finalizer).unwrap(); - - // insert transactions in different order - let b1b = fork_chain - .with_transaction(t2.clone()) - .with_transaction(t1.clone()) - .generate(&mut fork_finalizer).unwrap(); - - let b2 = fork_chain - .with_transaction(t3.clone()) - .generate(&mut fork_finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let b1a = genesis.add_block_with_transactions(vec![t1.clone(), t2.clone()]); + // insert transactions in different order, + // the block has lower difficulty, so the hash is also different + let b1b = genesis.add_block_with(|| BlockOptions { + difficulty: 9.into(), + transactions: vec![t2.clone(), t1.clone()], + ..Default::default() + }); + let b2 = b1b.add_block_with_transactions(iter::once(t3.clone())); - let b1a_hash = BlockView::new(&b1a).header_view().sha3(); - let b1b_hash = BlockView::new(&b1b).header_view().sha3(); - let b2_hash = BlockView::new(&b2).header_view().sha3(); + let b1a_hash = b1a.last().hash(); + let b1b_hash = b1b.last().hash(); + let b2_hash = b2.last().hash(); let t1_hash = t1.hash(); let t2_hash = t2.hash(); let t3_hash = t3.hash(); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b1a, vec![]); + let _ = bc.insert_block(&mut batch, &b1a.last().encoded(), vec![]); bc.commit(); - let _ = bc.insert_block(&mut batch, &b1b, vec![]); + let _ = bc.insert_block(&mut batch, &b1b.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b1a_hash); assert_eq!(bc.transaction_address(&t1_hash), Some(TransactionAddress { - block_hash: b1a_hash.clone(), + block_hash: b1a_hash, index: 0, })); assert_eq!(bc.transaction_address(&t2_hash), Some(TransactionAddress { - block_hash: b1a_hash.clone(), + block_hash: b1a_hash, index: 1, })); // now let's make forked chain the canon chain let mut batch = db.transaction(); - let _ = bc.insert_block(&mut batch, &b2, vec![]); + let _ = bc.insert_block(&mut batch, &b2.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); assert_eq!(bc.best_block_hash(), b2_hash); assert_eq!(bc.transaction_address(&t1_hash), Some(TransactionAddress { - block_hash: b1b_hash.clone(), + block_hash: b1b_hash, index: 1, })); assert_eq!(bc.transaction_address(&t2_hash), Some(TransactionAddress { - block_hash: b1b_hash.clone(), + block_hash: b1b_hash, index: 0, })); assert_eq!(bc.transaction_address(&t3_hash), Some(TransactionAddress { - block_hash: b2_hash.clone(), + block_hash: b2_hash, index: 0, })); } #[test] - #[cfg_attr(feature="dev", allow(cyclomatic_complexity))] fn test_small_fork() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let b1 = canon_chain.generate(&mut finalizer).unwrap(); - let b2 = canon_chain.generate(&mut finalizer).unwrap(); - let b3b = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); - let b3a = canon_chain.generate(&mut finalizer).unwrap(); - - let genesis_hash = BlockView::new(&genesis).header_view().sha3(); - let b1_hash= BlockView::new(&b1).header_view().sha3(); - let b2_hash= BlockView::new(&b2).header_view().sha3(); - let b3a_hash= BlockView::new(&b3a).header_view().sha3(); - let b3b_hash= BlockView::new(&b3b).header_view().sha3(); + let genesis = BlockBuilder::genesis(); + let b1 = genesis.add_block(); + let b2 = b1.add_block(); + let b3a = b2.add_block(); + let b3b = b2.add_block_with_difficulty(9); + + let genesis_hash = genesis.last().hash(); + let b1_hash = b1.last().hash(); + let b2_hash = b2.last().hash(); + let b3a_hash = b3a.last().hash(); + let b3b_hash = b3b.last().hash(); // b3a is a part of canon chain, whereas b3b is part of sidechain - let best_block_hash = b3a_hash.clone(); + let best_block_hash = b3a_hash; let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); - let ir1 = bc.insert_block(&mut batch, &b1, vec![]); + let ir1 = bc.insert_block(&mut batch, &b1.last().encoded(), vec![]); bc.commit(); - let ir2 = bc.insert_block(&mut batch, &b2, vec![]); + let ir2 = bc.insert_block(&mut batch, &b2.last().encoded(), vec![]); bc.commit(); - let ir3b = bc.insert_block(&mut batch, &b3b, vec![]); + let ir3b = bc.insert_block(&mut batch, &b3b.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); assert_eq!(bc.block_hash(3).unwrap(), b3b_hash); - let mut batch =db.transaction(); - let ir3a = bc.insert_block(&mut batch, &b3a, vec![]); + let mut batch = db.transaction(); + let ir3a = bc.insert_block(&mut batch, &b3a.last().encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); @@ -1852,79 +1773,78 @@ mod tests { assert_eq!(bc.block_hash(3).unwrap(), b3a_hash); // test trie route - let r0_1 = bc.tree_route(genesis_hash.clone(), b1_hash.clone()).unwrap(); + let r0_1 = bc.tree_route(genesis_hash, b1_hash).unwrap(); assert_eq!(r0_1.ancestor, genesis_hash); - assert_eq!(r0_1.blocks, [b1_hash.clone()]); + assert_eq!(r0_1.blocks, [b1_hash]); assert_eq!(r0_1.index, 0); - let r0_2 = bc.tree_route(genesis_hash.clone(), b2_hash.clone()).unwrap(); + let r0_2 = bc.tree_route(genesis_hash, b2_hash).unwrap(); assert_eq!(r0_2.ancestor, genesis_hash); - assert_eq!(r0_2.blocks, [b1_hash.clone(), b2_hash.clone()]); + assert_eq!(r0_2.blocks, [b1_hash, b2_hash]); assert_eq!(r0_2.index, 0); - let r1_3a = bc.tree_route(b1_hash.clone(), b3a_hash.clone()).unwrap(); + let r1_3a = bc.tree_route(b1_hash, b3a_hash).unwrap(); assert_eq!(r1_3a.ancestor, b1_hash); - assert_eq!(r1_3a.blocks, [b2_hash.clone(), b3a_hash.clone()]); + assert_eq!(r1_3a.blocks, [b2_hash, b3a_hash]); assert_eq!(r1_3a.index, 0); - let r1_3b = bc.tree_route(b1_hash.clone(), b3b_hash.clone()).unwrap(); + let r1_3b = bc.tree_route(b1_hash, b3b_hash).unwrap(); assert_eq!(r1_3b.ancestor, b1_hash); - assert_eq!(r1_3b.blocks, [b2_hash.clone(), b3b_hash.clone()]); + assert_eq!(r1_3b.blocks, [b2_hash, b3b_hash]); assert_eq!(r1_3b.index, 0); - let r3a_3b = bc.tree_route(b3a_hash.clone(), b3b_hash.clone()).unwrap(); + let r3a_3b = bc.tree_route(b3a_hash, b3b_hash).unwrap(); assert_eq!(r3a_3b.ancestor, b2_hash); - assert_eq!(r3a_3b.blocks, [b3a_hash.clone(), b3b_hash.clone()]); + assert_eq!(r3a_3b.blocks, [b3a_hash, b3b_hash]); assert_eq!(r3a_3b.index, 1); - let r1_0 = bc.tree_route(b1_hash.clone(), genesis_hash.clone()).unwrap(); + let r1_0 = bc.tree_route(b1_hash, genesis_hash).unwrap(); assert_eq!(r1_0.ancestor, genesis_hash); - assert_eq!(r1_0.blocks, [b1_hash.clone()]); + assert_eq!(r1_0.blocks, [b1_hash]); assert_eq!(r1_0.index, 1); - let r2_0 = bc.tree_route(b2_hash.clone(), genesis_hash.clone()).unwrap(); + let r2_0 = bc.tree_route(b2_hash, genesis_hash).unwrap(); assert_eq!(r2_0.ancestor, genesis_hash); - assert_eq!(r2_0.blocks, [b2_hash.clone(), b1_hash.clone()]); + assert_eq!(r2_0.blocks, [b2_hash, b1_hash]); assert_eq!(r2_0.index, 2); - let r3a_1 = bc.tree_route(b3a_hash.clone(), b1_hash.clone()).unwrap(); + let r3a_1 = bc.tree_route(b3a_hash, b1_hash).unwrap(); assert_eq!(r3a_1.ancestor, b1_hash); - assert_eq!(r3a_1.blocks, [b3a_hash.clone(), b2_hash.clone()]); + assert_eq!(r3a_1.blocks, [b3a_hash, b2_hash]); assert_eq!(r3a_1.index, 2); - let r3b_1 = bc.tree_route(b3b_hash.clone(), b1_hash.clone()).unwrap(); + let r3b_1 = bc.tree_route(b3b_hash, b1_hash).unwrap(); assert_eq!(r3b_1.ancestor, b1_hash); - assert_eq!(r3b_1.blocks, [b3b_hash.clone(), b2_hash.clone()]); + assert_eq!(r3b_1.blocks, [b3b_hash, b2_hash]); assert_eq!(r3b_1.index, 2); - let r3b_3a = bc.tree_route(b3b_hash.clone(), b3a_hash.clone()).unwrap(); + let r3b_3a = bc.tree_route(b3b_hash, b3a_hash).unwrap(); assert_eq!(r3b_3a.ancestor, b2_hash); - assert_eq!(r3b_3a.blocks, [b3b_hash.clone(), b3a_hash.clone()]); + assert_eq!(r3b_3a.blocks, [b3b_hash, b3a_hash]); assert_eq!(r3b_3a.index, 1); } #[test] fn test_reopen_blockchain_db() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let first = canon_chain.generate(&mut finalizer).unwrap(); - let genesis_hash = BlockView::new(&genesis).header_view().sha3(); - let first_hash = BlockView::new(&first).header_view().sha3(); + let genesis = BlockBuilder::genesis(); + let first = genesis.add_block(); + let genesis_hash = genesis.last().hash(); + let first_hash = first.last().hash(); + let db = new_db(); { - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); assert_eq!(bc.best_block_hash(), genesis_hash); - let mut batch =db.transaction(); - bc.insert_block(&mut batch, &first, vec![]); + let mut batch = db.transaction(); + bc.insert_block(&mut batch, &first.last().encoded(), vec![]); db.write(batch).unwrap(); bc.commit(); assert_eq!(bc.best_block_hash(), first_hash); } { - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); assert_eq!(bc.best_block_hash(), first_hash); } @@ -1997,11 +1917,6 @@ mod tests { #[test] fn test_logs() { - // given - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - // just insert dummy transaction so that #transactions=#receipts let t1 = Transaction { nonce: 0.into(), gas_price: 0.into(), @@ -2029,13 +1944,19 @@ mod tests { let tx_hash1 = t1.hash(); let tx_hash2 = t2.hash(); let tx_hash3 = t3.hash(); - let b1 = canon_chain.with_transaction(t1).with_transaction(t2).generate(&mut finalizer).unwrap(); - let b2 = canon_chain.with_transaction(t3).generate(&mut finalizer).unwrap(); + + let genesis = BlockBuilder::genesis(); + let b1 = genesis.add_block_with_transactions(vec![t1, t2]); + let b2 = b1.add_block_with_transactions(iter::once(t3)); + let b1_hash = b1.last().hash(); + let b1_number = b1.last().number(); + let b2_hash = b2.last().hash(); + let b2_number = b2.last().number(); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); - insert_block(&db, &bc, &b1, vec![Receipt { - state_root: Some(H256::default()), + let bc = new_chain(&genesis.last().encoded(), db.clone()); + insert_block(&db, &bc, &b1.last().encoded(), vec![Receipt { + outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), logs: vec![ @@ -2044,16 +1965,16 @@ mod tests { ], }, Receipt { - state_root: Some(H256::default()), + outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), logs: vec![ LogEntry { address: Default::default(), topics: vec![], data: vec![3], }, ], }]); - insert_block(&db, &bc, &b2, vec![ + insert_block(&db, &bc, &b2.last().encoded(), vec![ Receipt { - state_root: Some(H256::default()), + outcome: TransactionOutcome::StateRoot(H256::default()), gas_used: 10_000.into(), log_bloom: Default::default(), logs: vec![ @@ -2063,8 +1984,6 @@ mod tests { ]); // when - let block1 = BlockView::new(&b1); - let block2 = BlockView::new(&b2); let logs1 = bc.logs(vec![1, 2], |_| true, None); let logs2 = bc.logs(vec![1, 2], |_| true, Some(1)); @@ -2072,36 +1991,36 @@ mod tests { assert_eq!(logs1, vec![ LocalizedLogEntry { entry: LogEntry { address: Default::default(), topics: vec![], data: vec![1] }, - block_hash: block1.hash(), - block_number: block1.header().number(), - transaction_hash: tx_hash1.clone(), + block_hash: b1_hash, + block_number: b1_number, + transaction_hash: tx_hash1, transaction_index: 0, transaction_log_index: 0, log_index: 0, }, LocalizedLogEntry { entry: LogEntry { address: Default::default(), topics: vec![], data: vec![2] }, - block_hash: block1.hash(), - block_number: block1.header().number(), - transaction_hash: tx_hash1.clone(), + block_hash: b1_hash, + block_number: b1_number, + transaction_hash: tx_hash1, transaction_index: 0, transaction_log_index: 1, log_index: 1, }, LocalizedLogEntry { entry: LogEntry { address: Default::default(), topics: vec![], data: vec![3] }, - block_hash: block1.hash(), - block_number: block1.header().number(), - transaction_hash: tx_hash2.clone(), + block_hash: b1_hash, + block_number: b1_number, + transaction_hash: tx_hash2, transaction_index: 1, transaction_log_index: 0, log_index: 2, }, LocalizedLogEntry { entry: LogEntry { address: Default::default(), topics: vec![], data: vec![4] }, - block_hash: block2.hash(), - block_number: block2.header().number(), - transaction_hash: tx_hash3.clone(), + block_hash: b2_hash, + block_number: b2_number, + transaction_hash: tx_hash3, transaction_index: 0, transaction_log_index: 0, log_index: 0, @@ -2110,9 +2029,9 @@ mod tests { assert_eq!(logs2, vec![ LocalizedLogEntry { entry: LogEntry { address: Default::default(), topics: vec![], data: vec![4] }, - block_hash: block2.hash(), - block_number: block2.header().number(), - transaction_hash: tx_hash3.clone(), + block_hash: b2_hash, + block_number: b2_number, + transaction_hash: tx_hash3, transaction_index: 0, transaction_log_index: 0, log_index: 0, @@ -2122,64 +2041,64 @@ mod tests { #[test] fn test_bloom_filter_simple() { - // TODO: From here - let bloom_b1: H2048 = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into(); + let bloom_b1: Bloom = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into(); - let bloom_b2: H2048 = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let bloom_b2: Bloom = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); - let bloom_ba: H2048 = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + let bloom_ba: Bloom = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let mut fork = canon_chain.fork(1); - let mut fork_finalizer = finalizer.fork(); - let b1 = fork.with_bloom(bloom_b1.clone()).generate(&mut fork_finalizer).unwrap(); - let b2 = fork.with_bloom(bloom_b2.clone()).generate(&mut fork_finalizer).unwrap(); - let b3 = fork.with_bloom(bloom_ba.clone()).generate(&mut fork_finalizer).unwrap(); - let b1a = canon_chain.with_bloom(bloom_ba.clone()).generate(&mut finalizer).unwrap(); - let b2a = canon_chain.with_bloom(bloom_ba.clone()).generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let b1 = genesis.add_block_with(|| BlockOptions { + bloom: bloom_b1.clone(), + difficulty: 9.into(), + ..Default::default() + }); + let b2 = b1.add_block_with_bloom(bloom_b2); + let b3 = b2.add_block_with_bloom(bloom_ba); + + let b1a = genesis.add_block_with_bloom(bloom_ba); + let b2a = b1a.add_block_with_bloom(bloom_ba); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); - assert_eq!(blocks_b1, Vec::::new()); - assert_eq!(blocks_b2, Vec::::new()); + assert!(blocks_b1.is_empty()); + assert!(blocks_b2.is_empty()); - insert_block(&db, &bc, &b1, vec![]); + insert_block(&db, &bc, &b1.last().encoded(), vec![]); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); assert_eq!(blocks_b1, vec![1]); - assert_eq!(blocks_b2, Vec::::new()); + assert!(blocks_b2.is_empty()); - insert_block(&db, &bc, &b2, vec![]); + insert_block(&db, &bc, &b2.last().encoded(), vec![]); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b2, vec![2]); // hasn't been forked yet - insert_block(&db, &bc, &b1a, vec![]); + insert_block(&db, &bc, &b1a.last().encoded(), vec![]); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5); assert_eq!(blocks_b1, vec![1]); assert_eq!(blocks_b2, vec![2]); - assert_eq!(blocks_ba, Vec::::new()); + assert!(blocks_ba.is_empty()); // fork has happend - insert_block(&db, &bc, &b2a, vec![]); + insert_block(&db, &bc, &b2a.last().encoded(), vec![]); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5); - assert_eq!(blocks_b1, Vec::::new()); - assert_eq!(blocks_b2, Vec::::new()); + assert!(blocks_b1.is_empty()); + assert!(blocks_b2.is_empty()); assert_eq!(blocks_ba, vec![1, 2]); // fork back - insert_block(&db, &bc, &b3, vec![]); + insert_block(&db, &bc, &b3.last().encoded(), vec![]); let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 5); let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 5); let blocks_ba = bc.blocks_with_bloom(&bloom_ba, 0, 5); @@ -2188,89 +2107,95 @@ mod tests { assert_eq!(blocks_ba, vec![3]); } + #[test] + fn test_insert_unordered() { + let bloom_b1: Bloom = "00000020000000000000000000000000000000000000000002000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000400000000000000000000002000".into(); + + let bloom_b2: Bloom = "00000000000000000000000000000000000000000000020000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + + let bloom_b3: Bloom = "00000000000000000000000000000000000000000000020000000800000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000008000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(); + + let genesis = BlockBuilder::genesis(); + let b1 = genesis.add_block_with_bloom(bloom_b1); + let b2 = b1.add_block_with_bloom(bloom_b2); + let b3 = b2.add_block_with_bloom(bloom_b3); + let b1_total_difficulty = genesis.last().difficulty() + b1.last().difficulty(); + + let db = new_db(); + let bc = new_chain(&genesis.last().encoded(), db.clone()); + let mut batch = db.transaction(); + bc.insert_unordered_block(&mut batch, &b2.last().encoded(), vec![], Some(b1_total_difficulty), false, false); + bc.commit(); + bc.insert_unordered_block(&mut batch, &b3.last().encoded(), vec![], None, true, false); + bc.commit(); + bc.insert_unordered_block(&mut batch, &b1.last().encoded(), vec![], None, false, false); + bc.commit(); + db.write(batch).unwrap(); + + assert_eq!(bc.best_block_hash(), b3.last().hash()); + assert_eq!(bc.block_hash(1).unwrap(), b1.last().hash()); + assert_eq!(bc.block_hash(2).unwrap(), b2.last().hash()); + assert_eq!(bc.block_hash(3).unwrap(), b3.last().hash()); + + let blocks_b1 = bc.blocks_with_bloom(&bloom_b1, 0, 3); + let blocks_b2 = bc.blocks_with_bloom(&bloom_b2, 0, 3); + let blocks_b3 = bc.blocks_with_bloom(&bloom_b3, 0, 3); + + assert_eq!(blocks_b1, vec![1]); + assert_eq!(blocks_b2, vec![2]); + assert_eq!(blocks_b3, vec![3]); + } + #[test] fn test_best_block_update() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let next_5 = genesis.add_blocks(5); + let uncle = genesis.add_block_with_difficulty(9); + let generator = BlockGenerator::new(iter::once(next_5)); let db = new_db(); { - let bc = new_chain(&genesis, db.clone()); - let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); // create a longer fork - for _ in 0..5 { - let canon_block = canon_chain.generate(&mut finalizer).unwrap(); - bc.insert_block(&mut batch, &canon_block, vec![]); + for block in generator { + bc.insert_block(&mut batch, &block.encoded(), vec![]); bc.commit(); } assert_eq!(bc.best_block_number(), 5); - bc.insert_block(&mut batch, &uncle, vec![]); + bc.insert_block(&mut batch, &uncle.last().encoded(), vec![]); db.write(batch).unwrap(); bc.commit(); } // re-loading the blockchain should load the correct best block. - let bc = new_chain(&genesis, db); + let bc = new_chain(&genesis.last().encoded(), db); assert_eq!(bc.best_block_number(), 5); } - #[test] - fn test_rewind() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); - let first = canon_chain.generate(&mut finalizer).unwrap(); - let second = canon_chain.generate(&mut finalizer).unwrap(); - let genesis_hash = BlockView::new(&genesis).header_view().sha3(); - let first_hash = BlockView::new(&first).header_view().sha3(); - let second_hash = BlockView::new(&second).header_view().sha3(); - - let db = new_db(); - let bc = new_chain(&genesis, db.clone()); - - let mut batch =db.transaction(); - bc.insert_block(&mut batch, &first, vec![]); - bc.commit(); - bc.insert_block(&mut batch, &second, vec![]); - bc.commit(); - db.write(batch).unwrap(); - - assert_eq!(bc.rewind(), Some(first_hash.clone())); - assert!(!bc.is_known(&second_hash)); - assert_eq!(bc.best_block_number(), 1); - assert_eq!(bc.best_block_hash(), first_hash.clone()); - - assert_eq!(bc.rewind(), Some(genesis_hash.clone())); - assert_eq!(bc.rewind(), None); - } - #[test] fn epoch_transitions_iter() { use ::engines::EpochTransition; - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let next_5 = genesis.add_blocks(5); + let uncle = genesis.add_block_with_difficulty(9); + let generator = BlockGenerator::new(iter::once(next_5)); let db = new_db(); { - let bc = new_chain(&genesis, db.clone()); - let uncle = canon_chain.fork(1).generate(&mut finalizer.fork()).unwrap(); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); // create a longer fork - for i in 0..5 { - let canon_block = canon_chain.generate(&mut finalizer).unwrap(); - let hash = BlockView::new(&canon_block).header_view().sha3(); - - bc.insert_block(&mut batch, &canon_block, vec![]); - bc.insert_epoch_transition(&mut batch, i, EpochTransition { - block_hash: hash, - block_number: i + 1, + for (i, block) in generator.into_iter().enumerate() { + + bc.insert_block(&mut batch, &block.encoded(), vec![]); + bc.insert_epoch_transition(&mut batch, i as u64, EpochTransition { + block_hash: block.hash(), + block_number: i as u64 + 1, proof: vec![], }); bc.commit(); @@ -2278,10 +2203,9 @@ mod tests { assert_eq!(bc.best_block_number(), 5); - let hash = BlockView::new(&uncle).header_view().sha3(); - bc.insert_block(&mut batch, &uncle, vec![]); + bc.insert_block(&mut batch, &uncle.last().encoded(), vec![]); bc.insert_epoch_transition(&mut batch, 999, EpochTransition { - block_hash: hash, + block_hash: uncle.last().hash(), block_number: 1, proof: vec![], }); @@ -2294,7 +2218,7 @@ mod tests { } // re-loading the blockchain should load the correct best block. - let bc = new_chain(&genesis, db); + let bc = new_chain(&genesis.last().encoded(), db); assert_eq!(bc.best_block_number(), 5); assert_eq!(bc.epoch_transitions().map(|(i, _)| i).collect::>(), vec![0, 1, 2, 3, 4]); @@ -2304,13 +2228,18 @@ mod tests { fn epoch_transition_for() { use ::engines::EpochTransition; - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let fork_7 = genesis.add_blocks_with(7, || BlockOptions { + difficulty: 9.into(), + ..Default::default() + }); + let next_10 = genesis.add_blocks(10); + let fork_generator = BlockGenerator::new(iter::once(fork_7)); + let next_generator = BlockGenerator::new(iter::once(next_10)); let db = new_db(); - let bc = new_chain(&genesis, db.clone()); + let bc = new_chain(&genesis.last().encoded(), db.clone()); let mut batch = db.transaction(); bc.insert_epoch_transition(&mut batch, 0, EpochTransition { @@ -2323,14 +2252,10 @@ mod tests { // set up a chain where we have a canonical chain of 10 blocks // and a non-canonical fork of 8 from genesis. let fork_hash = { - let mut fork_chain = canon_chain.fork(1); - let mut fork_finalizer = finalizer.fork(); - - for _ in 0..7 { + for block in fork_generator { let mut batch = db.transaction(); - let fork_block = fork_chain.generate(&mut fork_finalizer).unwrap(); - bc.insert_block(&mut batch, &fork_block, vec![]); + bc.insert_block(&mut batch, &block.encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); } @@ -2339,11 +2264,9 @@ mod tests { bc.chain_info().best_block_hash }; - for _ in 0..10 { + for block in next_generator { let mut batch = db.transaction(); - let canon_block = canon_chain.generate(&mut finalizer).unwrap(); - - bc.insert_block(&mut batch, &canon_block, vec![]); + bc.insert_block(&mut batch, &block.encoded(), vec![]); bc.commit(); db.write(batch).unwrap(); diff --git a/ethcore/src/blockchain/config.rs b/ethcore/src/blockchain/config.rs index 4be606b33fa664a88c4aa8b3eefe7cf0eb78c019..312289b060abdaf5b5ee738cd3a489b43283269a 100644 --- a/ethcore/src/blockchain/config.rs +++ b/ethcore/src/blockchain/config.rs @@ -23,8 +23,6 @@ pub struct Config { pub pref_cache_size: usize, /// Maximum cache size in bytes. pub max_cache_size: usize, - /// Backing db cache_size - pub db_cache_size: Option, } impl Default for Config { @@ -32,8 +30,6 @@ impl Default for Config { Config { pref_cache_size: 1 << 14, max_cache_size: 1 << 20, - db_cache_size: None, } } } - diff --git a/ethcore/src/blockchain/extras.rs b/ethcore/src/blockchain/extras.rs index 0e2396f8c699a469b7a68216a07ad91d05da8722..97583a693a6c9a72661ea00542577d30fbef1f6f 100644 --- a/ethcore/src/blockchain/extras.rs +++ b/ethcore/src/blockchain/extras.rs @@ -18,15 +18,15 @@ use std::ops; use std::io::Write; -use bloomchain; use blooms::{GroupPosition, BloomGroup}; use db::Key; use engines::epoch::{Transition as EpochTransition}; use header::BlockNumber; use receipt::Receipt; -use util::{HeapSizeOf, H256, H264, U256}; -use util::kvdb::PREFIX_LEN as DB_PREFIX_LEN; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, H264, U256}; +use kvdb::PREFIX_LEN as DB_PREFIX_LEN; /// Represents index of extra data in database #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] @@ -96,32 +96,17 @@ impl ops::Deref for LogGroupKey { } } -#[derive(Debug, PartialEq, Eq, Hash, Clone)] -pub struct LogGroupPosition(GroupPosition); - -impl From for LogGroupPosition { - fn from(position: bloomchain::group::GroupPosition) -> Self { - LogGroupPosition(From::from(position)) - } -} - -impl HeapSizeOf for LogGroupPosition { - fn heap_size_of_children(&self) -> usize { - self.0.heap_size_of_children() - } -} - -impl Key for LogGroupPosition { +impl Key for GroupPosition { type Target = LogGroupKey; fn key(&self) -> Self::Target { let mut result = [0u8; 6]; result[0] = ExtrasIndex::BlocksBlooms as u8; - result[1] = self.0.level; - result[2] = (self.0.index >> 24) as u8; - result[3] = (self.0.index >> 16) as u8; - result[4] = (self.0.index >> 8) as u8; - result[5] = self.0.index as u8; + result[1] = self.level; + result[2] = (self.index >> 24) as u8; + result[3] = (self.index >> 16) as u8; + result[4] = (self.index >> 8) as u8; + result[5] = self.index as u8; LogGroupKey(result) } } diff --git a/ethcore/src/blockchain/generator.rs b/ethcore/src/blockchain/generator.rs new file mode 100644 index 0000000000000000000000000000000000000000..5f990a4d98050d83d618f6bcdf96f584c0c446b7 --- /dev/null +++ b/ethcore/src/blockchain/generator.rs @@ -0,0 +1,223 @@ +// 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 . + +//! Blockchain generator for tests. + +use std::collections::VecDeque; +use ethereum_types::{U256, H256, Bloom}; + +use bytes::Bytes; +use header::Header; +use rlp::encode; +use transaction::SignedTransaction; +use views::BlockView; + +/// Helper structure, used for encoding blocks. +#[derive(Default, Clone, RlpEncodable)] +pub struct Block { + pub header: Header, + pub transactions: Vec, + pub uncles: Vec
+} + +impl Block { + #[inline] + pub fn header(&self) -> Header { + self.header.clone() + } + + #[inline] + pub fn hash(&self) -> H256 { + BlockView::new(&self.encoded()).header_view().hash() + } + + #[inline] + pub fn number(&self) -> u64 { + self.header.number() + } + + #[inline] + pub fn encoded(&self) -> Bytes { + encode(self).into_vec() + } + + #[inline] + pub fn difficulty(&self) -> U256 { + *self.header.difficulty() + } +} + +#[derive(Debug)] +pub struct BlockOptions { + pub difficulty: U256, + pub bloom: Bloom, + pub transactions: Vec, +} + +impl Default for BlockOptions { + fn default() -> Self { + BlockOptions { + difficulty: 10.into(), + bloom: Bloom::default(), + transactions: Vec::new(), + } + } +} + +#[derive(Clone)] +pub struct BlockBuilder { + blocks: VecDeque, +} + +impl BlockBuilder { + pub fn genesis() -> Self { + let mut blocks = VecDeque::with_capacity(1); + blocks.push_back(Block::default()); + + BlockBuilder { + blocks, + } + } + + #[inline] + pub fn add_block(&self) -> Self { + self.add_block_with(|| BlockOptions::default()) + } + + #[inline] + pub fn add_blocks(&self, count: usize) -> Self { + self.add_blocks_with(count, || BlockOptions::default()) + } + + #[inline] + pub fn add_block_with(&self, get_metadata: T) -> Self where T: Fn() -> BlockOptions { + self.add_blocks_with(1, get_metadata) + } + + #[inline] + pub fn add_block_with_difficulty(&self, difficulty: T) -> Self where T: Into { + let difficulty = difficulty.into(); + self.add_blocks_with(1, move || BlockOptions { + difficulty, + ..Default::default() + }) + } + + #[inline] + pub fn add_block_with_transactions(&self, transactions: T) -> Self + where T: IntoIterator { + let transactions = transactions.into_iter().collect::>(); + self.add_blocks_with(1, || BlockOptions { + transactions: transactions.clone(), + ..Default::default() + }) + } + + #[inline] + pub fn add_block_with_bloom(&self, bloom: Bloom) -> Self { + self.add_blocks_with(1, move || BlockOptions { + bloom, + ..Default::default() + }) + } + + pub fn add_blocks_with(&self, count: usize, get_metadata: T) -> Self where T: Fn() -> BlockOptions { + assert!(count > 0, "There must be at least 1 block"); + let mut parent_hash = self.last().hash(); + let mut parent_number = self.last().number(); + let mut blocks = VecDeque::with_capacity(count); + for _ in 0..count { + let mut block = Block::default(); + let metadata = get_metadata(); + let block_number = parent_number + 1; + block.header.set_parent_hash(parent_hash); + block.header.set_number(block_number); + block.header.set_log_bloom(metadata.bloom); + block.header.set_difficulty(metadata.difficulty); + block.transactions = metadata.transactions; + + parent_hash = block.hash(); + parent_number = block_number; + + blocks.push_back(block); + } + + BlockBuilder { + blocks, + } + } + + #[inline] + pub fn last(&self) -> &Block { + self.blocks.back().expect("There is always at least 1 block") + } +} + +#[derive(Clone)] +pub struct BlockGenerator { + builders: VecDeque, +} + +impl BlockGenerator { + pub fn new(builders: T) -> Self where T: IntoIterator { + BlockGenerator { + builders: builders.into_iter().collect(), + } + } +} + +impl Iterator for BlockGenerator { + type Item = Block; + + fn next(&mut self) -> Option { + loop { + match self.builders.front_mut() { + Some(ref mut builder) => { + if let Some(block) = builder.blocks.pop_front() { + return Some(block); + } + }, + None => return None, + } + self.builders.pop_front(); + } + + } +} + +#[cfg(test)] +mod tests { + use super::{BlockBuilder, BlockOptions, BlockGenerator}; + + #[test] + fn test_block_builder() { + let genesis = BlockBuilder::genesis(); + let block_1 = genesis.add_block(); + let block_1001 = block_1.add_blocks(1000); + let block_1002 = block_1001.add_block_with(|| BlockOptions::default()); + let generator = BlockGenerator::new(vec![genesis, block_1, block_1001, block_1002]); + assert_eq!(generator.count(), 1003); + } + + #[test] + fn test_block_builder_fork() { + let genesis = BlockBuilder::genesis(); + let block_10a = genesis.add_blocks(10); + let block_11b = genesis.add_blocks(11); + assert_eq!(block_10a.last().number(), 10); + assert_eq!(block_11b.last().number(), 11); + } +} diff --git a/ethcore/src/blockchain/generator/block.rs b/ethcore/src/blockchain/generator/block.rs deleted file mode 100644 index 05fd1503128e143543825fd17b00a9fd900ccd86..0000000000000000000000000000000000000000 --- a/ethcore/src/blockchain/generator/block.rs +++ /dev/null @@ -1,72 +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 . - -use rlp::*; -use util::{H256, H2048}; -use util::bytes::Bytes; -use header::Header; -use transaction::SignedTransaction; - -use super::fork::Forkable; -use super::bloom::WithBloom; -use super::complete::CompleteBlock; -use super::transaction::WithTransaction; - -/// Helper structure, used for encoding blocks. -#[derive(Default)] -pub struct Block { - pub header: Header, - pub transactions: Vec, - pub uncles: Vec
-} - -impl Encodable for Block { - fn rlp_append(&self, s: &mut RlpStream) { - s.begin_list(3); - s.append(&self.header); - s.append_list(&self.transactions); - s.append_list(&self.uncles); - } -} - -impl Forkable for Block { - fn fork(mut self, fork_number: usize) -> Self where Self: Sized { - let difficulty = self.header.difficulty().clone() - fork_number.into(); - self.header.set_difficulty(difficulty); - self - } -} - -impl WithBloom for Block { - fn with_bloom(mut self, bloom: H2048) -> Self where Self: Sized { - self.header.set_log_bloom(bloom); - self - } -} - -impl WithTransaction for Block { - fn with_transaction(mut self, transaction: SignedTransaction) -> Self where Self: Sized { - self.transactions.push(transaction); - self - } -} - -impl CompleteBlock for Block { - fn complete(mut self, parent_hash: H256) -> Bytes { - self.header.set_parent_hash(parent_hash); - encode(&self).into_vec() - } -} diff --git a/ethcore/src/blockchain/generator/bloom.rs b/ethcore/src/blockchain/generator/bloom.rs deleted file mode 100644 index 5f39a49b847175c79ff0a33ff9fd24e92b45b74f..0000000000000000000000000000000000000000 --- a/ethcore/src/blockchain/generator/bloom.rs +++ /dev/null @@ -1,35 +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 . - -use util::hash::H2048; - -pub trait WithBloom { - fn with_bloom(self, bloom: H2048) -> Self where Self: Sized; -} - -pub struct Bloom<'a, I> where I: 'a { - pub iter: &'a mut I, - pub bloom: H2048, -} - -impl<'a, I> Iterator for Bloom<'a, I> where I: Iterator, ::Item: WithBloom { - type Item = ::Item; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|item| item.with_bloom(self.bloom.clone())) - } -} diff --git a/ethcore/src/blockchain/generator/complete.rs b/ethcore/src/blockchain/generator/complete.rs deleted file mode 100644 index 0c22d4dfc971d4218d929d457bc3dc047635342c..0000000000000000000000000000000000000000 --- a/ethcore/src/blockchain/generator/complete.rs +++ /dev/null @@ -1,53 +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 . - -use util::hash::H256; -use util::bytes::Bytes; -use util::sha3::Hashable; -use views::BlockView; - -#[derive(Default, Clone)] -pub struct BlockFinalizer { - parent_hash: H256 -} - -impl BlockFinalizer { - pub fn fork(&self) -> Self { - self.clone() - } -} - -pub trait CompleteBlock { - fn complete(self, parent_hash: H256) -> Bytes; -} - -pub struct Complete<'a, I> where I: 'a { - pub iter: &'a mut I, - pub finalizer: &'a mut BlockFinalizer, -} - -impl<'a, I> Iterator for Complete<'a, I> where I: Iterator, ::Item: CompleteBlock { - type Item = Bytes; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|item| { - let rlp = item.complete(self.finalizer.parent_hash.clone()); - self.finalizer.parent_hash = BlockView::new(&rlp).header_view().sha3(); - rlp - }) - } -} diff --git a/ethcore/src/blockchain/generator/fork.rs b/ethcore/src/blockchain/generator/fork.rs deleted file mode 100644 index 4f09f3c0413d067581ff55d7a9b58ca937fb0395..0000000000000000000000000000000000000000 --- a/ethcore/src/blockchain/generator/fork.rs +++ /dev/null @@ -1,42 +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 . - -pub trait Forkable { - fn fork(self, fork_number: usize) -> Self where Self: Sized; -} - -pub struct Fork { - pub iter: I, - pub fork_number: usize, -} - -impl Clone for Fork where I: Iterator + Clone { - fn clone(&self) -> Self { - Fork { - iter: self.iter.clone(), - fork_number: self.fork_number - } - } -} - -impl Iterator for Fork where I: Iterator, ::Item: Forkable { - type Item = ::Item; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|item| item.fork(self.fork_number)) - } -} diff --git a/ethcore/src/blockchain/generator/generator.rs b/ethcore/src/blockchain/generator/generator.rs deleted file mode 100644 index a2c2c441a4678a468a9e1ee6297e13cce34a8a55..0000000000000000000000000000000000000000 --- a/ethcore/src/blockchain/generator/generator.rs +++ /dev/null @@ -1,178 +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 . - -use util::{U256, H2048, Bytes}; -use header::BlockNumber; -use transaction::SignedTransaction; -use super::fork::Fork; -use super::bloom::Bloom; -use super::complete::{BlockFinalizer, CompleteBlock, Complete}; -use super::block::Block; -use super::transaction::Transaction; - -/// Chain iterator interface. -pub trait ChainIterator: Iterator + Sized { - /// Should be called to create a fork of current iterator. - /// Blocks generated by fork will have lower difficulty than current chain. - fn fork(&self, fork_number: usize) -> Fork where Self: Clone; - /// Should be called to make every consecutive block have given bloom. - fn with_bloom(&mut self, bloom: H2048) -> Bloom; - /// Should be called to make every consecutive block have given transaction. - fn with_transaction(&mut self, transaction: SignedTransaction) -> Transaction; - /// Should be called to complete block. Without complete, block may have incorrect hash. - fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self>; - /// Completes and generates block. - fn generate<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Option where Self::Item: CompleteBlock; -} - -impl ChainIterator for I where I: Iterator + Sized { - fn fork(&self, fork_number: usize) -> Fork where I: Clone { - Fork { - iter: self.clone(), - fork_number: fork_number - } - } - - fn with_bloom(&mut self, bloom: H2048) -> Bloom { - Bloom { - iter: self, - bloom: bloom - } - } - - fn with_transaction(&mut self, transaction: SignedTransaction) -> Transaction { - Transaction { - iter: self, - transaction: transaction, - } - } - - fn complete<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Complete<'a, Self> { - Complete { - iter: self, - finalizer: finalizer - } - } - - fn generate<'a>(&'a mut self, finalizer: &'a mut BlockFinalizer) -> Option where ::Item: CompleteBlock { - self.complete(finalizer).next() - } -} - -/// Blockchain generator. -#[derive(Clone)] -pub struct ChainGenerator { - /// Next block number. - number: BlockNumber, - /// Next block difficulty. - difficulty: U256, -} - -impl ChainGenerator { - fn prepare_block(&self) -> Block { - let mut block = Block::default(); - block.header.set_number(self.number); - block.header.set_difficulty(self.difficulty); - block - } -} - -impl Default for ChainGenerator { - fn default() -> Self { - ChainGenerator { - number: 0, - difficulty: 1000.into(), - } - } -} - -impl Iterator for ChainGenerator { - type Item = Block; - - fn next(&mut self) -> Option { - let block = self.prepare_block(); - self.number += 1; - Some(block) - } -} - -mod tests { - use util::hash::{H256, H2048}; - use util::sha3::Hashable; - use views::BlockView; - use blockchain::generator::{ChainIterator, ChainGenerator, BlockFinalizer}; - - #[test] - fn canon_chain_generator() { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - - let genesis_rlp = canon_chain.generate(&mut finalizer).unwrap(); - let genesis = BlockView::new(&genesis_rlp); - - assert_eq!(genesis.header_view().parent_hash(), H256::default()); - assert_eq!(genesis.header_view().number(), 0); - - let b1_rlp = canon_chain.generate(&mut finalizer).unwrap(); - let b1 = BlockView::new(&b1_rlp); - - assert_eq!(b1.header_view().parent_hash(), genesis.header_view().sha3()); - assert_eq!(b1.header_view().number(), 1); - - let mut fork_chain = canon_chain.fork(1); - - let b2_rlp_fork = fork_chain.generate(&mut finalizer.fork()).unwrap(); - let b2_fork = BlockView::new(&b2_rlp_fork); - - assert_eq!(b2_fork.header_view().parent_hash(), b1.header_view().sha3()); - assert_eq!(b2_fork.header_view().number(), 2); - - let b2_rlp = canon_chain.generate(&mut finalizer).unwrap(); - let b2 = BlockView::new(&b2_rlp); - - assert_eq!(b2.header_view().parent_hash(), b1.header_view().sha3()); - assert_eq!(b2.header_view().number(), 2); - assert!(b2.header_view().difficulty() > b2_fork.header_view().difficulty()); - } - - #[test] - fn with_bloom_generator() { - let bloom = H2048([0x1; 256]); - let mut gen = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - - let block0_rlp = gen.with_bloom(bloom).generate(&mut finalizer).unwrap(); - let block1_rlp = gen.generate(&mut finalizer).unwrap(); - let block0 = BlockView::new(&block0_rlp); - let block1 = BlockView::new(&block1_rlp); - - assert_eq!(block0.header_view().number(), 0); - assert_eq!(block0.header_view().parent_hash(), H256::default()); - - assert_eq!(block1.header_view().number(), 1); - assert_eq!(block1.header_view().parent_hash(), block0.header_view().sha3()); - - } - - #[test] - fn generate_1000_blocks() { - let generator = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let blocks: Vec<_> = generator.take(1000).complete(&mut finalizer).collect(); - assert_eq!(blocks.len(), 1000); - } -} - diff --git a/ethcore/src/blockchain/generator/mod.rs b/ethcore/src/blockchain/generator/mod.rs deleted file mode 100644 index c32c4a3d7cb139805d8c1319592039f48d9dcfec..0000000000000000000000000000000000000000 --- a/ethcore/src/blockchain/generator/mod.rs +++ /dev/null @@ -1,27 +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 . - -//! Blockchain generator for tests. - -mod bloom; -mod block; -mod complete; -mod fork; -pub mod generator; -mod transaction; - -pub use self::complete::BlockFinalizer; -pub use self::generator::{ChainIterator, ChainGenerator}; diff --git a/ethcore/src/blockchain/import_route.rs b/ethcore/src/blockchain/import_route.rs index e86639e73d0290ca85297088ec9521cf6e9128da..cf5d3ca1e78d2542877d97e13c8408ba9cedbc69 100644 --- a/ethcore/src/blockchain/import_route.rs +++ b/ethcore/src/blockchain/import_route.rs @@ -16,7 +16,7 @@ //! Import route. -use util::H256; +use ethereum_types::H256; use blockchain::block_info::{BlockInfo, BlockLocation}; /// Import route for newly inserted block. @@ -67,7 +67,7 @@ impl From for ImportRoute { #[cfg(test)] mod tests { - use util::{U256, H256}; + use ethereum_types::{H256, U256}; use blockchain::block_info::{BlockInfo, BlockLocation, BranchBecomingCanonChainData}; use blockchain::ImportRoute; diff --git a/ethcore/src/blockchain/mod.rs b/ethcore/src/blockchain/mod.rs index 55a67e2b65ea6bddf22616841dbd62188daaeebe..062068c704de03d2b8d049dead0525fba3d292f1 100644 --- a/ethcore/src/blockchain/mod.rs +++ b/ethcore/src/blockchain/mod.rs @@ -18,10 +18,10 @@ mod best_block; mod block_info; -pub mod blockchain; +mod blockchain; mod cache; mod config; -pub mod extras; +mod extras; mod import_route; mod update; @@ -31,5 +31,6 @@ pub mod generator; pub use self::blockchain::{BlockProvider, BlockChain}; pub use self::cache::CacheSize; pub use self::config::Config; -pub use types::tree_route::TreeRoute; +pub use self::extras::{BlockReceipts, BlockDetails, TransactionAddress}; pub use self::import_route::ImportRoute; +pub use types::tree_route::TreeRoute; diff --git a/ethcore/src/blockchain/update.rs b/ethcore/src/blockchain/update.rs index 914b8aa996a264ddfd36844616cc2aa948e983bb..467ccc8d17b7a93dc0162aab350c3ead20bd0798 100644 --- a/ethcore/src/blockchain/update.rs +++ b/ethcore/src/blockchain/update.rs @@ -1,9 +1,9 @@ use std::collections::HashMap; -use util::H256; +use ethereum_types::H256; use header::BlockNumber; use blockchain::block_info::BlockInfo; -use blooms::BloomGroup; -use super::extras::{BlockDetails, BlockReceipts, TransactionAddress, LogGroupPosition}; +use blockchain::extras::{BlockDetails, BlockReceipts, TransactionAddress}; +use blooms::{BloomGroup, GroupPosition}; /// Block extras update info. pub struct ExtrasUpdate<'a> { @@ -20,7 +20,7 @@ pub struct ExtrasUpdate<'a> { /// Modified block receipts. pub block_receipts: HashMap, /// Modified blocks blooms. - pub blocks_blooms: HashMap, + pub blocks_blooms: HashMap, /// Modified transaction addresses (None signifies removed transactions). pub transactions_addresses: HashMap>, } diff --git a/ethcore/src/blooms/bloom.rs b/ethcore/src/blooms/bloom.rs deleted file mode 100644 index c79091cb4d01be871f60216d6510d2a7f70a864d..0000000000000000000000000000000000000000 --- a/ethcore/src/blooms/bloom.rs +++ /dev/null @@ -1,49 +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 . - -use bloomchain as bc; -use util::HeapSizeOf; -use basic_types::LogBloom; - -/// Helper structure representing bloom of the trace. -#[derive(Debug, Clone, RlpEncodableWrapper, RlpDecodableWrapper)] -pub struct Bloom(LogBloom); - -impl From for Bloom { - fn from(bloom: LogBloom) -> Self { - Bloom(bloom) - } -} - -impl From for Bloom { - fn from(bloom: bc::Bloom) -> Self { - let bytes: [u8; 256] = bloom.into(); - Bloom(LogBloom::from(bytes)) - } -} - -impl Into for Bloom { - fn into(self) -> bc::Bloom { - let log = self.0; - bc::Bloom::from(log.0) - } -} - -impl HeapSizeOf for Bloom { - fn heap_size_of_children(&self) -> usize { - 0 - } -} diff --git a/ethcore/src/blooms/bloom_group.rs b/ethcore/src/blooms/bloom_group.rs index 087f20b6fda2f2058f07eccc3de9487fe5fcc863..4b47b1ad9473b9ff55068d34d4720c7e854e668d 100644 --- a/ethcore/src/blooms/bloom_group.rs +++ b/ethcore/src/blooms/bloom_group.rs @@ -15,58 +15,39 @@ // along with Parity. If not, see . use bloomchain::group as bc; -use rlp::*; -use util::HeapSizeOf; -use super::Bloom; +use heapsize::HeapSizeOf; +use ethereum_types::Bloom; /// Represents group of X consecutive blooms. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, RlpEncodableWrapper, RlpDecodableWrapper)] pub struct BloomGroup { blooms: Vec, } +impl BloomGroup { + pub fn accrue_bloom_group(&mut self, group: &BloomGroup) { + for (bloom, other) in self.blooms.iter_mut().zip(group.blooms.iter()) { + bloom.accrue_bloom(other); + } + } +} + impl From for BloomGroup { fn from(group: bc::BloomGroup) -> Self { - let blooms = group.blooms - .into_iter() - .map(From::from) - .collect(); - BloomGroup { - blooms: blooms + blooms: group.blooms } } } impl Into for BloomGroup { fn into(self) -> bc::BloomGroup { - let blooms = self.blooms - .into_iter() - .map(Into::into) - .collect(); - bc::BloomGroup { - blooms: blooms + blooms: self.blooms } } } -impl Decodable for BloomGroup { - fn decode(rlp: &UntrustedRlp) -> Result { - let blooms = rlp.as_list()?; - let group = BloomGroup { - blooms: blooms - }; - Ok(group) - } -} - -impl Encodable for BloomGroup { - fn rlp_append(&self, s: &mut RlpStream) { - s.append_list(&self.blooms); - } -} - impl HeapSizeOf for BloomGroup { fn heap_size_of_children(&self) -> usize { self.blooms.heap_size_of_children() diff --git a/ethcore/src/blooms/group_position.rs b/ethcore/src/blooms/group_position.rs index bb28b3c1c5da1a3c6455ef0c81838870b5801935..b1ea82792618d500052285929ad1fde41f12d647 100644 --- a/ethcore/src/blooms/group_position.rs +++ b/ethcore/src/blooms/group_position.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use bloomchain::group as bc; -use util::HeapSizeOf; +use heapsize::HeapSizeOf; /// Represents `BloomGroup` position in database. #[derive(PartialEq, Eq, Hash, Clone, Debug)] diff --git a/ethcore/src/blooms/mod.rs b/ethcore/src/blooms/mod.rs index 3d021bf9f8fe9bd52578a7e1838f157aad6b4a42..a66485782b31f3373062ad636f307a737395ed30 100644 --- a/ethcore/src/blooms/mod.rs +++ b/ethcore/src/blooms/mod.rs @@ -16,10 +16,8 @@ //! Bridge between bloomchain crate types and ethcore. -mod bloom; mod bloom_group; mod group_position; -pub use self::bloom::Bloom; pub use self::bloom_group::BloomGroup; pub use self::group_position::GroupPosition; diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 9e49e610cbf3bb6111ef19b33b8b71ce7c39c64e..c18e1f3cd304a0ca34a9c928c6853f571e094497 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -23,7 +23,9 @@ use crypto::ripemd160::Ripemd160 as Ripemd160Digest; use crypto::digest::Digest; use num::{BigUint, Zero, One}; -use util::{U256, H256, Hashable, BytesRef}; +use hash::keccak; +use ethereum_types::{H256, U256}; +use bytes::BytesRef; use ethkey::{Signature, recover as ec_recover}; use ethjson; @@ -61,7 +63,7 @@ struct Linear { } /// A special pricing model for modular exponentiation. -struct Modexp { +struct ModexpPricer { divisor: usize, } @@ -71,7 +73,20 @@ impl Pricer for Linear { } } -impl Pricer for Modexp { +/// A alt_bn128_parinig pricing model. This computes a price using a base cost and a cost per pair. +struct AltBn128PairingPricer { + base: usize, + pair: usize, +} + +impl Pricer for AltBn128PairingPricer { + fn cost(&self, input: &[u8]) -> U256 { + let cost = U256::from(self.base) + U256::from(self.pair) * U256::from(input.len() / 192); + cost + } +} + +impl Pricer for ModexpPricer { fn cost(&self, input: &[u8]) -> U256 { let mut reader = input.chain(io::repeat(0)); let mut buf = [0; 32]; @@ -85,17 +100,51 @@ impl Pricer for Modexp { let exp_len = read_len(); let mod_len = read_len(); - // floor(max(length_of_MODULUS, length_of_BASE) ** 2 * max(length_of_EXPONENT, 1) / GQUADDIVISOR) - // TODO: is saturating the best behavior here? + if mod_len.is_zero() && base_len.is_zero() { + return U256::zero() + } + + let max_len = U256::from(u32::max_value() / 2); + if base_len > max_len || mod_len > max_len || exp_len > max_len { + return U256::max_value(); + } + let (base_len, exp_len, mod_len) = (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64()); + let m = max(mod_len, base_len); - match m.overflowing_mul(m) { - (_, true) => U256::max_value(), - (val, _) => { - match val.overflowing_mul(max(exp_len, U256::one())) { - (_, true) => U256::max_value(), - (val, _) => val / (self.divisor as u64).into() - } - } + // read fist 32-byte word of the exponent. + let exp_low = if base_len + 96 >= input.len() as u64 { U256::zero() } else { + let mut buf = [0; 32]; + let mut reader = input[(96 + base_len as usize)..].chain(io::repeat(0)); + let len = min(exp_len, 32) as usize; + reader.read_exact(&mut buf[(32 - len)..]).expect("reading from zero-extended memory cannot fail; qed"); + U256::from(H256::from_slice(&buf[..])) + }; + + let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low); + + let (gas, overflow) = Self::mult_complexity(m).overflowing_mul(max(adjusted_exp_len, 1)); + if overflow { + return U256::max_value(); + } + (gas / self.divisor as u64).into() + } +} + +impl ModexpPricer { + fn adjusted_exp_len(len: u64, exp_low: U256) -> u64 { + let bit_index = if exp_low.is_zero() { 0 } else { (255 - exp_low.leading_zeros()) as u64 }; + if len <= 32 { + bit_index + } else { + 8 * (len - 32) + bit_index + } + } + + fn mult_complexity(x: u64) -> u64 { + match x { + x if x <= 64 => x * x, + x if x <= 1024 => (x * x) / 4 + 96 * x - 3072, + x => (x * x) / 16 + 480 * x - 199680, } } } @@ -135,7 +184,7 @@ impl From for Builtin { }) } ethjson::spec::Pricing::Modexp(exp) => { - Box::new(Modexp { + Box::new(ModexpPricer { divisor: if exp.divisor == 0 { warn!("Zero modexp divisor specified. Falling back to default."); 10 @@ -144,6 +193,12 @@ impl From for Builtin { } }) } + ethjson::spec::Pricing::AltBn128Pairing(pricer) => { + Box::new(AltBn128PairingPricer { + base: pricer.base, + pair: pricer.pair, + }) + } }; Builtin { @@ -162,9 +217,9 @@ fn ethereum_builtin(name: &str) -> Box { "sha256" => Box::new(Sha256) as Box, "ripemd160" => Box::new(Ripemd160) as Box, "modexp" => Box::new(ModexpImpl) as Box, - "bn128_add" => Box::new(Bn128AddImpl) as Box, - "bn128_mul" => Box::new(Bn128MulImpl) as Box, - "bn128_pairing" => Box::new(Bn128PairingImpl) as Box, + "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, + "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, + "alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box, _ => panic!("invalid builtin name: {}", name), } } @@ -228,7 +283,7 @@ impl Impl for EcRecover { let s = Signature::from_rsv(&r, &s, bit); if s.is_valid() { if let Ok(p) = ec_recover(&s, &hash) { - let r = p.sha3(); + let r = keccak(p); output.write(0, &[0; 12]); output.write(12, &r[12..r.len()]); } @@ -266,6 +321,38 @@ impl Impl for Ripemd160 { } } +// calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular. +fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint { + use num::Integer; + + if modulus <= BigUint::one() { // n^m % 0 || n^m % 1 + return BigUint::zero(); + } + + if exp.is_zero() { // n^0 % m + return BigUint::one(); + } + + if base.is_zero() { // 0^n % m, n>0 + return BigUint::zero(); + } + + let mut result = BigUint::one(); + base = base % &modulus; + + // fast path for base divisible by modulus. + if base.is_zero() { return BigUint::zero() } + while !exp.is_zero() { + if exp.is_odd() { + result = (result * &base) % &modulus; + } + + exp = exp >> 1; + base = (base.clone() * base) % &modulus; + } + result +} + impl Impl for ModexpImpl { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { let mut reader = input.chain(io::repeat(0)); @@ -283,47 +370,25 @@ impl Impl for ModexpImpl { let exp_len = read_len(&mut reader); let mod_len = read_len(&mut reader); - // read the numbers themselves. - let mut buf = vec![0; max(mod_len, max(base_len, exp_len))]; - let mut read_num = |len| { - reader.read_exact(&mut buf[..len]).expect("reading from zero-extended memory cannot fail; qed"); - BigUint::from_bytes_be(&buf[..len]) - }; - - let base = read_num(base_len); - let exp = read_num(exp_len); - let modulus = read_num(mod_len); - - // calculate modexp: exponentiation by squaring. the `num` crate has pow, but not modular. - fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint { - use num::Integer; - - match (base.is_zero(), exp.is_zero()) { - (_, true) => return BigUint::one(), // n^0 % m - (true, false) => return BigUint::zero(), // 0^n % m, n>0 - (false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 0. - _ => {} - } - - let mut result = BigUint::one(); - base = base % &modulus; - - // fast path for base divisible by modulus. - if base.is_zero() { return result } - while !exp.is_zero() { - if exp.is_odd() { - result = (result * &base) % &modulus; - } - - exp = exp >> 1; - base = (base.clone() * base) % &modulus; - } + // Gas formula allows arbitrary large exp_len when base and modulus are empty, so we need to handle empty base first. + let r = if base_len == 0 && mod_len == 0 { + BigUint::zero() + } else { + // read the numbers themselves. + let mut buf = vec![0; max(mod_len, max(base_len, exp_len))]; + let mut read_num = |len| { + reader.read_exact(&mut buf[..len]).expect("reading from zero-extended memory cannot fail; qed"); + BigUint::from_bytes_be(&buf[..len]) + }; - result - } + let base = read_num(base_len); + let exp = read_num(exp_len); + let modulus = read_num(mod_len); + modexp(base, exp, modulus) + }; // write output to given memory, left padded and same length as the modulus. - let bytes = modexp(base, exp, modulus).to_bytes_be(); + let bytes = r.to_bytes_be(); // always true except in the case of zero-length modulus, which leads to // output of length and value 1. @@ -353,7 +418,6 @@ fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Err reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); let py = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point y coordinate"))?; - Ok( if px == Fq::zero() && py == Fq::zero() { G1::zero() @@ -404,50 +468,29 @@ impl Impl for Bn128MulImpl { } } -mod bn128_gen { - use bn::{AffineG1, AffineG2, Fq, Fq2, G1, G2, Gt, pairing}; - - lazy_static! { - pub static ref P1: G1 = G1::from(AffineG1::new( - Fq::from_str("1").expect("1 is a valid field element"), - Fq::from_str("2").expect("2 is a valid field element"), - ).expect("Generator P1(1, 2) is a valid curve point")); - } - - lazy_static! { - pub static ref P2: G2 = G2::from(AffineG2::new( - Fq2::new( - Fq::from_str("10857046999023057135944570762232829481370756359578518086990519993285655852781") - .expect("a valid field element"), - Fq::from_str("11559732032986387107991004021392285783925812861821192530917403151452391805634") - .expect("a valid field element"), - ), - Fq2::new( - Fq::from_str("8495653923123431417604973247489272438418190587263600148770280649306958101930") - .expect("a valid field element"), - Fq::from_str("4082367875863433681332203403145435568316851327593401208105741076214120093531") - .expect("a valid field element"), - ), - ).expect("the generator P2(10857046999023057135944570762232829481370756359578518086990519993285655852781 + 11559732032986387107991004021392285783925812861821192530917403151452391805634i, 8495653923123431417604973247489272438418190587263600148770280649306958101930 + 4082367875863433681332203403145435568316851327593401208105741076214120093531i) is a valid curve point")); - } - - lazy_static! { - pub static ref P1_P2_PAIRING: Gt = pairing(P1.clone(), P2.clone()); - } -} - impl Impl for Bn128PairingImpl { /// Can fail if: /// - input length is not a multiple of 192 /// - any of odd points does not belong to bn128 curve /// - any of even points does not belong to the twisted bn128 curve over the field F_p^2 = F_p[i] / (i^2 + 1) fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - use bn::{AffineG1, AffineG2, Fq, Fq2, pairing, G1, G2, Gt}; - - let elements = input.len() / 192; // (a, b_a, b_b - each 64-byte affine coordinates) if input.len() % 192 != 0 { return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into()) } + + if let Err(err) = self.execute_with_error(input, output) { + trace!("Pairining error: {:?}", err); + return Err(err) + } + Ok(()) + } +} + +impl Bn128PairingImpl { + fn execute_with_error(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + use bn::{AffineG1, AffineG2, Fq, Fq2, pairing, G1, G2, Gt, Group}; + + let elements = input.len() / 192; // (a, b_a, b_b - each 64-byte affine coordinates) let ret_val = if input.len() == 0 { U256::one() } else { @@ -459,34 +502,36 @@ impl Impl for Bn128PairingImpl { let a_y = Fq::from_slice(&input[idx*192+32..idx*192+64]) .map_err(|_| Error::from("Invalid a argument y coordinate"))?; - let b_b_x = Fq::from_slice(&input[idx*192+64..idx*192+96]) + let b_a_y = Fq::from_slice(&input[idx*192+64..idx*192+96]) .map_err(|_| Error::from("Invalid b argument imaginary coeff x coordinate"))?; - let b_b_y = Fq::from_slice(&input[idx*192+96..idx*192+128]) + let b_a_x = Fq::from_slice(&input[idx*192+96..idx*192+128]) .map_err(|_| Error::from("Invalid b argument imaginary coeff y coordinate"))?; - let b_a_x = Fq::from_slice(&input[idx*192+128..idx*192+160]) + let b_b_y = Fq::from_slice(&input[idx*192+128..idx*192+160]) .map_err(|_| Error::from("Invalid b argument real coeff x coordinate"))?; - let b_a_y = Fq::from_slice(&input[idx*192+160..idx*192+192]) + let b_b_x = Fq::from_slice(&input[idx*192+160..idx*192+192]) .map_err(|_| Error::from("Invalid b argument real coeff y coordinate"))?; - vals.push(( - G1::from( - AffineG1::new(a_x, a_y).map_err(|_| Error::from("Invalid a argument - not on curve"))? - ), - G2::from( - AffineG2::new( - Fq2::new(b_a_x, b_a_y), - Fq2::new(b_b_x, b_b_y), - ).map_err(|_| Error::from("Invalid b argument - not on curve"))? - ), - )); + let b_a = Fq2::new(b_a_x, b_a_y); + let b_b = Fq2::new(b_b_x, b_b_y); + let b = if b_a.is_zero() && b_b.is_zero() { + G2::zero() + } else { + G2::from(AffineG2::new(b_a, b_b).map_err(|_| Error::from("Invalid b argument - not on curve"))?) + }; + let a = if a_x.is_zero() && a_y.is_zero() { + G1::zero() + } else { + G1::from(AffineG1::new(a_x, a_y).map_err(|_| Error::from("Invalid a argument - not on curve"))?) + }; + vals.push((a, b)); }; let mul = vals.into_iter().fold(Gt::one(), |s, (a, b)| s * pairing(a, b)); - if mul == *bn128_gen::P1_P2_PAIRING { + if mul == Gt::one() { U256::one() } else { U256::zero() @@ -503,10 +548,45 @@ impl Impl for Bn128PairingImpl { #[cfg(test)] mod tests { - use super::{Builtin, Linear, ethereum_builtin, Pricer, Modexp}; + use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me}; use ethjson; - use util::{U256, BytesRef}; + use ethereum_types::U256; + use bytes::BytesRef; use rustc_hex::FromHex; + use num::{BigUint, Zero, One}; + + #[test] + fn modexp_func() { + // n^0 % m == 1 + let mut base = BigUint::parse_bytes(b"12345", 10).unwrap(); + let mut exp = BigUint::zero(); + let mut modulus = BigUint::parse_bytes(b"789", 10).unwrap(); + assert_eq!(me(base, exp, modulus), BigUint::one()); + + // 0^n % m == 0 + base = BigUint::zero(); + exp = BigUint::parse_bytes(b"12345", 10).unwrap(); + modulus = BigUint::parse_bytes(b"789", 10).unwrap(); + assert_eq!(me(base, exp, modulus), BigUint::zero()); + + // n^m % 1 == 0 + base = BigUint::parse_bytes(b"12345", 10).unwrap(); + exp = BigUint::parse_bytes(b"789", 10).unwrap(); + modulus = BigUint::one(); + assert_eq!(me(base, exp, modulus), BigUint::zero()); + + // if n % d == 0, then n^m % d == 0 + base = BigUint::parse_bytes(b"12345", 10).unwrap(); + exp = BigUint::parse_bytes(b"789", 10).unwrap(); + modulus = BigUint::parse_bytes(b"15", 10).unwrap(); + assert_eq!(me(base, exp, modulus), BigUint::zero()); + + // others + base = BigUint::parse_bytes(b"12345", 10).unwrap(); + exp = BigUint::parse_bytes(b"789", 10).unwrap(); + modulus = BigUint::parse_bytes(b"97", 10).unwrap(); + assert_eq!(me(base, exp, modulus), BigUint::parse_bytes(b"55", 10).unwrap()); + } #[test] fn identity() { @@ -572,14 +652,6 @@ mod tests { #[test] fn ecrecover() { - /*let k = KeyPair::from_secret(b"test".sha3()).unwrap(); - let a: Address = From::from(k.public().sha3()); - println!("Address: {}", a); - let m = b"hello world".sha3(); - println!("Message: {}", m); - let s = k.sign(&m).unwrap(); - println!("Signed: {}", s);*/ - let f = ethereum_builtin("ecrecover"); let i = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); @@ -632,10 +704,36 @@ mod tests { fn modexp() { let f = Builtin { - pricer: Box::new(Modexp { divisor: 20 }), + pricer: Box::new(ModexpPricer { divisor: 20 }), native: ethereum_builtin("modexp"), activate_at: 0, }; + + // test for potential gas cost multiplication overflow + { + let input = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3").unwrap(); + let expected_cost = U256::max_value(); + assert_eq!(f.cost(&input[..]), expected_cost.into()); + } + + + // test for potential exp len overflow + { + let input = FromHex::from_hex("\ + 00000000000000000000000000000000000000000000000000000000000000ff\ + 2a1e530000000000000000000000000000000000000000000000000000000000\ + 0000000000000000000000000000000000000000000000000000000000000000" + ).unwrap(); + + let mut output = vec![0u8; 32]; + let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let expected_cost = U256::max_value(); + + f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should fail"); + assert_eq!(output, expected); + assert_eq!(f.cost(&input[..]), expected_cost.into()); + } + // fermat's little theorem example. { let input = FromHex::from_hex("\ @@ -649,7 +747,7 @@ mod tests { let mut output = vec![0u8; 32]; let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let expected_cost = 1638; + let expected_cost = 13056; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); @@ -660,15 +758,15 @@ mod tests { { let input = FromHex::from_hex("\ 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000020\ - 0000000000000000000000000000000000000000000000000000000000000020\ - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" + 0000000000000000000000000000000000000000000000000000000000000020\ + 0000000000000000000000000000000000000000000000000000000000000020\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" ).unwrap(); let mut output = vec![0u8; 32]; let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let expected_cost = 1638; + let expected_cost = 13056; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); @@ -688,7 +786,7 @@ mod tests { let mut output = vec![0u8; 32]; let expected = FromHex::from_hex("3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab").unwrap(); - let expected_cost = 102; + let expected_cost = 768; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); @@ -719,7 +817,7 @@ mod tests { let f = Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("bn128_add"), + native: ethereum_builtin("alt_bn128_add"), activate_at: 0, }; @@ -780,7 +878,7 @@ mod tests { let f = Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("bn128_mul"), + native: ethereum_builtin("alt_bn128_mul"), activate_at: 0, }; @@ -820,7 +918,7 @@ mod tests { fn builtin_pairing() -> Builtin { Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("bn128_pairing"), + native: ethereum_builtin("alt_bn128_pairing"), activate_at: 0, } } diff --git a/ethcore/src/client/ancient_import.rs b/ethcore/src/client/ancient_import.rs index d4d8696d2505aee2d188daebe4a772527818bfb5..13699ea5a0e5d2cc0f9c578c55c4e68aee8780e6 100644 --- a/ethcore/src/client/ancient_import.rs +++ b/ethcore/src/client/ancient_import.rs @@ -19,11 +19,12 @@ use std::sync::Arc; use blockchain::BlockChain; -use engines::{Engine, EpochVerifier}; +use engines::{EthEngine, EpochVerifier}; use header::Header; +use machine::EthereumMachine; use rand::Rng; -use util::RwLock; +use parking_lot::RwLock; // do "heavy" verification on ~1/50 blocks, randomly sampled. const HEAVY_VERIFY_RATE: f32 = 0.02; @@ -31,13 +32,13 @@ const HEAVY_VERIFY_RATE: f32 = 0.02; /// Ancient block verifier: import an ancient sequence of blocks in order from a starting /// epoch. pub struct AncientVerifier { - cur_verifier: RwLock>, - engine: Arc, + cur_verifier: RwLock>>, + engine: Arc, } impl AncientVerifier { /// Create a new ancient block verifier with the given engine and initial verifier. - pub fn new(engine: Arc, start_verifier: Box) -> Self { + pub fn new(engine: Arc, start_verifier: Box>) -> Self { AncientVerifier { cur_verifier: RwLock::new(start_verifier), engine: engine, diff --git a/ethcore/src/client/chain_notify.rs b/ethcore/src/client/chain_notify.rs index 0a9bff8d73b2c71b738c09c361ecd759aaedf3fd..d05c95b8c850cfc03b829de3950da602c8278982 100644 --- a/ethcore/src/client/chain_notify.rs +++ b/ethcore/src/client/chain_notify.rs @@ -14,11 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ipc::IpcConfig; -use util::{H256, Bytes}; +use ethereum_types::H256; +use bytes::Bytes; /// Represents what has to be handled by actor listening to chain events -#[ipc] pub trait ChainNotify : Send + Sync { /// fires when chain has new blocks. fn new_blocks( @@ -56,5 +55,3 @@ pub trait ChainNotify : Send + Sync { // does nothing by default } } - -impl IpcConfig for ChainNotify { } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index ac8a0aea9a5d4932618aa31af4a17d911b138343..c4c2b6a2ee63f1ea2b8c6533ccbd7c1f6534b113 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -19,53 +19,56 @@ use std::str::FromStr; use std::sync::{Arc, Weak}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::time::{Instant}; -use time::precise_time_ns; use itertools::Itertools; // util -use util::{Bytes, PerfTimer, Mutex, RwLock, MutexGuard, Hashable}; -use util::{journaldb, DBValue, TrieFactory, Trie}; -use util::{U256, H256, Address, H2048}; -use util::trie::TrieSpec; -use util::kvdb::*; +use hash::keccak; +use bytes::Bytes; +use journaldb; +use trie::{TrieSpec, TrieFactory, Trie}; +use kvdb::{DBValue, KeyValueDB, DBTransaction}; +use util_error::UtilError; // other -use basic_types::Seal; -use block::*; -use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute}; -use blockchain::extras::TransactionAddress; +use ethereum_types::{H256, Address, U256}; +use block::{IsBlock, LockedBlock, Drain, ClosedBlock, OpenBlock, enact_verified, SealedBlock}; +use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute, TransactionAddress}; use client::ancient_import::AncientVerifier; use client::Error as ClientError; +use client::{ + Nonce, Balance, ChainInfo, BlockInfo, CallContract, TransactionInfo, + RegistryInfo, ReopenBlock, PrepareOpenBlock, ScheduleInfo, ImportSealedBlock, + BroadcastProposalBlock, ImportBlock, StateOrBlock, StateInfo, StateClient, Call, + AccountData, BlockChain as BlockChainTrait, BlockProducer, SealedBlockImporter, + ClientIoMessage +}; use client::{ BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient, - MiningBlockChainClient, EngineClient, TraceFilter, CallAnalytics, BlockImportError, Mode, - ChainNotify, PruningInfo, ProvingBlockChainClient, + MiningBlockChainClient, TraceFilter, CallAnalytics, BlockImportError, Mode, + ChainNotify, PruningInfo, ProvingBlockChainClient, EngineInfo }; use encoded; -use engines::{Engine, EpochTransition}; +use engines::{EthEngine, EpochTransition}; use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError}; use vm::{EnvInfo, LastHashes}; -use evm::{Factory as EvmFactory, Schedule}; +use evm::Schedule; use executive::{Executive, Executed, TransactOptions, contract_address}; -use factory::Factories; -use futures::{future, Future}; +use factory::{Factories, VmFactory}; use header::{BlockNumber, Header}; -use io::*; +use io::IoChannel; use log_entry::LocalizedLogEntry; -use miner::{Miner, MinerService, TransactionImportResult}; -use native_contracts::Registry; +use miner::{Miner, MinerService}; +use parking_lot::{Mutex, RwLock}; use rand::OsRng; use receipt::{Receipt, LocalizedReceipt}; use rlp::UntrustedRlp; -use service::ClientIoMessage; use snapshot::{self, io as snapshot_io}; use spec::Spec; use state_db::StateDB; use state::{self, State}; use trace; use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase}; -use trace::FlatTransactionTraces; -use transaction::{LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action}; +use transaction::{self, LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action}; use types::filter::Filter; use types::mode::Mode as IpcMode; use verification; @@ -79,6 +82,8 @@ pub use types::block_status::BlockStatus; pub use blockchain::CacheSize as BlockChainCacheSize; pub use verification::queue::QueueInfo as BlockQueueInfo; +use_contract!(registry, "Registry", "res/contracts/registrar.json"); + const MAX_TX_QUEUE_SIZE: usize = 4096; const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2; const MIN_HISTORY_SIZE: u64 = 8; @@ -135,336 +140,109 @@ impl SleepState { } } +struct Importer { + /// Lock used during block import + pub import_lock: Mutex<()>, // FIXME Maybe wrap the whole `Importer` instead? + + /// Used to verify blocks + pub verifier: Box>, + + /// Queue containing pending blocks + pub block_queue: BlockQueue, + + /// Handles block sealing + pub miner: Arc, + + /// Ancient block verifier: import an ancient sequence of blocks in order from a starting epoch + pub ancient_verifier: Mutex>, + + /// Random number generator used by `AncientVerifier` + pub rng: Mutex, + + /// Ethereum engine to be used during import + pub engine: Arc, +} + /// Blockchain database client backed by a persistent database. Owns and manages a blockchain and a block queue. /// Call `import_block()` to import a block asynchronously; `flush_queue()` flushes the queue. pub struct Client { + /// Flag used to disable the client forever. Not to be confused with `liveness`. + /// + /// For example, auto-updater will disable client forever if there is a + /// hard fork registered on-chain that we don't have capability for. + /// When hard fork block rolls around, the client (if `update` is false) + /// knows it can't proceed further. enabled: AtomicBool, + + /// Operating mode for the client mode: Mutex, + chain: RwLock>, tracedb: RwLock>, - engine: Arc, + engine: Arc, + + /// Client configuration config: ClientConfig, + + /// Database pruning strategy to use for StateDB pruning: journaldb::Algorithm, + + /// Client uses this to store blocks, traces, etc. db: RwLock>, - state_db: Mutex, - block_queue: BlockQueue, + + state_db: RwLock, + + /// Report on the status of client report: RwLock, - import_lock: Mutex<()>, - verifier: Box, - miner: Arc, + sleep_state: Mutex, + + /// Flag changed by `sleep` and `wake_up` methods. Not to be confused with `enabled`. liveness: AtomicBool, io_channel: Mutex>, + + /// List of actors to be notified on certain chain events notify: RwLock>>, + + /// Count of pending transactions in the queue queue_transactions: AtomicUsize, last_hashes: RwLock>, factories: Factories, + + /// Number of eras kept in a journal before they are pruned history: u64, - rng: Mutex, - ancient_verifier: Mutex>, + + /// An action to be done if a mode/spec_name change happens on_user_defaults_change: Mutex) + 'static + Send>>>, - registrar: Mutex>, + + /// Link to a registry object useful for looking up names + registrar: registry::Registry, + registrar_address: Option
, + + /// A closure to call when we want to restart the client exit_handler: Mutex) + 'static + Send>>>, + + importer: Importer, } -impl Client { - /// Create a new client with given parameters. - /// The database is assumed to have been initialized with the correct columns. +impl Importer { pub fn new( - config: ClientConfig, - spec: &Spec, - db: Arc, - miner: Arc, + config: &ClientConfig, + engine: Arc, message_channel: IoChannel, - ) -> Result, ::error::Error> { - let trie_spec = match config.fat_db { - true => TrieSpec::Fat, - false => TrieSpec::Secure, - }; - - let trie_factory = TrieFactory::new(trie_spec); - let factories = Factories { - vm: EvmFactory::new(config.vm_type.clone(), config.jump_table_size), - trie: trie_factory, - accountdb: Default::default(), - }; - - let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE); - let mut state_db = StateDB::new(journal_db, config.state_cache_size); - if state_db.journal_db().is_empty() { - // Sets the correct state root. - state_db = spec.ensure_db_good(state_db, &factories)?; - let mut batch = DBTransaction::new(); - state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash())?; - db.write(batch).map_err(ClientError::Database)?; - } - - let gb = spec.genesis_block(); - let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone())); - let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.clone(), chain.clone())); - - trace!("Cleanup journal: DB Earliest = {:?}, Latest = {:?}", state_db.journal_db().earliest_era(), state_db.journal_db().latest_era()); - - let history = if config.history < MIN_HISTORY_SIZE { - info!(target: "client", "Ignoring pruning history parameter of {}\ - , falling back to minimum of {}", - config.history, MIN_HISTORY_SIZE); - MIN_HISTORY_SIZE - } else { - config.history - }; - - if !chain.block_header(&chain.best_block_hash()).map_or(true, |h| state_db.journal_db().contains(h.state_root())) { - warn!("State root not found for block #{} ({})", chain.best_block_number(), chain.best_block_hash().hex()); - } - - let engine = spec.engine.clone(); - + miner: Arc, + ) -> Result { let block_queue = BlockQueue::new(config.queue.clone(), engine.clone(), message_channel.clone(), config.verifier_type.verifying_seal()); - let awake = match config.mode { Mode::Dark(..) | Mode::Off => false, _ => true }; - - let client = Arc::new(Client { - enabled: AtomicBool::new(true), - sleep_state: Mutex::new(SleepState::new(awake)), - liveness: AtomicBool::new(awake), - mode: Mutex::new(config.mode.clone()), - chain: RwLock::new(chain), - tracedb: tracedb, - engine: engine, - pruning: config.pruning.clone(), - verifier: verification::new(config.verifier_type.clone()), - config: config, - db: RwLock::new(db), - state_db: Mutex::new(state_db), - block_queue: block_queue, - report: RwLock::new(Default::default()), + Ok(Importer { import_lock: Mutex::new(()), - miner: miner, - io_channel: Mutex::new(message_channel), - notify: RwLock::new(Vec::new()), - queue_transactions: AtomicUsize::new(0), - last_hashes: RwLock::new(VecDeque::new()), - factories: factories, - history: history, - rng: Mutex::new(OsRng::new().map_err(::util::UtilError::StdIo)?), + verifier: verification::new(config.verifier_type.clone()), + block_queue, + miner, ancient_verifier: Mutex::new(None), - on_user_defaults_change: Mutex::new(None), - registrar: Mutex::new(None), - exit_handler: Mutex::new(None), - }); - - // prune old states. - { - let state_db = client.state_db.lock().boxed_clone(); - let chain = client.chain.read(); - client.prune_ancient(state_db, &chain)?; - } - - // ensure genesis epoch proof in the DB. - { - let chain = client.chain.read(); - let gh = spec.genesis_header(); - if chain.epoch_transition(0, gh.hash()).is_none() { - trace!(target: "client", "No genesis transition found."); - - let proof = client.with_proving_caller( - BlockId::Number(0), - |call| client.engine.genesis_epoch_data(&gh, call) - ); - let proof = match proof { - Ok(proof) => proof, - Err(e) => { - warn!(target: "client", "Error generating genesis epoch data: {}. Snapshots generated may not be complete.", e); - Vec::new() - } - }; - - debug!(target: "client", "Obtained genesis transition proof: {:?}", proof); - - let mut batch = DBTransaction::new(); - chain.insert_epoch_transition(&mut batch, 0, EpochTransition { - block_hash: gh.hash(), - block_number: 0, - proof: proof, - }); - - client.db.read().write_buffered(batch); - } - } - - if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) { - trace!(target: "client", "Found registrar at {}", reg_addr); - let registrar = Registry::new(reg_addr); - *client.registrar.lock() = Some(registrar); - } - - // ensure buffered changes are flushed. - client.db.read().flush().map_err(ClientError::Database)?; - Ok(client) - } - - /// Wakes up client if it's a sleep. - pub fn keep_alive(&self) { - let should_wake = match *self.mode.lock() { - Mode::Dark(..) | Mode::Passive(..) => true, - _ => false, - }; - if should_wake { - self.wake_up(); - (*self.sleep_state.lock()).last_activity = Some(Instant::now()); - } - } - - /// Adds an actor to be notified on certain events - pub fn add_notify(&self, target: Arc) { - self.notify.write().push(Arc::downgrade(&target)); - } - - /// Set a closure to call when we want to restart the client - pub fn set_exit_handler(&self, f: F) where F: Fn(bool, Option) + 'static + Send { - *self.exit_handler.lock() = Some(Box::new(f)); - } - - /// Returns engine reference. - pub fn engine(&self) -> &Engine { - &*self.engine - } - - fn notify(&self, f: F) where F: Fn(&ChainNotify) { - for np in self.notify.read().iter() { - if let Some(n) = np.upgrade() { - f(&*n); - } - } - } - - /// Get the Registry object - useful for looking up names. - pub fn registrar(&self) -> MutexGuard> { - self.registrar.lock() - } - - /// Register an action to be done if a mode/spec_name change happens. - pub fn on_user_defaults_change(&self, f: F) where F: 'static + FnMut(Option) + Send { - *self.on_user_defaults_change.lock() = Some(Box::new(f)); - } - - /// Flush the block import queue. - pub fn flush_queue(&self) { - self.block_queue.flush(); - while !self.block_queue.queue_info().is_empty() { - self.import_verified_blocks(); - } - } - - /// The env info as of the best block. - pub fn latest_env_info(&self) -> EnvInfo { - self.env_info(BlockId::Latest).expect("Best block header always stored; qed") - } - - /// The env info as of a given block. - /// returns `None` if the block unknown. - pub fn env_info(&self, id: BlockId) -> Option { - self.block_header(id).map(|header| { - EnvInfo { - number: header.number(), - author: header.author(), - timestamp: header.timestamp(), - difficulty: header.difficulty(), - last_hashes: self.build_last_hashes(header.parent_hash()), - gas_used: U256::default(), - gas_limit: header.gas_limit(), - } - }) - } - - fn build_last_hashes(&self, parent_hash: H256) -> Arc { - { - let hashes = self.last_hashes.read(); - if hashes.front().map_or(false, |h| h == &parent_hash) { - let mut res = Vec::from(hashes.clone()); - res.resize(256, H256::default()); - return Arc::new(res); - } - } - let mut last_hashes = LastHashes::new(); - last_hashes.resize(256, H256::default()); - last_hashes[0] = parent_hash; - let chain = self.chain.read(); - for i in 0..255 { - match chain.block_details(&last_hashes[i]) { - Some(details) => { - last_hashes[i + 1] = details.parent.clone(); - }, - None => break, - } - } - let mut cached_hashes = self.last_hashes.write(); - *cached_hashes = VecDeque::from(last_hashes.clone()); - Arc::new(last_hashes) - } - - fn check_and_close_block(&self, block: &PreverifiedBlock) -> Result { - let engine = &*self.engine; - let header = &block.header; - - let chain = self.chain.read(); - // Check the block isn't so old we won't be able to enact it. - let best_block_number = chain.best_block_number(); - if self.pruning_info().earliest_state > header.number() { - warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number); - return Err(()); - } - - // Verify Block Family - let verify_family_result = self.verifier.verify_block_family(header, &block.bytes, engine, &**chain); - if let Err(e) = verify_family_result { - warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - return Err(()); - }; - - let verify_external_result = self.verifier.verify_block_external(header, &block.bytes, engine); - if let Err(e) = verify_external_result { - warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - return Err(()); - }; - - // Check if Parent is in chain - let chain_has_parent = chain.block_header(header.parent_hash()); - if let Some(parent) = chain_has_parent { - // Enact Verified Block - let last_hashes = self.build_last_hashes(header.parent_hash().clone()); - let db = self.state_db.lock().boxed_clone_canon(header.parent_hash()); - - let is_epoch_begin = chain.epoch_transition(parent.number(), *header.parent_hash()).is_some(); - let enact_result = enact_verified(block, - engine, - self.tracedb.read().tracing_enabled(), - db, - &parent, - last_hashes, - self.factories.clone(), - is_epoch_begin, - ); - let mut locked_block = enact_result.map_err(|e| { - warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - })?; - - if header.number() < self.engine().params().validate_receipts_transition && header.receipts_root() != locked_block.block().header().receipts_root() { - locked_block = locked_block.strip_receipts(); - } - - // Final Verification - if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header()) { - warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); - return Err(()); - } - - Ok(locked_block) - } else { - warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash()); - Err(()) - } + rng: Mutex::new(OsRng::new()?), + engine, + }) } fn calculate_enacted_retracted(&self, import_results: &[ImportRoute]) -> (Vec, Vec) { @@ -494,10 +272,10 @@ impl Client { } /// This is triggered by a message coming from a block queue when the block is ready for insertion - pub fn import_verified_blocks(&self) -> usize { + pub fn import_verified_blocks(&self, client: &Client) -> usize { // Shortcut out if we know we're incapable of syncing the chain. - if !self.enabled.load(AtomicOrdering::Relaxed) { + if !client.enabled.load(AtomicOrdering::Relaxed) { return 0; } @@ -513,8 +291,8 @@ impl Client { if blocks.is_empty() { return 0; } - let _timer = PerfTimer::new("import_verified_blocks"); - let start = precise_time_ns(); + trace_time!("import_verified_blocks"); + let start = Instant::now(); for block in blocks { let header = &block.header; @@ -523,17 +301,17 @@ impl Client { invalid_blocks.insert(header.hash()); continue; } - if let Ok(closed_block) = self.check_and_close_block(&block) { + if let Ok(closed_block) = self.check_and_close_block(&block, client) { if self.engine.is_proposal(&block.header) { self.block_queue.mark_as_good(&[header.hash()]); proposed_blocks.push(block.bytes); } else { imported_blocks.push(header.hash()); - let route = self.commit_block(closed_block, &header, &block.bytes); + let route = self.commit_block(closed_block, &header, &block.bytes, client); import_results.push(route); - self.report.write().accrue_block(&block); + client.report.write().accrue_block(&block); } } else { invalid_blocks.insert(header.hash()); @@ -547,7 +325,10 @@ impl Client { self.block_queue.mark_as_bad(&invalid_blocks); } let is_empty = self.block_queue.mark_as_good(&imported_blocks); - let duration_ns = precise_time_ns() - start; + let duration_ns = { + let elapsed = start.elapsed(); + elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64 + }; (imported_blocks, import_results, invalid_blocks, imported, proposed_blocks, duration_ns, is_empty) }; @@ -556,10 +337,10 @@ impl Client { let (enacted, retracted) = self.calculate_enacted_retracted(&import_results); if is_empty { - self.miner.chain_new_blocks(self, &imported_blocks, &invalid_blocks, &enacted, &retracted); + self.miner.chain_new_blocks(client, &imported_blocks, &invalid_blocks, &enacted, &retracted); } - self.notify(|notify| { + client.notify(|notify| { notify.new_blocks( imported_blocks.clone(), invalid_blocks.clone(), @@ -573,14 +354,91 @@ impl Client { } } - self.db.read().flush().expect("DB flush failed."); + client.db.read().flush().expect("DB flush failed."); imported } + fn check_and_close_block(&self, block: &PreverifiedBlock, client: &Client) -> Result { + let engine = &*self.engine; + let header = &block.header; + + let chain = client.chain.read(); + // Check the block isn't so old we won't be able to enact it. + let best_block_number = chain.best_block_number(); + if client.pruning_info().earliest_state > header.number() { + warn!(target: "client", "Block import failed for #{} ({})\nBlock is ancient (current best block: #{}).", header.number(), header.hash(), best_block_number); + return Err(()); + } + + // Check if parent is in chain + let parent = match chain.block_header(header.parent_hash()) { + Some(h) => h, + None => { + warn!(target: "client", "Block import failed for #{} ({}): Parent not found ({}) ", header.number(), header.hash(), header.parent_hash()); + return Err(()); + } + }; + + // Verify Block Family + let verify_family_result = self.verifier.verify_block_family( + header, + &parent, + engine, + Some(verification::FullFamilyParams { + block_bytes: &block.bytes, + transactions: &block.transactions, + block_provider: &**chain, + client + }), + ); + + if let Err(e) = verify_family_result { + warn!(target: "client", "Stage 3 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); + return Err(()); + }; + + let verify_external_result = self.verifier.verify_block_external(header, engine); + if let Err(e) = verify_external_result { + warn!(target: "client", "Stage 4 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); + return Err(()); + }; + + // Enact Verified Block + let last_hashes = client.build_last_hashes(header.parent_hash()); + let db = client.state_db.read().boxed_clone_canon(header.parent_hash()); + + let is_epoch_begin = chain.epoch_transition(parent.number(), *header.parent_hash()).is_some(); + let enact_result = enact_verified(block, + engine, + client.tracedb.read().tracing_enabled(), + db, + &parent, + last_hashes, + client.factories.clone(), + is_epoch_begin, + ); + let mut locked_block = enact_result.map_err(|e| { + warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); + })?; + + if header.number() < engine.params().validate_receipts_transition && header.receipts_root() != locked_block.block().header().receipts_root() { + locked_block = locked_block.strip_receipts(); + } + + // Final Verification + if let Err(e) = self.verifier.verify_block_final(header, locked_block.block().header()) { + warn!(target: "client", "Stage 5 block verification failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e); + return Err(()); + } + + Ok(locked_block) + } + /// Import a block with transaction receipts. - /// The block is guaranteed to be the next best blocks in the first block sequence. - /// Does no sealing or transaction validation. - fn import_old_block(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { + /// + /// The block is guaranteed to be the next best blocks in the + /// first block sequence. Does no sealing or transaction validation. + fn import_old_block(&self, block_bytes: Bytes, receipts_bytes: Bytes, db: &KeyValueDB, chain: &BlockChain) -> Result { let block = BlockView::new(&block_bytes); let header = block.header(); let receipts = ::rlp::decode_list(&receipts_bytes); @@ -588,8 +446,7 @@ impl Client { let _import_lock = self.import_lock.lock(); { - let _timer = PerfTimer::new("import_old_block"); - let chain = self.chain.read(); + trace_time!("import_old_block"); let mut ancient_verifier = self.ancient_verifier.lock(); { @@ -597,7 +454,8 @@ impl Client { let verify_with = |verifier: &AncientVerifier| -> Result<(), ::error::Error> { // verify the block, passing the chain for updating the epoch // verifier. - verifier.verify(&mut *self.rng.lock(), &header, &chain) + let mut rng = OsRng::new().map_err(UtilError::from)?; + verifier.verify(&mut rng, &header, &chain) }; // initialize the ancient block verifier if we don't have one already. @@ -628,10 +486,10 @@ impl Client { let mut batch = DBTransaction::new(); chain.insert_unordered_block(&mut batch, &block_bytes, receipts, None, false, true); // Final commit to the DB - self.db.read().write_buffered(batch); + db.write_buffered(batch); chain.commit(); } - self.db.read().flush().expect("DB flush failed."); + db.flush().expect("DB flush failed."); Ok(hash) } @@ -639,20 +497,17 @@ impl Client { // it is for reconstructing the state transition. // // The header passed is from the original block data and is sealed. - fn commit_block(&self, block: B, header: &Header, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain { + fn commit_block(&self, block: B, header: &Header, block_data: &[u8], client: &Client) -> ImportRoute where B: IsBlock + Drain { let hash = &header.hash(); let number = header.number(); let parent = header.parent_hash(); - let chain = self.chain.read(); + let chain = client.chain.read(); // Commit results let receipts = block.receipts().to_owned(); - let traces = block.traces().clone().unwrap_or_else(Vec::new); - let traces: Vec = traces.into_iter() - .map(Into::into) - .collect(); + let traces = block.traces().clone().drain(); - assert_eq!(header.hash(), BlockView::new(block_data).header_view().sha3()); + assert_eq!(header.hash(), BlockView::new(block_data).header_view().hash()); //let traces = From::from(block.traces().clone().unwrap_or_else(Vec::new)); @@ -672,12 +527,13 @@ impl Client { &state, &chain, &mut batch, + client ); state.journal_under(&mut batch, number, hash).expect("DB commit failed"); let route = chain.insert_block(&mut batch, block_data, receipts.clone()); - self.tracedb.read().import(&mut batch, TraceImportRequest { + client.tracedb.read().import(&mut batch, TraceImportRequest { traces: traces.into(), block_hash: hash.clone(), block_number: number, @@ -688,14 +544,14 @@ impl Client { let is_canon = route.enacted.last().map_or(false, |h| h == hash); state.sync_cache(&route.enacted, &route.retracted, is_canon); // Final commit to the DB - self.db.read().write_buffered(batch); + client.db.read().write_buffered(batch); chain.commit(); - self.check_epoch_end(&header, &chain); + self.check_epoch_end(&header, &chain, client); - self.update_last_hashes(&parent, hash); + client.update_last_hashes(&parent, hash); - if let Err(e) = self.prune_ancient(state, &chain) { + if let Err(e) = client.prune_ancient(state, &chain) { warn!("Failed to prune ancient state data: {}", e); } @@ -712,11 +568,17 @@ impl Client { state_db: &StateDB, chain: &BlockChain, batch: &mut DBTransaction, + client: &Client, ) { use engines::EpochChange; let hash = header.hash(); - match self.engine.signals_epoch_end(header, Some(block_bytes), Some(&receipts)) { + let auxiliary = ::machine::AuxiliaryData { + bytes: Some(block_bytes), + receipts: Some(&receipts), + }; + + match self.engine.signals_epoch_end(header, auxiliary) { EpochChange::Yes(proof) => { use engines::epoch::PendingTransition; use engines::Proof; @@ -729,94 +591,328 @@ impl Client { author: header.author().clone(), timestamp: header.timestamp(), difficulty: header.difficulty().clone(), - last_hashes: self.build_last_hashes(header.parent_hash().clone()), + last_hashes: client.build_last_hashes(header.parent_hash()), gas_used: U256::default(), gas_limit: u64::max_value().into(), }; - let call = move |addr, data| { - let mut state_db = state_db.boxed_clone(); - let backend = ::state::backend::Proving::new(state_db.as_hashdb_mut()); + let call = move |addr, data| { + let mut state_db = state_db.boxed_clone(); + let backend = ::state::backend::Proving::new(state_db.as_hashdb_mut()); + + let transaction = + client.contract_call_tx(BlockId::Hash(*header.parent_hash()), addr, data); + + let mut state = State::from_existing( + backend, + header.state_root().clone(), + self.engine.account_start_nonce(header.number()), + client.factories.clone(), + ).expect("state known to be available for just-imported block; qed"); + + let options = TransactOptions::with_no_tracing().dont_check_nonce(); + let res = Executive::new(&mut state, &env_info, self.engine.machine()) + .transact(&transaction, options); + + let res = match res { + Err(ExecutionError::Internal(e)) => + Err(format!("Internal error: {}", e)), + Err(e) => { + trace!(target: "client", "Proved call failed: {}", e); + Ok((Vec::new(), state.drop().1.extract_proof())) + } + Ok(res) => Ok((res.output, state.drop().1.extract_proof())), + }; + + res.map(|(output, proof)| (output, proof.into_iter().map(|x| x.into_vec()).collect())) + }; + + match with_state.generate_proof(&call) { + Ok(proof) => proof, + Err(e) => { + warn!(target: "client", "Failed to generate transition proof for block {}: {}", hash, e); + warn!(target: "client", "Snapshots produced by this client may be incomplete"); + Vec::new() + } + } + } + }; + + debug!(target: "client", "Block {} signals epoch end.", hash); + + let pending = PendingTransition { proof: proof }; + chain.insert_pending_transition(batch, hash, pending); + }, + EpochChange::No => {}, + EpochChange::Unsure(_) => { + warn!(target: "client", "Detected invalid engine implementation."); + warn!(target: "client", "Engine claims to require more block data, but everything provided."); + } + } + } + + // check for ending of epoch and write transition if it occurs. + fn check_epoch_end<'a>(&self, header: &'a Header, chain: &BlockChain, client: &Client) { + let is_epoch_end = self.engine.is_epoch_end( + header, + &(|hash| chain.block_header(&hash)), + &(|hash| chain.get_pending_transition(hash)), // TODO: limit to current epoch. + ); + + if let Some(proof) = is_epoch_end { + debug!(target: "client", "Epoch transition at block {}", header.hash()); + + let mut batch = DBTransaction::new(); + chain.insert_epoch_transition(&mut batch, header.number(), EpochTransition { + block_hash: header.hash(), + block_number: header.number(), + proof: proof, + }); + + // always write the batch directly since epoch transition proofs are + // fetched from a DB iterator and DB iterators are only available on + // flushed data. + client.db.read().write(batch).expect("DB flush failed"); + } + } +} + +impl Client { + /// Create a new client with given parameters. + /// The database is assumed to have been initialized with the correct columns. + pub fn new( + config: ClientConfig, + spec: &Spec, + db: Arc, + miner: Arc, + message_channel: IoChannel, + ) -> Result, ::error::Error> { + let trie_spec = match config.fat_db { + true => TrieSpec::Fat, + false => TrieSpec::Secure, + }; + + let trie_factory = TrieFactory::new(trie_spec); + let factories = Factories { + vm: VmFactory::new(config.vm_type.clone(), config.jump_table_size), + trie: trie_factory, + accountdb: Default::default(), + }; + + let journal_db = journaldb::new(db.clone(), config.pruning, ::db::COL_STATE); + let mut state_db = StateDB::new(journal_db, config.state_cache_size); + if state_db.journal_db().is_empty() { + // Sets the correct state root. + state_db = spec.ensure_db_good(state_db, &factories)?; + let mut batch = DBTransaction::new(); + state_db.journal_under(&mut batch, 0, &spec.genesis_header().hash())?; + db.write(batch).map_err(ClientError::Database)?; + } + + let gb = spec.genesis_block(); + let chain = Arc::new(BlockChain::new(config.blockchain.clone(), &gb, db.clone())); + let tracedb = RwLock::new(TraceDB::new(config.tracing.clone(), db.clone(), chain.clone())); + + trace!("Cleanup journal: DB Earliest = {:?}, Latest = {:?}", state_db.journal_db().earliest_era(), state_db.journal_db().latest_era()); + + let history = if config.history < MIN_HISTORY_SIZE { + info!(target: "client", "Ignoring pruning history parameter of {}\ + , falling back to minimum of {}", + config.history, MIN_HISTORY_SIZE); + MIN_HISTORY_SIZE + } else { + config.history + }; + + if !chain.block_header(&chain.best_block_hash()).map_or(true, |h| state_db.journal_db().contains(h.state_root())) { + warn!("State root not found for block #{} ({:x})", chain.best_block_number(), chain.best_block_hash()); + } + + let engine = spec.engine.clone(); + + let awake = match config.mode { Mode::Dark(..) | Mode::Off => false, _ => true }; + + let importer = Importer::new(&config, engine.clone(), message_channel.clone(), miner)?; + + let registrar_address = engine.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()); + if let Some(ref addr) = registrar_address { + trace!(target: "client", "Found registrar at {}", addr); + } + + let client = Arc::new(Client { + enabled: AtomicBool::new(true), + sleep_state: Mutex::new(SleepState::new(awake)), + liveness: AtomicBool::new(awake), + mode: Mutex::new(config.mode.clone()), + chain: RwLock::new(chain), + tracedb: tracedb, + engine: engine, + pruning: config.pruning.clone(), + config: config, + db: RwLock::new(db), + state_db: RwLock::new(state_db), + report: RwLock::new(Default::default()), + io_channel: Mutex::new(message_channel), + notify: RwLock::new(Vec::new()), + queue_transactions: AtomicUsize::new(0), + last_hashes: RwLock::new(VecDeque::new()), + factories: factories, + history: history, + on_user_defaults_change: Mutex::new(None), + registrar: registry::Registry::default(), + registrar_address, + exit_handler: Mutex::new(None), + importer, + }); + + // prune old states. + { + let state_db = client.state_db.read().boxed_clone(); + let chain = client.chain.read(); + client.prune_ancient(state_db, &chain)?; + } + + // ensure genesis epoch proof in the DB. + { + let chain = client.chain.read(); + let gh = spec.genesis_header(); + if chain.epoch_transition(0, gh.hash()).is_none() { + trace!(target: "client", "No genesis transition found."); + + let proof = client.with_proving_caller( + BlockId::Number(0), + |call| client.engine.genesis_epoch_data(&gh, call) + ); + let proof = match proof { + Ok(proof) => proof, + Err(e) => { + warn!(target: "client", "Error generating genesis epoch data: {}. Snapshots generated may not be complete.", e); + Vec::new() + } + }; + + debug!(target: "client", "Obtained genesis transition proof: {:?}", proof); + + let mut batch = DBTransaction::new(); + chain.insert_epoch_transition(&mut batch, 0, EpochTransition { + block_hash: gh.hash(), + block_number: 0, + proof: proof, + }); + + client.db.read().write_buffered(batch); + } + } + + // ensure buffered changes are flushed. + client.db.read().flush().map_err(ClientError::Database)?; + Ok(client) + } + + /// Wakes up client if it's a sleep. + pub fn keep_alive(&self) { + let should_wake = match *self.mode.lock() { + Mode::Dark(..) | Mode::Passive(..) => true, + _ => false, + }; + if should_wake { + self.wake_up(); + (*self.sleep_state.lock()).last_activity = Some(Instant::now()); + } + } + + /// Adds an actor to be notified on certain events + pub fn add_notify(&self, target: Arc) { + self.notify.write().push(Arc::downgrade(&target)); + } - let transaction = - self.contract_call_tx(BlockId::Hash(*header.parent_hash()), addr, data); + /// Set a closure to call when we want to restart the client + pub fn set_exit_handler(&self, f: F) where F: Fn(bool, Option) + 'static + Send { + *self.exit_handler.lock() = Some(Box::new(f)); + } - let mut state = State::from_existing( - backend, - header.state_root().clone(), - self.engine.account_start_nonce(header.number()), - self.factories.clone(), - ).expect("state known to be available for just-imported block; qed"); + /// Returns engine reference. + pub fn engine(&self) -> &EthEngine { + &*self.engine + } - let options = TransactOptions::with_no_tracing().dont_check_nonce(); - let res = Executive::new(&mut state, &env_info, &*self.engine) - .transact(&transaction, options); + fn notify(&self, f: F) where F: Fn(&ChainNotify) { + for np in self.notify.read().iter() { + if let Some(n) = np.upgrade() { + f(&*n); + } + } + } - let res = match res { - Err(ExecutionError::Internal(e)) => - Err(format!("Internal error: {}", e)), - Err(e) => { - trace!(target: "client", "Proved call failed: {}", e); - Ok((Vec::new(), state.drop().1.extract_proof())) - } - Ok(res) => Ok((res.output, state.drop().1.extract_proof())), - }; + /// Register an action to be done if a mode/spec_name change happens. + pub fn on_user_defaults_change(&self, f: F) where F: 'static + FnMut(Option) + Send { + *self.on_user_defaults_change.lock() = Some(Box::new(f)); + } - res.map(|(output, proof)| (output, proof.into_iter().map(|x| x.into_vec()).collect())) - }; + /// Flush the block import queue. + pub fn flush_queue(&self) { + self.importer.block_queue.flush(); + while !self.importer.block_queue.queue_info().is_empty() { + self.import_verified_blocks(); + } + } - match (with_state)(&call) { - Ok(proof) => proof, - Err(e) => { - warn!(target: "client", "Failed to generate transition proof for block {}: {}", hash, e); - warn!(target: "client", "Snapshots produced by this client may be incomplete"); - Vec::new() - } - } - } - }; + /// The env info as of the best block. + pub fn latest_env_info(&self) -> EnvInfo { + self.env_info(BlockId::Latest).expect("Best block header always stored; qed") + } - debug!(target: "client", "Block {} signals epoch end.", hash); + /// The env info as of a given block. + /// returns `None` if the block unknown. + pub fn env_info(&self, id: BlockId) -> Option { + self.block_header(id).map(|header| { + EnvInfo { + number: header.number(), + author: header.author(), + timestamp: header.timestamp(), + difficulty: header.difficulty(), + last_hashes: self.build_last_hashes(&header.parent_hash()), + gas_used: U256::default(), + gas_limit: header.gas_limit(), + } + }) + } - let pending = PendingTransition { proof: proof }; - chain.insert_pending_transition(batch, hash, pending); - }, - EpochChange::No => {}, - EpochChange::Unsure(_) => { - warn!(target: "client", "Detected invalid engine implementation."); - warn!(target: "client", "Engine claims to require more block data, but everything provided."); + fn build_last_hashes(&self, parent_hash: &H256) -> Arc { + { + let hashes = self.last_hashes.read(); + if hashes.front().map_or(false, |h| h == parent_hash) { + let mut res = Vec::from(hashes.clone()); + res.resize(256, H256::default()); + return Arc::new(res); + } + } + let mut last_hashes = LastHashes::new(); + last_hashes.resize(256, H256::default()); + last_hashes[0] = parent_hash.clone(); + let chain = self.chain.read(); + for i in 0..255 { + match chain.block_details(&last_hashes[i]) { + Some(details) => { + last_hashes[i + 1] = details.parent.clone(); + }, + None => break, } } + let mut cached_hashes = self.last_hashes.write(); + *cached_hashes = VecDeque::from(last_hashes.clone()); + Arc::new(last_hashes) } - // check for ending of epoch and write transition if it occurs. - fn check_epoch_end<'a>(&self, header: &'a Header, chain: &BlockChain) { - let is_epoch_end = self.engine.is_epoch_end( - header, - &(|hash| chain.block_header(&hash)), - &(|hash| chain.get_pending_transition(hash)), // TODO: limit to current epoch. - ); - - if let Some(proof) = is_epoch_end { - debug!(target: "client", "Epoch transition at block {}", header.hash()); - - let mut batch = DBTransaction::new(); - chain.insert_epoch_transition(&mut batch, header.number(), EpochTransition { - block_hash: header.hash(), - block_number: header.number(), - proof: proof, - }); - // always write the batch directly since epoch transition proofs are - // fetched from a DB iterator and DB iterators are only available on - // flushed data. - self.db.read().write(batch).expect("DB flush failed"); - } + /// This is triggered by a message coming from a block queue when the block is ready for insertion + pub fn import_verified_blocks(&self) -> usize { + self.importer.import_verified_blocks(self) } // use a state-proving closure for the given block. fn with_proving_caller(&self, id: BlockId, with_call: F) -> T - where F: FnOnce(&::engines::Call) -> T + where F: FnOnce(&::machine::Call) -> T { let call = |a, d| { let tx = self.contract_call_tx(id, a, d); @@ -878,20 +974,20 @@ impl Client { /// Import transactions from the IO queue pub fn import_queued_transactions(&self, transactions: &[Bytes], peer_id: usize) -> usize { trace!(target: "external_tx", "Importing queued"); - let _timer = PerfTimer::new("import_queued_transactions"); + trace_time!("import_queued_transactions"); self.queue_transactions.fetch_sub(transactions.len(), AtomicOrdering::SeqCst); let txs: Vec = transactions.iter().filter_map(|bytes| UntrustedRlp::new(bytes).as_val().ok()).collect(); let hashes: Vec<_> = txs.iter().map(|tx| tx.hash()).collect(); self.notify(|notify| { notify.transactions_received(hashes.clone(), peer_id); }); - let results = self.miner.import_external_transactions(self, txs); + let results = self.importer.miner.import_external_transactions(self, txs); results.len() } /// Get shared miner reference. pub fn miner(&self) -> Arc { - self.miner.clone() + self.importer.miner.clone() } /// Replace io channel. Useful for testing. @@ -899,6 +995,18 @@ impl Client { *self.io_channel.lock() = io_channel; } + /// Get a copy of the best block's state. + pub fn latest_state(&self) -> State { + let header = self.best_block_header(); + State::from_existing( + self.state_db.read().boxed_clone_canon(&header.hash()), + header.state_root(), + self.engine.account_start_nonce(header.number()), + self.factories.clone() + ) + .expect("State root of best block header always valid.") + } + /// Attempt to get a copy of a specific block's final state. /// /// This will not fail if given BlockId::Latest. @@ -907,18 +1015,17 @@ impl Client { pub fn state_at(&self, id: BlockId) -> Option> { // fast path for latest state. match id.clone() { - BlockId::Pending => return self.miner.pending_state(self.chain.read().best_block_number()).or_else(|| Some(self.state())), - BlockId::Latest => return Some(self.state()), + BlockId::Latest => return Some(self.latest_state()), _ => {}, } - let block_number = match self.block_number(id.clone()) { + let block_number = match self.block_number(id) { Some(num) => num, None => return None, }; self.block_header(id).and_then(|header| { - let db = self.state_db.lock().boxed_clone(); + let db = self.state_db.read().boxed_clone(); // early exit for pruned blocks if db.is_pruned() && self.pruning_info().earliest_state > block_number { @@ -935,25 +1042,15 @@ impl Client { /// This will not fail if given BlockId::Latest. /// Otherwise, this can fail (but may not) if the DB prunes state. pub fn state_at_beginning(&self, id: BlockId) -> Option> { - // fast path for latest state. - match id { - BlockId::Pending => self.state_at(BlockId::Latest), - id => match self.block_number(id) { - None | Some(0) => None, - Some(n) => self.state_at(BlockId::Number(n - 1)), - } + match self.block_number(id) { + None | Some(0) => None, + Some(n) => self.state_at(BlockId::Number(n - 1)), } } /// Get a copy of the best block's state. - pub fn state(&self) -> State { - let header = self.best_block_header(); - State::from_existing( - self.state_db.lock().boxed_clone_canon(&header.hash()), - header.state_root(), - self.engine.account_start_nonce(header.number()), - self.factories.clone()) - .expect("State root of best block header always valid.") + pub fn state(&self) -> Box { + Box::new(self.latest_state()) as Box<_> } /// Get info on the cache. @@ -964,20 +1061,22 @@ impl Client { /// Get the report. pub fn report(&self) -> ClientReport { let mut report = self.report.read().clone(); - report.state_db_mem = self.state_db.lock().mem_used(); + report.state_db_mem = self.state_db.read().mem_used(); report } /// Tick the client. // TODO: manage by real events. - pub fn tick(&self) { + pub fn tick(&self, prevent_sleep: bool) { self.check_garbage(); - self.check_snooze(); + if !prevent_sleep { + self.check_snooze(); + } } fn check_garbage(&self) { self.chain.read().collect_garbage(); - self.block_queue.collect_garbage(); + self.importer.block_queue.collect_garbage(); self.tracedb.read().collect_garbage(); } @@ -1018,7 +1117,7 @@ impl Client { /// Take a snapshot at the given block. /// If the ID given is "latest", this will default to 1000 blocks behind. pub fn take_snapshot(&self, writer: W, at: BlockId, p: &snapshot::Progress) -> Result<(), EthcoreError> { - let db = self.state_db.lock().journal_db().boxed_clone(); + let db = self.state_db.read().journal_db().boxed_clone(); let best_block_number = self.chain_info().best_block_number; let block_number = self.block_number(at).ok_or(snapshot::Error::InvalidStartingBlock(at))?; @@ -1056,20 +1155,19 @@ impl Client { self.history } - fn block_hash(chain: &BlockChain, miner: &Miner, id: BlockId) -> Option { + fn block_hash(chain: &BlockChain, id: BlockId) -> Option { match id { BlockId::Hash(hash) => Some(hash), BlockId::Number(number) => chain.block_hash(number), BlockId::Earliest => chain.block_hash(0), BlockId::Latest => Some(chain.best_block_hash()), - BlockId::Pending => miner.pending_block_header(chain.best_block_number()).map(|header| header.hash()) } } fn transaction_address(&self, id: TransactionId) -> Option { match id { TransactionId::Hash(ref hash) => self.chain.read().transaction_address(hash), - TransactionId::Location(id, index) => Self::block_hash(&self.chain.read(), &self.miner, id).map(|hash| TransactionAddress { + TransactionId::Location(id, index) => Self::block_hash(&self.chain.read(), id).map(|hash| TransactionAddress { block_hash: hash, index: index, }) @@ -1080,7 +1178,7 @@ impl Client { if !self.liveness.load(AtomicOrdering::Relaxed) { self.liveness.store(true, AtomicOrdering::Relaxed); self.notify(|n| n.start()); - trace!(target: "mode", "wake_up: Waking."); + info!(target: "mode", "wake_up: Waking."); } } @@ -1090,11 +1188,11 @@ impl Client { if self.queue_info().total_queue_size() <= MAX_QUEUE_SIZE_TO_SLEEP_ON { self.liveness.store(false, AtomicOrdering::Relaxed); self.notify(|n| n.stop()); - trace!(target: "mode", "sleep: Sleeping."); + info!(target: "mode", "sleep: Sleeping."); } else { - trace!(target: "mode", "sleep: Cannot sleep - syncing ongoing."); + info!(target: "mode", "sleep: Cannot sleep - syncing ongoing."); // TODO: Consider uncommenting. - //*self.last_activity.lock() = Some(Instant::now()); + //(*self.sleep_state.lock()).last_activity = Some(Instant::now()); } } } @@ -1113,23 +1211,30 @@ impl Client { }.fake_sign(from) } - fn do_virtual_call(&self, env_info: &EnvInfo, state: &mut State, t: &SignedTransaction, analytics: CallAnalytics) -> Result { - fn call( + fn do_virtual_call( + machine: &::machine::EthereumMachine, + env_info: &EnvInfo, + state: &mut State, + t: &SignedTransaction, + analytics: CallAnalytics, + ) -> Result { + fn call( state: &mut State, env_info: &EnvInfo, - engine: &E, + machine: &::machine::EthereumMachine, state_diff: bool, transaction: &SignedTransaction, options: TransactOptions, - ) -> Result where - E: Engine + ?Sized, + ) -> Result, CallError> where T: trace::Tracer, V: trace::VMTracer, { - let options = options.dont_check_nonce(); + let options = options + .dont_check_nonce() + .save_output_from_contract(); let original_state = if state_diff { Some(state.clone()) } else { None }; - let mut ret = Executive::new(state, env_info, engine).transact_virtual(transaction, options)?; + let mut ret = Executive::new(state, env_info, machine).transact_virtual(transaction, options)?; if let Some(original) = original_state { ret.state_diff = Some(state.diff_from(original).map_err(ExecutionError::from)?); @@ -1138,59 +1243,216 @@ impl Client { } let state_diff = analytics.state_diffing; - let engine = &*self.engine; match (analytics.transaction_tracing, analytics.vm_tracing) { - (true, true) => call(state, env_info, engine, state_diff, t, TransactOptions::with_tracing_and_vm_tracing()), - (true, false) => call(state, env_info, engine, state_diff, t, TransactOptions::with_tracing()), - (false, true) => call(state, env_info, engine, state_diff, t, TransactOptions::with_vm_tracing()), - (false, false) => call(state, env_info, engine, state_diff, t, TransactOptions::with_no_tracing()), + (true, true) => call(state, env_info, machine, state_diff, t, TransactOptions::with_tracing_and_vm_tracing()), + (true, false) => call(state, env_info, machine, state_diff, t, TransactOptions::with_tracing()), + (false, true) => call(state, env_info, machine, state_diff, t, TransactOptions::with_vm_tracing()), + (false, false) => call(state, env_info, machine, state_diff, t, TransactOptions::with_no_tracing()), + } + } + + fn block_number_ref(&self, id: &BlockId) -> Option { + match *id { + BlockId::Number(number) => Some(number), + BlockId::Hash(ref hash) => self.chain.read().block_number(hash), + BlockId::Earliest => Some(0), + BlockId::Latest => Some(self.chain.read().best_block_number()), + } + } +} + +impl snapshot::DatabaseRestore for Client { + /// Restart the client with a new backend + fn restore_db(&self, new_db: &str) -> Result<(), EthcoreError> { + trace!(target: "snapshot", "Replacing client database with {:?}", new_db); + + let _import_lock = self.importer.import_lock.lock(); + let mut state_db = self.state_db.write(); + let mut chain = self.chain.write(); + let mut tracedb = self.tracedb.write(); + self.importer.miner.clear(); + let db = self.db.write(); + db.restore(new_db)?; + + let cache_size = state_db.cache_size(); + *state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE), cache_size); + *chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone())); + *tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone()); + Ok(()) + } +} + +impl Nonce for Client { + fn nonce(&self, address: &Address, id: BlockId) -> Option { + self.state_at(id).and_then(|s| s.nonce(address).ok()) + } +} + +impl Balance for Client { + fn balance(&self, address: &Address, state: StateOrBlock) -> Option { + match state { + StateOrBlock::State(s) => s.balance(address).ok(), + StateOrBlock::Block(id) => self.state_at(id).and_then(|s| s.balance(address).ok()) + } + } +} + +impl AccountData for Client {} + +impl ChainInfo for Client { + fn chain_info(&self) -> BlockChainInfo { + let mut chain_info = self.chain.read().chain_info(); + chain_info.pending_total_difficulty = chain_info.total_difficulty + self.importer.block_queue.total_difficulty(); + chain_info + } +} + +impl BlockInfo for Client { + fn block_header(&self, id: BlockId) -> Option<::encoded::Header> { + let chain = self.chain.read(); + + Self::block_hash(&chain, id).and_then(|hash| chain.block_header_data(&hash)) + } + + fn best_block_header(&self) -> encoded::Header { + self.chain.read().best_block_header() + } + + fn block(&self, id: BlockId) -> Option { + let chain = self.chain.read(); + + Self::block_hash(&chain, id).and_then(|hash| { + chain.block(&hash) + }) + } + + fn code_hash(&self, address: &Address, id: BlockId) -> Option { + self.state_at(id).and_then(|s| s.code_hash(address).ok()) + } +} + +impl TransactionInfo for Client { + fn transaction_block(&self, id: TransactionId) -> Option { + self.transaction_address(id).map(|addr| addr.block_hash) + } +} + +impl BlockChainTrait for Client {} + +impl RegistryInfo for Client { + fn registry_address(&self, name: String, block: BlockId) -> Option
{ + let address = self.registrar_address?; + + self.registrar.functions() + .get_address() + .call(keccak(name.as_bytes()), "A", &|data| self.call_contract(block, address, data)) + .ok() + .and_then(|a| if a.is_zero() { + None + } else { + Some(a) + }) + } +} + +impl CallContract for Client { + fn call_contract(&self, block_id: BlockId, address: Address, data: Bytes) -> Result { + let state_pruned = || CallError::StatePruned.to_string(); + let state = &mut self.state_at(block_id).ok_or_else(&state_pruned)?; + let header = self.block_header(block_id).ok_or_else(&state_pruned)?; + + let transaction = self.contract_call_tx(block_id, address, data); + + self.call(&transaction, Default::default(), state, &header.decode()) + .map_err(|e| format!("{:?}", e)) + .map(|executed| executed.output) + } +} + +impl ImportBlock for Client { + fn import_block(&self, bytes: Bytes) -> Result { + use verification::queue::kind::BlockLike; + use verification::queue::kind::blocks::Unverified; + + // create unverified block here so the `keccak` calculation can be cached. + let unverified = Unverified::new(bytes); + + { + if self.chain.read().is_known(&unverified.hash()) { + return Err(BlockImportError::Import(ImportError::AlreadyInChain)); + } + let status = self.block_status(BlockId::Hash(unverified.parent_hash())); + if status == BlockStatus::Unknown || status == BlockStatus::Pending { + return Err(BlockImportError::Block(BlockError::UnknownParent(unverified.parent_hash()))); + } + } + Ok(self.importer.block_queue.import(unverified)?) + } + + fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { + { + // check block order + let header = BlockView::new(&block_bytes).header_view(); + if self.chain.read().is_known(&header.hash()) { + return Err(BlockImportError::Import(ImportError::AlreadyInChain)); + } + let status = self.block_status(BlockId::Hash(header.parent_hash())); + if status == BlockStatus::Unknown || status == BlockStatus::Pending { + return Err(BlockImportError::Block(BlockError::UnknownParent(header.parent_hash()))); + } } + + self.importer.import_old_block(block_bytes, receipts_bytes, &**self.db.read(), &*self.chain.read()).map_err(Into::into) } } -impl snapshot::DatabaseRestore for Client { - /// Restart the client with a new backend - fn restore_db(&self, new_db: &str) -> Result<(), EthcoreError> { - trace!(target: "snapshot", "Replacing client database with {:?}", new_db); +impl StateClient for Client { + type State = State<::state_db::StateDB>; - let _import_lock = self.import_lock.lock(); - let mut state_db = self.state_db.lock(); - let mut chain = self.chain.write(); - let mut tracedb = self.tracedb.write(); - self.miner.clear(); - let db = self.db.write(); - db.restore(new_db)?; + fn latest_state(&self) -> Self::State { + Client::latest_state(self) + } - let cache_size = state_db.cache_size(); - *state_db = StateDB::new(journaldb::new(db.clone(), self.pruning, ::db::COL_STATE), cache_size); - *chain = Arc::new(BlockChain::new(self.config.blockchain.clone(), &[], db.clone())); - *tracedb = TraceDB::new(self.config.tracing.clone(), db.clone(), chain.clone()); - Ok(()) + fn state_at(&self, id: BlockId) -> Option { + Client::state_at(self, id) } } -impl BlockChainClient for Client { - fn call(&self, transaction: &SignedTransaction, analytics: CallAnalytics, block: BlockId) -> Result { - let mut env_info = self.env_info(block).ok_or(CallError::StatePruned)?; - env_info.gas_limit = U256::max_value(); - - // that's just a copy of the state. - let mut state = self.state_at(block).ok_or(CallError::StatePruned)?; +impl Call for Client { + type State = State<::state_db::StateDB>; + + fn call(&self, transaction: &SignedTransaction, analytics: CallAnalytics, state: &mut Self::State, header: &Header) -> Result { + let env_info = EnvInfo { + number: header.number(), + author: header.author().clone(), + timestamp: header.timestamp(), + difficulty: header.difficulty().clone(), + last_hashes: self.build_last_hashes(header.parent_hash()), + gas_used: U256::default(), + gas_limit: U256::max_value(), + }; + let machine = self.engine.machine(); - self.do_virtual_call(&env_info, &mut state, transaction, analytics) + Self::do_virtual_call(&machine, &env_info, state, transaction, analytics) } - fn call_many(&self, transactions: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result, CallError> { - let mut env_info = self.env_info(block).ok_or(CallError::StatePruned)?; - env_info.gas_limit = U256::max_value(); + fn call_many(&self, transactions: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result, CallError> { + let mut env_info = EnvInfo { + number: header.number(), + author: header.author().clone(), + timestamp: header.timestamp(), + difficulty: header.difficulty().clone(), + last_hashes: self.build_last_hashes(header.parent_hash()), + gas_used: U256::default(), + gas_limit: U256::max_value(), + }; - // that's just a copy of the state. - let mut state = self.state_at(block).ok_or(CallError::StatePruned)?; let mut results = Vec::with_capacity(transactions.len()); + let machine = self.engine.machine(); for &(ref t, analytics) in transactions { - let ret = self.do_virtual_call(&env_info, &mut state, t, analytics)?; + let ret = Self::do_virtual_call(machine, &env_info, state, t, analytics)?; env_info.gas_used = ret.cumulative_gas_used; results.push(ret); } @@ -1198,36 +1460,41 @@ impl BlockChainClient for Client { Ok(results) } - fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result { - const UPPER_CEILING: u64 = 1_000_000_000_000u64; - let (mut upper, env_info) = { - let mut env_info = self.env_info(block).ok_or(CallError::StatePruned)?; - let initial_upper = env_info.gas_limit; - env_info.gas_limit = UPPER_CEILING.into(); - (initial_upper, env_info) + fn estimate_gas(&self, t: &SignedTransaction, state: &Self::State, header: &Header) -> Result { + let (mut upper, max_upper, env_info) = { + let init = *header.gas_limit(); + let max = init * U256::from(10); + + let env_info = EnvInfo { + number: header.number(), + author: header.author().clone(), + timestamp: header.timestamp(), + difficulty: header.difficulty().clone(), + last_hashes: self.build_last_hashes(header.parent_hash()), + gas_used: U256::default(), + gas_limit: max, + }; + + (init, max, env_info) }; - // that's just a copy of the state. - let original_state = self.state_at(block).ok_or(CallError::StatePruned)?; let sender = t.sender(); - let options = || TransactOptions::with_tracing(); + let options = || TransactOptions::with_tracing().dont_check_nonce(); let cond = |gas| { let mut tx = t.as_unsigned().clone(); tx.gas = gas; let tx = tx.fake_sign(sender); - let mut state = original_state.clone(); - Ok(Executive::new(&mut state, &env_info, &*self.engine) + let mut clone = state.clone(); + Ok(Executive::new(&mut clone, &env_info, self.engine.machine()) .transact_virtual(&tx, options()) .map(|r| r.exception.is_none()) .unwrap_or(false)) }; if !cond(upper)? { - // impossible at block gas limit - try `UPPER_CEILING` instead. - // TODO: consider raising limit by powers of two. - upper = UPPER_CEILING.into(); + upper = max_upper; if !cond(upper)? { trace!(target: "estimate_gas", "estimate_gas failed with {}", upper); let err = ExecutionError::Internal(format!("Requires higher than upper limit of {}", upper)); @@ -1263,31 +1530,44 @@ impl BlockChainClient for Client { trace!(target: "estimate_gas", "estimate_gas chopping {} .. {}", lower, upper); binary_chop(lower, upper, cond) } +} + +impl EngineInfo for Client { + fn engine(&self) -> &EthEngine { + Client::engine(self) + } +} +impl BlockChainClient for Client { fn replay(&self, id: TransactionId, analytics: CallAnalytics) -> Result { let address = self.transaction_address(id).ok_or(CallError::TransactionNotFound)?; - let mut env_info = self.env_info(BlockId::Hash(address.block_hash)).ok_or(CallError::StatePruned)?; - let body = self.block_body(BlockId::Hash(address.block_hash)).ok_or(CallError::StatePruned)?; - let mut state = self.state_at_beginning(BlockId::Hash(address.block_hash)).ok_or(CallError::StatePruned)?; - let mut txs = body.transactions(); + let block = BlockId::Hash(address.block_hash); - if address.index >= txs.len() { - return Err(CallError::TransactionNotFound); - } + const PROOF: &'static str = "The transaction address contains a valid index within block; qed"; + Ok(self.replay_block_transactions(block, analytics)?.nth(address.index).expect(PROOF)) + } + + fn replay_block_transactions(&self, block: BlockId, analytics: CallAnalytics) -> Result>, CallError> { + let mut env_info = self.env_info(block).ok_or(CallError::StatePruned)?; + let body = self.block_body(block).ok_or(CallError::StatePruned)?; + let mut state = self.state_at_beginning(block).ok_or(CallError::StatePruned)?; + let txs = body.transactions(); + let engine = self.engine.clone(); const PROOF: &'static str = "Transactions fetched from blockchain; blockchain transactions are valid; qed"; - let rest = txs.split_off(address.index); - for t in txs { - let t = SignedTransaction::new(t).expect(PROOF); - let x = Executive::new(&mut state, &env_info, &*self.engine).transact(&t, TransactOptions::with_no_tracing())?; - env_info.gas_used = env_info.gas_used + x.gas_used; - } - let first = rest.into_iter().next().expect("We split off < `address.index`; Length is checked earlier; qed"); - let t = SignedTransaction::new(first).expect(PROOF); + const EXECUTE_PROOF: &'static str = "Transaction replayed; qed"; - self.do_virtual_call(&env_info, &mut state, &t, analytics) + Ok(Box::new(txs.into_iter() + .map(move |t| { + let t = SignedTransaction::new(t).expect(PROOF); + let machine = engine.machine(); + let x = Self::do_virtual_call(machine, &env_info, &mut state, &t, analytics).expect(EXECUTE_PROOF); + env_info.gas_used = env_info.gas_used + x.gas_used; + x + }))) } + fn mode(&self) -> IpcMode { let r = self.mode.lock().clone().into(); trace!(target: "mode", "Asked for mode = {:?}. returning {:?}", &*self.mode.lock(), r); @@ -1337,94 +1617,29 @@ impl BlockChainClient for Client { } } - fn best_block_header(&self) -> encoded::Header { - self.chain.read().best_block_header() - } - - fn block_header(&self, id: BlockId) -> Option<::encoded::Header> { - let chain = self.chain.read(); - - if let BlockId::Pending = id { - if let Some(block) = self.miner.pending_block(chain.best_block_number()) { - return Some(encoded::Header::new(block.header.rlp(Seal::Without))); - } - // fall back to latest - return self.block_header(BlockId::Latest); - } - - Self::block_hash(&chain, &self.miner, id).and_then(|hash| chain.block_header_data(&hash)) - } - fn block_number(&self, id: BlockId) -> Option { - match id { - BlockId::Number(number) => Some(number), - BlockId::Hash(ref hash) => self.chain.read().block_number(hash), - BlockId::Earliest => Some(0), - BlockId::Latest => Some(self.chain.read().best_block_number()), - BlockId::Pending => Some(self.chain.read().best_block_number() + 1), - } + self.block_number_ref(&id) } fn block_body(&self, id: BlockId) -> Option { let chain = self.chain.read(); - if let BlockId::Pending = id { - if let Some(block) = self.miner.pending_block(chain.best_block_number()) { - return Some(encoded::Body::new(BlockChain::block_to_body(&block.rlp_bytes(Seal::Without)))); - } - // fall back to latest - return self.block_body(BlockId::Latest); - } - - Self::block_hash(&chain, &self.miner, id).and_then(|hash| chain.block_body(&hash)) - } - - fn block(&self, id: BlockId) -> Option { - let chain = self.chain.read(); - - if let BlockId::Pending = id { - if let Some(block) = self.miner.pending_block(chain.best_block_number()) { - return Some(encoded::Block::new(block.rlp_bytes(Seal::Without))); - } - // fall back to latest - return self.block(BlockId::Latest); - } - - Self::block_hash(&chain, &self.miner, id).and_then(|hash| { - chain.block(&hash) - }) + Self::block_hash(&chain, id).and_then(|hash| chain.block_body(&hash)) } fn block_status(&self, id: BlockId) -> BlockStatus { - if let BlockId::Pending = id { - return BlockStatus::Pending; - } - let chain = self.chain.read(); - match Self::block_hash(&chain, &self.miner, id) { + match Self::block_hash(&chain, id) { Some(ref hash) if chain.is_known(hash) => BlockStatus::InChain, - Some(hash) => self.block_queue.status(&hash).into(), + Some(hash) => self.importer.block_queue.status(&hash).into(), None => BlockStatus::Unknown } } fn block_total_difficulty(&self, id: BlockId) -> Option { let chain = self.chain.read(); - if let BlockId::Pending = id { - let latest_difficulty = self.block_total_difficulty(BlockId::Latest).expect("blocks in chain have details; qed"); - let pending_difficulty = self.miner.pending_block_header(chain.best_block_number()).map(|header| *header.difficulty()); - if let Some(difficulty) = pending_difficulty { - return Some(difficulty + latest_difficulty); - } - // fall back to latest - return Some(latest_difficulty); - } - Self::block_hash(&chain, &self.miner, id).and_then(|hash| chain.block_details(&hash)).map(|d| d.total_difficulty) - } - - fn nonce(&self, address: &Address, id: BlockId) -> Option { - self.state_at(id).and_then(|s| s.nonce(address).ok()) + Self::block_hash(&chain, id).and_then(|hash| chain.block_details(&hash)).map(|d| d.total_difficulty) } fn storage_root(&self, address: &Address, id: BlockId) -> Option { @@ -1433,19 +1648,24 @@ impl BlockChainClient for Client { fn block_hash(&self, id: BlockId) -> Option { let chain = self.chain.read(); - Self::block_hash(&chain, &self.miner, id) + Self::block_hash(&chain, id) } - fn code(&self, address: &Address, id: BlockId) -> Option> { - self.state_at(id).and_then(|s| s.code(address).ok()).map(|c| c.map(|c| (&*c).clone())) - } + fn code(&self, address: &Address, state: StateOrBlock) -> Option> { + let result = match state { + StateOrBlock::State(s) => s.code(address).ok(), + StateOrBlock::Block(id) => self.state_at(id).and_then(|s| s.code(address).ok()) + }; - fn balance(&self, address: &Address, id: BlockId) -> Option { - self.state_at(id).and_then(|s| s.balance(address).ok()) + // Converting from `Option>>` to `Option>` + result.map(|c| c.map(|c| (&*c).clone())) } - fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option { - self.state_at(id).and_then(|s| s.storage_at(address, position).ok()) + fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option { + match state { + StateOrBlock::State(s) => s.storage_at(address, position).ok(), + StateOrBlock::Block(id) => self.state_at(id).and_then(|s| s.storage_at(address, position).ok()) + } } fn list_accounts(&self, id: BlockId, after: Option<&Address>, count: u64) -> Option> { @@ -1503,7 +1723,7 @@ impl BlockChainClient for Client { }; let (_, db) = state.drop(); - let account_db = self.factories.accountdb.readonly(db.as_hashdb(), account.sha3()); + let account_db = self.factories.accountdb.readonly(db.as_hashdb(), keccak(account)); let trie = match self.factories.trie.readonly(account_db.as_hashdb(), &root) { Ok(trie) => trie, _ => { @@ -1534,10 +1754,6 @@ impl BlockChainClient for Client { self.transaction_address(id).and_then(|address| self.chain.read().transaction(&address)) } - fn transaction_block(&self, id: TransactionId) -> Option { - self.transaction_address(id).map(|addr| addr.block_hash) - } - fn uncle(&self, id: UncleId) -> Option { let index = id.position; self.block_body(id.block).and_then(|body| body.view().uncle_rlp_at(index)) @@ -1560,7 +1776,7 @@ impl BlockChainClient for Client { .collect(); match (transaction, previous_receipts) { (Some(transaction), Some(previous_receipts)) => { - Some(transaction_receipt(self.engine(), transaction, previous_receipts)) + Some(transaction_receipt(self.engine().machine(), transaction, previous_receipts)) }, _ => None, } @@ -1580,75 +1796,36 @@ impl BlockChainClient for Client { } fn state_data(&self, hash: &H256) -> Option { - self.state_db.lock().journal_db().state(hash) + self.state_db.read().journal_db().state(hash) } fn block_receipts(&self, hash: &H256) -> Option { self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts).into_vec()) } - fn import_block(&self, bytes: Bytes) -> Result { - use verification::queue::kind::BlockLike; - use verification::queue::kind::blocks::Unverified; - - // create unverified block here so the `sha3` calculation can be cached. - let unverified = Unverified::new(bytes); - - { - if self.chain.read().is_known(&unverified.hash()) { - return Err(BlockImportError::Import(ImportError::AlreadyInChain)); - } - let status = self.block_status(BlockId::Hash(unverified.parent_hash())); - if status == BlockStatus::Unknown || status == BlockStatus::Pending { - return Err(BlockImportError::Block(BlockError::UnknownParent(unverified.parent_hash()))); - } - } - Ok(self.block_queue.import(unverified)?) - } - - fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result { - { - // check block order - let header = BlockView::new(&block_bytes).header_view(); - if self.chain.read().is_known(&header.hash()) { - return Err(BlockImportError::Import(ImportError::AlreadyInChain)); - } - let status = self.block_status(BlockId::Hash(header.parent_hash())); - if status == BlockStatus::Unknown || status == BlockStatus::Pending { - return Err(BlockImportError::Block(BlockError::UnknownParent(header.parent_hash()))); - } - } - self.import_old_block(block_bytes, receipts_bytes).map_err(Into::into) - } - fn queue_info(&self) -> BlockQueueInfo { - self.block_queue.queue_info() + self.importer.block_queue.queue_info() } fn clear_queue(&self) { - self.block_queue.clear(); - } - - fn chain_info(&self) -> BlockChainInfo { - let mut chain_info = self.chain.read().chain_info(); - chain_info.pending_total_difficulty = chain_info.total_difficulty + self.block_queue.total_difficulty(); - chain_info + self.importer.block_queue.clear(); } fn additional_params(&self) -> BTreeMap { self.engine.additional_params().into_iter().collect() } - fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option> { - match (self.block_number(from_block), self.block_number(to_block)) { - (Some(from), Some(to)) => Some(self.chain.read().blocks_with_bloom(bloom, from, to)), - _ => None - } - } - fn logs(&self, filter: Filter) -> Vec { + let (from, to) = match (self.block_number_ref(&filter.from_block), self.block_number_ref(&filter.to_block)) { + (Some(from), Some(to)) => (from, to), + _ => return Vec::new(), + }; + + let chain = self.chain.read(); let blocks = filter.bloom_possibilities().iter() - .filter_map(|bloom| self.blocks_with_bloom(bloom, filter.from_block.clone(), filter.to_block.clone())) + .map(move |bloom| { + chain.blocks_with_bloom(bloom, from, to) + }) .flat_map(|m| m) // remove duplicate elements .collect::>() @@ -1659,22 +1836,22 @@ impl BlockChainClient for Client { } fn filter_traces(&self, filter: TraceFilter) -> Option> { - let start = self.block_number(filter.range.start); - let end = self.block_number(filter.range.end); - - match (start, end) { - (Some(s), Some(e)) => { - let filter = trace::Filter { - range: s as usize..e as usize, - from_address: From::from(filter.from_address), - to_address: From::from(filter.to_address), - }; + let start = self.block_number(filter.range.start)?; + let end = self.block_number(filter.range.end)?; - let traces = self.tracedb.read().filter(&filter); - Some(traces) - }, - _ => None, - } + let db_filter = trace::Filter { + range: start as usize..end as usize, + from_address: filter.from_address.into(), + to_address: filter.to_address.into(), + }; + + let traces = self.tracedb.read() + .filter(&db_filter) + .into_iter() + .skip(filter.after.unwrap_or(0)) + .take(filter.count.unwrap_or(usize::max_value())) + .collect(); + Some(traces) } fn trace(&self, trace: TraceId) -> Option { @@ -1700,7 +1877,7 @@ impl BlockChainClient for Client { } fn last_hashes(&self) -> LastHashes { - (*self.build_last_hashes(self.chain.read().best_block_hash())).clone() + (*self.build_last_hashes(&self.chain.read().best_block_hash())).clone() } fn queue_transactions(&self, transactions: Vec, peer_id: usize) { @@ -1726,7 +1903,7 @@ impl BlockChainClient for Client { let chain = self.chain.read(); (chain.best_block_number(), chain.best_block_timestamp()) }; - self.miner.ready_transactions(number, timestamp) + self.importer.miner.ready_transactions(number, timestamp) } fn queue_consensus_message(&self, message: Bytes) { @@ -1753,48 +1930,27 @@ impl BlockChainClient for Client { fn pruning_info(&self) -> PruningInfo { PruningInfo { earliest_chain: self.chain.read().first_block_number().unwrap_or(1), - earliest_state: self.state_db.lock().journal_db().earliest_era().unwrap_or(0), + earliest_state: self.state_db.read().journal_db().earliest_era().unwrap_or(0), } } - fn call_contract(&self, block_id: BlockId, address: Address, data: Bytes) -> Result { - let transaction = self.contract_call_tx(block_id, address, data); - - self.call(&transaction, Default::default(), block_id) - .map_err(|e| format!("{:?}", e)) - .map(|executed| { - executed.output - }) - } - - fn transact_contract(&self, address: Address, data: Bytes) -> Result { + fn transact_contract(&self, address: Address, data: Bytes) -> Result { let transaction = Transaction { - nonce: self.latest_nonce(&self.miner.author()), + nonce: self.latest_nonce(&self.importer.miner.author()), action: Action::Call(address), - gas: self.miner.gas_floor_target(), - gas_price: self.miner.sensible_gas_price(), + gas: self.importer.miner.gas_floor_target(), + gas_price: self.importer.miner.sensible_gas_price(), value: U256::zero(), data: data, }; let chain_id = self.engine.signing_chain_id(&self.latest_env_info()); let signature = self.engine.sign(transaction.hash(chain_id))?; let signed = SignedTransaction::new(transaction.with_signature(signature, chain_id))?; - self.miner.import_own_transaction(self, signed.into()) + self.importer.miner.import_own_transaction(self, signed.into()) } fn registrar_address(&self) -> Option
{ - self.registrar.lock().as_ref().map(|r| r.address) - } - - fn registry_address(&self, name: String) -> Option
{ - self.registrar.lock().as_ref() - .and_then(|r| { - let dispatch = move |reg_addr, data| { - future::done(self.call_contract(BlockId::Latest, reg_addr, data)) - }; - r.get_address(dispatch, name.as_bytes().sha3(), "A".to_string()).wait().ok() - }) - .and_then(|a| if a.is_zero() { None } else { Some(a) }) + self.registrar_address.clone() } fn eip86_transition(&self) -> u64 { @@ -1802,11 +1958,36 @@ impl BlockChainClient for Client { } } -impl MiningBlockChainClient for Client { - fn latest_schedule(&self) -> Schedule { - self.engine.schedule(self.latest_env_info().number) +impl ReopenBlock for Client { + fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { + let engine = &*self.engine; + let mut block = block.reopen(engine); + let max_uncles = engine.maximum_uncle_count(block.header().number()); + if block.uncles().len() < max_uncles { + let chain = self.chain.read(); + let h = chain.best_block_hash(); + // Add new uncles + let uncles = chain + .find_uncle_hashes(&h, engine.maximum_uncle_age()) + .unwrap_or_else(Vec::new); + + for h in uncles { + if !block.uncles().iter().any(|header| header.hash() == h) { + let uncle = chain.block_header(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed"); + block.push_uncle(uncle).expect("pushing up to maximum_uncle_count; + push_uncle is not ok only if more than maximum_uncle_count is pushed; + so all push_uncle are Ok; + qed"); + if block.uncles().len() >= max_uncles { break } + } + } + + } + block } +} +impl PrepareOpenBlock for Client { fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { let engine = &*self.engine; let chain = self.chain.read(); @@ -1818,10 +1999,10 @@ 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.state_db.lock().boxed_clone_canon(&h), + self.tracedb.read().tracing_enabled(), + self.state_db.read().boxed_clone_canon(&h), best_header, - self.build_last_hashes(h.clone()), + self.build_last_hashes(&h), author, gas_range_target, extra_data, @@ -1833,7 +2014,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; @@ -1844,71 +2025,36 @@ impl MiningBlockChainClient for Client { open_block } +} - fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { - let engine = &*self.engine; - let mut block = block.reopen(engine); - let max_uncles = engine.maximum_uncle_count(); - if block.uncles().len() < max_uncles { - let chain = self.chain.read(); - let h = chain.best_block_hash(); - // Add new uncles - let uncles = chain - .find_uncle_hashes(&h, engine.maximum_uncle_age()) - .unwrap_or_else(Vec::new); - - for h in uncles { - if !block.uncles().iter().any(|header| header.hash() == h) { - let uncle = chain.block_header(&h).expect("find_uncle_hashes only returns hashes for existing headers; qed"); - block.push_uncle(uncle).expect("pushing up to maximum_uncle_count; - push_uncle is not ok only if more than maximum_uncle_count is pushed; - so all push_uncle are Ok; - qed"); - if block.uncles().len() >= max_uncles { break } - } - } - - } - block - } - - fn vm_factory(&self) -> &EvmFactory { - &self.factories.vm - } +impl BlockProducer for Client {} - fn broadcast_proposal_block(&self, block: SealedBlock) { - self.notify(|notify| { - notify.new_blocks( - vec![], - vec![], - vec![], - vec![], - vec![], - vec![block.rlp_bytes()], - 0, - ); - }); +impl ScheduleInfo for Client { + fn latest_schedule(&self) -> Schedule { + self.engine.schedule(self.latest_env_info().number) } +} +impl ImportSealedBlock for Client { fn import_sealed_block(&self, block: SealedBlock) -> ImportResult { let h = block.header().hash(); - let start = precise_time_ns(); + let start = Instant::now(); let route = { // scope for self.import_lock - let _import_lock = self.import_lock.lock(); - let _timer = PerfTimer::new("import_sealed_block"); + let _import_lock = self.importer.import_lock.lock(); + trace_time!("import_sealed_block"); let number = block.header().number(); let block_data = block.rlp_bytes(); let header = block.header().clone(); - let route = self.commit_block(block, &header, &block_data); + let route = self.importer.commit_block(block, &header, &block_data, self); trace!(target: "client", "Imported sealed block #{} ({})", number, h); - self.state_db.lock().sync_cache(&route.enacted, &route.retracted, false); + self.state_db.write().sync_cache(&route.enacted, &route.retracted, false); route }; - let (enacted, retracted) = self.calculate_enacted_retracted(&[route]); - self.miner.chain_new_blocks(self, &[h.clone()], &[], &enacted, &retracted); + let (enacted, retracted) = self.importer.calculate_enacted_retracted(&[route]); + self.importer.miner.chain_new_blocks(self, &[h.clone()], &[], &enacted, &retracted); self.notify(|notify| { notify.new_blocks( vec![h.clone()], @@ -1917,7 +2063,10 @@ impl MiningBlockChainClient for Client { retracted.clone(), vec![h.clone()], vec![], - precise_time_ns() - start, + { + let elapsed = start.elapsed(); + elapsed.as_secs() * 1_000_000_000 + elapsed.subsec_nanos() as u64 + }, ); }); self.db.read().flush().expect("DB flush failed."); @@ -1925,13 +2074,37 @@ impl MiningBlockChainClient for Client { } } -impl EngineClient for Client { +impl BroadcastProposalBlock for Client { + fn broadcast_proposal_block(&self, block: SealedBlock) { + self.notify(|notify| { + notify.new_blocks( + vec![], + vec![], + vec![], + vec![], + vec![], + vec![block.rlp_bytes()], + 0, + ); + }); + } +} + +impl SealedBlockImporter for Client {} + +impl MiningBlockChainClient for Client { + fn vm_factory(&self) -> &VmFactory { + &self.factories.vm + } +} + +impl super::traits::EngineClient for Client { fn update_sealing(&self) { - self.miner.update_sealing(self) + self.importer.miner.update_sealing(self) } fn submit_seal(&self, block_hash: H256, seal: Vec) { - if self.miner.submit_seal(self, block_hash, seal).is_err() { + if self.importer.miner.submit_seal(self, block_hash, seal).is_err() { warn!(target: "poa", "Wrong internal seal submission!") } } @@ -1943,6 +2116,16 @@ impl EngineClient for Client { fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition> { self.chain.read().epoch_transition_for(parent_hash) } + + fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) } + + fn block_number(&self, id: BlockId) -> Option { + BlockChainClient::block_number(self, id) + } + + fn block_header(&self, id: BlockId) -> Option<::encoded::Header> { + BlockChainClient::block_header(self, id) + } } impl ProvingBlockChainClient for Client { @@ -1957,27 +2140,30 @@ impl ProvingBlockChainClient for Client { } fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec)> { - let (state, mut env_info) = match (self.state_at(id), self.env_info(id)) { + let (header, mut env_info) = match (self.block_header(id), self.env_info(id)) { (Some(s), Some(e)) => (s, e), _ => return None, }; env_info.gas_limit = transaction.gas.clone(); - let mut jdb = self.state_db.lock().journal_db().boxed_clone(); - let backend = state::backend::Proving::new(jdb.as_hashdb_mut()); - - let mut state = state.replace_backend(backend); - let options = TransactOptions::with_no_tracing().dont_check_nonce(); - let res = Executive::new(&mut state, &env_info, &*self.engine).transact(&transaction, options); - - match res { - Err(ExecutionError::Internal(_)) => None, - Err(e) => { - trace!(target: "client", "Proved call failed: {}", e); - Some((Vec::new(), state.drop().1.extract_proof())) - } - Ok(res) => Some((res.output, state.drop().1.extract_proof())), - } + let mut jdb = self.state_db.read().journal_db().boxed_clone(); + + state::prove_transaction( + jdb.as_hashdb_mut(), + header.state_root().clone(), + &transaction, + self.engine.machine(), + &env_info, + self.factories.clone(), + false, + ) + } + + + fn epoch_signal(&self, hash: H256) -> Option> { + // pending transitions are never deleted, and do not contain + // finality proofs by definition. + self.chain.read().get_pending_transition(hash).map(|pending| pending.proof) } } @@ -1989,7 +2175,7 @@ impl Drop for Client { /// Returns `LocalizedReceipt` given `LocalizedTransaction` /// and a vector of receipts from given block up to transaction index. -fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { +fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided."); let sender = tx.sender(); @@ -2013,7 +2199,7 @@ fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receip gas_used: receipt.gas_used - prior_gas_used, contract_address: match tx.action { Action::Call(_) => None, - Action::Create => Some(contract_address(engine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data).0) + Action::Create => Some(contract_address(machine.create_address_scheme(block_number), &sender, &tx.nonce, &tx.data).0) }, logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { entry: log, @@ -2025,7 +2211,7 @@ fn transaction_receipt(engine: &Engine, mut tx: LocalizedTransaction, mut receip log_index: no_of_logs + i, }).collect(), log_bloom: receipt.log_bloom, - state_root: receipt.state_root, + outcome: receipt.outcome, } } @@ -2034,14 +2220,14 @@ mod tests { #[test] fn should_not_cache_details_before_commit() { - use client::BlockChainClient; - use tests::helpers::*; + use client::{BlockChainClient, ChainInfo}; + use tests::helpers::{generate_dummy_client, get_good_dummy_block_hash}; use std::thread; use std::time::Duration; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; - use util::kvdb::DBTransaction; + use kvdb::DBTransaction; let client = generate_dummy_client(0); let genesis = client.chain_info().best_block_hash; @@ -2067,22 +2253,21 @@ mod tests { #[test] fn should_return_correct_log_index() { + use hash::keccak; use super::transaction_receipt; use ethkey::KeyPair; use log_entry::{LogEntry, LocalizedLogEntry}; - use receipt::{Receipt, LocalizedReceipt}; + use receipt::{Receipt, LocalizedReceipt, TransactionOutcome}; use transaction::{Transaction, LocalizedTransaction, Action}; - use util::Hashable; - use tests::helpers::TestEngine; // given - let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap(); + let key = KeyPair::from_secret_slice(&keccak("test")).unwrap(); let secret = key.secret(); - let engine = TestEngine::new(0); + let machine = ::ethereum::new_frontier_test_machine(); let block_number = 1; let block_hash = 5.into(); - let state_root = Some(99.into()); + let state_root = 99.into(); let gas_used = 10.into(); let raw_tx = Transaction { nonce: 0.into(), @@ -2110,19 +2295,19 @@ mod tests { data: vec![], }]; let receipts = vec![Receipt { - state_root: state_root, + outcome: TransactionOutcome::StateRoot(state_root), gas_used: 5.into(), log_bloom: Default::default(), logs: vec![logs[0].clone()], }, Receipt { - state_root: state_root, + outcome: TransactionOutcome::StateRoot(state_root), gas_used: gas_used, log_bloom: Default::default(), logs: logs.clone(), }]; // when - let receipt = transaction_receipt(&engine, transaction, receipts); + let receipt = transaction_receipt(&machine, transaction, receipts); // then assert_eq!(receipt, LocalizedReceipt { @@ -2151,7 +2336,7 @@ mod tests { log_index: 2, }], log_bloom: Default::default(), - state_root: state_root, + outcome: TransactionOutcome::StateRoot(state_root), }); } } diff --git a/ethcore/src/client/config.rs b/ethcore/src/client/config.rs index 43a7a821ae221e4ca8b693a250dceb77d4dbd687..3c26c462123c50babb53f02f4cdf3cd83d7d2eb8 100644 --- a/ethcore/src/client/config.rs +++ b/ethcore/src/client/config.rs @@ -20,7 +20,8 @@ use std::fmt::{Display, Formatter, Error as FmtError}; use mode::Mode as IpcMode; use verification::{VerifierType, QueueConfig}; -use util::{journaldb, CompactionProfile}; +use journaldb; +use kvdb_rocksdb::CompactionProfile; pub use std::time::Duration; pub use blockchain::Config as BlockChainConfig; @@ -140,7 +141,7 @@ pub struct ClientConfig { pub pruning: journaldb::Algorithm, /// The name of the client instance. pub name: String, - /// RocksDB state column cache-size if not default + /// RocksDB column cache-size if not default pub db_cache_size: Option, /// State db compaction profile pub db_compaction: DatabaseCompactionProfile, diff --git a/ethcore/src/client/error.rs b/ethcore/src/client/error.rs index ff8b6d2ce107bfdf17abcc96fba1e5e2b008338f..d2af13a3b27f8da862c0431c7add05e4083f51f3 100644 --- a/ethcore/src/client/error.rs +++ b/ethcore/src/client/error.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::UtilError; use std::fmt::{Display, Formatter, Error as FmtError}; - -use util::trie::TrieError; +use util_error::UtilError; +use kvdb; +use trie::TrieError; /// Client configuration errors. #[derive(Debug)] @@ -25,7 +25,7 @@ pub enum Error { /// TrieDB-related error. Trie(TrieError), /// Database error - Database(String), + Database(kvdb::Error), /// Util error Util(UtilError), } diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index a455a37240195a3a7bafcae8a46b73469adea604..b91414ca8fa69ce85072908abece3bc300ffa07a 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -18,24 +18,25 @@ use std::fmt; use std::sync::Arc; -use util::{self, U256, H256, journaldb, trie}; -use util::kvdb::{self, KeyValueDB}; -use {state, state_db, client, executive, trace, transaction, db, spec, pod_state}; +use ethereum_types::{H256, U256, H160}; +use {factory, journaldb, trie, kvdb_memorydb, bytes}; +use kvdb::{self, KeyValueDB}; +use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt}; use factory::Factories; -use evm::{self, VMType}; +use evm::{VMType, FinalizationResult}; use vm::{self, ActionParams}; /// EVM test Error. #[derive(Debug)] pub enum EvmTestError { /// Trie integrity error. - Trie(util::TrieError), + Trie(trie::TrieError), /// EVM error. Evm(vm::Error), /// Initialization error. ClientError(::error::Error), /// Low-level database error. - Database(String), + Database(kvdb::Error), /// Post-condition failure, PostCondition(String), } @@ -68,7 +69,8 @@ lazy_static! { pub static ref HOMESTEAD: spec::Spec = ethereum::new_homestead_test(); pub static ref EIP150: spec::Spec = ethereum::new_eip150_test(); pub static ref EIP161: spec::Spec = ethereum::new_eip161_test(); - pub static ref _METROPOLIS: spec::Spec = ethereum::new_metropolis_test(); + pub static ref BYZANTIUM: spec::Spec = ethereum::new_byzantium_test(); + pub static ref BYZANTIUM_TRANSITION: spec::Spec = ethereum::new_transition_test(); } /// Simplified, single-block EVM test client. @@ -77,6 +79,15 @@ pub struct EvmTestClient<'a> { spec: &'a spec::Spec, } +impl<'a> fmt::Debug for EvmTestClient<'a> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("EvmTestClient") + .field("state", &self.state) + .field("spec", &self.spec.name) + .finish() + } +} + impl<'a> EvmTestClient<'a> { /// Converts a json spec definition into spec. pub fn spec_from_json(spec: &ForkSpec) -> Option<&'static spec::Spec> { @@ -85,7 +96,10 @@ impl<'a> EvmTestClient<'a> { ForkSpec::Homestead => Some(&*HOMESTEAD), ForkSpec::EIP150 => Some(&*EIP150), ForkSpec::EIP158 => Some(&*EIP161), - ForkSpec::Metropolis | ForkSpec::Byzantium | ForkSpec::Constantinople => None, + ForkSpec::Byzantium => Some(&*BYZANTIUM), + ForkSpec::EIP158ToByzantiumAt5 => Some(&BYZANTIUM_TRANSITION), + ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, + _ => None, } } @@ -113,14 +127,14 @@ impl<'a> EvmTestClient<'a> { fn factories() -> Factories { Factories { - vm: evm::Factory::new(VMType::Interpreter, 5 * 1024), + vm: factory::VmFactory::new(VMType::Interpreter, 5 * 1024), trie: trie::TrieFactory::new(trie::TrieSpec::Secure), accountdb: Default::default(), } } fn state_from_spec(spec: &'a spec::Spec, factories: &Factories) -> Result, EvmTestError> { - let db = Arc::new(kvdb::in_memory(db::NUM_COLUMNS.expect("We use column-based DB; qed"))); + let db = Arc::new(kvdb_memorydb::create(db::NUM_COLUMNS.expect("We use column-based DB; qed"))); let journal_db = journaldb::new(db.clone(), journaldb::Algorithm::EarlyMerge, db::COL_STATE); let mut state_db = state_db::StateDB::new(journal_db, 5 * 1024 * 1024); state_db = spec.ensure_db_good(state_db, factories)?; @@ -142,7 +156,7 @@ impl<'a> EvmTestClient<'a> { } fn state_from_pod(spec: &'a spec::Spec, factories: &Factories, pod_state: pod_state::PodState) -> Result, EvmTestError> { - let db = Arc::new(kvdb::in_memory(db::NUM_COLUMNS.expect("We use column-based DB; qed"))); + let db = Arc::new(kvdb_memorydb::create(db::NUM_COLUMNS.expect("We use column-based DB; qed"))); let journal_db = journaldb::new(db.clone(), journaldb::Algorithm::EarlyMerge, db::COL_STATE); let state_db = state_db::StateDB::new(journal_db, 5 * 1024 * 1024); let mut state = state::State::new( @@ -155,10 +169,19 @@ impl<'a> EvmTestClient<'a> { Ok(state) } + /// Return current state. + pub fn state(&self) -> &state::State { + &self.state + } + /// Execute the VM given ActionParams and tracer. /// Returns amount of gas left and the output. - pub fn call(&mut self, params: ActionParams, vm_tracer: &mut T) - -> Result<(U256, Vec), EvmTestError> + pub fn call( + &mut self, + params: ActionParams, + tracer: &mut T, + vm_tracer: &mut V, + ) -> Result { let genesis = self.spec.genesis_header(); let info = client::EnvInfo { @@ -166,52 +189,62 @@ impl<'a> EvmTestClient<'a> { author: *genesis.author(), timestamp: genesis.timestamp(), difficulty: *genesis.difficulty(), - last_hashes: Arc::new([util::H256::default(); 256].to_vec()), + last_hashes: Arc::new([H256::default(); 256].to_vec()), gas_used: 0.into(), gas_limit: *genesis.gas_limit(), }; let mut substate = state::Substate::new(); - let mut tracer = trace::NoopTracer; let mut output = vec![]; - let mut executive = executive::Executive::new(&mut self.state, &info, &*self.spec.engine); - let (gas_left, _) = executive.call( + let mut executive = executive::Executive::new(&mut self.state, &info, self.spec.engine.machine()); + executive.call( params, &mut substate, - util::BytesRef::Flexible(&mut output), - &mut tracer, + bytes::BytesRef::Flexible(&mut output), + tracer, vm_tracer, - ).map_err(EvmTestError::Evm)?; - - Ok((gas_left, output)) + ).map_err(EvmTestError::Evm) } /// Executes a SignedTransaction within context of the provided state and `EnvInfo`. /// Returns the state root, gas left and the output. - pub fn transact( + pub fn transact( &mut self, env_info: &client::EnvInfo, transaction: transaction::SignedTransaction, - vm_tracer: T, - ) -> TransactResult { + tracer: T, + vm_tracer: V, + ) -> TransactResult { let initial_gas = transaction.gas; // Verify transaction let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition); if let Err(error) = is_ok { return TransactResult::Err { state_root: *self.state.root(), - error, + error: error.into(), }; } // Apply transaction - let tracer = trace::NoopTracer; - let result = self.state.apply_with_tracing(&env_info, &*self.spec.engine, &transaction, tracer, vm_tracer); + let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer); + let scheme = self.spec.engine.machine().create_address_scheme(env_info.number); match result { - Ok(result) => TransactResult::Ok { - state_root: *self.state.root(), - gas_left: initial_gas - result.receipt.gas_used, - output: result.output + Ok(result) => { + self.state.commit().ok(); + TransactResult::Ok { + state_root: *self.state.root(), + gas_left: initial_gas - result.receipt.gas_used, + outcome: result.receipt.outcome, + output: result.output, + trace: result.trace, + vm_trace: result.vm_trace, + logs: result.receipt.logs, + contract_address: if let transaction::Action::Create = transaction.action { + Some(executive::contract_address(scheme, &transaction.sender(), &transaction.nonce, &transaction.data).0) + } else { + None + } + } }, Err(error) => TransactResult::Err { state_root: *self.state.root(), @@ -222,7 +255,8 @@ impl<'a> EvmTestClient<'a> { } /// A result of applying transaction to the state. -pub enum TransactResult { +#[derive(Debug)] +pub enum TransactResult { /// Successful execution Ok { /// State root @@ -231,6 +265,16 @@ pub enum TransactResult { gas_left: U256, /// Output output: Vec, + /// Traces + trace: Vec, + /// VM Traces + vm_trace: Option, + /// Created contract address (if any) + contract_address: Option, + /// Generated logs + logs: Vec, + /// outcome + outcome: receipt::TransactionOutcome, }, /// Transaction failed to run Err { diff --git a/ethcore/src/client/io_message.rs b/ethcore/src/client/io_message.rs new file mode 100644 index 0000000000000000000000000000000000000000..c2823a39f652d7d18fe7fda9860393dd4f141f69 --- /dev/null +++ b/ethcore/src/client/io_message.rs @@ -0,0 +1,41 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use ethereum_types::H256; +use bytes::Bytes; +use snapshot::ManifestData; + +/// Message type for external and internal events +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum ClientIoMessage { + /// Best Block Hash in chain has been changed + NewChainHead, + /// A block is ready + BlockVerified, + /// New transaction RLPs are ready to be imported + NewTransactions(Vec, usize), + /// Begin snapshot restoration + BeginRestoration(ManifestData), + /// Feed a state chunk to the snapshot service + FeedStateChunk(H256, Bytes), + /// Feed a block chunk to the snapshot service + FeedBlockChunk(H256, Bytes), + /// Take a snapshot for the block with given number. + TakeSnapshot(u64), + /// New consensus message received. + NewMessage(Bytes) +} + diff --git a/ethcore/src/client/mod.rs b/ethcore/src/client/mod.rs index 9377c2f4430410725c16a3016721aa35bd8c6235..b92240591b5c5af1f5e81e24050f10972f3dc96b 100644 --- a/ethcore/src/client/mod.rs +++ b/ethcore/src/client/mod.rs @@ -17,22 +17,27 @@ //! Blockchain database client. mod ancient_import; +mod client; mod config; mod error; mod evm_test_client; +mod io_message; mod test_client; mod trace; -mod client; pub use self::client::*; pub use self::config::{Mode, ClientConfig, DatabaseCompactionProfile, BlockChainConfig, VMType}; pub use self::error::Error; pub use self::evm_test_client::{EvmTestClient, EvmTestError, TransactResult}; +pub use self::io_message::ClientIoMessage; pub use self::test_client::{TestBlockChainClient, EachBlockWith}; pub use self::chain_notify::ChainNotify; -pub use self::traits::{BlockChainClient, MiningBlockChainClient, EngineClient}; - -pub use self::traits::ProvingBlockChainClient; +pub use self::traits::{ + Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, PrepareOpenBlock, CallContract, TransactionInfo, RegistryInfo, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, + StateOrBlock, StateClient, Call, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter +}; +pub use state::StateInfo; +pub use self::traits::{BlockChainClient, MiningBlockChainClient, EngineClient, ProvingBlockChainClient}; pub use types::ids::*; pub use types::trace_filter::Filter as TraceFilter; @@ -42,24 +47,9 @@ pub use types::call_analytics::CallAnalytics; pub use executive::{Executed, Executive, TransactOptions}; pub use vm::{LastHashes, EnvInfo}; -pub use error::{BlockImportError, TransactionImportError, TransactionImportResult}; +pub use error::{BlockImportError, TransactionImportError}; pub use verification::VerifierType; -/// IPC interfaces -#[cfg(feature="ipc")] -pub mod remote { - pub use super::traits::RemoteClient; - pub use super::chain_notify::ChainNotifyClient; -} - -mod traits { - #![allow(dead_code, unused_assignments, unused_variables, missing_docs)] // codegen issues - include!(concat!(env!("OUT_DIR"), "/traits.rs")); -} - -pub mod chain_notify { - //! Chain notify interface - #![allow(dead_code, unused_assignments, unused_variables, missing_docs)] // codegen issues - include!(concat!(env!("OUT_DIR"), "/chain_notify.rs")); -} +mod traits; +mod chain_notify; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 0e7e53e4381b117bdfbfcf36283e181dbd1578c7..b806183a2c941d792a2135939a87015d597e4f98 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -22,27 +22,34 @@ use std::collections::{HashMap, BTreeMap}; use std::mem; use itertools::Itertools; use rustc_hex::FromHex; -use util::*; +use hash::keccak; +use ethereum_types::{H256, U256, Address}; +use parking_lot::RwLock; +use journaldb; +use kvdb::DBValue; +use kvdb_memorydb; +use bytes::Bytes; use rlp::*; use ethkey::{Generator, Random}; -use devtools::*; -use transaction::{Transaction, LocalizedTransaction, PendingTransaction, SignedTransaction, Action}; -use blockchain::TreeRoute; +use transaction::{self, Transaction, LocalizedTransaction, PendingTransaction, SignedTransaction, Action}; +use blockchain::{TreeRoute, BlockReceipts}; use client::{ - BlockChainClient, MiningBlockChainClient, EngineClient, BlockChainInfo, BlockStatus, BlockId, + Nonce, Balance, ChainInfo, BlockInfo, ReopenBlock, CallContract, TransactionInfo, RegistryInfo, + PrepareOpenBlock, BlockChainClient, MiningBlockChainClient, BlockChainInfo, BlockStatus, BlockId, TransactionId, UncleId, TraceId, TraceFilter, LastHashes, CallAnalytics, BlockImportError, - ProvingBlockChainClient, + ProvingBlockChainClient, ScheduleInfo, ImportSealedBlock, BroadcastProposalBlock, ImportBlock, StateOrBlock, + Call, StateClient, EngineInfo, AccountData, BlockChain, BlockProducer, SealedBlockImporter }; use db::{NUM_COLUMNS, COL_STATE}; use header::{Header as BlockHeader, BlockNumber}; use filter::Filter; use log_entry::LocalizedLogEntry; -use receipt::{Receipt, LocalizedReceipt}; -use blockchain::extras::BlockReceipts; +use receipt::{Receipt, LocalizedReceipt, TransactionOutcome}; use error::{ImportResult, Error as EthcoreError}; -use evm::{Factory as EvmFactory, VMType}; +use evm::VMType; +use factory::VmFactory; use vm::Schedule; -use miner::{Miner, MinerService, TransactionImportResult}; +use miner::{Miner, MinerService}; use spec::Spec; use types::basic_account::BasicAccount; use types::mode::Mode; @@ -54,7 +61,11 @@ use executive::Executed; use error::CallError; use trace::LocalizedTrace; use state_db::StateDB; +use header::Header; use encoded; +use engines::EthEngine; +use trie; +use state::StateInfo; /// Test client. pub struct TestBlockChainClient { @@ -91,7 +102,7 @@ pub struct TestBlockChainClient { /// Spec pub spec: Spec, /// VM Factory - pub vm_factory: EvmFactory, + pub vm_factory: VmFactory, /// Timestamp assigned to latest sealed block pub latest_block_timestamp: RwLock, /// Ancient block info. @@ -162,7 +173,7 @@ impl TestBlockChainClient { queue_size: AtomicUsize::new(0), miner: Arc::new(Miner::with_spec(&spec)), spec: spec, - vm_factory: EvmFactory::new(VMType::Interpreter, 1024 * 1024), + vm_factory: VmFactory::new(VMType::Interpreter, 1024 * 1024), latest_block_timestamp: RwLock::new(10_000_000), ancient_block: RwLock::new(None), first_block: RwLock::new(None), @@ -241,7 +252,7 @@ impl TestBlockChainClient { uncle_header.set_parent_hash(self.last_hash.read().clone()); uncle_header.set_number(n as BlockNumber); uncles.append(&uncle_header); - header.set_uncles_hash(uncles.as_raw().sha3()); + header.set_uncles_hash(keccak(uncles.as_raw())); uncles }, _ => RlpStream::new_list(0) @@ -311,7 +322,7 @@ impl TestBlockChainClient { BlockId::Hash(hash) => Some(hash), BlockId::Number(n) => self.numbers.read().get(&(n as usize)).cloned(), BlockId::Earliest => self.numbers.read().get(&0).cloned(), - BlockId::Latest | BlockId::Pending => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned() + BlockId::Latest => self.numbers.read().get(&(self.numbers.read().len() - 1)).cloned() } } @@ -331,7 +342,7 @@ impl TestBlockChainClient { let hash = signed_tx.hash(); let res = self.miner.import_external_transactions(self, vec![signed_tx.into()]); let res = res.into_iter().next().unwrap().expect("Successful import"); - assert_eq!(res, TransactionImportResult::Current); + assert_eq!(res, transaction::ImportResult::Current); hash } @@ -346,27 +357,23 @@ impl TestBlockChainClient { } } -pub fn get_temp_state_db() -> GuardedTempResult { - let temp = RandomTempPath::new(); - let db = Database::open(&DatabaseConfig::with_columns(NUM_COLUMNS), temp.as_str()).unwrap(); +pub fn get_temp_state_db() -> StateDB { + let db = kvdb_memorydb::create(NUM_COLUMNS.unwrap_or(0)); let journal_db = journaldb::new(Arc::new(db), journaldb::Algorithm::EarlyMerge, COL_STATE); - let state_db = StateDB::new(journal_db, 1024 * 1024); - GuardedTempResult { - _temp: temp, - result: Some(state_db) - } + StateDB::new(journal_db, 1024 * 1024) } -impl MiningBlockChainClient for TestBlockChainClient { - fn latest_schedule(&self) -> Schedule { - Schedule::new_post_eip150(24576, true, true, true) +impl ReopenBlock for TestBlockChainClient { + fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { + block.reopen(&*self.spec.engine) } +} +impl PrepareOpenBlock for TestBlockChainClient { fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { let engine = &*self.spec.engine; let genesis_header = self.spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = self.spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = self.spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = vec![genesis_header.hash()]; let mut open_block = OpenBlock::new( @@ -385,43 +392,229 @@ impl MiningBlockChainClient for TestBlockChainClient { open_block.set_timestamp(*self.latest_block_timestamp.read()); open_block } +} - fn reopen_block(&self, block: ClosedBlock) -> OpenBlock { - block.reopen(&*self.spec.engine) - } - - fn vm_factory(&self) -> &EvmFactory { - &self.vm_factory +impl ScheduleInfo for TestBlockChainClient { + fn latest_schedule(&self) -> Schedule { + Schedule::new_post_eip150(24576, true, true, true) } +} +impl ImportSealedBlock for TestBlockChainClient { fn import_sealed_block(&self, _block: SealedBlock) -> ImportResult { Ok(H256::default()) } +} + +impl BlockProducer for TestBlockChainClient {} +impl BroadcastProposalBlock for TestBlockChainClient { fn broadcast_proposal_block(&self, _block: SealedBlock) {} } -impl BlockChainClient for TestBlockChainClient { - fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics, _block: BlockId) -> Result { +impl SealedBlockImporter for TestBlockChainClient {} + +impl MiningBlockChainClient for TestBlockChainClient { + fn vm_factory(&self) -> &VmFactory { + &self.vm_factory + } +} + +impl Nonce for TestBlockChainClient { + fn nonce(&self, address: &Address, id: BlockId) -> Option { + match id { + BlockId::Latest => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)), + _ => None, + } + } + + fn latest_nonce(&self, address: &Address) -> U256 { + self.nonce(address, BlockId::Latest).unwrap() + } +} + +impl Balance for TestBlockChainClient { + fn balance(&self, address: &Address, state: StateOrBlock) -> Option { + match state { + StateOrBlock::Block(BlockId::Latest) | StateOrBlock::State(_) => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)), + _ => None, + } + } + + fn latest_balance(&self, address: &Address) -> U256 { + self.balance(address, BlockId::Latest.into()).unwrap() + } +} + +impl AccountData for TestBlockChainClient {} + +impl ChainInfo for TestBlockChainClient { + fn chain_info(&self) -> BlockChainInfo { + let number = self.blocks.read().len() as BlockNumber - 1; + BlockChainInfo { + total_difficulty: *self.difficulty.read(), + pending_total_difficulty: *self.difficulty.read(), + genesis_hash: self.genesis_hash.clone(), + best_block_hash: self.last_hash.read().clone(), + best_block_number: number, + best_block_timestamp: number, + first_block_hash: self.first_block.read().as_ref().map(|x| x.0), + first_block_number: self.first_block.read().as_ref().map(|x| x.1), + ancient_block_hash: self.ancient_block.read().as_ref().map(|x| x.0), + ancient_block_number: self.ancient_block.read().as_ref().map(|x| x.1) + } + } +} + +impl BlockInfo for TestBlockChainClient { + fn block_header(&self, id: BlockId) -> Option { + self.block_hash(id) + .and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec())) + .map(encoded::Header::new) + } + + fn best_block_header(&self) -> encoded::Header { + self.block_header(BlockId::Hash(self.chain_info().best_block_hash)) + .expect("Best block always has header.") + } + + fn block(&self, id: BlockId) -> Option { + self.block_hash(id) + .and_then(|hash| self.blocks.read().get(&hash).cloned()) + .map(encoded::Block::new) + } + + fn code_hash(&self, address: &Address, id: BlockId) -> Option { + match id { + BlockId::Latest => self.code.read().get(address).map(|c| keccak(&c)), + _ => None, + } + } +} + +impl CallContract for TestBlockChainClient { + fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result { Ok(vec![]) } +} + +impl TransactionInfo for TestBlockChainClient { + fn transaction_block(&self, _id: TransactionId) -> Option { + None // Simple default. + } +} + +impl BlockChain for TestBlockChainClient {} + +impl RegistryInfo for TestBlockChainClient { + fn registry_address(&self, _name: String, _block: BlockId) -> Option
{ None } +} + +impl ImportBlock for TestBlockChainClient { + fn import_block(&self, b: Bytes) -> Result { + let header = Rlp::new(&b).val_at::(0); + let h = header.hash(); + let number: usize = header.number() as usize; + if number > self.blocks.read().len() { + panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number); + } + if number > 0 { + match self.blocks.read().get(header.parent_hash()) { + Some(parent) => { + let parent = Rlp::new(parent).val_at::(0); + if parent.number() != (header.number() - 1) { + panic!("Unexpected block parent"); + } + }, + None => { + panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number); + } + } + } + let len = self.numbers.read().len(); + if number == len { + { + let mut difficulty = self.difficulty.write(); + *difficulty = *difficulty + header.difficulty().clone(); + } + mem::replace(&mut *self.last_hash.write(), h.clone()); + self.blocks.write().insert(h.clone(), b); + self.numbers.write().insert(number, h.clone()); + let mut parent_hash = header.parent_hash().clone(); + if number > 0 { + let mut n = number - 1; + while n > 0 && self.numbers.read()[&n] != parent_hash { + *self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone(); + n -= 1; + parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::(0).parent_hash().clone(); + } + } + } + else { + self.blocks.write().insert(h.clone(), b.to_vec()); + } + Ok(h) + } + + fn import_block_with_receipts(&self, b: Bytes, _r: Bytes) -> Result { + self.import_block(b) + } +} + +impl Call for TestBlockChainClient { + // State will not be used by test client anyway, since all methods that accept state are mocked + type State = (); + + fn call(&self, _t: &SignedTransaction, _analytics: CallAnalytics, _state: &mut Self::State, _header: &Header) -> Result { self.execution_result.read().clone().unwrap() } - fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result, CallError> { + fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result, CallError> { let mut res = Vec::with_capacity(txs.len()); for &(ref tx, analytics) in txs { - res.push(self.call(tx, analytics, block)?); + res.push(self.call(tx, analytics, state, header)?); } Ok(res) } - fn estimate_gas(&self, _t: &SignedTransaction, _block: BlockId) -> Result { + fn estimate_gas(&self, _t: &SignedTransaction, _state: &Self::State, _header: &Header) -> Result { Ok(21000.into()) } +} + +impl StateInfo for () { + fn nonce(&self, _address: &Address) -> trie::Result { unimplemented!() } + fn balance(&self, _address: &Address) -> trie::Result { unimplemented!() } + fn storage_at(&self, _address: &Address, _key: &H256) -> trie::Result { unimplemented!() } + fn code(&self, _address: &Address) -> trie::Result>> { unimplemented!() } +} + +impl StateClient for TestBlockChainClient { + // State will not be used by test client anyway, since all methods that accept state are mocked + type State = (); + + fn latest_state(&self) -> Self::State { + () + } + + fn state_at(&self, _id: BlockId) -> Option { + Some(()) + } +} + +impl EngineInfo for TestBlockChainClient { + fn engine(&self) -> &EthEngine { + unimplemented!() + } +} +impl BlockChainClient for TestBlockChainClient { fn replay(&self, _id: TransactionId, _analytics: CallAnalytics) -> Result { self.execution_result.read().clone().unwrap() } + fn replay_block_transactions(&self, _block: BlockId, _analytics: CallAnalytics) -> Result>, CallError> { + Ok(Box::new(self.execution_result.read().clone().unwrap().into_iter())) + } + fn block_total_difficulty(&self, _id: BlockId) -> Option { Some(U256::zero()) } @@ -430,42 +623,20 @@ impl BlockChainClient for TestBlockChainClient { Self::block_hash(self, id) } - fn nonce(&self, address: &Address, id: BlockId) -> Option { - match id { - BlockId::Latest | BlockId::Pending => Some(self.nonces.read().get(address).cloned().unwrap_or(self.spec.params().account_start_nonce)), - _ => None, - } - } - fn storage_root(&self, _address: &Address, _id: BlockId) -> Option { None } - fn latest_nonce(&self, address: &Address) -> U256 { - self.nonce(address, BlockId::Latest).unwrap() - } - - fn code(&self, address: &Address, id: BlockId) -> Option> { - match id { - BlockId::Latest | BlockId::Pending => Some(self.code.read().get(address).cloned()), + fn code(&self, address: &Address, state: StateOrBlock) -> Option> { + match state { + StateOrBlock::Block(BlockId::Latest) => Some(self.code.read().get(address).cloned()), _ => None, } } - fn balance(&self, address: &Address, id: BlockId) -> Option { - match id { - BlockId::Latest | BlockId::Pending => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)), - _ => None, - } - } - - fn latest_balance(&self, address: &Address) -> U256 { - self.balance(address, BlockId::Latest).unwrap() - } - - fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option { - match id { - BlockId::Latest | BlockId::Pending => Some(self.storage.read().get(&(address.clone(), position.clone())).cloned().unwrap_or_else(H256::new)), + fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option { + match state { + StateOrBlock::Block(BlockId::Latest) => Some(self.storage.read().get(&(address.clone(), position.clone())).cloned().unwrap_or_else(H256::new)), _ => None, } } @@ -481,10 +652,6 @@ impl BlockChainClient for TestBlockChainClient { None // Simple default. } - fn transaction_block(&self, _id: TransactionId) -> Option { - None // Simple default. - } - fn uncle(&self, _id: UncleId) -> Option { None // Simple default. } @@ -497,10 +664,6 @@ impl BlockChainClient for TestBlockChainClient { self.receipts.read().get(&id).cloned() } - fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockId, _to_block: BlockId) -> Option> { - unimplemented!(); - } - fn logs(&self, filter: Filter) -> Vec { let mut logs = self.logs.read().clone(); let len = logs.len(); @@ -514,17 +677,6 @@ impl BlockChainClient for TestBlockChainClient { unimplemented!(); } - fn best_block_header(&self) -> encoded::Header { - self.block_header(BlockId::Hash(self.chain_info().best_block_hash)) - .expect("Best block always has header.") - } - - fn block_header(&self, id: BlockId) -> Option { - self.block_hash(id) - .and_then(|hash| self.blocks.read().get(&hash).map(|r| Rlp::new(r).at(0).as_raw().to_vec())) - .map(encoded::Header::new) - } - fn block_number(&self, _id: BlockId) -> Option { unimplemented!() } @@ -538,12 +690,6 @@ impl BlockChainClient for TestBlockChainClient { })) } - fn block(&self, id: BlockId) -> Option { - self.block_hash(id) - .and_then(|hash| self.blocks.read().get(&hash).cloned()) - .map(encoded::Block::new) - } - fn block_extra_info(&self, id: BlockId) -> Option> { self.block(id) .map(|block| block.view().header()) @@ -556,7 +702,6 @@ impl BlockChainClient for TestBlockChainClient { BlockId::Number(number) if (number as usize) < self.blocks.read().len() => BlockStatus::InChain, BlockId::Hash(ref hash) if self.blocks.read().get(hash).is_some() => BlockStatus::InChain, BlockId::Latest | BlockId::Earliest => BlockStatus::InChain, - BlockId::Pending => BlockStatus::Pending, _ => BlockStatus::Unknown, } } @@ -610,7 +755,7 @@ impl BlockChainClient for TestBlockChainClient { // starts with 'f' ? if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { let receipt = BlockReceipts::new(vec![Receipt::new( - Some(H256::zero()), + TransactionOutcome::StateRoot(H256::zero()), U256::zero(), vec![])]); let mut rlp = RlpStream::new(); @@ -620,55 +765,6 @@ impl BlockChainClient for TestBlockChainClient { None } - fn import_block(&self, b: Bytes) -> Result { - let header = Rlp::new(&b).val_at::(0); - let h = header.hash(); - let number: usize = header.number() as usize; - if number > self.blocks.read().len() { - panic!("Unexpected block number. Expected {}, got {}", self.blocks.read().len(), number); - } - if number > 0 { - match self.blocks.read().get(header.parent_hash()) { - Some(parent) => { - let parent = Rlp::new(parent).val_at::(0); - if parent.number() != (header.number() - 1) { - panic!("Unexpected block parent"); - } - }, - None => { - panic!("Unknown block parent {:?} for block {}", header.parent_hash(), number); - } - } - } - let len = self.numbers.read().len(); - if number == len { - { - let mut difficulty = self.difficulty.write(); - *difficulty = *difficulty + header.difficulty().clone(); - } - mem::replace(&mut *self.last_hash.write(), h.clone()); - self.blocks.write().insert(h.clone(), b); - self.numbers.write().insert(number, h.clone()); - let mut parent_hash = header.parent_hash().clone(); - if number > 0 { - let mut n = number - 1; - while n > 0 && self.numbers.read()[&n] != parent_hash { - *self.numbers.write().get_mut(&n).unwrap() = parent_hash.clone(); - n -= 1; - parent_hash = Rlp::new(&self.blocks.read()[&parent_hash]).val_at::(0).parent_hash().clone(); - } - } - } - else { - self.blocks.write().insert(h.clone(), b.to_vec()); - } - Ok(h) - } - - fn import_block_with_receipts(&self, b: Bytes, _r: Bytes) -> Result { - self.import_block(b) - } - fn queue_info(&self) -> QueueInfo { QueueInfo { verified_queue_size: self.queue_size.load(AtomicOrder::Relaxed), @@ -687,22 +783,6 @@ impl BlockChainClient for TestBlockChainClient { Default::default() } - fn chain_info(&self) -> BlockChainInfo { - let number = self.blocks.read().len() as BlockNumber - 1; - BlockChainInfo { - total_difficulty: *self.difficulty.read(), - pending_total_difficulty: *self.difficulty.read(), - genesis_hash: self.genesis_hash.clone(), - best_block_hash: self.last_hash.read().clone(), - best_block_number: number, - best_block_timestamp: number, - first_block_hash: self.first_block.read().as_ref().map(|x| x.0), - first_block_number: self.first_block.read().as_ref().map(|x| x.1), - ancient_block_hash: self.ancient_block.read().as_ref().map(|x| x.0), - ancient_block_number: self.ancient_block.read().as_ref().map(|x| x.1) - } - } - fn filter_traces(&self, _filter: TraceFilter) -> Option> { self.traces.read().clone() } @@ -754,9 +834,7 @@ impl BlockChainClient for TestBlockChainClient { } } - fn call_contract(&self, _id: BlockId, _address: Address, _data: Bytes) -> Result { Ok(vec![]) } - - fn transact_contract(&self, address: Address, data: Bytes) -> Result { + fn transact_contract(&self, address: Address, data: Bytes) -> Result { let transaction = Transaction { nonce: self.latest_nonce(&self.miner.author()), action: Action::Call(address), @@ -773,8 +851,6 @@ impl BlockChainClient for TestBlockChainClient { fn registrar_address(&self) -> Option
{ None } - fn registry_address(&self, _name: String) -> Option
{ None } - fn eip86_transition(&self) -> u64 { u64::max_value() } } @@ -790,9 +866,13 @@ impl ProvingBlockChainClient for TestBlockChainClient { fn prove_transaction(&self, _: SignedTransaction, _: BlockId) -> Option<(Bytes, Vec)> { None } + + fn epoch_signal(&self, _: H256) -> Option> { + None + } } -impl EngineClient for TestBlockChainClient { +impl super::traits::EngineClient for TestBlockChainClient { fn update_sealing(&self) { self.miner.update_sealing(self) } @@ -808,4 +888,14 @@ impl EngineClient for TestBlockChainClient { fn epoch_transition_for(&self, _block_hash: H256) -> Option<::engines::EpochTransition> { None } + + fn as_full_client(&self) -> Option<&BlockChainClient> { Some(self) } + + fn block_number(&self, id: BlockId) -> Option { + BlockChainClient::block_number(self, id) + } + + fn block_header(&self, id: BlockId) -> Option<::encoded::Header> { + BlockChainClient::block_header(self, id) + } } diff --git a/ethcore/src/client/trace.rs b/ethcore/src/client/trace.rs index 3ab01757ee2f211410b4d91bbc8d3b3095976839..75e0fe34a1e383342e0cb344610df0f6a225792f 100644 --- a/ethcore/src/client/trace.rs +++ b/ethcore/src/client/trace.rs @@ -1,11 +1,10 @@ //! Bridge between Tracedb and Blockchain. -use util::{H256}; +use ethereum_types::H256; use header::BlockNumber; use trace::DatabaseExtras as TraceDatabaseExtras; -use blockchain::{BlockChain, BlockProvider}; -use blockchain::extras::TransactionAddress; +use blockchain::{BlockChain, BlockProvider, TransactionAddress}; pub use types::trace_filter::Filter; impl TraceDatabaseExtras for BlockChain { diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index d7b7bba44abd31bcd60b4a1676b0da1d707acc5a..1228f87683c04cd97dffe957d591fd5ec50dd6c9 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -21,21 +21,24 @@ use block::{OpenBlock, SealedBlock, ClosedBlock}; use blockchain::TreeRoute; use encoded; use vm::LastHashes; -use error::{ImportResult, CallError, Error as EthcoreError}; -use error::{TransactionImportResult, BlockImportError}; -use evm::{Factory as EvmFactory, Schedule}; +use error::{ImportResult, CallError, Error as EthcoreError, BlockImportError}; +use evm::Schedule; +use factory::VmFactory; use executive::Executed; use filter::Filter; use header::{BlockNumber}; -use ipc::IpcConfig; use log_entry::LocalizedLogEntry; use receipt::LocalizedReceipt; use trace::LocalizedTrace; -use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction}; +use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction, ImportResult as TransactionImportResult}; use verification::queue::QueueInfo as BlockQueueInfo; +use state::StateInfo; +use header::Header; +use engines::EthEngine; -use util::{U256, Address, H256, H2048, Bytes}; -use util::hashdb::DBValue; +use ethereum_types::{H256, U256, Address}; +use bytes::Bytes; +use hashdb::DBValue; use types::ids::*; use types::basic_account::BasicAccount; @@ -46,13 +49,158 @@ use types::block_status::BlockStatus; use types::mode::Mode; use types::pruning_info::PruningInfo; -#[ipc(client_ident="RemoteClient")] -/// Blockchain database client. Owns and manages a blockchain and a block queue. -pub trait BlockChainClient : Sync + Send { +/// State information to be used during client query +pub enum StateOrBlock { + /// State to be used, may be pending + State(Box), + + /// Id of an existing block from a chain to get state from + Block(BlockId) +} + +impl From for StateOrBlock { + fn from(info: S) -> StateOrBlock { + StateOrBlock::State(Box::new(info) as Box<_>) + } +} + +impl From> for StateOrBlock { + fn from(info: Box) -> StateOrBlock { + StateOrBlock::State(info) + } +} + +impl From for StateOrBlock { + fn from(id: BlockId) -> StateOrBlock { + StateOrBlock::Block(id) + } +} + +/// Provides `nonce` and `latest_nonce` methods +pub trait Nonce { + /// Attempt to get address nonce at given block. + /// May not fail on BlockId::Latest. + fn nonce(&self, address: &Address, id: BlockId) -> Option; + + /// Get address nonce at the latest block's state. + fn latest_nonce(&self, address: &Address) -> U256 { + self.nonce(address, BlockId::Latest) + .expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \ + Therefore nonce has returned Some; qed") + } +} +/// Provides `balance` and `latest_balance` methods +pub trait Balance { + /// Get address balance at the given block's state. + /// + /// May not return None if given BlockId::Latest. + /// Returns None if and only if the block's root hash has been pruned from the DB. + fn balance(&self, address: &Address, state: StateOrBlock) -> Option; + + /// Get address balance at the latest block's state. + fn latest_balance(&self, address: &Address) -> U256 { + self.balance(address, BlockId::Latest.into()) + .expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \ + Therefore balance has returned Some; qed") + } +} + +/// Provides methods to access account info +pub trait AccountData: Nonce + Balance {} + +/// Provides `chain_info` method +pub trait ChainInfo { + /// Get blockchain information. + fn chain_info(&self) -> BlockChainInfo; +} + +/// Provides various information on a block by it's ID +pub trait BlockInfo { /// Get raw block header data by block id. fn block_header(&self, id: BlockId) -> Option; + /// Get the best block header. + fn best_block_header(&self) -> encoded::Header; + + /// Get raw block data by block header hash. + fn block(&self, id: BlockId) -> Option; + + /// Get address code hash at given block's state. + fn code_hash(&self, address: &Address, id: BlockId) -> Option; +} + +/// Provides various information on a transaction by it's ID +pub trait TransactionInfo { + /// Get the hash of block that contains the transaction, if any. + fn transaction_block(&self, id: TransactionId) -> Option; +} + +/// Provides methods to access chain state +pub trait StateClient { + /// Type representing chain state + type State: StateInfo; + + /// Get a copy of the best block's state. + fn latest_state(&self) -> Self::State; + + /// Attempt to get a copy of a specific block's final state. + /// + /// This will not fail if given BlockId::Latest. + /// Otherwise, this can fail (but may not) if the DB prunes state or the block + /// is unknown. + fn state_at(&self, id: BlockId) -> Option; +} + +/// Provides various blockchain information, like block header, chain state etc. +pub trait BlockChain: ChainInfo + BlockInfo + TransactionInfo {} + +/// Provides information on a blockchain service and it's registry +pub trait RegistryInfo { + /// Get the address of a particular blockchain service, if available. + fn registry_address(&self, name: String, block: BlockId) -> Option
; +} + +// FIXME Why these methods belong to BlockChainClient and not MiningBlockChainClient? +/// Provides methods to import block into blockchain +pub trait ImportBlock { + /// Import a block into the blockchain. + fn import_block(&self, bytes: Bytes) -> Result; + + /// Import a block with transaction receipts. Does no sealing and transaction validation. + fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result; +} + +/// Provides `call_contract` method +pub trait CallContract { + /// Like `call`, but with various defaults. Designed to be used for calling contracts. + fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result; +} + +/// Provides `call` and `call_many` methods +pub trait Call { + /// Type representing chain state + type State: StateInfo; + + /// Makes a non-persistent transaction call. + fn call(&self, tx: &SignedTransaction, analytics: CallAnalytics, state: &mut Self::State, header: &Header) -> Result; + + /// Makes multiple non-persistent but dependent transaction calls. + /// Returns a vector of successes or a failure if any of the transaction fails. + fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], state: &mut Self::State, header: &Header) -> Result, CallError>; + + /// Estimates how much gas will be necessary for a call. + fn estimate_gas(&self, t: &SignedTransaction, state: &Self::State, header: &Header) -> Result; +} + +/// Provides `engine` method +pub trait EngineInfo { + /// Get underlying engine object + fn engine(&self) -> &EthEngine; +} + +/// Blockchain database client. Owns and manages a blockchain and a block queue. +pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContract + RegistryInfo + ImportBlock { /// Look up the block number for the given block ID. fn block_number(&self, id: BlockId) -> Option; @@ -60,64 +208,39 @@ pub trait BlockChainClient : Sync + Send { /// Block body is an RLP list of two items: uncles and transactions. fn block_body(&self, id: BlockId) -> Option; - /// Get raw block data by block header hash. - fn block(&self, id: BlockId) -> Option; - /// Get block status by block header hash. fn block_status(&self, id: BlockId) -> BlockStatus; /// Get block total difficulty. fn block_total_difficulty(&self, id: BlockId) -> Option; - /// Attempt to get address nonce at given block. - /// May not fail on BlockId::Latest. - fn nonce(&self, address: &Address, id: BlockId) -> Option; - /// Attempt to get address storage root at given block. /// May not fail on BlockId::Latest. fn storage_root(&self, address: &Address, id: BlockId) -> Option; - /// Get address nonce at the latest block's state. - fn latest_nonce(&self, address: &Address) -> U256 { - self.nonce(address, BlockId::Latest) - .expect("nonce will return Some when given BlockId::Latest. nonce was given BlockId::Latest. \ - Therefore nonce has returned Some; qed") - } - /// Get block hash. fn block_hash(&self, id: BlockId) -> Option; /// Get address code at given block's state. - fn code(&self, address: &Address, id: BlockId) -> Option>; + fn code(&self, address: &Address, state: StateOrBlock) -> Option>; /// Get address code at the latest block's state. fn latest_code(&self, address: &Address) -> Option { - self.code(address, BlockId::Latest) + self.code(address, BlockId::Latest.into()) .expect("code will return Some if given BlockId::Latest; qed") } - /// Get address balance at the given block's state. - /// - /// May not return None if given BlockId::Latest. - /// Returns None if and only if the block's root hash has been pruned from the DB. - fn balance(&self, address: &Address, id: BlockId) -> Option; - - /// Get address balance at the latest block's state. - fn latest_balance(&self, address: &Address) -> U256 { - self.balance(address, BlockId::Latest) - .expect("balance will return Some if given BlockId::Latest. balance was given BlockId::Latest \ - Therefore balance has returned Some; qed") - } + /// Get address code hash at given block's state. /// Get value of the storage at given position at the given block's state. /// /// May not return None if given BlockId::Latest. /// Returns None if and only if the block's root hash has been pruned from the DB. - fn storage_at(&self, address: &Address, position: &H256, id: BlockId) -> Option; + fn storage_at(&self, address: &Address, position: &H256, state: StateOrBlock) -> Option; /// Get value of the storage at given position at the latest block's state. fn latest_storage_at(&self, address: &Address, position: &H256) -> H256 { - self.storage_at(address, position, BlockId::Latest) + self.storage_at(address, position, BlockId::Latest.into()) .expect("storage_at will return Some if given BlockId::Latest. storage_at was given BlockId::Latest. \ Therefore storage_at has returned Some; qed") } @@ -133,9 +256,6 @@ pub trait BlockChainClient : Sync + Send { /// Get transaction with given hash. fn transaction(&self, id: TransactionId) -> Option; - /// Get the hash of block that contains the transaction, if any. - fn transaction_block(&self, id: TransactionId) -> Option; - /// Get uncle with given id. fn uncle(&self, id: UncleId) -> Option; @@ -155,46 +275,24 @@ pub trait BlockChainClient : Sync + Send { /// Get raw block receipts data by block header hash. fn block_receipts(&self, hash: &H256) -> Option; - /// Import a block into the blockchain. - fn import_block(&self, bytes: Bytes) -> Result; - - /// Import a block with transaction receipts. Does no sealing and transaction validation. - fn import_block_with_receipts(&self, block_bytes: Bytes, receipts_bytes: Bytes) -> Result; - /// Get block queue information. fn queue_info(&self) -> BlockQueueInfo; /// Clear block queue and abort all import activity. fn clear_queue(&self); - /// Get blockchain information. - fn chain_info(&self) -> BlockChainInfo; - /// Get the registrar address, if it exists. fn additional_params(&self) -> BTreeMap; - /// Get the best block header. - fn best_block_header(&self) -> encoded::Header; - - /// Returns numbers of blocks containing given bloom. - fn blocks_with_bloom(&self, bloom: &H2048, from_block: BlockId, to_block: BlockId) -> Option>; - /// Returns logs matching given filter. fn logs(&self, filter: Filter) -> Vec; - /// Makes a non-persistent transaction call. - fn call(&self, tx: &SignedTransaction, analytics: CallAnalytics, block: BlockId) -> Result; - - /// Makes multiple non-persistent but dependent transaction calls. - /// Returns a vector of successes or a failure if any of the transaction fails. - fn call_many(&self, txs: &[(SignedTransaction, CallAnalytics)], block: BlockId) -> Result, CallError>; - - /// Estimates how much gas will be necessary for a call. - fn estimate_gas(&self, t: &SignedTransaction, block: BlockId) -> Result; - /// Replays a given transaction for inspection. fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result; + /// Replays all the transactions in a given block for inspection. + fn replay_block_transactions(&self, block: BlockId, analytics: CallAnalytics) -> Result>, CallError>; + /// Returns traces matching given filter. fn filter_traces(&self, filter: TraceFilter) -> Option>; @@ -268,51 +366,64 @@ pub trait BlockChainClient : Sync + Send { /// Returns information about pruning/data availability. fn pruning_info(&self) -> PruningInfo; - /// Like `call`, but with various defaults. Designed to be used for calling contracts. - fn call_contract(&self, id: BlockId, address: Address, data: Bytes) -> Result; - /// Import a transaction: used for misbehaviour reporting. fn transact_contract(&self, address: Address, data: Bytes) -> Result; /// Get the address of the registry itself. fn registrar_address(&self) -> Option
; - /// Get the address of a particular blockchain service, if available. - fn registry_address(&self, name: String) -> Option
; - /// Get the EIP-86 transition block number. fn eip86_transition(&self) -> u64; } -impl IpcConfig for BlockChainClient { } +/// Provides `reopen_block` method +pub trait ReopenBlock { + /// Reopens an OpenBlock and updates uncles. + fn reopen_block(&self, block: ClosedBlock) -> OpenBlock; +} -/// Extended client interface used for mining -pub trait MiningBlockChainClient: BlockChainClient { +/// Provides `prepare_open_block` method +pub trait PrepareOpenBlock { /// Returns OpenBlock prepared for closing. fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes ) -> OpenBlock; +} - /// Reopens an OpenBlock and updates uncles. - fn reopen_block(&self, block: ClosedBlock) -> OpenBlock; +/// Provides methods used for sealing new state +pub trait BlockProducer: PrepareOpenBlock + ReopenBlock {} - /// Returns EvmFactory. - fn vm_factory(&self) -> &EvmFactory; +/// Provides `latest_schedule` method +pub trait ScheduleInfo { + /// Returns latest schedule. + fn latest_schedule(&self) -> Schedule; +} + +///Provides `import_sealed_block` method +pub trait ImportSealedBlock { + /// Import sealed block. Skips all verifications. + fn import_sealed_block(&self, block: SealedBlock) -> ImportResult; +} +/// Provides `broadcast_proposal_block` method +pub trait BroadcastProposalBlock { /// Broadcast a block proposal. fn broadcast_proposal_block(&self, block: SealedBlock); +} - /// Import sealed block. Skips all verifications. - fn import_sealed_block(&self, block: SealedBlock) -> ImportResult; +/// Provides methods to import sealed block and broadcast a block proposal +pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {} - /// Returns latest schedule. - fn latest_schedule(&self) -> Schedule; +/// Extended client interface used for mining +pub trait MiningBlockChainClient: BlockChainClient + BlockProducer + ScheduleInfo + SealedBlockImporter { + /// Returns EvmFactory. + fn vm_factory(&self) -> &VmFactory; } /// Client facilities used by internally sealing Engines. -pub trait EngineClient: MiningBlockChainClient { +pub trait EngineClient: Sync + Send + ChainInfo { /// Make a new block and seal it. fn update_sealing(&self); @@ -328,6 +439,15 @@ pub trait EngineClient: MiningBlockChainClient { /// /// The block corresponding the the parent hash must be stored already. fn epoch_transition_for(&self, parent_hash: H256) -> Option<::engines::EpochTransition>; + + /// Attempt to cast the engine client to a full client. + fn as_full_client(&self) -> Option<&BlockChainClient>; + + /// Get a block number by ID. + fn block_number(&self, id: BlockId) -> Option; + + /// Get raw block header data by block id. + fn block_header(&self, id: BlockId) -> Option; } /// Extended client interface for providing proofs of the state. @@ -347,4 +467,7 @@ pub trait ProvingBlockChainClient: BlockChainClient { /// Returns the output of the call and a vector of database items necessary /// to reproduce it. fn prove_transaction(&self, transaction: SignedTransaction, id: BlockId) -> Option<(Bytes, Vec)>; + + /// Get an epoch change signal by block hash. + fn epoch_signal(&self, hash: H256) -> Option>; } diff --git a/ethcore/src/db.rs b/ethcore/src/db.rs index bccb8e943b12fd2fd8bbf10060858df204f43e2a..d11adc7710d4d334efc99ee47256453d469e3261 100644 --- a/ethcore/src/db.rs +++ b/ethcore/src/db.rs @@ -19,7 +19,8 @@ use std::ops::Deref; use std::hash::Hash; use std::collections::HashMap; -use util::{DBTransaction, KeyValueDB, RwLock}; +use parking_lot::RwLock; +use kvdb::{DBTransaction, KeyValueDB}; use rlp; diff --git a/ethcore/src/encoded.rs b/ethcore/src/encoded.rs index 125a00fd0f7d54ba56f1a09edbc26aaa715baa55..098a90a8ab467e19da3e51889741798106e77295 100644 --- a/ethcore/src/encoded.rs +++ b/ethcore/src/encoded.rs @@ -28,12 +28,13 @@ use header::{BlockNumber, Header as FullHeader}; use transaction::UnverifiedTransaction; use views; -use util::{Address, Hashable, H256, H2048, U256, HeapSizeOf}; +use hash::keccak; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, Bloom, U256, Address}; use rlp::Rlp; /// Owning header view. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "ipc", binary)] pub struct Header(Vec); impl HeapSizeOf for Header { @@ -64,7 +65,7 @@ impl Header { // forwarders to borrowed view. impl Header { /// Returns the header hash. - pub fn hash(&self) -> H256 { self.sha3() } + pub fn hash(&self) -> H256 { keccak(&self.0) } /// Returns the parent hash. pub fn parent_hash(&self) -> H256 { self.view().parent_hash() } @@ -85,7 +86,7 @@ impl Header { pub fn receipts_root(&self) -> H256 { self.view().receipts_root() } /// Returns the block log bloom - pub fn log_bloom(&self) -> H2048 { self.view().log_bloom() } + pub fn log_bloom(&self) -> Bloom { self.view().log_bloom() } /// Difficulty of this block pub fn difficulty(&self) -> U256 { self.view().difficulty() } @@ -109,15 +110,8 @@ impl Header { pub fn seal(&self) -> Vec> { self.view().seal() } } -impl Hashable for Header { - fn sha3(&self) -> H256 { - self.0.sha3() - } -} - /// Owning block body view. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "ipc", binary)] pub struct Body(Vec); impl HeapSizeOf for Body { @@ -177,7 +171,6 @@ impl Body { /// Owning block view. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "ipc", binary)] pub struct Block(Vec); impl HeapSizeOf for Block { @@ -218,7 +211,7 @@ impl Block { // forwarders to borrowed header view. impl Block { /// Returns the header hash. - pub fn hash(&self) -> H256 { self.header_view().sha3() } + pub fn hash(&self) -> H256 { self.header_view().hash() } /// Returns the parent hash. pub fn parent_hash(&self) -> H256 { self.header_view().parent_hash() } @@ -239,7 +232,7 @@ impl Block { pub fn receipts_root(&self) -> H256 { self.header_view().receipts_root() } /// Returns the block log bloom - pub fn log_bloom(&self) -> H2048 { self.header_view().log_bloom() } + pub fn log_bloom(&self) -> Bloom { self.header_view().log_bloom() } /// Difficulty of this block pub fn difficulty(&self) -> U256 { self.header_view().difficulty() } diff --git a/ethcore/src/engines/authority_round/finality.rs b/ethcore/src/engines/authority_round/finality.rs index 4e1bdf6a32c0da10cbfd3b40a8d78d61e0dbb576..61f1c182294d4e36f411d976657691df10ea3011 100644 --- a/ethcore/src/engines/authority_round/finality.rs +++ b/ethcore/src/engines/authority_round/finality.rs @@ -19,7 +19,7 @@ use std::collections::{VecDeque}; use std::collections::hash_map::{HashMap, Entry}; -use util::{Address, H256}; +use ethereum_types::{H256, Address}; use engines::validator_set::SimpleList; @@ -30,7 +30,7 @@ pub struct UnknownValidator; /// Rolling finality checker for authority round consensus. /// Stores a chain of unfinalized hashes that can be pushed onto. pub struct RollingFinality { - headers: VecDeque<(H256, Address)>, + headers: VecDeque<(H256, Vec
)>, signers: SimpleList, sign_count: HashMap, last_pushed: Option, @@ -52,28 +52,31 @@ impl RollingFinality { /// /// Fails if any provided signature isn't part of the signers set. pub fn build_ancestry_subchain(&mut self, iterable: I) -> Result<(), UnknownValidator> - where I: IntoIterator + where I: IntoIterator)> { self.clear(); - for (hash, signer) in iterable { - if !self.signers.contains(&signer) { return Err(UnknownValidator) } + for (hash, signers) in iterable { + if signers.iter().any(|s| !self.signers.contains(s)) { return Err(UnknownValidator) } if self.last_pushed.is_none() { self.last_pushed = Some(hash) } // break when we've got our first finalized block. { let current_signed = self.sign_count.len(); - let would_be_finalized = (current_signed + 1) * 2 > self.signers.len(); - let entry = self.sign_count.entry(signer); - if let (true, &Entry::Vacant(_)) = (would_be_finalized, &entry) { + let new_signers = signers.iter().filter(|s| !self.sign_count.contains_key(s)).count(); + let would_be_finalized = (current_signed + new_signers) * 2 > self.signers.len(); + + if would_be_finalized { trace!(target: "finality", "Encountered already finalized block {}", hash); break } - *entry.or_insert(0) += 1; + for signer in signers.iter() { + *self.sign_count.entry(*signer).or_insert(0) += 1; + } } - self.headers.push_front((hash, signer)); + self.headers.push_front((hash, signers)); } trace!(target: "finality", "Rolling finality state: {:?}", self.headers); @@ -103,30 +106,35 @@ impl RollingFinality { /// Fails if `signer` isn't a member of the active validator set. /// Returns a list of all newly finalized headers. // TODO: optimize with smallvec. - pub fn push_hash(&mut self, head: H256, signer: Address) -> Result, UnknownValidator> { - if !self.signers.contains(&signer) { return Err(UnknownValidator) } + pub fn push_hash(&mut self, head: H256, signers: Vec
) -> Result, UnknownValidator> { + if signers.iter().any(|s| !self.signers.contains(s)) { return Err(UnknownValidator) } - self.headers.push_back((head, signer)); - *self.sign_count.entry(signer).or_insert(0) += 1; + for signer in signers.iter() { + *self.sign_count.entry(*signer).or_insert(0) += 1; + } + + self.headers.push_back((head, signers)); let mut newly_finalized = Vec::new(); while self.sign_count.len() * 2 > self.signers.len() { - let (hash, signer) = self.headers.pop_front() + let (hash, signers) = self.headers.pop_front() .expect("headers length always greater than sign count length; qed"); newly_finalized.push(hash); - match self.sign_count.entry(signer) { - Entry::Occupied(mut entry) => { - // decrement count for this signer and purge on zero. - *entry.get_mut() -= 1; + for signer in signers { + match self.sign_count.entry(signer) { + Entry::Occupied(mut entry) => { + // decrement count for this signer and purge on zero. + *entry.get_mut() -= 1; - if *entry.get() == 0 { - entry.remove(); + if *entry.get() == 0 { + entry.remove(); + } } + Entry::Vacant(_) => panic!("all hashes in `header` should have entries in `sign_count` for their signers; qed"), } - Entry::Vacant(_) => panic!("all hashes in `header` should have an entry in `sign_count` for their signer; qed"), } } @@ -137,7 +145,7 @@ impl RollingFinality { } } -pub struct Iter<'a>(::std::collections::vec_deque::Iter<'a, (H256, Address)>); +pub struct Iter<'a>(::std::collections::vec_deque::Iter<'a, (H256, Vec
)>); impl<'a> Iterator for Iter<'a> { type Item = H256; @@ -149,14 +157,14 @@ impl<'a> Iterator for Iter<'a> { #[cfg(test)] mod tests { - use util::{Address, H256}; + use ethereum_types::{H256, Address}; use super::RollingFinality; #[test] - fn rejects_unknown_signer() { - let signers = (0..3).map(|_| Address::random()).collect(); - let mut finality = RollingFinality::blank(signers); - assert!(finality.push_hash(H256::random(), Address::random()).is_err()); + fn rejects_unknown_signers() { + let signers = (0..3).map(|_| Address::random()).collect::>(); + let mut finality = RollingFinality::blank(signers.clone()); + assert!(finality.push_hash(H256::random(), vec![signers[0], Address::random()]).is_err()); } #[test] @@ -169,19 +177,29 @@ mod tests { // 3 / 6 signers is < 51% so no finality. for (i, hash) in hashes.iter().take(6).cloned().enumerate() { let i = i % 3; - assert!(finality.push_hash(hash, signers[i]).unwrap().len() == 0); + assert!(finality.push_hash(hash, vec![signers[i]]).unwrap().len() == 0); } // after pushing a block signed by a fourth validator, the first four // blocks of the unverified chain become verified. - assert_eq!(finality.push_hash(hashes[6], signers[4]).unwrap(), + assert_eq!(finality.push_hash(hashes[6], vec![signers[4]]).unwrap(), vec![hashes[0], hashes[1], hashes[2], hashes[3]]); } + #[test] + fn finalize_multiple_signers() { + let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); + let mut finality = RollingFinality::blank(signers.clone()); + let hash = H256::random(); + + // after pushing a block signed by four validators, it becomes verified right away. + assert_eq!(finality.push_hash(hash, signers[0..4].to_vec()).unwrap(), vec![hash]); + } + #[test] fn from_ancestry() { let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); - let hashes: Vec<_> = (0..12).map(|i| (H256::random(), signers[i % 6])).collect(); + let hashes: Vec<_> = (0..12).map(|i| (H256::random(), vec![signers[i % 6]])).collect(); let mut finality = RollingFinality::blank(signers.clone()); finality.build_ancestry_subchain(hashes.iter().rev().cloned()).unwrap(); @@ -189,4 +207,20 @@ mod tests { assert_eq!(finality.unfinalized_hashes().count(), 3); assert_eq!(finality.subchain_head(), Some(hashes[11].0)); } + + #[test] + fn from_ancestry_multiple_signers() { + let signers: Vec<_> = (0..6).map(|_| Address::random()).collect(); + let hashes: Vec<_> = (0..12).map(|i| { + (H256::random(), vec![signers[i % 6], signers[(i + 1) % 6], signers[(i + 2) % 6]]) + }).collect(); + + let mut finality = RollingFinality::blank(signers.clone()); + finality.build_ancestry_subchain(hashes.iter().rev().cloned()).unwrap(); + + // only the last hash has < 51% of authorities' signatures + assert_eq!(finality.unfinalized_hashes().count(), 1); + assert_eq!(finality.unfinalized_hashes().next(), Some(hashes[11].0)); + assert_eq!(finality.subchain_head(), Some(hashes[11].0)); + } } diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 508cd3e257e9d22c33d31a51fafbd9bba4475916..0acde347e2b8aa848288a63999540ed27fce7da2 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -16,41 +16,46 @@ //! A blockchain engine that supports a non-instant BFT proof-of-authority. +use std::fmt; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::{Weak, Arc}; use std::time::{UNIX_EPOCH, Duration}; -use std::collections::{BTreeMap, HashSet, HashMap}; -use std::cmp; +use std::collections::{BTreeMap, HashSet}; +use std::iter::FromIterator; use account_provider::AccountProvider; use block::*; -use builtin::Builtin; -use client::{Client, EngineClient}; -use engines::{Call, Engine, Seal, EngineError, ConstructedVerifier}; -use error::{Error, TransactionError, BlockError}; +use client::EngineClient; +use engines::{Engine, Seal, EngineError, ConstructedVerifier}; +use error::{Error, BlockError}; use ethjson; +use machine::{AuxiliaryData, Call, EthereumMachine}; +use hash::keccak; use header::{Header, BlockNumber}; -use spec::CommonParams; -use state::CleanupMode; -use transaction::UnverifiedTransaction; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; use self::finality::RollingFinality; -use ethkey::{verify_address, Signature}; +use ethkey::{public_to_address, recover, verify_address, Signature}; use io::{IoContext, IoHandler, TimerToken, IoService}; use itertools::{self, Itertools}; -use rlp::{UntrustedRlp, encode}; -use util::*; +use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, UntrustedRlp}; +use ethereum_types::{H256, H520, Address, U128, U256}; +use parking_lot::{Mutex, RwLock}; +use unexpected::{Mismatch, OutOfBounds}; 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, /// Valid validators. @@ -61,17 +66,39 @@ pub struct AuthorityRoundParams { pub validate_step_transition: u64, /// Immediate transitions. 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, + /// Empty step messages transition block. + pub empty_steps_transition: u64, + /// Number of accepted empty steps. + pub maximum_empty_steps: usize, } +const U16_MAX: usize = ::std::u16::MAX as usize; + impl From 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), + empty_steps_transition: p.empty_steps_transition.map_or(u64::max_value(), |n| ::std::cmp::max(n.into(), 1)), + maximum_empty_steps: p.maximum_empty_steps.map_or(0, Into::into), } } } @@ -81,40 +108,83 @@ impl From 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)) + .map(Duration::from_secs); + + match expected_seconds { + Some(step_end) if step_end > now => step_end - now, + Some(_) => 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); } } - fn is_future(&self, given: usize) -> bool { - if given > self.load() + 1 { - // Make absolutely sure that the given step is correct. - self.calibrate(); - given > self.load() + 1 + + fn check_future(&self, given: usize) -> Result<(), Option>> { + const REJECTED_STEP_DRIFT: usize = 4; + + // Verify if the step is correct. + if given <= self.load() { + return Ok(()); + } + + // Make absolutely sure that the given step is incorrect. + self.calibrate(); + let current = self.load(); + + // reject blocks too far in the future + if given > current + REJECTED_STEP_DRIFT { + Err(None) + // wait a bit for blocks in near future + } else if given > current { + let d = self.duration as u64; + Err(Some(OutOfBounds { + min: None, + max: Some(d * current as u64), + found: d * given as u64, + })) } else { - false + Ok(()) } } } +// Chain scoring: total weight is sqrt(U256::max_value())*height - step +fn calculate_score(parent_step: U256, current_step: U256, current_empty_steps: U256) -> U256 { + U256::from(U128::max_value()) + parent_step - current_step + current_empty_steps +} + struct EpochManager { epoch_transition_hash: H256, epoch_transition_number: BlockNumber, @@ -133,7 +203,7 @@ impl EpochManager { } // zoom to epoch for given header. returns true if succeeded, false otherwise. - fn zoom_to(&mut self, client: &EngineClient, engine: &Engine, validators: &ValidatorSet, header: &Header) -> bool { + fn zoom_to(&mut self, client: &EngineClient, machine: &EthereumMachine, validators: &ValidatorSet, header: &Header) -> bool { let last_was_parent = self.finality_checker.subchain_head() == Some(header.parent_hash().clone()); // early exit for current target == chain head, but only if the epochs are @@ -159,7 +229,6 @@ impl EpochManager { } }; - // extract other epoch set if it's not the same as the last. if last_transition.block_hash != self.epoch_transition_hash { let (signal_number, set_proof, _) = destructure_proofs(&last_transition.proof) @@ -171,7 +240,7 @@ impl EpochManager { let first = signal_number == 0; let epoch_set = validators.epoch_set( first, - engine, + machine, signal_number, // use signal number so multi-set first calculation is correct. set_proof, ) @@ -201,10 +270,112 @@ impl EpochManager { } } +/// A message broadcast by authorities when it's their turn to seal a block but there are no +/// transactions. Other authorities accumulate these messages and later include them in the seal as +/// proof. +#[derive(Clone, Debug)] +struct EmptyStep { + signature: H520, + step: usize, + parent_hash: H256, +} + +impl EmptyStep { + fn from_sealed(sealed_empty_step: SealedEmptyStep, parent_hash: &H256) -> EmptyStep { + let signature = sealed_empty_step.signature; + let step = sealed_empty_step.step; + let parent_hash = parent_hash.clone(); + EmptyStep { signature, step, parent_hash } + } + + fn verify(&self, validators: &ValidatorSet) -> Result { + let message = keccak(empty_step_rlp(self.step, &self.parent_hash)); + let correct_proposer = step_proposer(validators, &self.parent_hash, self.step); + + verify_address(&correct_proposer, &self.signature.into(), &message) + .map_err(|e| e.into()) + } + + fn author(&self) -> Result { + let message = keccak(empty_step_rlp(self.step, &self.parent_hash)); + let public = recover(&self.signature.into(), &message)?; + Ok(public_to_address(&public)) + } + + fn sealed(&self) -> SealedEmptyStep { + let signature = self.signature; + let step = self.step; + SealedEmptyStep { signature, step } + } +} + +impl fmt::Display for EmptyStep { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "({}, {}, {})", self.signature, self.step, self.parent_hash) + } +} + +impl Encodable for EmptyStep { + fn rlp_append(&self, s: &mut RlpStream) { + let empty_step_rlp = empty_step_rlp(self.step, &self.parent_hash); + s.begin_list(2) + .append(&self.signature) + .append_raw(&empty_step_rlp, 1); + } +} + +impl Decodable for EmptyStep { + fn decode(rlp: &UntrustedRlp) -> Result { + let signature = rlp.val_at(0)?; + let empty_step_rlp = rlp.at(1)?; + + let step = empty_step_rlp.val_at(0)?; + let parent_hash = empty_step_rlp.val_at(1)?; + + Ok(EmptyStep { signature, step, parent_hash }) + } +} + +pub fn empty_step_full_rlp(signature: &H520, empty_step_rlp: &[u8]) -> Vec { + let mut s = RlpStream::new_list(2); + s.append(signature).append_raw(empty_step_rlp, 1); + s.out() +} + +pub fn empty_step_rlp(step: usize, parent_hash: &H256) -> Vec { + let mut s = RlpStream::new_list(2); + s.append(&step).append(parent_hash); + s.out() +} + +/// An empty step message that is included in a seal, the only difference is that it doesn't include +/// the `parent_hash` in order to save space. The included signature is of the original empty step +/// message, which can be reconstructed by using the parent hash of the block in which this sealed +/// empty message is included. +struct SealedEmptyStep { + signature: H520, + step: usize, +} + +impl Encodable for SealedEmptyStep { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(2) + .append(&self.signature) + .append(&self.step); + } +} + +impl Decodable for SealedEmptyStep { + fn decode(rlp: &UntrustedRlp) -> Result { + let signature = rlp.val_at(0)?; + let step = rlp.val_at(1)?; + + Ok(SealedEmptyStep { signature, step }) + } +} + /// Engine using `AuthorityRound` proof-of-authority BFT consensus. pub struct AuthorityRound { - params: CommonParams, - builtins: BTreeMap, transition_service: IoService<()>, step: Arc, can_propose: AtomicBool, @@ -213,71 +384,136 @@ pub struct AuthorityRound { validators: Box, validate_score_transition: u64, validate_step_transition: u64, + empty_steps: Mutex>, epoch_manager: Mutex, immediate_transitions: bool, + block_reward: U256, + maximum_uncle_count_transition: u64, + maximum_uncle_count: usize, + empty_steps_transition: u64, + maximum_empty_steps: usize, + machine: EthereumMachine, } // header-chain validator. struct EpochVerifier { step: Arc, subchain_validators: SimpleList, + empty_steps_transition: u64, } -impl super::EpochVerifier for EpochVerifier { +impl super::EpochVerifier for EpochVerifier { fn verify_light(&self, header: &Header) -> Result<(), Error> { + // Validate the timestamp + verify_timestamp(&*self.step, header_step(header, self.empty_steps_transition)?)?; // always check the seal since it's fast. // nothing heavier to do. - verify_external(header, &self.subchain_validators, &*self.step, |_| {}) + verify_external(header, &self.subchain_validators, self.empty_steps_transition) } fn check_finality_proof(&self, proof: &[u8]) -> Option> { - macro_rules! otry { - ($e: expr) => { - match $e { - Some(x) => x, - None => return None, - } - } - } - let mut finality_checker = RollingFinality::blank(self.subchain_validators.clone().into_inner()); let mut finalized = Vec::new(); - let headers: Vec
= otry!(UntrustedRlp::new(proof).as_list().ok()); + let headers: Vec
= UntrustedRlp::new(proof).as_list().ok()?; + + { + let mut push_header = |parent_header: &Header, header: Option<&Header>| { + // ensure all headers have correct number of seal fields so we can `verify_external` + // and get `empty_steps` without panic. + if parent_header.seal().len() != header_expected_seal_fields(parent_header, self.empty_steps_transition) { + return None + } + if header.iter().any(|h| h.seal().len() != header_expected_seal_fields(h, self.empty_steps_transition)) { + return None + } + + // `verify_external` checks that signature is correct and author == signer. + verify_external(parent_header, &self.subchain_validators, self.empty_steps_transition).ok()?; + + let mut signers = match header { + Some(header) => header_empty_steps_signers(header, self.empty_steps_transition).ok()?, + _ => Vec::new(), + }; + signers.push(parent_header.author().clone()); + + let newly_finalized = finality_checker.push_hash(parent_header.hash(), signers).ok()?; + finalized.extend(newly_finalized); + Some(()) + }; - for header in &headers { - // ensure all headers have correct number of seal fields so we can `verify_external` - // without panic. - // - // `verify_external` checks that signature is correct and author == signer. - if header.seal().len() != 2 { return None } - otry!(verify_external(header, &self.subchain_validators, &*self.step, |_| {}).ok()); + for window in headers.windows(2) { + push_header(&window[0], Some(&window[1]))?; + } - let newly_finalized = otry!(finality_checker.push_hash(header.hash(), header.author().clone()).ok()); - finalized.extend(newly_finalized); + if let Some(last) = headers.last() { + push_header(last, None)?; + } } if finalized.is_empty() { None } else { Some(finalized) } } } -// Report misbehavior -#[derive(Debug)] -#[allow(dead_code)] -enum Report { - // Malicious behavior - Malicious(Address, BlockNumber, Bytes), - // benign misbehavior - Benign(Address, BlockNumber), +fn header_seal_hash(header: &Header, empty_steps_rlp: Option<&[u8]>) -> H256 { + match empty_steps_rlp { + Some(empty_steps_rlp) => { + let mut message = header.bare_hash().to_vec(); + message.extend_from_slice(empty_steps_rlp); + keccak(message) + }, + None => { + header.bare_hash() + }, + } +} + +fn header_expected_seal_fields(header: &Header, empty_steps_transition: u64) -> usize { + if header.number() >= empty_steps_transition { + 3 + } else { + 2 + } +} + +fn header_step(header: &Header, empty_steps_transition: u64) -> Result { + let expected_seal_fields = header_expected_seal_fields(header, empty_steps_transition); + UntrustedRlp::new(&header.seal().get(0).expect( + &format!("was either checked with verify_block_basic or is genesis; has {} fields; qed (Make sure the spec file has a correct genesis seal)", expected_seal_fields))).as_val() +} + +fn header_signature(header: &Header, empty_steps_transition: u64) -> Result { + let expected_seal_fields = header_expected_seal_fields(header, empty_steps_transition); + UntrustedRlp::new(&header.seal().get(1).expect( + &format!("was checked with verify_block_basic; has {} fields; qed", expected_seal_fields))).as_val::().map(Into::into) } -fn header_step(header: &Header) -> Result { - UntrustedRlp::new(&header.seal().get(0).expect("was either checked with verify_block_basic or is genesis; has 2 fields; qed (Make sure the spec file has a correct genesis seal)")).as_val() +// extracts the raw empty steps vec from the header seal. should only be called when there are 3 fields in the seal +// (i.e. header.number() >= self.empty_steps_transition) +fn header_empty_steps_raw(header: &Header) -> &[u8] { + header.seal().get(2).expect("was checked with verify_block_basic; has 3 fields; qed") } -fn header_signature(header: &Header) -> Result { - UntrustedRlp::new(&header.seal().get(1).expect("was checked with verify_block_basic; has 2 fields; qed")).as_val::().map(Into::into) +// extracts the empty steps from the header seal. should only be called when there are 3 fields in the seal +// (i.e. header.number() >= self.empty_steps_transition). +fn header_empty_steps(header: &Header) -> Result, ::rlp::DecoderError> { + let empty_steps = UntrustedRlp::new(header_empty_steps_raw(header)).as_list::()?; + Ok(empty_steps.into_iter().map(|s| EmptyStep::from_sealed(s, header.parent_hash())).collect()) +} + +// gets the signers of empty step messages for the given header, does not include repeated signers +fn header_empty_steps_signers(header: &Header, empty_steps_transition: u64) -> Result, Error> { + if header.number() >= empty_steps_transition { + let mut signers = HashSet::new(); + for empty_step in header_empty_steps(header)? { + signers.insert(empty_step.author()?); + } + + Ok(Vec::from_iter(signers.into_iter())) + } else { + Ok(Vec::new()) + } } fn step_proposer(validators: &ValidatorSet, bh: &H256, step: usize) -> Address { @@ -290,28 +526,44 @@ fn is_step_proposer(validators: &ValidatorSet, bh: &H256, step: usize, address: step_proposer(validators, bh, step) == *address } -fn verify_external(header: &Header, validators: &ValidatorSet, step: &Step, report: F) - -> Result<(), Error> -{ - let header_step = header_step(header)?; +fn verify_timestamp(step: &Step, header_step: usize) -> Result<(), BlockError> { + match step.check_future(header_step) { + Err(None) => { + trace!(target: "engine", "verify_timestamp: block from the future"); + Err(BlockError::InvalidSeal.into()) + }, + Err(Some(oob)) => { + // NOTE This error might be returned only in early stage of verification (Stage 1). + // Returning it further won't recover the sync process. + trace!(target: "engine", "verify_timestamp: block too early"); + Err(BlockError::TemporarilyInvalid(oob).into()) + }, + Ok(_) => Ok(()), + } +} - // Give one step slack if step is lagging, double vote is still not possible. - if step.is_future(header_step) { - trace!(target: "engine", "verify_block_external: block from the future"); - report(Report::Benign(*header.author(), header.number())); - Err(BlockError::InvalidSeal)? - } else { - let proposer_signature = header_signature(header)?; - let correct_proposer = validators.get(header.parent_hash(), header_step); - let is_invalid_proposer = *header.author() != correct_proposer || - !verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())?; - - if is_invalid_proposer { - trace!(target: "engine", "verify_block_external: bad proposer for step: {}", header_step); - Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))? +fn verify_external(header: &Header, validators: &ValidatorSet, empty_steps_transition: u64) -> Result<(), Error> { + let header_step = header_step(header, empty_steps_transition)?; + + let proposer_signature = header_signature(header, empty_steps_transition)?; + let correct_proposer = validators.get(header.parent_hash(), header_step); + let is_invalid_proposer = *header.author() != correct_proposer || { + let empty_steps_rlp = if header.number() >= empty_steps_transition { + Some(header_empty_steps_raw(header)) } else { - Ok(()) - } + None + }; + + let header_seal_hash = header_seal_hash(header, empty_steps_rlp); + !verify_address(&correct_proposer, &proposer_signature, &header_seal_hash)? + }; + + if is_invalid_proposer { + trace!(target: "engine", "verify_block_external: bad proposer for step: {}", header_step); + validators.report_benign(header.author(), header.number(), header.number()); + Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))? + } else { + Ok(()) } } @@ -342,13 +594,15 @@ impl AsMillis for Duration { impl AuthorityRound { /// Create a new instance of AuthorityRound engine. - pub fn new(params: CommonParams, our_params: AuthorityRoundParams, builtins: BTreeMap) -> Result, Error> { + pub fn new(our_params: AuthorityRoundParams, machine: EthereumMachine) -> Result, 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 { - params: params, - builtins: builtins, transition_service: IoService::<()>::start()?, step: Arc::new(Step { inner: AtomicUsize::new(initial_step), @@ -361,8 +615,15 @@ impl AuthorityRound { validators: our_params.validators, validate_score_transition: our_params.validate_score_transition, validate_step_transition: our_params.validate_step_transition, + empty_steps: Mutex::new(Vec::new()), 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, + empty_steps_transition: our_params.empty_steps_transition, + maximum_empty_steps: our_params.maximum_empty_steps, + machine: machine, }); // Do not initialize timeouts for tests. @@ -372,6 +633,52 @@ impl AuthorityRound { } Ok(engine) } + + fn empty_steps(&self, from_step: U256, to_step: U256, parent_hash: H256) -> Vec { + self.empty_steps.lock().iter().filter(|e| { + U256::from(e.step) > from_step && + U256::from(e.step) < to_step && + e.parent_hash == parent_hash + }).cloned().collect() + } + + + fn clear_empty_steps(&self, step: U256) { + // clear old `empty_steps` messages + self.empty_steps.lock().retain(|e| U256::from(e.step) > step); + } + + fn handle_empty_step_message(&self, empty_step: EmptyStep) { + let mut empty_steps = self.empty_steps.lock(); + empty_steps.push(empty_step); + } + + fn generate_empty_step(&self, parent_hash: &H256) { + let step = self.step.load(); + let empty_step_rlp = empty_step_rlp(step, parent_hash); + + if let Ok(signature) = self.sign(keccak(&empty_step_rlp)).map(Into::into) { + let message_rlp = empty_step_full_rlp(&signature, &empty_step_rlp); + + let parent_hash = *parent_hash; + let empty_step = EmptyStep { signature, step, parent_hash }; + + trace!(target: "engine", "broadcasting empty step message: {:?}", empty_step); + self.broadcast_message(message_rlp); + self.handle_empty_step_message(empty_step); + + } else { + warn!(target: "engine", "generate_empty_step: FAIL: accounts secret key unavailable"); + } + } + + fn broadcast_message(&self, message: Vec) { + if let Some(ref weak) = *self.client.read() { + if let Some(c) = weak.upgrade() { + c.broadcast_consensus_message(message); + } + } + } } fn unix_now() -> Duration { @@ -396,31 +703,32 @@ impl IoHandler<()> for TransitionHandler { fn timeout(&self, io: &IoContext<()>, timer: TimerToken) { if timer == ENGINE_TIMEOUT_TOKEN { if let Some(engine) = self.engine.upgrade() { - engine.step(); - let remaining = engine.step.duration_remaining(); - io.register_timer_once(ENGINE_TIMEOUT_TOKEN, remaining.as_millis()) + // NOTE we might be lagging by couple of steps in case the timeout + // has not been called fast enough. + // Make sure to advance up to the actual step. + while engine.step.duration_remaining().as_millis() == 0 { + engine.step(); + } + + let next_run_at = engine.step.duration_remaining().as_millis() >> 2; + io.register_timer_once(ENGINE_TIMEOUT_TOKEN, next_run_at) .unwrap_or_else(|e| warn!(target: "engine", "Failed to restart consensus step timer: {}.", e)) } } } } -impl Engine for AuthorityRound { +impl Engine for AuthorityRound { fn name(&self) -> &str { "AuthorityRound" } - fn version(&self) -> SemanticVersion { SemanticVersion::new(1, 0, 0) } - - /// Two fields - consensus step and the corresponding proposer signature. - fn seal_fields(&self) -> usize { 2 } + fn machine(&self) -> &EthereumMachine { &self.machine } - fn params(&self) -> &CommonParams { &self.params } - - fn additional_params(&self) -> HashMap { - hash_map!["registrar".to_owned() => self.params().registrar.hex()] + /// Three fields - consensus step and the corresponding proposer signature, and a list of empty + /// step messages (which should be empty if no steps are skipped) + fn seal_fields(&self, header: &Header) -> usize { + header_expected_seal_fields(header, self.empty_steps_transition) } - fn builtins(&self) -> &BTreeMap { &self.builtins } - fn step(&self) { self.step.increment(); self.can_propose.store(true, AtomicOrdering::SeqCst); @@ -433,43 +741,117 @@ impl Engine for AuthorityRound { /// Additional engine-specific information for the user/developer concerning `header`. fn extra_info(&self, header: &Header) -> BTreeMap { - map![ - "step".into() => header_step(header).as_ref().map(ToString::to_string).unwrap_or("".into()), - "signature".into() => header_signature(header).as_ref().map(ToString::to_string).unwrap_or("".into()) - ] - } - - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { - // 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); - header.set_gas_limit({ - let gas_limit = parent.gas_limit().clone(); - let bound_divisor = self.params().gas_limit_bound_divisor; - if gas_limit < gas_floor_target { - cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) - } else { - cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) - } - }); + let step = header_step(header, self.empty_steps_transition).as_ref().map(ToString::to_string).unwrap_or("".into()); + let signature = header_signature(header, self.empty_steps_transition).as_ref().map(ToString::to_string).unwrap_or("".into()); + + let mut info = map![ + "step".into() => step, + "signature".into() => signature + ]; + + if header.number() >= self.empty_steps_transition { + let empty_steps = + if let Ok(empty_steps) = header_empty_steps(header).as_ref() { + format!("[{}]", + empty_steps.iter().fold( + "".to_string(), + |acc, e| if acc.len() > 0 { acc + ","} else { acc } + &e.to_string())) + + } else { + "".into() + }; + + info.insert("emptySteps".into(), empty_steps); + } + + info + } + + 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) { + let parent_step = header_step(parent, self.empty_steps_transition).expect("Header has been verified; qed"); + let current_step = self.step.load(); + + let current_empty_steps_len = if header.number() >= self.empty_steps_transition { + self.empty_steps(parent_step.into(), current_step.into(), parent.hash()).len() + } else { + 0 + }; + + let score = calculate_score(parent_step.into(), current_step.into(), current_empty_steps_len.into()); + header.set_difficulty(score); } fn seals_internally(&self) -> Option { + // TODO: accept a `&Call` here so we can query the validator set. Some(self.signer.read().is_some()) } + fn handle_message(&self, rlp: &[u8]) -> Result<(), EngineError> { + fn fmt_err(x: T) -> EngineError { + EngineError::MalformedMessage(format!("{:?}", x)) + } + + let rlp = UntrustedRlp::new(rlp); + let empty_step: EmptyStep = rlp.as_val().map_err(fmt_err)?;; + + if empty_step.verify(&*self.validators).unwrap_or(false) { + if self.step.check_future(empty_step.step).is_ok() { + trace!(target: "engine", "handle_message: received empty step message {:?}", empty_step); + self.handle_empty_step_message(empty_step); + } else { + trace!(target: "engine", "handle_message: empty step message from the future {:?}", empty_step); + } + } else { + trace!(target: "engine", "handle_message: received invalid step message {:?}", empty_step); + }; + + Ok(()) + } + /// Attempt to seal the block internally. /// /// 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, self.empty_steps_transition) + .expect("Header has been verified; qed").into(); + let step = self.step.load(); + // filter messages from old and future steps and different parents + let empty_steps = if header.number() >= self.empty_steps_transition { + self.empty_steps(parent_step.into(), step.into(), *header.parent_hash()) + } else { + Vec::new() + }; + + let expected_diff = calculate_score(parent_step, step.into(), empty_steps.len().into()); + + if header.difficulty() != &expected_diff { + debug!(target: "engine", "Aborting seal generation. The step or empty_steps have changed in the meantime. {:?} != {:?}", + header.difficulty(), expected_diff); + return Seal::None; + } + + if parent_step > step.into() { + warn!(target: "engine", "Aborting seal generation for invalid step: {} > {}", parent_step, step); + return Seal::None; + } + // fetch correct validator set for current epoch, taking into account // finality of previous transitions. let active_set; @@ -486,7 +868,7 @@ impl Engine for AuthorityRound { } }; - if !epoch_manager.zoom_to(&*client, self, &*self.validators, header) { + if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, header) { debug!(target: "engine", "Unable to zoom to epoch."); return Seal::None; } @@ -496,12 +878,49 @@ impl Engine for AuthorityRound { }; if is_step_proposer(validators, header.parent_hash(), step, header.author()) { - if let Ok(signature) = self.sign(header.bare_hash()) { + // 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 there are no transactions to include in the block, we don't seal and instead broadcast a signed + // `EmptyStep(step, parent_hash)` message. If we exceed the maximum amount of `empty_step` rounds we proceed + // with the seal. + if header.number() >= self.empty_steps_transition && + block.transactions().is_empty() && + empty_steps.len() < self.maximum_empty_steps { + + self.generate_empty_step(header.parent_hash()); + return Seal::None; + } + + let empty_steps_rlp = if header.number() >= self.empty_steps_transition { + let empty_steps: Vec<_> = empty_steps.iter().map(|e| e.sealed()).collect(); + Some(::rlp::encode_list(&empty_steps).into_vec()) + } else { + None + }; + + if let Ok(signature) = self.sign(header_seal_hash(header, empty_steps_rlp.as_ref().map(|e| &**e))) { trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step); // only issue the seal if we were the first to reach the compare_and_swap. if self.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) { - return Seal::Regular(vec![encode(&step).into_vec(), encode(&(&H520::from(signature) as &[u8])).into_vec()]); + + self.clear_empty_steps(parent_step); + + let mut fields = vec![ + encode(&step).into_vec(), + encode(&(&H520::from(signature) as &[u8])).into_vec(), + ]; + + if let Some(empty_steps_rlp) = empty_steps_rlp { + fields.push(empty_steps_rlp); + } + + return Seal::Regular(fields); } } else { warn!(target: "engine", "generate_seal: FAIL: Accounts secret key unavailable."); @@ -510,31 +929,30 @@ impl Engine for AuthorityRound { trace!(target: "engine", "generate_seal: {} not a proposer for step {}.", header.author(), step); } + Seal::None } + fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { + Ok(()) + } + fn on_new_block( &self, block: &mut ExecutedBlock, - last_hashes: Arc<::vm::LastHashes>, epoch_begin: bool, ) -> Result<(), Error> { - let parent_hash = block.fields().header.parent_hash().clone(); - ::engines::common::push_last_hash(block, last_hashes.clone(), self, &parent_hash)?; - // with immediate transitions, we don't use the epoch mechanism anyway. // the genesis is always considered an epoch, but we ignore it intentionally. if self.immediate_transitions || !epoch_begin { return Ok(()) } // genesis is never a new block, but might as well check. - let header = block.fields().header.clone(); + let header = block.header().clone(); let first = header.number() == 0; let mut call = |to, data| { - let result = ::engines::common::execute_as_system( + let result = self.machine.execute_as_system( block, - last_hashes.clone(), - self, to, U256::max_value(), // unbounded gas? maybe make configurable. Some(data), @@ -548,91 +966,142 @@ impl Engine for AuthorityRound { /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { - let fields = block.fields_mut(); - // Bestow block reward - let reward = self.params().block_reward; - let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) - .map_err(::error::Error::from) - .and_then(|_| fields.state.commit()); - // Commit state so that we can actually figure out the state root. - if let Err(ref e) = res { - warn!("Encountered error on closing block: {}", e); + use parity_machine::WithBalances; + + let mut rewards = Vec::new(); + if block.header().number() >= self.empty_steps_transition { + let empty_steps = if block.header().seal().is_empty() { + // this is a new block, calculate rewards based on the empty steps messages we have accumulated + let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { + Some(client) => client, + None => { + debug!(target: "engine", "Unable to close block: missing client ref."); + return Err(EngineError::RequiresClient.into()) + }, + }; + + let parent = client.block_header(::client::BlockId::Hash(*block.header().parent_hash())) + .expect("hash is from parent; parent header must exist; qed") + .decode(); + + let parent_step = header_step(&parent, self.empty_steps_transition)?; + let current_step = self.step.load(); + self.empty_steps(parent_step.into(), current_step.into(), parent.hash()) + } else { + // we're verifying a block, extract empty steps from the seal + header_empty_steps(block.header())? + }; + + for empty_step in empty_steps { + let author = empty_step.author()?; + rewards.push((author, self.block_reward)); + } } - res + + let author = *block.header().author(); + rewards.push((author, self.block_reward)); + + for &(ref author, ref block_reward) in rewards.iter() { + self.machine.add_balance(block, author, block_reward)?; + } + self.machine.note_rewards(block, &rewards, &[]) } /// Check the number of seal fields. - fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - if header.seal().len() != self.seal_fields() { - trace!(target: "engine", "verify_block_basic: wrong number of seal fields"); - Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal().len() } - ))) - } else if header.number() >= self.validate_score_transition && *header.difficulty() >= U256::from(U128::max_value()) { - Err(From::from(BlockError::DifficultyOutOfBounds( + fn verify_block_basic(&self, header: &Header) -> Result<(), Error> { + if header.number() >= self.validate_score_transition && *header.difficulty() >= U256::from(U128::max_value()) { + return Err(From::from(BlockError::DifficultyOutOfBounds( OutOfBounds { min: None, max: Some(U256::from(U128::max_value())), found: *header.difficulty() } - ))) - } else { - Ok(()) + ))); } - } - fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - Ok(()) - } + // TODO [ToDr] Should this go from epoch manager? + // If yes then probably benign reporting needs to be moved further in the verification. + let set_number = header.number(); - /// Do the step and gas limit validation. - fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - let step = header_step(header)?; - - // Do not calculate difficulty for genesis blocks. - if header.number() == 0 { - return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); + match verify_timestamp(&*self.step, header_step(header, self.empty_steps_transition)?) { + Err(BlockError::InvalidSeal) => { + self.validators.report_benign(header.author(), set_number, header.number()); + Err(BlockError::InvalidSeal.into()) + } + Err(e) => Err(e.into()), + Ok(()) => Ok(()), } + } - let parent_step = header_step(parent)?; + /// Do the step and gas limit validation. + fn verify_block_family(&self, header: &Header, parent: &Header) -> Result<(), Error> { + let step = header_step(header, self.empty_steps_transition)?; + let parent_step = header_step(parent, self.empty_steps_transition)?; + // TODO [ToDr] Should this go from epoch manager? + let set_number = header.number(); // Ensure header is from the step after parent. if step == parent_step || (header.number() >= self.validate_step_transition && step <= parent_step) { trace!(target: "engine", "Multiple blocks proposed for step {}.", parent_step); - self.validators.report_malicious(header.author(), header.number(), header.number(), Default::default()); + self.validators.report_malicious(header.author(), set_number, header.number(), Default::default()); Err(EngineError::DoubleVote(header.author().clone()))?; } - // Report skipped primaries. - if let (true, Some(me)) = (step > parent_step + 1, self.signer.read().address()) { - debug!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}", - header.author(), step, parent_step); - let mut reported = HashSet::new(); - for s in parent_step + 1..step { - let skipped_primary = step_proposer(&*self.validators, &parent.hash(), s); - // Do not report this signer. - if skipped_primary != me { - self.validators.report_benign(&skipped_primary, header.number(), header.number()); + + // If empty step messages are enabled we will validate the messages in the seal, missing messages are not + // reported as there's no way to tell whether the empty step message was never sent or simply not included. + if header.number() >= self.empty_steps_transition { + let validate_empty_steps = || -> Result<(), Error> { + let empty_steps = header_empty_steps(header)?; + for empty_step in empty_steps { + if empty_step.step <= parent_step || empty_step.step >= step { + Err(EngineError::InsufficientProof( + format!("empty step proof for invalid step: {:?}", empty_step.step)))?; + } + + if empty_step.parent_hash != *header.parent_hash() { + Err(EngineError::InsufficientProof( + format!("empty step proof for invalid parent hash: {:?}", empty_step.parent_hash)))?; + } + + if !empty_step.verify(&*self.validators).unwrap_or(false) { + Err(EngineError::InsufficientProof( + format!("invalid empty step proof: {:?}", empty_step)))?; + } } - // Stop reporting once validators start repeating. - if !reported.insert(skipped_primary) { break; } + Ok(()) + }; + + if let err @ Err(_) = validate_empty_steps() { + self.validators.report_benign(header.author(), set_number, header.number()); + return err; } - } - let gas_limit_divisor = self.params().gas_limit_bound_divisor; - let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor; - let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; - if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))); + } else { + // Report skipped primaries. + if let (true, Some(me)) = (step > parent_step + 1, self.signer.read().address()) { + debug!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}", + header.author(), step, parent_step); + let mut reported = HashSet::new(); + for s in parent_step + 1..step { + let skipped_primary = step_proposer(&*self.validators, &parent.hash(), s); + // Do not report this signer. + if skipped_primary != me { + self.validators.report_benign(&skipped_primary, set_number, header.number()); + // Stop reporting once validators start repeating. + if !reported.insert(skipped_primary) { break; } + } + } + } } + Ok(()) } // Check the validators. - fn verify_block_external(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { + fn verify_block_external(&self, header: &Header) -> Result<(), Error> { // fetch correct validator set for current epoch, taking into account // finality of previous transitions. let active_set; - - let (validators, set_number) = if self.immediate_transitions { - (&*self.validators, header.number()) + let validators = if self.immediate_transitions { + &*self.validators } else { // get correct validator set for epoch. let client = match self.client.read().as_ref().and_then(|weak| weak.upgrade()) { @@ -644,25 +1113,23 @@ impl Engine for AuthorityRound { }; let mut epoch_manager = self.epoch_manager.lock(); - if !epoch_manager.zoom_to(&*client, self, &*self.validators, header) { + if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, header) { debug!(target: "engine", "Unable to zoom to epoch."); return Err(EngineError::RequiresClient.into()) } active_set = epoch_manager.validators().clone(); - (&active_set as &_, epoch_manager.epoch_transition_number) - }; - - let report = |report| match report { - Report::Benign(address, block_number) => - self.validators.report_benign(&address, set_number, block_number), - Report::Malicious(address, block_number, proof) => - self.validators.report_malicious(&address, set_number, block_number, proof), + &active_set as &_ }; // verify signature against fixed list, but reports should go to the // contract itself. - verify_external(header, validators, &*self.step, report) + let res = verify_external(header, validators, self.empty_steps_transition); + if res.is_ok() { + let header_step = header_step(header, self.empty_steps_transition)?; + self.clear_empty_steps(header_step.into()); + } + res } fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result, String> { @@ -670,19 +1137,19 @@ impl Engine for AuthorityRound { .map(|set_proof| combine_proofs(0, &set_proof, &[])) } - fn signals_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>) - -> super::EpochChange + fn signals_epoch_end(&self, header: &Header, aux: AuxiliaryData) + -> super::EpochChange { if self.immediate_transitions { return super::EpochChange::No } let first = header.number() == 0; - self.validators.signals_epoch_end(first, header, block, receipts) + self.validators.signals_epoch_end(first, header, aux) } fn is_epoch_end( &self, chain_head: &Header, - chain: &super::Headers, + chain: &super::Headers
, transition_store: &super::PendingTransitionStore, ) -> Option> { // epochs only matter if we want to support light clients. @@ -706,7 +1173,7 @@ impl Engine for AuthorityRound { // find most recently finalized blocks, then check transition store for pending transitions. let mut epoch_manager = self.epoch_manager.lock(); - if !epoch_manager.zoom_to(&*client, self, &*self.validators, chain_head) { + if !epoch_manager.zoom_to(&*client, &self.machine, &*self.validators, chain_head) { return None; } @@ -717,20 +1184,39 @@ impl Engine for AuthorityRound { chain_head.hash(), chain_head.parent_hash()); let mut hash = chain_head.parent_hash().clone(); + let mut parent_empty_steps_signers = match header_empty_steps_signers(&chain_head, self.empty_steps_transition) { + Ok(empty_step_signers) => empty_step_signers, + Err(_) => { + warn!(target: "finality", "Failed to get empty step signatures from block {}", chain_head.hash()); + return None; + } + }; + let epoch_transition_hash = epoch_manager.epoch_transition_hash; // walk the chain within current epoch backwards. - // author == ec_recover(sig) known since - // the blocks are in the DB. + // author == ec_recover(sig) known since the blocks are in the DB. + // the empty steps messages in a header signal approval of the parent header. let ancestry_iter = itertools::repeat_call(move || { chain(hash).and_then(|header| { if header.number() == 0 { return None } - let res = (hash, header.author().clone()); - trace!(target: "finality", "Ancestry iteration: yielding {:?}", res); + let mut signers = vec![header.author().clone()]; + signers.extend(parent_empty_steps_signers.drain(..)); + + if let Ok(empty_step_signers) = header_empty_steps_signers(&header, self.empty_steps_transition) { + let res = (hash, signers); + trace!(target: "finality", "Ancestry iteration: yielding {:?}", res); + + hash = header.parent_hash().clone(); + parent_empty_steps_signers = empty_step_signers; - hash = header.parent_hash().clone(); - Some(res) + Some(res) + + } else { + warn!(target: "finality", "Failed to get empty step signatures from block {}", header.hash()); + None + } }) }) .while_some() @@ -743,15 +1229,20 @@ impl Engine for AuthorityRound { } { - if let Ok(finalized) = epoch_manager.finality_checker.push_hash(chain_head.hash(), *chain_head.author()) { + if let Ok(finalized) = epoch_manager.finality_checker.push_hash(chain_head.hash(), vec![chain_head.author().clone()]) { let mut finalized = finalized.into_iter(); - while let Some(hash) = finalized.next() { - if let Some(pending) = transition_store(hash) { - let finality_proof = ::std::iter::once(hash) + while let Some(finalized_hash) = finalized.next() { + if let Some(pending) = transition_store(finalized_hash) { + let finality_proof = ::std::iter::once(finalized_hash) .chain(finalized) .chain(epoch_manager.finality_checker.unfinalized_hashes()) - .map(|hash| chain(hash) - .expect("these headers fetched before when constructing finality checker; qed")) + .map(|h| if h == chain_head.hash() { + // chain closure only stores ancestry, but the chain head is also + // unfinalized. + chain_head.clone() + } else { + chain(h).expect("these headers fetched before when constructing finality checker; qed") + }) .collect::>(); // this gives us the block number for `hash`, assuming it's ancestry. @@ -780,18 +1271,19 @@ impl Engine for AuthorityRound { None } - fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a> { + fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> { let (signal_number, set_proof, finality_proof) = match destructure_proofs(proof) { Ok(x) => x, Err(e) => return ConstructedVerifier::Err(e), }; let first = signal_number == 0; - match self.validators.epoch_set(first, self, signal_number, set_proof) { + match self.validators.epoch_set(first, &self.machine, signal_number, set_proof) { Ok((list, finalize)) => { let verifier = Box::new(EpochVerifier { step: self.step.clone(), subchain_validators: list, + empty_steps_transition: self.empty_steps_transition, }); match finalize { @@ -803,21 +1295,9 @@ impl Engine for AuthorityRound { } } - fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> { - t.check_low_s()?; - - if let Some(n) = t.chain_id() { - if header.number() >= self.params().eip155_transition && n != self.params().chain_id { - return Err(TransactionError::InvalidChainId.into()); - } - } - - Ok(()) - } - - fn register_client(&self, client: Weak) { + fn register_client(&self, client: Weak) { *self.client.write() = Some(client.clone()); - self.validators.register_contract(client); + self.validators.register_client(client); } fn set_signer(&self, ap: Arc, address: Address, password: String) { @@ -841,23 +1321,27 @@ impl Engine for AuthorityRound { mod tests { use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; - use util::*; + use hash::keccak; + use ethereum_types::{Address, H520, H256, U256}; use header::Header; - use error::{Error, BlockError}; use rlp::encode; use block::*; - use tests::helpers::*; + use tests::helpers::{ + generate_dummy_client_with_spec_and_accounts, get_temp_state_db, generate_dummy_client, + TestNotify + }; use account_provider::AccountProvider; use spec::Spec; - use engines::{Seal, Engine}; + use transaction::{Action, Transaction}; + use engines::{Seal, Engine, EngineError, EthEngine}; use engines::validator_set::TestSet; - use super::{AuthorityRoundParams, AuthorityRound}; + use error::Error; + use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep}; #[test] fn has_valid_metadata() { let engine = Spec::new_test_round().engine; assert!(!engine.name().is_empty()); - assert!(engine.version().major >= 1); } #[test] @@ -868,35 +1352,21 @@ mod tests { assert!(schedule.stack_limit > 0); } - #[test] - fn verification_fails_on_short_seal() { - let engine = Spec::new_test_round().engine; - let header: Header = Header::default(); - - let verify_result = engine.verify_block_basic(&header, None); - - match verify_result { - Err(Error::Block(BlockError::InvalidSealArity(_))) => {}, - Err(_) => { panic!("should be block seal-arity mismatch error (got {:?})", verify_result); }, - _ => { panic!("Should be error, got Ok"); }, - } - } - #[test] fn can_do_signature_verification_fail() { let engine = Spec::new_test_round().engine; let mut header: Header = Header::default(); header.set_seal(vec![encode(&H520::default()).into_vec()]); - let verify_result = engine.verify_block_external(&header, None); + let verify_result = engine.verify_block_external(&header); assert!(verify_result.is_err()); } #[test] fn generates_seal_and_does_not_double_propose() { let tap = Arc::new(AccountProvider::transient_provider()); - let addr1 = tap.insert_account("1".sha3().into(), "1").unwrap(); - let addr2 = tap.insert_account("2".sha3().into(), "2").unwrap(); + let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap(); + let addr2 = tap.insert_account(keccak("2").into(), "2").unwrap(); let spec = Spec::new_test_round(); let engine = &*spec.engine; @@ -910,24 +1380,58 @@ 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 => {} + } + } } } #[test] fn proposer_switching() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account("0".sha3().into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); let mut parent_header: Header = Header::default(); parent_header.set_seal(vec![encode(&0usize).into_vec()]); parent_header.set_gas_limit("222222".parse::().unwrap()); @@ -942,17 +1446,17 @@ mod tests { // Two validators. // Spec starts with step 2. header.set_seal(vec![encode(&2usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]); - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); - assert!(engine.verify_block_external(&header, None).is_err()); + assert!(engine.verify_block_family(&header, &parent_header).is_ok()); + assert!(engine.verify_block_external(&header).is_err()); header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]); - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); - assert!(engine.verify_block_external(&header, None).is_ok()); + assert!(engine.verify_block_family(&header, &parent_header).is_ok()); + assert!(engine.verify_block_external(&header).is_ok()); } #[test] fn rejects_future_block() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account("0".sha3().into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); let mut parent_header: Header = Header::default(); parent_header.set_seal(vec![encode(&0usize).into_vec()]); @@ -968,17 +1472,16 @@ mod tests { // Two validators. // Spec starts with step 2. header.set_seal(vec![encode(&1usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]); - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); - assert!(engine.verify_block_external(&header, None).is_ok()); + assert!(engine.verify_block_family(&header, &parent_header).is_ok()); + assert!(engine.verify_block_external(&header).is_ok()); header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]); - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); - assert!(engine.verify_block_external(&header, None).is_err()); + assert!(engine.verify_block_basic(&header).is_err()); } #[test] fn rejects_step_backwards() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account("0".sha3().into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); let mut parent_header: Header = Header::default(); parent_header.set_seal(vec![encode(&4usize).into_vec()]); @@ -994,27 +1497,33 @@ mod tests { // Two validators. // Spec starts with step 2. header.set_seal(vec![encode(&5usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]); - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); + assert!(engine.verify_block_family(&header, &parent_header).is_ok()); header.set_seal(vec![encode(&3usize).into_vec(), encode(&(&*signature as &[u8])).into_vec()]); - assert!(engine.verify_block_family(&header, &parent_header, None).is_err()); + assert!(engine.verify_block_family(&header, &parent_header).is_err()); } #[test] 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, + empty_steps_transition: u64::max_value(), + maximum_empty_steps: 0, + block_reward: Default::default(), }; let aura = { let mut c_params = ::spec::CommonParams::default(); c_params.gas_limit_bound_divisor = 5.into(); - AuthorityRound::new(c_params, params, Default::default()).unwrap() + let machine = ::machine::EthereumMachine::regular(c_params, Default::default()); + AuthorityRound::new(params, machine).unwrap() }; let mut parent_header: Header = Header::default(); @@ -1026,12 +1535,359 @@ mod tests { header.set_seal(vec![encode(&3usize).into_vec()]); // Do not report when signer not present. - assert!(aura.verify_block_family(&header, &parent_header, None).is_ok()); + assert!(aura.verify_block_family(&header, &parent_header).is_ok()); assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0); aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), Default::default()); - assert!(aura.verify_block_family(&header, &parent_header, None).is_ok()); + 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, + empty_steps_transition: u64::max_value(), + maximum_empty_steps: 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, + empty_steps_transition: u64::max_value(), + maximum_empty_steps: 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(); + } + + fn setup_empty_steps() -> (Spec, Arc, Vec
) { + let spec = Spec::new_test_round_empty_steps(); + 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 accounts = vec![addr1, addr2]; + + (spec, tap, accounts) + } + + fn empty_step(engine: &EthEngine, step: usize, parent_hash: &H256) -> EmptyStep { + let empty_step_rlp = super::empty_step_rlp(step, parent_hash); + let signature = engine.sign(keccak(&empty_step_rlp)).unwrap().into(); + let parent_hash = parent_hash.clone(); + EmptyStep { step, signature, parent_hash } + } + + fn sealed_empty_step(engine: &EthEngine, step: usize, parent_hash: &H256) -> SealedEmptyStep { + let empty_step_rlp = super::empty_step_rlp(step, parent_hash); + let signature = engine.sign(keccak(&empty_step_rlp)).unwrap().into(); + SealedEmptyStep { signature, step } + } + + #[test] + fn broadcast_empty_step_message() { + let (spec, tap, accounts) = setup_empty_steps(); + + let addr1 = accounts[0]; + + let engine = &*spec.engine; + let genesis_header = spec.genesis_header(); + let db1 = 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 client = generate_dummy_client(0); + let notify = Arc::new(TestNotify::default()); + client.add_notify(notify.clone()); + engine.register_client(Arc::downgrade(&client) as _); + + engine.set_signer(tap.clone(), addr1, "1".into()); + + // the block is empty so we don't seal and instead broadcast an empty step message + assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + + // spec starts with step 2 + let empty_step_rlp = encode(&empty_step(engine, 2, &genesis_header.hash())).into_vec(); + + // we've received the message + assert!(notify.messages.read().contains(&empty_step_rlp)); + } + + #[test] + fn seal_with_empty_steps() { + let (spec, tap, accounts) = setup_empty_steps(); + + let addr1 = accounts[0]; + let addr2 = accounts[1]; + + 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()]); + + // step 2 + 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(); + + // since the block is empty it isn't sealed and we generate empty steps + engine.set_signer(tap.clone(), addr1, "1".into()); + assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.step(); + + // step 3 + let mut b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + b2.push_transaction(Transaction { + action: Action::Create, + nonce: U256::from(0), + gas_price: U256::from(3000), + gas: U256::from(53_000), + value: U256::from(1), + data: vec![], + }.fake_sign(addr2), None).unwrap(); + let b2 = b2.close_and_lock(); + + // we will now seal a block with 1tx and include the accumulated empty step message + engine.set_signer(tap.clone(), addr2, "0".into()); + if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) { + engine.set_signer(tap.clone(), addr1, "1".into()); + let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); + let empty_steps = ::rlp::encode_list(&vec![empty_step2]); + + assert_eq!(seal[0], encode(&3usize).into_vec()); + assert_eq!(seal[2], empty_steps.into_vec()); + } + } + + #[test] + fn seal_empty_block_with_empty_steps() { + let (spec, tap, accounts) = setup_empty_steps(); + + let addr1 = accounts[0]; + let addr2 = accounts[1]; + + 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 db3 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + + let last_hashes = Arc::new(vec![genesis_header.hash()]); + + // step 2 + 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(); + + // since the block is empty it isn't sealed and we generate empty steps + engine.set_signer(tap.clone(), addr1, "1".into()); + assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.step(); + + // step 3 + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b2 = b2.close_and_lock(); + engine.set_signer(tap.clone(), addr2, "0".into()); + assert_eq!(engine.generate_seal(b2.block(), &genesis_header), Seal::None); + engine.step(); + + // step 4 + // the spec sets the maximum_empty_steps to 2 so we will now seal an empty block and include the empty step messages + let b3 = OpenBlock::new(engine, Default::default(), false, db3, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b3 = b3.close_and_lock(); + + engine.set_signer(tap.clone(), addr1, "1".into()); + if let Seal::Regular(seal) = engine.generate_seal(b3.block(), &genesis_header) { + let empty_step2 = sealed_empty_step(engine, 2, &genesis_header.hash()); + engine.set_signer(tap.clone(), addr2, "0".into()); + let empty_step3 = sealed_empty_step(engine, 3, &genesis_header.hash()); + + let empty_steps = ::rlp::encode_list(&vec![empty_step2, empty_step3]); + + assert_eq!(seal[0], encode(&4usize).into_vec()); + assert_eq!(seal[2], empty_steps.into_vec()); + } + } + + #[test] + fn reward_empty_steps() { + let (spec, tap, accounts) = setup_empty_steps(); + + let addr1 = accounts[0]; + + 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 client = generate_dummy_client_with_spec_and_accounts(Spec::new_test_round_empty_steps, None); + engine.register_client(Arc::downgrade(&client) as _); + + // step 2 + let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b1 = b1.close_and_lock(); + + // since the block is empty it isn't sealed and we generate empty steps + engine.set_signer(tap.clone(), addr1, "1".into()); + assert_eq!(engine.generate_seal(b1.block(), &genesis_header), Seal::None); + engine.step(); + + // step 3 + // the signer of the accumulated empty step message should be rewarded + let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let addr1_balance = b2.block().state().balance(&addr1).unwrap(); + + // after closing the block `addr1` should be reward twice, one for the included empty step message and another for block creation + let b2 = b2.close_and_lock(); + + // the spec sets the block reward to 10 + assert_eq!(b2.block().state().balance(&addr1).unwrap(), addr1_balance + (10 * 2).into()) + } + + #[test] + fn verify_seal_empty_steps() { + let (spec, tap, accounts) = setup_empty_steps(); + let addr1 = accounts[0]; + let addr2 = accounts[1]; + let engine = &*spec.engine; + + let mut parent_header: Header = Header::default(); + parent_header.set_seal(vec![encode(&0usize).into_vec()]); + parent_header.set_gas_limit("222222".parse::().unwrap()); + + let mut header: Header = Header::default(); + header.set_parent_hash(parent_header.hash()); + header.set_number(1); + header.set_gas_limit("222222".parse::().unwrap()); + header.set_author(addr1); + + let signature = tap.sign(addr1, Some("1".into()), header.bare_hash()).unwrap(); + + // empty step with invalid step + let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 2 }]; + header.set_seal(vec![ + encode(&2usize).into_vec(), + encode(&(&*signature as &[u8])).into_vec(), + ::rlp::encode_list(&empty_steps).into_vec(), + ]); + + assert!(match engine.verify_block_family(&header, &parent_header) { + Err(Error::Engine(EngineError::InsufficientProof(ref s))) + if s.contains("invalid step") => true, + _ => false, + }); + + // empty step with invalid signature + let empty_steps = vec![SealedEmptyStep { signature: 0.into(), step: 1 }]; + header.set_seal(vec![ + encode(&2usize).into_vec(), + encode(&(&*signature as &[u8])).into_vec(), + ::rlp::encode_list(&empty_steps).into_vec(), + ]); + + assert!(match engine.verify_block_family(&header, &parent_header) { + Err(Error::Engine(EngineError::InsufficientProof(ref s))) + if s.contains("invalid empty step proof") => true, + _ => false, + }); + + // empty step with valid signature from incorrect proposer for step + engine.set_signer(tap.clone(), addr1, "1".into()); + let empty_steps = vec![sealed_empty_step(engine, 1, &parent_header.hash())]; + header.set_seal(vec![ + encode(&2usize).into_vec(), + encode(&(&*signature as &[u8])).into_vec(), + ::rlp::encode_list(&empty_steps).into_vec(), + ]); + + assert!(match engine.verify_block_family(&header, &parent_header) { + Err(Error::Engine(EngineError::InsufficientProof(ref s))) + if s.contains("invalid empty step proof") => true, + _ => false, + }); + + // valid empty steps + engine.set_signer(tap.clone(), addr1, "1".into()); + let empty_step2 = sealed_empty_step(engine, 2, &parent_header.hash()); + engine.set_signer(tap.clone(), addr2, "0".into()); + let empty_step3 = sealed_empty_step(engine, 3, &parent_header.hash()); + + let empty_steps = vec![empty_step2, empty_step3]; + header.set_seal(vec![ + encode(&4usize).into_vec(), + encode(&(&*signature as &[u8])).into_vec(), + ::rlp::encode_list(&empty_steps).into_vec(), + ]); + + assert!(match engine.verify_block_family(&header, &parent_header) { + Ok(_) => true, + _ => false, + }); + } } diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 5d6a44fc5b678f70e92fc0719214bb7d4e7877f5..4d1f38dce4cbb770e4302da6bc3b471e6c74ca67 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -17,20 +17,17 @@ //! A blockchain engine that supports a basic, non-BFT proof-of-authority. use std::sync::{Weak, Arc}; -use std::collections::BTreeMap; -use std::cmp; -use util::*; +use ethereum_types::{H256, H520, Address}; +use parking_lot::RwLock; use ethkey::{recover, public_to_address, Signature}; use account_provider::AccountProvider; use block::*; -use builtin::Builtin; -use spec::CommonParams; -use engines::{Engine, Seal, Call, ConstructedVerifier, EngineError}; +use engines::{Engine, Seal, ConstructedVerifier, EngineError}; use error::{BlockError, Error}; -use evm::Schedule; use ethjson; -use header::{Header, BlockNumber}; -use client::Client; +use header::Header; +use client::EngineClient; +use machine::{AuxiliaryData, Call, EthereumMachine}; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; @@ -53,7 +50,7 @@ struct EpochVerifier { list: SimpleList, } -impl super::EpochVerifier for EpochVerifier { +impl super::EpochVerifier for EpochVerifier { fn verify_light(&self, header: &Header) -> Result<(), Error> { verify_external(header, &self.list) } @@ -78,59 +75,36 @@ fn verify_external(header: &Header, validators: &ValidatorSet) -> Result<(), Err /// Engine using `BasicAuthority`, trivial proof-of-authority consensus. pub struct BasicAuthority { - params: CommonParams, - builtins: BTreeMap, + machine: EthereumMachine, signer: RwLock, validators: Box, } impl BasicAuthority { /// Create a new instance of BasicAuthority engine - pub fn new(params: CommonParams, our_params: BasicAuthorityParams, builtins: BTreeMap) -> Self { + pub fn new(our_params: BasicAuthorityParams, machine: EthereumMachine) -> Self { BasicAuthority { - params: params, - builtins: builtins, - validators: new_validator_set(our_params.validators), + machine: machine, signer: Default::default(), + validators: new_validator_set(our_params.validators), } } } -impl Engine for BasicAuthority { +impl Engine for BasicAuthority { fn name(&self) -> &str { "BasicAuthority" } - fn version(&self) -> SemanticVersion { SemanticVersion::new(1, 0, 0) } - // One field - the signature - fn seal_fields(&self) -> usize { 1 } - - fn params(&self) -> &CommonParams { &self.params } - fn builtins(&self) -> &BTreeMap { &self.builtins } - /// Additional engine-specific information for the user/developer concerning `header`. - fn extra_info(&self, _header: &Header) -> BTreeMap { map!["signature".to_owned() => "TODO".to_owned()] } + fn machine(&self) -> &EthereumMachine { &self.machine } - fn schedule(&self, _block_number: BlockNumber) -> Schedule { - Schedule::new_homestead() - } - - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { - header.set_difficulty(parent.difficulty().clone()); - header.set_gas_limit({ - let gas_limit = parent.gas_limit().clone(); - let bound_divisor = self.params().gas_limit_bound_divisor; - if gas_limit < gas_floor_target { - cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) - } else { - cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) - } - }); - } + // One field - the signature + fn seal_fields(&self, _header: &Header) -> usize { 1 } fn seals_internally(&self) -> Option { Some(self.signer.read().is_some()) } /// 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) { @@ -144,41 +118,11 @@ impl Engine for BasicAuthority { Seal::None } - fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - // check the seal fields. - // TODO: pull this out into common code. - if header.seal().len() != self.seal_fields() { - return Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal().len() } - ))); - } - Ok(()) - } - - fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { + fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { Ok(()) } - fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - // Do not calculate difficulty for genesis blocks. - if header.number() == 0 { - return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); - } - - // Check difficulty is correct given the two timestamps. - if header.difficulty() != parent.difficulty() { - return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: *parent.difficulty(), found: *header.difficulty() }))) - } - let gas_limit_divisor = self.params().gas_limit_bound_divisor; - let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor; - let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; - if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))); - } - Ok(()) - } - - fn verify_block_external(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { + fn verify_block_external(&self, header: &Header) -> Result<(), Error> { verify_external(header, &*self.validators) } @@ -187,26 +131,26 @@ impl Engine for BasicAuthority { } #[cfg(not(test))] - fn signals_epoch_end(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[::receipt::Receipt]>) - -> super::EpochChange + fn signals_epoch_end(&self, _header: &Header, _auxiliary: AuxiliaryData) + -> super::EpochChange { // don't bother signalling even though a contract might try. super::EpochChange::No } #[cfg(test)] - fn signals_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>) - -> super::EpochChange + fn signals_epoch_end(&self, header: &Header, auxiliary: AuxiliaryData) + -> super::EpochChange { // in test mode, always signal even though they don't be finalized. let first = header.number() == 0; - self.validators.signals_epoch_end(first, header, block, receipts) + self.validators.signals_epoch_end(first, header, auxiliary) } fn is_epoch_end( &self, chain_head: &Header, - _chain: &super::Headers, + _chain: &super::Headers
, _transition_store: &super::PendingTransitionStore, ) -> Option> { let first = chain_head.number() == 0; @@ -215,10 +159,10 @@ impl Engine for BasicAuthority { self.validators.is_epoch_end(first, chain_head) } - fn epoch_verifier<'a>(&self, header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a> { + fn epoch_verifier<'a>(&self, header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> { let first = header.number() == 0; - match self.validators.epoch_set(first, self, header.number(), proof) { + match self.validators.epoch_set(first, &self.machine, header.number(), proof) { Ok((list, finalize)) => { let verifier = Box::new(EpochVerifier { list: list }); @@ -232,8 +176,8 @@ impl Engine for BasicAuthority { } } - fn register_client(&self, client: Weak) { - self.validators.register_contract(client); + fn register_client(&self, client: Weak) { + self.validators.register_client(client); } fn set_signer(&self, ap: Arc, address: Address, password: String) { @@ -252,26 +196,27 @@ impl Engine for BasicAuthority { #[cfg(test)] mod tests { use std::sync::Arc; - use util::*; + use hash::keccak; + use ethereum_types::H520; use block::*; - use error::{BlockError, Error}; - use tests::helpers::*; + use tests::helpers::get_temp_state_db; use account_provider::AccountProvider; use header::Header; use spec::Spec; use engines::Seal; + use tempdir::TempDir; /// Create a new test chain spec with `BasicAuthority` consensus engine. fn new_test_authority() -> Spec { let bytes: &[u8] = include_bytes!("../../res/basic_authority.json"); - Spec::load(::std::env::temp_dir(), bytes).expect("invalid chain spec") + let tempdir = TempDir::new("").unwrap(); + Spec::load(&tempdir.path(), bytes).expect("invalid chain spec") } #[test] fn has_valid_metadata() { let engine = new_test_authority().engine; assert!(!engine.name().is_empty()); - assert!(engine.version().major >= 1); } #[test] @@ -281,34 +226,20 @@ mod tests { assert!(schedule.stack_limit > 0); } - #[test] - fn can_do_seal_verification_fail() { - let engine = new_test_authority().engine; - let header: Header = Header::default(); - - let verify_result = engine.verify_block_basic(&header, None); - - match verify_result { - Err(Error::Block(BlockError::InvalidSealArity(_))) => {}, - Err(_) => { panic!("should be block seal-arity mismatch error (got {:?})", verify_result); }, - _ => { panic!("Should be error, got Ok"); }, - } - } - #[test] fn can_do_signature_verification_fail() { let engine = new_test_authority().engine; let mut header: Header = Header::default(); header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]); - let verify_result = engine.verify_block_family(&header, &Default::default(), None); + let verify_result = engine.verify_block_external(&header); assert!(verify_result.is_err()); } #[test] fn can_generate_seal() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account("".sha3().into(), "").unwrap(); + let addr = tap.insert_account(keccak("").into(), "").unwrap(); let spec = new_test_authority(); let engine = &*spec.engine; @@ -318,7 +249,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()); } } @@ -326,7 +257,7 @@ mod tests { #[test] fn seals_internally() { let tap = AccountProvider::transient_provider(); - let authority = tap.insert_account("".sha3().into(), "").unwrap(); + let authority = tap.insert_account(keccak("").into(), "").unwrap(); let engine = new_test_authority().engine; assert!(!engine.seals_internally().unwrap()); diff --git a/ethcore/src/engines/epoch.rs b/ethcore/src/engines/epoch.rs index 586059e8387a73e7689d950c459e3b4fbe4fa408..dffc822cbf819dfbe4d6cf05953d911b63741a09 100644 --- a/ethcore/src/engines/epoch.rs +++ b/ethcore/src/engines/epoch.rs @@ -16,12 +16,12 @@ //! Epoch verifiers and transitions. -use util::H256; -use error::Error; -use header::Header; +use ethereum_types::H256; + +use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; /// A full epoch transition. -#[derive(Debug, Clone, RlpEncodable, RlpDecodable)] +#[derive(Debug, Clone)] pub struct Transition { /// Block hash at which the transition occurred. pub block_hash: H256, @@ -31,24 +31,54 @@ pub struct Transition { pub proof: Vec, } +impl Encodable for Transition { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(3) + .append(&self.block_hash) + .append(&self.block_number) + .append(&self.proof); + } +} + +impl Decodable for Transition { + fn decode(rlp: &UntrustedRlp) -> Result { + Ok(Transition { + block_hash: rlp.val_at(0)?, + block_number: rlp.val_at(1)?, + proof: rlp.val_at(2)?, + }) + } +} + /// An epoch transition pending a finality proof. /// Not all transitions need one. -#[derive(RlpEncodableWrapper, RlpDecodableWrapper)] pub struct PendingTransition { /// "transition/epoch" proof from the engine. pub proof: Vec, } +impl Encodable for PendingTransition { + fn rlp_append(&self, s: &mut RlpStream) { + s.append(&self.proof); + } +} + +impl Decodable for PendingTransition { + fn decode(rlp: &UntrustedRlp) -> Result { + Ok(PendingTransition { + proof: rlp.as_val()?, + }) + } +} + /// Verifier for all blocks within an epoch with self-contained state. -/// -/// See docs on `Engine` relating to proving functions for more details. -pub trait EpochVerifier: Send + Sync { +pub trait EpochVerifier: Send + Sync { /// Lightly verify the next block header. /// This may not be a header belonging to a different epoch. - fn verify_light(&self, header: &Header) -> Result<(), Error>; + fn verify_light(&self, header: &M::Header) -> Result<(), M::Error>; /// Perform potentially heavier checks on the next block header. - fn verify_heavy(&self, header: &Header) -> Result<(), Error> { + fn verify_heavy(&self, header: &M::Header) -> Result<(), M::Error> { self.verify_light(header) } @@ -63,6 +93,6 @@ pub trait EpochVerifier: Send + Sync { /// Special "no-op" verifier for stateless, epoch-less engines. pub struct NoOp; -impl EpochVerifier for NoOp { - fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) } +impl EpochVerifier for NoOp { + fn verify_light(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } } diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 976f815e04ed1b8fd22b183ccdba8ad58911627b..9c2600212d09c6ed9b4f7f6ac6dc982c11617f0e 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -14,58 +14,49 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::collections::{BTreeMap, HashMap}; -use util::Address; -use builtin::Builtin; use engines::{Engine, Seal}; -use spec::CommonParams; -use block::{ExecutedBlock, IsBlock}; +use parity_machine::{Machine, Transactions}; /// An engine which does not provide any consensus mechanism, just seals blocks internally. -pub struct InstantSeal { - params: CommonParams, - builtins: BTreeMap, +/// Only seals blocks which have transactions. +pub struct InstantSeal { + machine: M, } -impl InstantSeal { - /// Returns new instance of InstantSeal with default VM Factory - pub fn new(params: CommonParams, builtins: BTreeMap) -> Self { +impl InstantSeal { + /// Returns new instance of InstantSeal over the given state machine. + pub fn new(machine: M) -> Self { InstantSeal { - params: params, - builtins: builtins, + machine: machine, } } } -impl Engine for InstantSeal { +impl Engine for InstantSeal + where M::LiveBlock: Transactions +{ fn name(&self) -> &str { "InstantSeal" } - fn params(&self) -> &CommonParams { - &self.params - } - - fn additional_params(&self) -> HashMap { - hash_map!["registrar".to_owned() => self.params().registrar.hex()] - } - - fn builtins(&self) -> &BTreeMap { - &self.builtins - } + fn machine(&self) -> &M { &self.machine } fn seals_internally(&self) -> Option { Some(true) } - fn generate_seal(&self, block: &ExecutedBlock) -> Seal { + fn generate_seal(&self, block: &M::LiveBlock, _parent: &M::Header) -> Seal { if block.transactions().is_empty() { Seal::None } else { Seal::Regular(Vec::new()) } } + + fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> { + Ok(()) + } } #[cfg(test)] mod tests { use std::sync::Arc; - use util::*; - use tests::helpers::*; + use ethereum_types::{H520, Address}; + use tests::helpers::{get_temp_state_db}; use spec::Spec; use header::Header; use block::*; @@ -80,7 +71,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()); } } @@ -90,10 +81,10 @@ mod tests { let engine = Spec::new_instant().engine; let mut header: Header = Header::default(); - assert!(engine.verify_block_basic(&header, None).is_ok()); + assert!(engine.verify_block_basic(&header).is_ok()); header.set_seal(vec![::rlp::encode(&H520::default()).into_vec()]); - assert!(engine.verify_block_unordered(&header, None).is_ok()); + assert!(engine.verify_block_unordered(&header).is_ok()); } } diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 00f3223180863b764a0c2f5b400d01f75b427fce..5b2b9abb0e06c7337aaa8c2effadce73003571e6 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -42,23 +42,23 @@ use std::fmt; use self::epoch::PendingTransition; use account_provider::AccountProvider; -use block::ExecutedBlock; use builtin::Builtin; -use client::Client; -use vm::{EnvInfo, LastHashes, Schedule, CreateContractAddress}; +use vm::{EnvInfo, Schedule, CreateContractAddress}; use error::Error; use header::{Header, BlockNumber}; -use receipt::Receipt; use snapshot::SnapshotComponents; use spec::CommonParams; use transaction::{UnverifiedTransaction, SignedTransaction}; use ethkey::Signature; -use util::*; +use parity_machine::{Machine, LocalizedMachine as Localized}; +use ethereum_types::{H256, U256, Address}; +use unexpected::{Mismatch, OutOfBounds}; +use bytes::Bytes; /// Default EIP-210 contrat code. -/// As defined in https://github.com/ethereum/EIPs/pull/210/commits/9df24a3714af42e3bf350265bdc75b486c909d7f#diff-e02a92c2fb96c1a1bfb05e4c6e2ef5daR49 -pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b610161565b436000351215801561008c5780610095565b623567e0600035125b9050156100a757600060605260206060f35b610100600035430312156100ca57610100600035075460805260206080f3610160565b62010000600035430312156100e857600061010060003507146100eb565b60005b1561010d576101006101006000350507610100015460a052602060a0f361015f565b63010000006000354303121561012d576000620100006000350714610130565b60005b1561015357610100620100006000350507610200015460c052602060c0f361015e565b600060e052602060e0f35b5b5b5b5b"; +/// As defined in https://github.com/ethereum/EIPs/pull/210 +pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b"; /// Voting errors. #[derive(Debug)] @@ -77,6 +77,8 @@ pub enum EngineError { InsufficientProof(String), /// Failed system call. FailedSystemCall(String), + /// Malformed consensus message. + MalformedMessage(String), /// Requires client ref, but none registered. RequiresClient, } @@ -92,6 +94,7 @@ impl fmt::Display for EngineError { BadSealFieldSize(ref oob) => format!("Seal field has an unexpected length: {}", oob), InsufficientProof(ref msg) => format!("Insufficient validation proof: {}", msg), FailedSystemCall(ref msg) => format!("Failed to make system call: {}", msg), + MalformedMessage(ref msg) => format!("Received malformed consensus message: {}", msg), RequiresClient => format!("Call requires client but none registered"), }; @@ -110,39 +113,46 @@ pub enum Seal { None, } -/// Type alias for a function we can make calls through synchronously. -/// Returns the call result and state proof for each call. -pub type Call<'a> = Fn(Address, Bytes) -> Result<(Bytes, Vec>), String> + 'a; - /// Type alias for a function we can get headers by hash through. -pub type Headers<'a> = Fn(H256) -> Option
+ 'a; +pub type Headers<'a, H> = Fn(H256) -> Option + 'a; /// Type alias for a function we can query pending transitions by block hash through. pub type PendingTransitionStore<'a> = Fn(H256) -> Option + 'a; +/// Proof dependent on state. +pub trait StateDependentProof: Send + Sync { + /// Generate a proof, given the state. + // TODO: make this into an &M::StateContext + fn generate_proof<'a>(&self, state: &>::StateContext) -> Result, String>; + /// Check a proof generated elsewhere (potentially by a peer). + // `engine` needed to check state proofs, while really this should + // just be state machine params. + fn check_proof(&self, machine: &M, proof: &[u8]) -> Result<(), String>; +} + /// Proof generated on epoch change. -pub enum Proof { - /// Known proof (exctracted from signal) +pub enum Proof { + /// Known proof (extracted from signal) Known(Vec), - /// Extract proof from caller. - WithState(Box Result, String>>), + /// State dependent proof. + WithState(Arc>), } /// Generated epoch verifier. -pub enum ConstructedVerifier<'a> { +pub enum ConstructedVerifier<'a, M: Machine> { /// Fully trusted verifier. - Trusted(Box), + Trusted(Box>), /// Verifier unconfirmed. Check whether given finality proof finalizes given hash /// under previous epoch. - Unconfirmed(Box, &'a [u8], H256), + Unconfirmed(Box>, &'a [u8], H256), /// Error constructing verifier. Err(Error), } -impl<'a> ConstructedVerifier<'a> { +impl<'a, M: Machine> ConstructedVerifier<'a, M> { /// Convert to a result, indicating that any necessary confirmation has been done /// already. - pub fn known_confirmed(self) -> Result, Error> { + pub fn known_confirmed(self) -> Result>, Error> { match self { ConstructedVerifier::Trusted(v) | ConstructedVerifier::Unconfirmed(v, _, _) => Ok(v), ConstructedVerifier::Err(e) => Err(e), @@ -151,84 +161,49 @@ impl<'a> ConstructedVerifier<'a> { } /// Results of a query of whether an epoch change occurred at the given block. -pub enum EpochChange { +pub enum EpochChange { /// Cannot determine until more data is passed. - Unsure(Unsure), + Unsure(M::AuxiliaryRequest), /// No epoch change. No, /// The epoch will change, with proof. - Yes(Proof), -} - -/// More data required to determine if an epoch change occurred at a given block. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum Unsure { - /// Needs the body. - NeedsBody, - /// Needs the receipts. - NeedsReceipts, - /// Needs both body and receipts. - NeedsBoth, + Yes(Proof), } /// A consensus mechanism for the chain. Generally either proof-of-work or proof-of-stake-based. /// Provides hooks into each of the major parts of block import. -pub trait Engine : Sync + Send { +pub trait Engine: Sync + Send { /// The name of this engine. fn name(&self) -> &str; - /// The version of this engine. Should be of the form - fn version(&self) -> SemanticVersion { SemanticVersion::new(0, 0, 0) } + + /// Get access to the underlying state machine. + // TODO: decouple. + fn machine(&self) -> &M; /// The number of additional header fields required for this engine. - fn seal_fields(&self) -> usize { 0 } + fn seal_fields(&self, _header: &M::Header) -> usize { 0 } /// Additional engine-specific information for the user/developer concerning `header`. - fn extra_info(&self, _header: &Header) -> BTreeMap { BTreeMap::new() } + fn extra_info(&self, _header: &M::Header) -> BTreeMap { BTreeMap::new() } - /// Additional information. - fn additional_params(&self) -> HashMap { HashMap::new() } - - /// Get the general parameters of the chain. - fn params(&self) -> &CommonParams; - - /// Get the EVM schedule for the given `block_number`. - fn schedule(&self, block_number: BlockNumber) -> Schedule { - self.params().schedule(block_number) - } - - /// Builtin-contracts we would like to see in the chain. - /// (In principle these are just hints for the engine since that has the last word on them.) - fn builtins(&self) -> &BTreeMap; - - /// Some intrinsic operation parameters; by default they take their value from the `spec()`'s `engine_params`. - fn maximum_extra_data_size(&self) -> usize { self.params().maximum_extra_data_size } /// Maximum number of uncles a block is allowed to declare. - fn maximum_uncle_count(&self) -> usize { 2 } + 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 } - /// The nonce with which accounts begin at given block. - fn account_start_nonce(&self, block: u64) -> U256 { - if block >= self.params().dust_protection_transition { - U256::from(self.params().nonce_cap_increment) * U256::from(block) - } else { - self.params().account_start_nonce - } - } /// Block transformation functions, before the transactions. /// `epoch_begin` set to true if this block kicks off an epoch. fn on_new_block( &self, - block: &mut ExecutedBlock, - last_hashes: Arc, + _block: &mut M::LiveBlock, _epoch_begin: bool, - ) -> Result<(), Error> { - let parent_hash = block.fields().header.parent_hash().clone(); - common::push_last_hash(block, last_hashes, self, &parent_hash) + ) -> Result<(), M::Error> { + Ok(()) } /// Block transformation functions, after the transactions. - fn on_close_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> { + fn on_close_block(&self, _block: &mut M::LiveBlock) -> Result<(), M::Error> { Ok(()) } @@ -236,68 +211,57 @@ pub trait Engine : Sync + Send { /// Some(true) means the engine is currently prime for seal generation (i.e. node is the current validator). /// Some(false) means that the node might seal internally but is not qualified now. fn seals_internally(&self) -> Option { None } + /// Attempt to seal the block internally. /// /// If `Some` is returned, then you get a valid seal. /// /// This operation is synchronous and may (quite reasonably) not be available, in which None will /// be returned. - fn generate_seal(&self, _block: &ExecutedBlock) -> Seal { Seal::None } - - /// Phase 1 quick block verification. Only does checks that are cheap. `block` (the header's full block) - /// may be provided for additional checks. Returns either a null `Ok` or a general error detailing the problem with import. - fn verify_block_basic(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) } - - /// Phase 2 verification. Perform costly checks such as transaction signatures. `block` (the header's full block) - /// may be provided for additional checks. Returns either a null `Ok` or a general error detailing the problem with import. - fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) } - - /// Phase 3 verification. Check block information against parent and uncles. `block` (the header's full block) - /// may be provided for additional checks. Returns either a null `Ok` or a general error detailing the problem with import. - fn verify_block_family(&self, _header: &Header, _parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) } + /// + /// It is fine to require access to state or a full client for this function, since + /// light clients do not generate seals. + fn generate_seal(&self, _block: &M::LiveBlock, _parent: &M::Header) -> Seal { Seal::None } - /// Phase 4 verification. Verify block header against potentially external data. - fn verify_block_external(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { Ok(()) } + /// Verify a locally-generated seal of a header. + /// + /// If this engine seals internally, + /// no checks have to be done here, since all internally generated seals + /// should be valid. + /// + /// Externally-generated seals (e.g. PoW) will need to be checked for validity. + /// + /// It is fine to require access to state or a full client for this function, since + /// light clients do not generate seals. + fn verify_local_seal(&self, header: &M::Header) -> Result<(), M::Error>; - /// Additional verification for transactions in blocks. - // TODO: Add flags for which bits of the transaction to check. - // TODO: consider including State in the params. - fn verify_transaction_basic(&self, t: &UnverifiedTransaction, _header: &Header) -> Result<(), Error> { - t.verify_basic(true, Some(self.params().chain_id), true)?; - Ok(()) - } + /// Phase 1 quick block verification. Only does checks that are cheap. Returns either a null `Ok` or a general error detailing the problem with import. + fn verify_block_basic(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } - /// Verify a particular transaction is valid. - fn verify_transaction(&self, t: UnverifiedTransaction, _header: &Header) -> Result { - SignedTransaction::new(t) - } + /// Phase 2 verification. Perform costly checks such as transaction signatures. Returns either a null `Ok` or a general error detailing the problem with import. + fn verify_block_unordered(&self, _header: &M::Header) -> Result<(), M::Error> { Ok(()) } - /// The network ID that transactions should be signed with. - fn signing_chain_id(&self, _env_info: &EnvInfo) -> Option { - Some(self.params().chain_id) - } + /// Phase 3 verification. Check block information against parent. Returns either a null `Ok` or a general error detailing the problem with import. + fn verify_block_family(&self, _header: &M::Header, _parent: &M::Header) -> Result<(), Error> { Ok(()) } - /// Verify the seal of a block. This is an auxilliary method that actually just calls other `verify_` methods - /// to get the job done. By default it must pass `verify_basic` and `verify_block_unordered`. If more or fewer - /// methods are needed for an Engine, this may be overridden. - fn verify_block_seal(&self, header: &Header) -> Result<(), Error> { - self.verify_block_basic(header, None).and_then(|_| self.verify_block_unordered(header, None)) - } + /// Phase 4 verification. Verify block header against potentially external data. + /// Should only be called when `register_client` has been called previously. + fn verify_block_external(&self, _header: &M::Header) -> Result<(), Error> { Ok(()) } /// Genesis epoch data. - fn genesis_epoch_data(&self, _header: &Header, _call: &Call) -> Result, String> { Ok(Vec::new()) } + fn genesis_epoch_data<'a>(&self, _header: &M::Header, _state: &>::StateContext) -> Result, String> { Ok(Vec::new()) } /// Whether an epoch change is signalled at the given header but will require finality. /// If a change can be enacted immediately then return `No` from this function but /// `Yes` from `is_epoch_end`. /// - /// If the block or receipts are required, return `Unsure` and the function will be + /// If auxiliary data of the block is required, return an auxiliary request and the function will be /// called again with them. /// Return `Yes` or `No` when the answer is definitively known. /// /// Should not interact with state. - fn signals_epoch_end(&self, _header: &Header, _block: Option<&[u8]>, _receipts: Option<&[Receipt]>) - -> EpochChange + fn signals_epoch_end<'a>(&self, _header: &M::Header, _aux: >::AuxiliaryData) + -> EpochChange { EpochChange::No } @@ -311,8 +275,8 @@ pub trait Engine : Sync + Send { /// Return optional transition proof. fn is_epoch_end( &self, - _chain_head: &Header, - _chain: &Headers, + _chain_head: &M::Header, + _chain: &Headers, _transition_store: &PendingTransitionStore, ) -> Option> { None @@ -320,35 +284,21 @@ pub trait Engine : Sync + Send { /// Create an epoch verifier from validation proof and a flag indicating /// whether finality is required. - fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> ConstructedVerifier<'a> { + fn epoch_verifier<'a>(&self, _header: &M::Header, _proof: &'a [u8]) -> ConstructedVerifier<'a, M> { ConstructedVerifier::Trusted(Box::new(self::epoch::NoOp)) } /// Populate a header's fields based on its parent's header. /// Usually implements the chain scoring rule based on weight. - /// The gas floor target must not be lower than the engine's minimum gas limit. - fn populate_from_parent(&self, header: &mut Header, parent: &Header, _gas_floor_target: U256, _gas_ceil_target: U256) { - header.set_difficulty(parent.difficulty().clone()); - header.set_gas_limit(parent.gas_limit().clone()); - } + fn populate_from_parent(&self, _header: &mut M::Header, _parent: &M::Header) { } /// Handle any potential consensus messages; /// updating consensus state and potentially issuing a new one. - fn handle_message(&self, _message: &[u8]) -> Result<(), Error> { Err(EngineError::UnexpectedMessage.into()) } - - /// Attempt to get a handle to a built-in contract. - /// Only returns references to activated built-ins. - // TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic - // from Spec into here and removing the Spec::builtins field. - fn builtin(&self, a: &Address, block_number: ::header::BlockNumber) -> Option<&Builtin> { - self.builtins() - .get(a) - .and_then(|b| if b.is_active(block_number) { Some(b) } else { None }) - } + fn handle_message(&self, _message: &[u8]) -> Result<(), EngineError> { Err(EngineError::UnexpectedMessage) } /// Find out if the block is a proposal block and should not be inserted into the DB. /// Takes a header of a fully verified block. - fn is_proposal(&self, _verified_header: &Header) -> bool { false } + fn is_proposal(&self, _verified_header: &M::Header) -> bool { false } /// Register an account which signs consensus messages. fn set_signer(&self, _account_provider: Arc, _address: Address, _password: String) {} @@ -356,8 +306,8 @@ pub trait Engine : Sync + Send { /// Sign using the EngineSigner, to be used for consensus tx signing. fn sign(&self, _hash: H256) -> Result { unimplemented!() } - /// Add Client which can be used for sealing, querying the state and sending messages. - fn register_client(&self, _client: Weak) {} + /// Add Client which can be used for sealing, potentially querying the state and sending messages. + fn register_client(&self, _client: Weak) {} /// Trigger next step of the consensus engine. fn step(&self) {} @@ -375,98 +325,71 @@ pub trait Engine : Sync + Send { fn supports_warp(&self) -> bool { self.snapshot_components().is_some() } +} + +/// Common type alias for an engine coupled with an Ethereum-like state machine. +// TODO: make this a _trait_ alias when those exist. +// fortunately the effect is largely the same since engines are mostly used +// via trait objects. +pub trait EthEngine: Engine<::machine::EthereumMachine> { + /// Get the general parameters of the chain. + fn params(&self) -> &CommonParams { + self.machine().params() + } + + /// Get the EVM schedule for the given block number. + fn schedule(&self, block_number: BlockNumber) -> Schedule { + self.machine().schedule(block_number) + } + + /// Builtin-contracts for the chain.. + fn builtins(&self) -> &BTreeMap { + self.machine().builtins() + } + + /// Attempt to get a handle to a built-in contract. + /// Only returns references to activated built-ins. + fn builtin(&self, a: &Address, block_number: BlockNumber) -> Option<&Builtin> { + self.machine().builtin(a, block_number) + } + + /// Some intrinsic operation parameters; by default they take their value from the `spec()`'s `engine_params`. + fn maximum_extra_data_size(&self) -> usize { + self.machine().maximum_extra_data_size() + } - /// If this engine supports wasm contracts. - fn supports_wasm(&self) -> bool { - self.params().wasm + /// The nonce with which accounts begin at given block. + fn account_start_nonce(&self, block: BlockNumber) -> U256 { + self.machine().account_start_nonce(block) + } + + /// The network ID that transactions should be signed with. + fn signing_chain_id(&self, env_info: &EnvInfo) -> Option { + self.machine().signing_chain_id(env_info) } /// Returns new contract address generation scheme at given block number. fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress { - if number >= self.params().eip86_transition { - CreateContractAddress::FromCodeHash - } else { - CreateContractAddress::FromSenderAndNonce - } + self.machine().create_address_scheme(number) } -} - -/// Common engine utilities -pub mod common { - use std::sync::Arc; - use block::ExecutedBlock; - use error::Error; - use transaction::SYSTEM_ADDRESS; - use executive::Executive; - use vm::{CallType, ActionParams, ActionValue, EnvInfo, LastHashes}; - use trace::{NoopTracer, NoopVMTracer}; - use state::Substate; - - use util::*; - use super::Engine; - - /// Execute a call as the system address. - pub fn execute_as_system( - block: &mut ExecutedBlock, - last_hashes: Arc, - engine: &E, - contract_address: Address, - gas: U256, - data: Option, - ) -> Result { - let env_info = { - let header = block.fields().header; - EnvInfo { - number: header.number(), - author: header.author().clone(), - timestamp: header.timestamp(), - difficulty: header.difficulty().clone(), - last_hashes: last_hashes, - gas_used: U256::zero(), - gas_limit: gas, - } - }; - let mut state = block.fields_mut().state; - let params = ActionParams { - code_address: contract_address.clone(), - address: contract_address.clone(), - sender: SYSTEM_ADDRESS.clone(), - origin: SYSTEM_ADDRESS.clone(), - gas: gas, - gas_price: 0.into(), - value: ActionValue::Transfer(0.into()), - code: state.code(&contract_address)?, - code_hash: Some(state.code_hash(&contract_address)?), - data: data, - call_type: CallType::Call, - }; - let mut ex = Executive::new(&mut state, &env_info, engine); - let mut substate = Substate::new(); - let mut output = Vec::new(); - if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) { - warn!("Encountered error on making system call: {}", e); - } + /// Verify a particular transaction is valid. + fn verify_transaction_unordered(&self, t: UnverifiedTransaction, header: &Header) -> Result { + self.machine().verify_transaction_unordered(t, header) + } - Ok(output) + /// Additional verification for transactions in blocks. + // TODO: Add flags for which bits of the transaction to check. + // TODO: consider including State in the params. + fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> { + self.machine().verify_transaction_basic(t, header) } - /// Push last known block hash to the state. - pub fn push_last_hash(block: &mut ExecutedBlock, last_hashes: Arc, engine: &E, hash: &H256) -> Result<(), Error> { - if block.fields().header.number() == engine.params().eip210_transition { - let state = block.fields_mut().state; - state.init_code(&engine.params().eip210_contract_address, engine.params().eip210_contract_code.clone())?; - } - if block.fields().header.number() >= engine.params().eip210_transition { - let _ = execute_as_system( - block, - last_hashes, - engine, - engine.params().eip210_contract_address, - engine.params().eip210_contract_gas, - Some(hash.to_vec()), - )?; - } - Ok(()) + /// Additional information. + fn additional_params(&self) -> HashMap { + self.machine().additional_params() } } + +// convenience wrappers for existing functions. +impl EthEngine for T where T: Engine<::machine::EthereumMachine> { } diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 552154580054f33e03f6fd454dabf61eea1bedeb..f20a9cdfd9d1df07f6439f1ac6940b10fbf4b25f 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -14,51 +14,92 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::collections::BTreeMap; -use util::Address; -use builtin::Builtin; +use ethereum_types::U256; use engines::Engine; -use spec::CommonParams; -use evm::Schedule; use header::BlockNumber; +use parity_machine::{Header, LiveBlock, WithBalances}; + +/// Params for a null engine. +#[derive(Clone, Default)] +pub struct NullEngineParams { + /// base reward for a block. + pub block_reward: U256, +} + +impl From<::ethjson::spec::NullEngineParams> for NullEngineParams { + fn from(p: ::ethjson::spec::NullEngineParams) -> Self { + NullEngineParams { + block_reward: p.block_reward.map_or_else(Default::default, Into::into), + } + } +} /// An engine which does not provide any consensus mechanism and does not seal blocks. -pub struct NullEngine { - params: CommonParams, - builtins: BTreeMap, +pub struct NullEngine { + params: NullEngineParams, + machine: M, } -impl NullEngine { +impl NullEngine { /// Returns new instance of NullEngine with default VM Factory - pub fn new(params: CommonParams, builtins: BTreeMap) -> Self { - NullEngine{ + pub fn new(params: NullEngineParams, machine: M) -> Self { + NullEngine { params: params, - builtins: builtins, + machine: machine, } } } -impl Default for NullEngine { +impl Default for NullEngine { fn default() -> Self { Self::new(Default::default(), Default::default()) } } -impl Engine for NullEngine { +impl Engine for NullEngine { fn name(&self) -> &str { "NullEngine" } - fn params(&self) -> &CommonParams { - &self.params - } + fn machine(&self) -> &M { &self.machine } + + fn on_close_block(&self, block: &mut M::LiveBlock) -> Result<(), M::Error> { + use std::ops::Shr; + + let author = *LiveBlock::header(&*block).author(); + let number = LiveBlock::header(&*block).number(); + + let reward = self.params.block_reward; + if reward == U256::zero() { return Ok(()) } - fn builtins(&self) -> &BTreeMap { - &self.builtins + let n_uncles = LiveBlock::uncles(&*block).len(); + + // Bestow block reward + let result_block_reward = reward + reward.shr(5) * U256::from(n_uncles); + let mut uncle_rewards = Vec::with_capacity(n_uncles); + + self.machine.add_balance(block, &author, &result_block_reward)?; + + // bestow uncle rewards. + for u in LiveBlock::uncles(&*block) { + let uncle_author = u.author(); + let result_uncle_reward = (reward * U256::from(8 + u.number() - number)).shr(3); + + uncle_rewards.push((*uncle_author, result_uncle_reward)); + } + + for &(ref a, ref reward) in &uncle_rewards { + self.machine.add_balance(block, a, reward)?; + } + + // note and trace. + self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards) } - fn schedule(&self, _block_number: BlockNumber) -> Schedule { - Schedule::new_homestead() + fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 } + + fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> { + Ok(()) } fn snapshot_components(&self) -> Option> { diff --git a/ethcore/src/engines/signer.rs b/ethcore/src/engines/signer.rs index 4069488abfa9249e08e464afb03a95c6797f47b6..d9e97fee06ecc6ebe8e6538356fff252d6df2b16 100644 --- a/ethcore/src/engines/signer.rs +++ b/ethcore/src/engines/signer.rs @@ -17,7 +17,7 @@ //! A signer used by Engines which need to sign messages. use std::sync::Arc; -use util::{H256, Address}; +use ethereum_types::{H256, Address}; use ethkey::Signature; use account_provider::{self, AccountProvider}; diff --git a/ethcore/src/engines/tendermint/message.rs b/ethcore/src/engines/tendermint/message.rs index 68bdcb0f7f323d1af16e9fdf5051ff09b944586e..1f71f41bcb508c3dbc951219da9de44d03ef9328 100644 --- a/ethcore/src/engines/tendermint/message.rs +++ b/ethcore/src/engines/tendermint/message.rs @@ -17,7 +17,9 @@ //! Tendermint message handling. use std::cmp; -use util::*; +use hash::keccak; +use ethereum_types::{H256, H520, Address}; +use bytes::Bytes; use super::{Height, View, BlockHash, Step}; use error::Error; use header::Header; @@ -99,7 +101,7 @@ impl ConsensusMessage { pub fn verify(&self) -> Result { let full_rlp = ::rlp::encode(self); let block_info = Rlp::new(&full_rlp).at(1); - let public_key = recover(&self.signature.into(), &block_info.as_raw().sha3())?; + let public_key = recover(&self.signature.into(), &keccak(block_info.as_raw()))?; Ok(public_to_address(&public_key)) } } @@ -194,13 +196,13 @@ pub fn message_full_rlp(signature: &H520, vote_info: &Bytes) -> Bytes { } pub fn message_hash(vote_step: VoteStep, block_hash: H256) -> H256 { - message_info_rlp(&vote_step, Some(block_hash)).sha3() + keccak(message_info_rlp(&vote_step, Some(block_hash))) } #[cfg(test)] mod tests { use std::sync::Arc; - use util::*; + use hash::keccak; use rlp::*; use account_provider::AccountProvider; use header::Header; @@ -228,7 +230,7 @@ mod tests { view: 123, step: Step::Precommit, }, - block_hash: Some("1".sha3()) + block_hash: Some(keccak("1")), }; let raw_rlp = ::rlp::encode(&message).into_vec(); let rlp = Rlp::new(&raw_rlp); @@ -251,12 +253,12 @@ mod tests { #[test] fn generate_and_verify() { let tap = Arc::new(AccountProvider::transient_provider()); - let addr = tap.insert_account("0".sha3().into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); tap.unlock_account_permanently(addr, "0".into()).unwrap(); let mi = message_info_rlp(&VoteStep::new(123, 2, Step::Precommit), Some(H256::default())); - let raw_rlp = message_full_rlp(&tap.sign(addr, None, mi.sha3()).unwrap().into(), &mi); + let raw_rlp = message_full_rlp(&tap.sign(addr, None, keccak(&mi)).unwrap().into(), &mi); let rlp = UntrustedRlp::new(&raw_rlp); let message: ConsensusMessage = rlp.as_val().unwrap(); diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index cc75e99c3e7b1902b7c89136fec29cd07ef4c633..4d0656749a35fc6c35beef3ab116835058d7c801 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -27,20 +27,20 @@ mod params; use std::sync::{Weak, Arc}; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; -use std::collections::{HashSet, BTreeMap, HashMap}; -use std::cmp; -use util::*; -use client::{Client, EngineClient}; +use std::collections::{HashSet, BTreeMap}; +use hash::keccak; +use ethereum_types::{H256, H520, U128, U256, Address}; +use parking_lot::RwLock; +use unexpected::{OutOfBounds, Mismatch}; +use client::EngineClient; +use bytes::Bytes; use error::{Error, BlockError}; use header::{Header, BlockNumber}; -use builtin::Builtin; use rlp::UntrustedRlp; use ethkey::{Message, public_to_address, recover, Signature}; use account_provider::AccountProvider; use block::*; -use spec::CommonParams; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; -use state::CleanupMode; use io::IoService; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList}; @@ -48,6 +48,7 @@ use super::transition::TransitionHandler; use super::vote_collector::VoteCollector; use self::message::*; use self::params::TendermintParams; +use machine::{AuxiliaryData, EthereumMachine}; #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum Step { @@ -72,8 +73,6 @@ pub type BlockHash = H256; /// Engine using `Tendermint` consensus algorithm, suitable for EVM chain. pub struct Tendermint { - params: CommonParams, - builtins: BTreeMap, step_service: IoService, client: RwLock>>, /// Blockchain height. @@ -98,6 +97,10 @@ pub struct Tendermint { last_proposed: RwLock, /// Set used to determine the current validators. validators: Box, + /// Reward per block, in base units. + block_reward: U256, + /// ethereum machine descriptor + machine: EthereumMachine, } struct EpochVerifier @@ -107,7 +110,7 @@ struct EpochVerifier recover: F } -impl super::EpochVerifier for EpochVerifier +impl super::EpochVerifier for EpochVerifier where F: Fn(&Signature, &Message) -> Result + Send + Sync { fn verify_light(&self, header: &Header) -> Result<(), Error> { @@ -161,11 +164,9 @@ fn destructure_proofs(combined: &[u8]) -> Result<(BlockNumber, &[u8], &[u8]), Er impl Tendermint { /// Create a new instance of Tendermint engine - pub fn new(params: CommonParams, our_params: TendermintParams, builtins: BTreeMap) -> Result, Error> { + pub fn new(our_params: TendermintParams, machine: EthereumMachine) -> Result, Error> { let engine = Arc::new( Tendermint { - params: params, - builtins: builtins, client: RwLock::new(None), step_service: IoService::::start()?, height: AtomicUsize::new(1), @@ -179,9 +180,13 @@ impl Tendermint { proposal_parent: Default::default(), last_proposed: Default::default(), validators: our_params.validators, + block_reward: our_params.block_reward, + machine: machine, }); - let handler = TransitionHandler::new(Arc::downgrade(&engine) as Weak, Box::new(our_params.timeouts)); + + let handler = TransitionHandler::new(Arc::downgrade(&engine) as Weak>, Box::new(our_params.timeouts)); engine.step_service.register_handler(Arc::new(handler))?; + Ok(engine) } @@ -214,11 +219,11 @@ impl Tendermint { let r = self.view.load(AtomicOrdering::SeqCst); let s = *self.step.read(); let vote_info = message_info_rlp(&VoteStep::new(h, r, s), block_hash); - match (self.signer.read().address(), self.sign(vote_info.sha3()).map(Into::into)) { + match (self.signer.read().address(), self.sign(keccak(&vote_info)).map(Into::into)) { (Some(validator), Ok(signature)) => { let message_rlp = message_full_rlp(&signature, &vote_info); let message = ConsensusMessage::new(signature, h, r, s, block_hash); - self.votes.vote(message.clone(), &validator); + self.votes.vote(message.clone(), validator); debug!(target: "engine", "Generated {:?} as {}.", message, validator); self.handle_valid_message(&message); @@ -432,23 +437,15 @@ impl Tendermint { } } -impl Engine for Tendermint { +impl Engine for Tendermint { fn name(&self) -> &str { "Tendermint" } - fn version(&self) -> SemanticVersion { SemanticVersion::new(1, 0, 0) } - /// (consensus view, proposal signature, authority signatures) - fn seal_fields(&self) -> usize { 3 } - - fn params(&self) -> &CommonParams { &self.params } - - fn additional_params(&self) -> HashMap { - hash_map!["registrar".to_owned() => self.params().registrar.hex()] - } + fn seal_fields(&self, _header: &Header) -> usize { 3 } - fn builtins(&self) -> &BTreeMap { &self.builtins } + 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 } @@ -463,19 +460,13 @@ impl Engine for Tendermint { ] } - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header) { // Chain scoring: total weight is sqrt(U256::max_value())*height - view - let new_difficulty = U256::from(U128::max_value()) + consensus_view(parent).expect("Header has been verified; qed").into() - self.view.load(AtomicOrdering::SeqCst).into(); + let new_difficulty = U256::from(U128::max_value()) + + consensus_view(parent).expect("Header has been verified; qed").into() + - self.view.load(AtomicOrdering::SeqCst).into(); + header.set_difficulty(new_difficulty); - header.set_gas_limit({ - let gas_limit = parent.gas_limit().clone(); - let bound_divisor = self.params().gas_limit_bound_divisor; - if gas_limit < gas_floor_target { - cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) - } else { - cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) - } - }); } /// Should this node participate. @@ -487,7 +478,7 @@ impl Engine 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. @@ -499,10 +490,10 @@ impl Engine for Tendermint { let view = self.view.load(AtomicOrdering::SeqCst); let bh = Some(header.bare_hash()); let vote_info = message_info_rlp(&VoteStep::new(height, view, Step::Propose), bh.clone()); - if let Ok(signature) = self.sign(vote_info.sha3()).map(Into::into) { + if let Ok(signature) = self.sign(keccak(&vote_info)).map(Into::into) { // Insert Propose vote. debug!(target: "engine", "Submitting proposal {} at height {} view {}.", header.bare_hash(), height, view); - self.votes.vote(ConsensusMessage::new(signature, height, view, Step::Propose, bh), author); + self.votes.vote(ConsensusMessage::new(signature, height, view, Step::Propose, bh), *author); // Remember the owned block. *self.last_proposed.write() = header.bare_hash(); // Remember proposal for later seal submission. @@ -519,19 +510,27 @@ impl Engine for Tendermint { } } - fn handle_message(&self, rlp: &[u8]) -> Result<(), Error> { + fn handle_message(&self, rlp: &[u8]) -> Result<(), EngineError> { + fn fmt_err(x: T) -> EngineError { + EngineError::MalformedMessage(format!("{:?}", x)) + } + let rlp = UntrustedRlp::new(rlp); - let message: ConsensusMessage = rlp.as_val()?; + let message: ConsensusMessage = rlp.as_val().map_err(fmt_err)?; if !self.votes.is_old_or_known(&message) { - let sender = public_to_address(&recover(&message.signature.into(), &rlp.at(1)?.as_raw().sha3())?); + let msg_hash = keccak(rlp.at(1).map_err(fmt_err)?.as_raw()); + let sender = public_to_address( + &recover(&message.signature.into(), &msg_hash).map_err(fmt_err)? + ); + if !self.is_authority(&sender) { - return Err(EngineError::NotAuthorized(sender).into()); + return Err(EngineError::NotAuthorized(sender)); } self.broadcast_message(rlp.as_raw().to_vec()); - if let Some(double) = self.votes.vote(message.clone(), &sender) { + if let Some(double) = self.votes.vote(message.clone(), sender) { let height = message.vote_step.height as BlockNumber; self.validators.report_malicious(&sender, height, height, ::rlp::encode(&double).into_vec()); - return Err(EngineError::DoubleVote(sender).into()); + return Err(EngineError::DoubleVote(sender)); } trace!(target: "engine", "Handling a valid {:?} from {}.", message, sender); self.handle_valid_message(&message); @@ -539,24 +538,43 @@ impl Engine for Tendermint { Ok(()) } + fn on_new_block(&self, block: &mut ExecutedBlock, epoch_begin: bool) -> Result<(), Error> { + if !epoch_begin { return Ok(()) } + + // genesis is never a new block, but might as well check. + let header = block.header().clone(); + let first = header.number() == 0; + + let mut call = |to, data| { + let result = self.machine.execute_as_system( + block, + to, + U256::max_value(), // unbounded gas? maybe make configurable. + Some(data), + ); + + result.map_err(|e| format!("{}", e)) + }; + + self.validators.on_epoch_begin(first, &header, &mut call) + } + /// Apply the block reward on finalisation of the block. fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error>{ - let fields = block.fields_mut(); - // Bestow block reward - let reward = self.params().block_reward; - let res = fields.state.add_balance(fields.header.author(), &reward, CleanupMode::NoEmpty) - .map_err(::error::Error::from) - .and_then(|_| fields.state.commit()); - // Commit state so that we can actually figure out the state root. - if let Err(ref e) = res { - warn!("Encountered error on closing block: {}", e); - } - res + use parity_machine::WithBalances; + let author = *block.header().author(); + self.machine.add_balance(block, &author, &self.block_reward)?; + self.machine.note_rewards(block, &[(author, self.block_reward)], &[]) + } + + fn verify_local_seal(&self, _header: &Header) -> Result<(), Error> { + Ok(()) } - fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { + fn verify_block_basic(&self, header: &Header) -> Result<(), Error> { let seal_length = header.seal().len(); - if seal_length == self.seal_fields() { + let expected_seal_fields = self.seal_fields(header); + if seal_length == expected_seal_fields { // Either proposal or commit. if (header.seal()[1] == ::rlp::NULL_RLP) != (header.seal()[2] == ::rlp::EMPTY_LIST_RLP) { @@ -567,27 +585,23 @@ impl Engine for Tendermint { } } else { Err(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: seal_length } + Mismatch { expected: expected_seal_fields, found: seal_length } ).into()) } } - fn verify_block_unordered(&self, _header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - Ok(()) - } - - /// Verify validators and gas limit. - fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - if header.number() == 0 { - return Err(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }).into()); - } - + fn verify_block_external(&self, header: &Header) -> Result<(), Error> { if let Ok(proposal) = ConsensusMessage::new_proposal(header) { let proposer = proposal.verify()?; if !self.is_authority(&proposer) { return Err(EngineError::NotAuthorized(proposer).into()); } - self.check_view_proposer(header.parent_hash(), proposal.vote_step.height, proposal.vote_step.view, &proposer)?; + self.check_view_proposer( + header.parent_hash(), + proposal.vote_step.height, + proposal.vote_step.view, + &proposer + ).map_err(Into::into) } else { let vote_step = VoteStep::new(header.number() as usize, consensus_view(header)?, Step::Precommit); let precommit_hash = message_hash(vote_step.clone(), header.bare_hash()); @@ -613,31 +627,21 @@ impl Engine for Tendermint { } } - self.check_above_threshold(origins.len())? + self.check_above_threshold(origins.len()).map_err(Into::into) } - - let gas_limit_divisor = self.params().gas_limit_bound_divisor; - let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor; - let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor; - if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { - self.validators.report_malicious(header.author(), header.number(), header.number(), Default::default()); - return Err(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }).into()); - } - - Ok(()) } - fn signals_epoch_end(&self, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>) - -> super::EpochChange + fn signals_epoch_end(&self, header: &Header, aux: AuxiliaryData) + -> super::EpochChange { let first = header.number() == 0; - self.validators.signals_epoch_end(first, header, block, receipts) + self.validators.signals_epoch_end(first, header, aux) } fn is_epoch_end( &self, chain_head: &Header, - _chain: &super::Headers, + _chain: &super::Headers
, transition_store: &super::PendingTransitionStore, ) -> Option> { let first = chain_head.number() == 0; @@ -654,14 +658,14 @@ impl Engine for Tendermint { None } - fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a> { + fn epoch_verifier<'a>(&self, _header: &Header, proof: &'a [u8]) -> ConstructedVerifier<'a, EthereumMachine> { let (signal_number, set_proof, finality_proof) = match destructure_proofs(proof) { Ok(x) => x, Err(e) => return ConstructedVerifier::Err(e), }; let first = signal_number == 0; - match self.validators.epoch_set(first, self, signal_number, set_proof) { + match self.validators.epoch_set(first, &self.machine, signal_number, set_proof) { Ok((list, finalize)) => { let verifier = Box::new(EpochVerifier { subchain_validators: list, @@ -715,7 +719,7 @@ impl Engine for Tendermint { *self.proposal.write() = proposal.block_hash.clone(); *self.proposal_parent.write() = header.parent_hash().clone(); } - self.votes.vote(proposal, &proposer); + self.votes.vote(proposal, proposer); true } @@ -759,13 +763,12 @@ impl Engine for Tendermint { self.to_step(next_step); } - fn register_client(&self, client: Weak) { - use client::BlockChainClient; + fn register_client(&self, client: Weak) { if let Some(c) = client.upgrade() { self.height.store(c.chain_info().best_block_number as usize + 1, AtomicOrdering::SeqCst); } *self.client.write() = Some(client.clone()); - self.validators.register_contract(client); + self.validators.register_client(client); } } @@ -773,16 +776,20 @@ impl Engine for Tendermint { mod tests { use std::str::FromStr; use rustc_hex::FromHex; - use util::*; + use ethereum_types::Address; + use bytes::Bytes; use block::*; use error::{Error, BlockError}; use header::Header; - use client::chain_notify::ChainNotify; + use client::ChainInfo; use miner::MinerService; - use tests::helpers::*; + use tests::helpers::{ + TestNotify, get_temp_state_db, generate_dummy_client, + generate_dummy_client_with_spec_and_accounts + }; use account_provider::AccountProvider; use spec::Spec; - use engines::{Engine, EngineError, Seal}; + use engines::{EthEngine, EngineError, Seal}; use engines::epoch::EpochVerifier; use super::*; @@ -800,16 +807,16 @@ 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!() } } - fn vote(engine: &Engine, signer: F, height: usize, view: usize, step: Step, block_hash: Option) -> Bytes where F: FnOnce(H256) -> Result { + fn vote(engine: &EthEngine, signer: F, height: usize, view: usize, step: Step, block_hash: Option) -> Bytes where F: FnOnce(H256) -> Result { let mi = message_info_rlp(&VoteStep::new(height, view, step), block_hash); - let m = message_full_rlp(&signer(mi.sha3()).unwrap().into(), &mi); + let m = message_full_rlp(&signer(keccak(&mi)).unwrap().into(), &mi); engine.handle_message(&m).unwrap(); m } @@ -817,7 +824,7 @@ mod tests { fn proposal_seal(tap: &Arc, header: &Header, view: View) -> Vec { let author = header.author(); let vote_info = message_info_rlp(&VoteStep::new(header.number() as Height, view, Step::Propose), Some(header.bare_hash())); - let signature = tap.sign(*author, None, vote_info.sha3()).unwrap(); + let signature = tap.sign(*author, None, keccak(vote_info)).unwrap(); vec![ ::rlp::encode(&view).into_vec(), ::rlp::encode(&H520::from(signature)).into_vec(), @@ -826,33 +833,21 @@ mod tests { } fn insert_and_unlock(tap: &Arc, acc: &str) -> Address { - let addr = tap.insert_account(acc.sha3().into(), acc).unwrap(); + let addr = tap.insert_account(keccak(acc).into(), acc).unwrap(); tap.unlock_account_permanently(addr, acc.into()).unwrap(); addr } - fn insert_and_register(tap: &Arc, engine: &Engine, acc: &str) -> Address { + fn insert_and_register(tap: &Arc, engine: &EthEngine, acc: &str) -> Address { let addr = insert_and_unlock(tap, acc); engine.set_signer(tap.clone(), addr.clone(), acc.into()); addr } - #[derive(Default)] - struct TestNotify { - messages: RwLock>, - } - - impl ChainNotify for TestNotify { - fn broadcast(&self, data: Vec) { - self.messages.write().push(data); - } - } - #[test] fn has_valid_metadata() { let engine = Spec::new_test_tendermint().engine; assert!(!engine.name().is_empty()); - assert!(engine.version().major >= 1); } #[test] @@ -868,7 +863,7 @@ mod tests { let engine = Spec::new_test_tendermint().engine; let header = Header::default(); - let verify_result = engine.verify_block_basic(&header, None); + let verify_result = engine.verify_block_basic(&header); match verify_result { Err(Error::Block(BlockError::InvalidSealArity(_))) => {}, @@ -893,14 +888,14 @@ mod tests { let seal = proposal_seal(&tap, &header, 0); header.set_seal(seal); // Good proposer. - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); + assert!(engine.verify_block_external(&header).is_ok()); let validator = insert_and_unlock(&tap, "0"); header.set_author(validator); let seal = proposal_seal(&tap, &header, 0); header.set_seal(seal); // Bad proposer. - match engine.verify_block_family(&header, &parent_header, None) { + match engine.verify_block_external(&header) { Err(Error::Engine(EngineError::NotProposer(_))) => {}, _ => panic!(), } @@ -910,7 +905,7 @@ mod tests { let seal = proposal_seal(&tap, &header, 0); header.set_seal(seal); // Not authority. - match engine.verify_block_family(&header, &parent_header, None) { + match engine.verify_block_external(&header) { Err(Error::Engine(EngineError::NotAuthorized(_))) => {}, _ => panic!(), }; @@ -933,34 +928,34 @@ mod tests { let mut seal = proposal_seal(&tap, &header, 0); let vote_info = message_info_rlp(&VoteStep::new(2, 0, Step::Precommit), Some(header.bare_hash())); - let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap(); + let signature1 = tap.sign(proposer, None, keccak(&vote_info)).unwrap(); seal[1] = ::rlp::NULL_RLP.to_vec(); seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec(); header.set_seal(seal.clone()); // One good signature is not enough. - match engine.verify_block_family(&header, &parent_header, None) { + match engine.verify_block_external(&header) { Err(Error::Engine(EngineError::BadSealFieldSize(_))) => {}, _ => panic!(), } let voter = insert_and_unlock(&tap, "0"); - let signature0 = tap.sign(voter, None, vote_info.sha3()).unwrap(); + let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap(); seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone()), H520::from(signature0.clone())]).into_vec(); header.set_seal(seal.clone()); - assert!(engine.verify_block_family(&header, &parent_header, None).is_ok()); + assert!(engine.verify_block_external(&header).is_ok()); let bad_voter = insert_and_unlock(&tap, "101"); - let bad_signature = tap.sign(bad_voter, None, vote_info.sha3()).unwrap(); + let bad_signature = tap.sign(bad_voter, None, keccak(vote_info)).unwrap(); seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec(); header.set_seal(seal); // One good and one bad signature. - match engine.verify_block_family(&header, &parent_header, None) { + match engine.verify_block_external(&header) { Err(Error::Engine(EngineError::NotAuthorized(_))) => {}, _ => panic!(), }; @@ -1006,7 +1001,7 @@ mod tests { let client = generate_dummy_client(0); let notify = Arc::new(TestNotify::default()); client.add_notify(notify.clone()); - engine.register_client(Arc::downgrade(&client)); + engine.register_client(Arc::downgrade(&client) as _); let prevote_current = vote(engine.as_ref(), |mh| tap.sign(v0, None, mh).map(H520::from), h, r, Step::Prevote, proposal); @@ -1024,7 +1019,6 @@ mod tests { fn seal_submission() { use ethkey::{Generator, Random}; use transaction::{Transaction, Action}; - use client::BlockChainClient; let tap = Arc::new(AccountProvider::transient_provider()); // Accounts for signing votes. @@ -1037,7 +1031,7 @@ mod tests { let notify = Arc::new(TestNotify::default()); client.add_notify(notify.clone()); - engine.register_client(Arc::downgrade(&client)); + engine.register_client(Arc::downgrade(&client) as _); let keypair = Random.generate().unwrap(); let transaction = Transaction { @@ -1087,10 +1081,10 @@ mod tests { let mut seal = proposal_seal(&tap, &header, 0); let vote_info = message_info_rlp(&VoteStep::new(2, 0, Step::Precommit), Some(header.bare_hash())); - let signature1 = tap.sign(proposer, None, vote_info.sha3()).unwrap(); + let signature1 = tap.sign(proposer, None, keccak(&vote_info)).unwrap(); let voter = insert_and_unlock(&tap, "0"); - let signature0 = tap.sign(voter, None, vote_info.sha3()).unwrap(); + let signature0 = tap.sign(voter, None, keccak(&vote_info)).unwrap(); seal[1] = ::rlp::NULL_RLP.to_vec(); seal[2] = ::rlp::encode_list(&vec![H520::from(signature1.clone())]).into_vec(); @@ -1127,7 +1121,7 @@ mod tests { assert!(epoch_verifier.verify_light(&header).is_ok()); let bad_voter = insert_and_unlock(&tap, "101"); - let bad_signature = tap.sign(bad_voter, None, vote_info.sha3()).unwrap(); + let bad_signature = tap.sign(bad_voter, None, keccak(&vote_info)).unwrap(); seal[2] = ::rlp::encode_list(&vec![H520::from(signature1), H520::from(bad_signature)]).into_vec(); header.set_seal(seal); diff --git a/ethcore/src/engines/tendermint/params.rs b/ethcore/src/engines/tendermint/params.rs index 7ff3d697f89814e441b6454bcec4b8d283817904..c1fd39eb1ca53bbb942a6ff281cae5e08f9933dc 100644 --- a/ethcore/src/engines/tendermint/params.rs +++ b/ethcore/src/engines/tendermint/params.rs @@ -17,7 +17,8 @@ //! Tendermint specific parameters. use ethjson; -use time::Duration; +use std::time::Duration; +use ethereum_types::U256; use super::super::validator_set::{ValidatorSet, new_validator_set}; use super::super::transition::Timeouts; use super::Step; @@ -28,6 +29,8 @@ pub struct TendermintParams { pub validators: Box, /// Timeout durations for different steps. pub timeouts: TendermintTimeouts, + /// Reward per block in base units. + pub block_reward: U256, } /// Base timeout of each step in ms. @@ -42,10 +45,10 @@ pub struct TendermintTimeouts { impl Default for TendermintTimeouts { fn default() -> Self { TendermintTimeouts { - propose: Duration::milliseconds(1000), - prevote: Duration::milliseconds(1000), - precommit: Duration::milliseconds(1000), - commit: Duration::milliseconds(1000), + propose: Duration::from_millis(1000), + prevote: Duration::from_millis(1000), + precommit: Duration::from_millis(1000), + commit: Duration::from_millis(1000), } } } @@ -67,7 +70,7 @@ impl Timeouts for TendermintTimeouts { fn to_duration(ms: ethjson::uint::Uint) -> Duration { let ms: usize = ms.into(); - Duration::milliseconds(ms as i64) + Duration::from_millis(ms as u64) } impl From for TendermintParams { @@ -81,6 +84,7 @@ impl From for TendermintParams { precommit: p.timeout_precommit.map_or(dt.precommit, to_duration), commit: p.timeout_commit.map_or(dt.commit, to_duration), }, + block_reward: p.block_reward.map_or(U256::default(), Into::into), } } } diff --git a/ethcore/src/engines/transition.rs b/ethcore/src/engines/transition.rs index 590fb6db2410acdc023f9b1d49ef39e9194b5ce1..dc745b6e3981b2376977e49e4bdf5997d6a9b7f1 100644 --- a/ethcore/src/engines/transition.rs +++ b/ethcore/src/engines/transition.rs @@ -17,9 +17,10 @@ //! Engine timeout transitioning calls `Engine.step()` on timeout. use std::sync::Weak; -use time::Duration; +use std::time::Duration; use io::{IoContext, IoHandler, TimerToken}; use engines::Engine; +use parity_machine::Machine; /// Timeouts lookup pub trait Timeouts: Send + Sync { @@ -31,14 +32,14 @@ pub trait Timeouts: Send + Sync { } /// Timeout transition handling. -pub struct TransitionHandler { - engine: Weak, +pub struct TransitionHandler { + engine: Weak>, timeouts: Box>, } -impl TransitionHandler where S: Sync + Send + Clone { +impl TransitionHandler where S: Sync + Send + Clone { /// New step caller by timeouts. - pub fn new(engine: Weak, timeouts: Box>) -> Self { + pub fn new(engine: Weak>, timeouts: Box>) -> Self { TransitionHandler { engine: engine, timeouts: timeouts, @@ -50,14 +51,17 @@ impl TransitionHandler where S: Sync + Send + Clone { pub const ENGINE_TIMEOUT_TOKEN: TimerToken = 23; fn set_timeout(io: &IoContext, timeout: Duration) { - io.register_timer_once(ENGINE_TIMEOUT_TOKEN, timeout.num_milliseconds() as u64) + let ms = timeout.as_secs() * 1_000 + timeout.subsec_nanos() as u64 / 1_000_000; + io.register_timer_once(ENGINE_TIMEOUT_TOKEN, ms) .unwrap_or_else(|e| warn!(target: "engine", "Failed to set consensus step timeout: {}.", e)) } -impl IoHandler for TransitionHandler where S: Sync + Send + Clone + 'static { +impl IoHandler for TransitionHandler + where S: Sync + Send + Clone + 'static, M: Machine +{ fn initialize(&self, io: &IoContext) { let initial = self.timeouts.initial(); - trace!(target: "engine", "Setting the initial timeout to {}.", initial); + trace!(target: "engine", "Setting the initial timeout to {:?}.", initial); set_timeout(io, initial); } diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index 7c18903798cf09a707cb98545aefda7dfe2907e1..0e27d594d548aa0159ffd6c6d969f893cb34840e 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -18,46 +18,53 @@ /// It can also report validators for misbehaviour with two levels: `reportMalicious` and `reportBenign`. use std::sync::Weak; -use util::*; -use futures::Future; -use native_contracts::ValidatorReport as Provider; +use bytes::Bytes; +use ethereum_types::{H256, Address}; +use parking_lot::RwLock; -use client::{Client, BlockChainClient}; -use engines::{Call, Engine}; +use client::EngineClient; use header::{Header, BlockNumber}; +use machine::{AuxiliaryData, Call, EthereumMachine}; use super::{ValidatorSet, SimpleList, SystemCall}; use super::safe_contract::ValidatorSafeContract; +use_contract!(validator_report, "ValidatorReport", "res/contracts/validator_report.json"); + /// A validator contract with reporting. pub struct ValidatorContract { + contract_address: Address, validators: ValidatorSafeContract, - provider: Provider, - client: RwLock>>, // TODO [keorn]: remove + provider: validator_report::ValidatorReport, + client: RwLock>>, // TODO [keorn]: remove } impl ValidatorContract { pub fn new(contract_address: Address) -> Self { ValidatorContract { + contract_address, validators: ValidatorSafeContract::new(contract_address), - provider: Provider::new(contract_address), + provider: validator_report::ValidatorReport::default(), client: RwLock::new(None), } } } impl ValidatorContract { - // could be `impl Trait`. - // note: dispatches transactions to network as well as execute. - // TODO [keorn]: Make more general. - fn transact(&self) -> Box Result> { - let client = self.client.read().clone(); - Box::new(move |a, d| client.as_ref() + fn transact(&self, data: Bytes) -> Result<(), String> { + let client = self.client.read().as_ref() .and_then(Weak::upgrade) - .ok_or("No client!".into()) - .and_then(|c| c.transact_contract(a, d).map_err(|e| format!("Transaction import error: {}", e))) - .map(|_| Default::default())) + .ok_or_else(|| "No client!")?; + + match client.as_full_client() { + Some(c) => { + c.transact_contract(self.contract_address, data) + .map_err(|e| format!("Transaction import error: {}", e))?; + Ok(()) + }, + None => Err("No full client!".into()), + } } } @@ -82,14 +89,13 @@ impl ValidatorSet for ValidatorContract { &self, first: bool, header: &Header, - block: Option<&[u8]>, - receipts: Option<&[::receipt::Receipt]>, - ) -> ::engines::EpochChange { - self.validators.signals_epoch_end(first, header, block, receipts) + aux: AuxiliaryData, + ) -> ::engines::EpochChange { + self.validators.signals_epoch_end(first, header, aux) } - fn epoch_set(&self, first: bool, engine: &Engine, number: BlockNumber, proof: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { - self.validators.epoch_set(first, engine, number, proof) + fn epoch_set(&self, first: bool, machine: &EthereumMachine, number: BlockNumber, proof: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { + self.validators.epoch_set(first, machine, number, proof) } fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool { @@ -105,21 +111,23 @@ impl ValidatorSet for ValidatorContract { } fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) { - match self.provider.report_malicious(&*self.transact(), *address, block.into(), proof).wait() { + let data = self.provider.functions().report_malicious().input(*address, block, proof); + match self.transact(data) { Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), } } fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) { - match self.provider.report_benign(&*self.transact(), *address, block.into()).wait() { + let data = self.provider.functions().report_benign().input(*address, block); + match self.transact(data) { Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), } } - fn register_contract(&self, client: Weak) { - self.validators.register_contract(client.clone()); + fn register_client(&self, client: Weak) { + self.validators.register_client(client.clone()); *self.client.write() = Some(client); } } @@ -128,14 +136,16 @@ impl ValidatorSet for ValidatorContract { mod tests { use std::sync::Arc; use rustc_hex::FromHex; - use util::*; + use hash::keccak; + use ethereum_types::{H520, Address}; + use bytes::ToPretty; use rlp::encode; use spec::Spec; use header::Header; use account_provider::AccountProvider; use miner::MinerService; use types::ids::BlockId; - use client::BlockChainClient; + use client::{BlockChainClient, ChainInfo, BlockInfo, CallContract}; use tests::helpers::generate_dummy_client_with_spec_and_accounts; use super::super::ValidatorSet; use super::ValidatorContract; @@ -144,7 +154,7 @@ mod tests { fn fetches_validators() { let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, None); let vc = Arc::new(ValidatorContract::new("0000000000000000000000000000000000000005".parse::
().unwrap())); - vc.register_contract(Arc::downgrade(&client)); + vc.register_client(Arc::downgrade(&client) as _); let last_hash = client.best_block_header().hash(); assert!(vc.contains(&last_hash, &"7d577a597b2742b498cb5cf0c26cdcd726d39e6e".parse::
().unwrap())); assert!(vc.contains(&last_hash, &"82a978b3f5962a5b0957d9ee9eef472ee55b42f1".parse::
().unwrap())); @@ -153,32 +163,46 @@ mod tests { #[test] fn reports_validators() { let tap = Arc::new(AccountProvider::transient_provider()); - let v1 = tap.insert_account("1".sha3().into(), "").unwrap(); + let v1 = tap.insert_account(keccak("1").into(), "").unwrap(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone())); - client.engine().register_client(Arc::downgrade(&client)); + client.engine().register_client(Arc::downgrade(&client) as _); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); // Make sure reporting can be done. client.miner().set_gas_floor_target(1_000_000.into()); - client.miner().set_engine_signer(v1, "".into()).unwrap(); + + // Check a block that is a bit in future, reject it but don't report the validator. let mut header = Header::default(); - let seal = vec![encode(&5u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()]; + let seal = vec![encode(&4u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()]; header.set_seal(seal); header.set_author(v1); header.set_number(2); header.set_parent_hash(client.chain_info().best_block_hash); + assert!(client.engine().verify_block_external(&header).is_err()); + client.engine().step(); + assert_eq!(client.chain_info().best_block_number, 0); + // Now create one that is more in future. That one should be rejected and validator should be reported. + let mut header = Header::default(); + let seal = vec![encode(&8u8).into_vec(), encode(&(&H520::default() as &[u8])).into_vec()]; + header.set_seal(seal); + header.set_author(v1); + header.set_number(2); + header.set_parent_hash(client.chain_info().best_block_hash); // `reportBenign` when the designated proposer releases block from the future (bad clock). - assert!(client.engine().verify_block_external(&header, None).is_err()); + assert!(client.engine().verify_block_basic(&header).is_err()); // Seal a block. client.engine().step(); assert_eq!(client.chain_info().best_block_number, 1); // Check if the unresponsive validator is `disliked`. - assert_eq!(client.call_contract(BlockId::Latest, validator_contract, "d8f2e0bf".from_hex().unwrap()).unwrap().to_hex(), "0000000000000000000000007d577a597b2742b498cb5cf0c26cdcd726d39e6e"); + assert_eq!( + client.call_contract(BlockId::Latest, validator_contract, "d8f2e0bf".from_hex().unwrap()).unwrap().to_hex(), + "0000000000000000000000007d577a597b2742b498cb5cf0c26cdcd726d39e6e" + ); // Simulate a misbehaving validator by handling a double proposal. let header = client.best_block_header().decode(); - assert!(client.engine().verify_block_family(&header, &header, None).is_err()); + assert!(client.engine().verify_block_family(&header, &header).is_err()); // Seal a block. client.engine().step(); client.engine().step(); diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index 56cff365ffcb46aacb176cc5f84cab8f5c387e25..de2164f918f86bf93418bf603786baccca5d0317 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -25,10 +25,12 @@ mod multi; use std::sync::Weak; use ids::BlockId; -use util::{Bytes, Address, H256}; +use ethereum_types::{H256, Address}; +use bytes::Bytes; use ethjson::spec::ValidatorSet as ValidatorSpec; -use client::Client; +use client::EngineClient; use header::{Header, BlockNumber}; +use machine::{AuxiliaryData, Call, EthereumMachine}; #[cfg(test)] pub use self::test::TestSet; @@ -37,8 +39,6 @@ use self::contract::ValidatorContract; use self::safe_contract::ValidatorSafeContract; use self::multi::Multi; -use super::{Call, Engine}; - /// A system-calling closure. Enacts calls on a block's state from the system address. pub type SystemCall<'a> = FnMut(Address, Bytes) -> Result + 'a; @@ -111,9 +111,8 @@ pub trait ValidatorSet: Send + Sync { &self, first: bool, header: &Header, - block: Option<&[u8]>, - receipts: Option<&[::receipt::Receipt]>, - ) -> ::engines::EpochChange; + aux: AuxiliaryData, + ) -> ::engines::EpochChange; /// Recover the validator set from the given proof, the block number, and /// whether this header is first in its set. @@ -123,7 +122,7 @@ pub trait ValidatorSet: Send + Sync { /// /// Returns the set, along with a flag indicating whether finality of a specific /// hash should be proven. - fn epoch_set(&self, first: bool, engine: &Engine, number: BlockNumber, proof: &[u8]) + fn epoch_set(&self, first: bool, machine: &EthereumMachine, number: BlockNumber, proof: &[u8]) -> Result<(SimpleList, Option), ::error::Error>; /// Checks if a given address is a validator, with the given function @@ -141,5 +140,5 @@ pub trait ValidatorSet: Send + Sync { /// Notifies about benign misbehaviour. fn report_benign(&self, _validator: &Address, _set_block: BlockNumber, _block: BlockNumber) {} /// Allows blockchain state access. - fn register_contract(&self, _client: Weak) {} + fn register_client(&self, _client: Weak) {} } diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 9acf6050b9f90af03e4b2467d7b4eb70cd8fabde..2794b57a2a43361d73d6ae8e18987368612a67cb 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -18,11 +18,13 @@ use std::collections::BTreeMap; use std::sync::Weak; -use engines::{Call, Engine}; -use util::{Bytes, H256, Address, RwLock}; +use ethereum_types::{H256, Address}; +use parking_lot::RwLock; +use bytes::Bytes; use ids::BlockId; use header::{BlockNumber, Header}; -use client::{Client, BlockChainClient}; +use client::EngineClient; +use machine::{AuxiliaryData, Call, EthereumMachine}; use super::{SystemCall, ValidatorSet}; type BlockNumberLookup = Box Result + Send + Sync + 'static>; @@ -90,20 +92,20 @@ impl ValidatorSet for Multi { set.is_epoch_end(first, chain_head) } - fn signals_epoch_end(&self, _first: bool, header: &Header, block: Option<&[u8]>, receipts: Option<&[::receipt::Receipt]>) - -> ::engines::EpochChange + fn signals_epoch_end(&self, _first: bool, header: &Header, aux: AuxiliaryData) + -> ::engines::EpochChange { let (set_block, set) = self.correct_set_by_number(header.number()); let first = set_block == header.number(); - set.signals_epoch_end(first, header, block, receipts) + set.signals_epoch_end(first, header, aux) } - fn epoch_set(&self, _first: bool, engine: &Engine, number: BlockNumber, proof: &[u8]) -> Result<(super::SimpleList, Option), ::error::Error> { + fn epoch_set(&self, _first: bool, machine: &EthereumMachine, number: BlockNumber, proof: &[u8]) -> Result<(super::SimpleList, Option), ::error::Error> { let (set_block, set) = self.correct_set_by_number(number); let first = set_block == number; - set.epoch_set(first, engine, number, proof) + set.epoch_set(first, machine, number, proof) } fn contains_with_caller(&self, bh: &H256, address: &Address, caller: &Call) -> bool { @@ -129,13 +131,13 @@ impl ValidatorSet for Multi { self.correct_set_by_number(set_block).1.report_benign(validator, set_block, block); } - fn register_contract(&self, client: Weak) { + fn register_client(&self, client: Weak) { for set in self.sets.values() { - set.register_contract(client.clone()); + set.register_client(client.clone()); } *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()))); } } @@ -144,8 +146,9 @@ impl ValidatorSet for Multi { mod tests { use std::sync::Arc; use std::collections::BTreeMap; + use hash::keccak; use account_provider::AccountProvider; - use client::{BlockChainClient, EngineClient}; + use client::{BlockChainClient, ChainInfo, BlockInfo, ImportBlock}; use engines::EpochChange; use engines::validator_set::ValidatorSet; use ethkey::Secret; @@ -154,20 +157,18 @@ mod tests { use spec::Spec; use tests::helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data}; use types::ids::BlockId; - use util::*; + use ethereum_types::Address; use super::Multi; #[test] fn uses_current_set() { - let _ = ::env_logger::init(); - let tap = Arc::new(AccountProvider::transient_provider()); - let s0: Secret = "0".sha3().into(); + let s0: Secret = keccak("0").into(); let v0 = tap.insert_account(s0.clone(), "").unwrap(); - let v1 = tap.insert_account("1".sha3().into(), "").unwrap(); + let v1 = tap.insert_account(keccak("1").into(), "").unwrap(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_multi, Some(tap)); - client.engine().register_client(Arc::downgrade(&client)); + client.engine().register_client(Arc::downgrade(&client) as _); // Make sure txs go through. client.miner().set_gas_floor_target(1_000_000.into()); @@ -175,27 +176,27 @@ mod tests { // Wrong signer for the first block. client.miner().set_engine_signer(v1, "".into()).unwrap(); client.transact_contract(Default::default(), Default::default()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 0); // Right signer for the first block. client.miner().set_engine_signer(v0, "".into()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); // This time v0 is wrong. client.transact_contract(Default::default(), Default::default()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); client.miner().set_engine_signer(v1, "".into()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // v1 is still good. client.transact_contract(Default::default(), Default::default()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 3); // Check syncing. let sync_client = generate_dummy_client_with_spec_and_data(Spec::new_validator_multi, 0, 0, &[]); - sync_client.engine().register_client(Arc::downgrade(&sync_client)); + sync_client.engine().register_client(Arc::downgrade(&sync_client) as _); for i in 1..4 { sync_client.import_block(client.block(BlockId::Number(i)).unwrap().into_inner()).unwrap(); } @@ -223,7 +224,7 @@ mod tests { let mut header = Header::new(); header.set_number(499); - match multi.signals_epoch_end(false, &header, None, None) { + match multi.signals_epoch_end(false, &header, Default::default()) { EpochChange::No => {}, _ => panic!("Expected no epoch signal change."), } @@ -231,7 +232,7 @@ mod tests { header.set_number(500); - match multi.signals_epoch_end(false, &header, None, None) { + match multi.signals_epoch_end(false, &header, Default::default()) { EpochChange::No => {}, _ => panic!("Expected no epoch signal change."), } diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index 1abcf2c8f5702cc125aee0b898a22da0566ffe67..490a762a610b2a0f2319e24e64983c62ce1d5c8c 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -17,16 +17,19 @@ /// Validator set maintained in a contract, updated using `getValidators` method. use std::sync::{Weak, Arc}; -use futures::Future; -use native_contracts::ValidatorSet as Provider; +use hash::keccak; -use util::*; -use util::cache::MemoryLruCache; +use ethereum_types::{H256, U256, Address, Bloom}; +use parking_lot::{Mutex, RwLock}; + +use bytes::Bytes; +use memory_cache::MemoryLruCache; +use unexpected::Mismatch; use rlp::{UntrustedRlp, RlpStream}; +use kvdb::DBValue; -use basic_types::LogBloom; -use client::{Client, BlockChainClient}; -use engines::{Call, Engine}; +use client::EngineClient; +use machine::{AuxiliaryData, Call, EthereumMachine, AuxiliaryRequest}; use header::Header; use ids::BlockId; use log_entry::LogEntry; @@ -35,21 +38,47 @@ use receipt::Receipt; use super::{SystemCall, ValidatorSet}; use super::simple_list::SimpleList; +use_contract!(validator_set, "ValidatorSet", "res/contracts/validator_set.json"); + const MEMOIZE_CAPACITY: usize = 500; // TODO: ethabi should be able to generate this. const EVENT_NAME: &'static [u8] = &*b"InitiateChange(bytes32,address[])"; lazy_static! { - static ref EVENT_NAME_HASH: H256 = EVENT_NAME.sha3(); + static ref EVENT_NAME_HASH: H256 = keccak(EVENT_NAME); +} + +// state-dependent proofs for the safe contract: +// only "first" proofs are such. +struct StateProof { + contract_address: Address, + header: Mutex
, + provider: validator_set::ValidatorSet, +} + +impl ::engines::StateDependentProof for StateProof { + fn generate_proof(&self, caller: &Call) -> Result, String> { + prove_initial(&self.provider, self.contract_address, &*self.header.lock(), caller) + } + + fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> { + let (header, state_items) = decode_first_proof(&UntrustedRlp::new(proof)) + .map_err(|e| format!("proof incorrectly encoded: {}", e))?; + if &header != &*self.header.lock(){ + return Err("wrong header in proof".into()); + } + + check_first_proof(machine, &self.provider, self.contract_address, header, &state_items).map(|_| ()) + } } /// The validator contract should have the following interface: pub struct ValidatorSafeContract { - pub address: Address, + contract_address: Address, validators: RwLock>, - provider: Provider, - client: RwLock>>, // TODO [keorn]: remove + provider: validator_set::ValidatorSet, + client: RwLock>>, // TODO [keorn]: remove } // first proof is just a state proof call of `getValidators` at header's state. @@ -63,6 +92,59 @@ fn encode_first_proof(header: &Header, state_items: &[Vec]) -> Bytes { stream.out() } +// check a first proof: fetch the validator set at the given block. +fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::ValidatorSet, contract_address: Address, old_header: Header, state_items: &[DBValue]) + -> Result, String> +{ + use transaction::{Action, Transaction}; + + // TODO: match client contract_call_tx more cleanly without duplication. + const PROVIDED_GAS: u64 = 50_000_000; + + let env_info = ::vm::EnvInfo { + number: old_header.number(), + author: *old_header.author(), + difficulty: *old_header.difficulty(), + gas_limit: PROVIDED_GAS.into(), + timestamp: old_header.timestamp(), + last_hashes: { + // this will break if we don't inclue all 256 last hashes. + let mut last_hashes: Vec<_> = (0..256).map(|_| H256::default()).collect(); + last_hashes[255] = *old_header.parent_hash(); + Arc::new(last_hashes) + }, + gas_used: 0.into(), + }; + + // check state proof using given machine. + let number = old_header.number(); + provider.functions().get_validators().call(&|data| { + let from = Address::default(); + let tx = Transaction { + nonce: machine.account_start_nonce(number), + action: Action::Call(contract_address), + gas: PROVIDED_GAS.into(), + gas_price: U256::default(), + value: U256::default(), + data, + }.fake_sign(from); + + let res = ::state::check_proof( + state_items, + *old_header.state_root(), + &tx, + machine, + &env_info, + ); + + match res { + ::state::ProvedExecution::BadProof => Err("Bad proof".into()), + ::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)), + ::state::ProvedExecution::Complete(e) => Ok(e.output), + } + }).map_err(|err| err.to_string()) +} + fn decode_first_proof(rlp: &UntrustedRlp) -> Result<(Header, Vec), ::error::Error> { let header = rlp.val_at(0)?; let state_items = rlp.at(1)?.iter().map(|x| { @@ -89,19 +171,19 @@ fn decode_proof(rlp: &UntrustedRlp) -> Result<(Header, Vec), ::error::E // given a provider and caller, generate proof. this will just be a state proof // of `getValidators`. -fn prove_initial(provider: &Provider, header: &Header, caller: &Call) -> Result, String> { +fn prove_initial(provider: &validator_set::ValidatorSet, contract_address: Address, header: &Header, caller: &Call) -> Result, String> { use std::cell::RefCell; let epoch_proof = RefCell::new(None); let res = { - let caller = |a, d| { - let (result, proof) = caller(a, d)?; + let caller = |data| { + let (result, proof) = caller(contract_address, data)?; *epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof)); Ok(result) }; - provider.get_validators(caller) - .wait() + provider.functions().get_validators().call(&caller) + .map_err(|err| err.to_string()) }; res.map(|validators| { @@ -120,17 +202,18 @@ fn prove_initial(provider: &Provider, header: &Header, caller: &Call) -> Result< impl ValidatorSafeContract { pub fn new(contract_address: Address) -> Self { ValidatorSafeContract { - address: contract_address, + contract_address, validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)), - provider: Provider::new(contract_address), + provider: validator_set::ValidatorSet::default(), client: RwLock::new(None), } } /// Queries the state and gets the set of validators. fn get_list(&self, caller: &Call) -> Option { - let caller = move |a, d| caller(a, d).map(|x| x.0); - match self.provider.get_validators(caller).wait() { + let contract_address = self.contract_address; + let caller = move |data| caller(contract_address, data).map(|x| x.0); + match self.provider.functions().get_validators().call(&caller) { Ok(new) => { debug!(target: "engine", "Set of validators obtained: {:?}", new); Some(SimpleList::new(new)) @@ -157,14 +240,14 @@ impl ValidatorSafeContract { // produce the same bloom. // // The log data is an array of all new validator addresses. - fn expected_bloom(&self, header: &Header) -> LogBloom { + fn expected_bloom(&self, header: &Header) -> Bloom { let topics = vec![*EVENT_NAME_HASH, *header.parent_hash()]; debug!(target: "engine", "Expected topics for header {}: {:?}", header.hash(), topics); LogEntry { - address: self.address, + address: self.contract_address, topics: topics, data: Vec::new(), // irrelevant for bloom. }.bloom() @@ -172,54 +255,31 @@ impl ValidatorSafeContract { // check receipts for log event. bloom should be `expected_bloom` for the // header the receipts correspond to. - fn extract_from_event(&self, bloom: LogBloom, header: &Header, receipts: &[Receipt]) -> Option { + fn extract_from_event(&self, bloom: Bloom, header: &Header, receipts: &[Receipt]) -> Option { let check_log = |log: &LogEntry| { - log.address == self.address && + log.address == self.contract_address && log.topics.len() == 2 && log.topics[0] == *EVENT_NAME_HASH && log.topics[1] == *header.parent_hash() }; - let event = Provider::contract(&self.provider) - .event("InitiateChange".into()) - .expect("Contract known ahead of time to have `InitiateChange` event; qed"); - - // iterate in reverse because only the _last_ change in a given - // block actually has any effect. - // the contract should only increment the nonce once. + let event = self.provider.events().initiate_change(); + //// iterate in reverse because only the _last_ change in a given + //// block actually has any effect. + //// the contract should only increment the nonce once. let mut decoded_events = receipts.iter() .rev() - .filter(|r| &bloom & &r.log_bloom == bloom) + .filter(|r| r.log_bloom.contains_bloom(&bloom)) .flat_map(|r| r.logs.iter()) .filter(move |l| check_log(l)) .filter_map(|log| { - let topics = log.topics.iter().map(|x| x.0.clone()).collect(); - event.decode_log(topics, log.data.clone()).ok() + event.parse_log((log.topics.clone(), log.data.clone()).into()).ok() }); + // only last log is taken into account match decoded_events.next() { None => None, - Some(matched_event) => { - - // decode log manually until the native contract generator is - // good enough to do it for us. - let validators_token = &matched_event[1].value; - - let validators = validators_token.clone().to_array() - .and_then(|a| a.into_iter() - .map(|x| x.to_address().map(H160)) - .collect::>>() - ) - .map(SimpleList::new); - - if validators.is_none() { - debug!(target: "engine", "Successfully decoded log turned out to be bad."); - } - - trace!(target: "engine", "decoded log. validators: {:?}", validators); - - validators - } + Some(matched_event) => Some(SimpleList::new(matched_event.new_set)) } } } @@ -229,35 +289,46 @@ 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()) - .and_then(|c| c.call_contract(id, addr, data)) + .ok_or_else(|| "No client!".into()) + .and_then(|c| { + match c.as_full_client() { + Some(c) => c.call_contract(id, addr, data), + None => Err("No full client!".into()), + } + }) .map(|out| (out, Vec::new()))) // generate no proofs in general } fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> { - self.provider.finalize_change(caller) - .wait() + let data = self.provider.functions().finalize_change().input(); + caller(self.contract_address, data) + .map(|_| ()) .map_err(::engines::EngineError::FailedSystemCall) .map_err(Into::into) } fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result, String> { - prove_initial(&self.provider, header, call) + prove_initial(&self.provider, self.contract_address, header, call) } fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option> { None // no immediate transitions to contract. } - fn signals_epoch_end(&self, first: bool, header: &Header, _block: Option<&[u8]>, receipts: Option<&[Receipt]>) - -> ::engines::EpochChange + fn signals_epoch_end(&self, first: bool, header: &Header, aux: AuxiliaryData) + -> ::engines::EpochChange { + let receipts = aux.receipts; + // transition to the first block of a contract requires finality but has no log event. if first { debug!(target: "engine", "signalling transition to fresh contract."); - let (provider, header) = (self.provider.clone(), header.clone()); - let with_caller: Box _> = Box::new(move |caller| prove_initial(&provider, &header, caller)); - return ::engines::EpochChange::Yes(::engines::Proof::WithState(with_caller)) + let state_proof = Arc::new(StateProof { + contract_address: self.contract_address, + header: Mutex::new(header.clone()), + provider: validator_set::ValidatorSet::default(), + }); + return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>)); } // otherwise, we're checking for logs. @@ -269,7 +340,7 @@ impl ValidatorSet for ValidatorSafeContract { trace!(target: "engine", "detected epoch change event bloom"); match receipts { - None => ::engines::EpochChange::Unsure(::engines::Unsure::NeedsReceipts), + None => ::engines::EpochChange::Unsure(AuxiliaryRequest::Receipts), Some(receipts) => match self.extract_from_event(bloom, header, receipts) { None => ::engines::EpochChange::No, Some(list) => { @@ -283,64 +354,19 @@ impl ValidatorSet for ValidatorSafeContract { } } - fn epoch_set(&self, first: bool, engine: &Engine, _number: ::header::BlockNumber, proof: &[u8]) + fn epoch_set(&self, first: bool, machine: &EthereumMachine, _number: ::header::BlockNumber, proof: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { - use transaction::{Action, Transaction}; - let rlp = UntrustedRlp::new(proof); if first { trace!(target: "engine", "Recovering initial epoch set"); - // TODO: match client contract_call_tx more cleanly without duplication. - const PROVIDED_GAS: u64 = 50_000_000; - let (old_header, state_items) = decode_first_proof(&rlp)?; - let old_hash = old_header.hash(); - - let env_info = ::vm::EnvInfo { - number: old_header.number(), - author: *old_header.author(), - difficulty: *old_header.difficulty(), - gas_limit: PROVIDED_GAS.into(), - timestamp: old_header.timestamp(), - last_hashes: { - // this will break if we don't inclue all 256 last hashes. - let mut last_hashes: Vec<_> = (0..256).map(|_| H256::default()).collect(); - last_hashes[255] = *old_header.parent_hash(); - Arc::new(last_hashes) - }, - gas_used: 0.into(), - }; - - // check state proof using given engine. let number = old_header.number(); - let addresses = self.provider.get_validators(move |a, d| { - let from = Address::default(); - let tx = Transaction { - nonce: engine.account_start_nonce(number), - action: Action::Call(a), - gas: PROVIDED_GAS.into(), - gas_price: U256::default(), - value: U256::default(), - data: d, - }.fake_sign(from); - - let res = ::state::check_proof( - &state_items, - *old_header.state_root(), - &tx, - engine, - &env_info, - ); - - match res { - ::state::ProvedExecution::BadProof => Err("Bad proof".into()), - ::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)), - ::state::ProvedExecution::Complete(e) => Ok(e.output), - } - }).wait().map_err(::engines::EngineError::InsufficientProof)?; + let old_hash = old_header.hash(); + let addresses = check_first_proof(machine, &self.provider, self.contract_address, old_header, &state_items) + .map_err(::engines::EngineError::InsufficientProof)?; trace!(target: "engine", "extracted epoch set at #{}: {} addresses", number, addresses.len()); @@ -351,8 +377,8 @@ impl ValidatorSet for ValidatorSafeContract { // ensure receipts match header. // TODO: optimize? these were just decoded. - let found_root = ::util::triehash::ordered_trie_root( - receipts.iter().map(::rlp::encode).map(|x| x.to_vec()) + let found_root = ::triehash::ordered_trie_root( + receipts.iter().map(::rlp::encode) ); if found_root != *old_header.receipts_root() { return Err(::error::BlockError::InvalidReceiptsRoot( @@ -414,7 +440,7 @@ impl ValidatorSet for ValidatorSafeContract { })) } - fn register_contract(&self, client: Weak) { + fn register_client(&self, client: Weak) { trace!(target: "engine", "Setting up contract caller."); *self.client.write() = Some(client); } @@ -424,12 +450,13 @@ impl ValidatorSet for ValidatorSafeContract { mod tests { use std::sync::Arc; use rustc_hex::FromHex; - use util::*; + use hash::keccak; + use ethereum_types::Address; use types::ids::BlockId; use spec::Spec; use account_provider::AccountProvider; use transaction::{Transaction, Action}; - use client::{BlockChainClient, EngineClient}; + use client::{ChainInfo, BlockInfo, ImportBlock}; use ethkey::Secret; use miner::MinerService; use tests::helpers::{generate_dummy_client_with_spec_and_accounts, generate_dummy_client_with_spec_and_data}; @@ -440,7 +467,7 @@ mod tests { fn fetches_validators() { let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); let vc = Arc::new(ValidatorSafeContract::new("0000000000000000000000000000000000000005".parse::
().unwrap())); - vc.register_contract(Arc::downgrade(&client)); + vc.register_client(Arc::downgrade(&client) as _); let last_hash = client.best_block_header().hash(); assert!(vc.contains(&last_hash, &"7d577a597b2742b498cb5cf0c26cdcd726d39e6e".parse::
().unwrap())); assert!(vc.contains(&last_hash, &"82a978b3f5962a5b0957d9ee9eef472ee55b42f1".parse::
().unwrap())); @@ -449,12 +476,12 @@ mod tests { #[test] fn knows_validators() { let tap = Arc::new(AccountProvider::transient_provider()); - let s0: Secret = "1".sha3().into(); + let s0: Secret = keccak("1").into(); let v0 = tap.insert_account(s0.clone(), "").unwrap(); - let v1 = tap.insert_account("0".sha3().into(), "").unwrap(); + let v1 = tap.insert_account(keccak("0").into(), "").unwrap(); let chain_id = Spec::new_validator_safe_contract().chain_id(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap)); - client.engine().register_client(Arc::downgrade(&client)); + client.engine().register_client(Arc::downgrade(&client) as _); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); client.miner().set_engine_signer(v1, "".into()).unwrap(); @@ -468,7 +495,7 @@ mod tests { data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); // Add "1" validator back in. let tx = Transaction { @@ -480,13 +507,13 @@ mod tests { data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); // The transaction is not yet included so still unable to seal. assert_eq!(client.chain_info().best_block_number, 1); // Switch to the validator that is still there. client.miner().set_engine_signer(v0, "".into()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // Switch back to the added validator, since the state is updated. client.miner().set_engine_signer(v1, "".into()).unwrap(); @@ -499,13 +526,13 @@ mod tests { data: Vec::new(), }.sign(&s0, Some(chain_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); - client.update_sealing(); + ::client::EngineClient::update_sealing(&*client); // Able to seal again. assert_eq!(client.chain_info().best_block_number, 3); // Check syncing. let sync_client = generate_dummy_client_with_spec_and_data(Spec::new_validator_safe_contract, 0, 0, &[]); - sync_client.engine().register_client(Arc::downgrade(&sync_client)); + sync_client.engine().register_client(Arc::downgrade(&sync_client) as _); for i in 1..4 { sync_client.import_block(client.block(BlockId::Number(i)).unwrap().into_inner()).unwrap(); } @@ -516,7 +543,8 @@ mod tests { #[test] fn detects_bloom() { use header::Header; - use engines::{EpochChange, Unsure}; + use engines::EpochChange; + use machine::AuxiliaryRequest; use log_entry::LogEntry; let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, None); @@ -536,7 +564,7 @@ mod tests { }; new_header.set_log_bloom(event.bloom()); - match engine.signals_epoch_end(&new_header, None, None) { + match engine.signals_epoch_end(&new_header, Default::default()) { EpochChange::No => {}, _ => panic!("Expected bloom to be unrecognized."), }; @@ -545,8 +573,8 @@ mod tests { event.topics.push(last_hash); new_header.set_log_bloom(event.bloom()); - match engine.signals_epoch_end(&new_header, None, None) { - EpochChange::Unsure(Unsure::NeedsReceipts) => {}, + match engine.signals_epoch_end(&new_header, Default::default()) { + EpochChange::Unsure(AuxiliaryRequest::Receipts) => {}, _ => panic!("Expected bloom to be recognized."), }; } @@ -562,7 +590,7 @@ mod tests { let mut new_header = Header::default(); new_header.set_number(0); // so the validator set doesn't look for a log - match engine.signals_epoch_end(&new_header, None, None) { + match engine.signals_epoch_end(&new_header, Default::default()) { EpochChange::Yes(Proof::WithState(_)) => {}, _ => panic!("Expected state to be required to prove initial signal"), }; diff --git a/ethcore/src/engines/validator_set/simple_list.rs b/ethcore/src/engines/validator_set/simple_list.rs index 8b8d1942d5441da1ee12b9be85d3aca81f7dfeb4..bb67c9778bf2606fefa3daa8ce5ff4e48873d40b 100644 --- a/ethcore/src/engines/validator_set/simple_list.rs +++ b/ethcore/src/engines/validator_set/simple_list.rs @@ -16,9 +16,10 @@ /// Preconfigured validator list. -use util::{H256, Address, HeapSizeOf}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, Address}; -use engines::{Call, Engine}; +use machine::{AuxiliaryData, Call, EthereumMachine}; use header::{BlockNumber, Header}; use super::ValidatorSet; @@ -74,13 +75,13 @@ impl ValidatorSet for SimpleList { } } - fn signals_epoch_end(&self, _: bool, _: &Header, _: Option<&[u8]>, _: Option<&[::receipt::Receipt]>) - -> ::engines::EpochChange + fn signals_epoch_end(&self, _: bool, _: &Header, _: AuxiliaryData) + -> ::engines::EpochChange { ::engines::EpochChange::No } - fn epoch_set(&self, _first: bool, _: &Engine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { + fn epoch_set(&self, _first: bool, _: &EthereumMachine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { Ok((self.clone(), None)) } @@ -106,7 +107,7 @@ impl ValidatorSet for SimpleList { #[cfg(test)] mod tests { use std::str::FromStr; - use util::Address; + use ethereum_types::Address; use super::super::ValidatorSet; use super::SimpleList; diff --git a/ethcore/src/engines/validator_set/test.rs b/ethcore/src/engines/validator_set/test.rs index 25eeff66e66cbcb75b742cafaf990351b2e0b965..a6b89304544f336e39d63720d73d1b5decb94f5e 100644 --- a/ethcore/src/engines/validator_set/test.rs +++ b/ethcore/src/engines/validator_set/test.rs @@ -19,9 +19,11 @@ use std::str::FromStr; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; -use util::{Bytes, H256, Address, HeapSizeOf}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, Address}; +use bytes::Bytes; -use engines::{Call, Engine}; +use machine::{AuxiliaryData, Call, EthereumMachine}; use header::{Header, BlockNumber}; use super::{ValidatorSet, SimpleList}; @@ -55,13 +57,13 @@ impl ValidatorSet for TestSet { fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option> { None } - fn signals_epoch_end(&self, _: bool, _: &Header, _: Option<&[u8]>, _: Option<&[::receipt::Receipt]>) - -> ::engines::EpochChange + fn signals_epoch_end(&self, _: bool, _: &Header, _: AuxiliaryData) + -> ::engines::EpochChange { ::engines::EpochChange::No } - fn epoch_set(&self, _: bool, _: &Engine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { + fn epoch_set(&self, _: bool, _: &EthereumMachine, _: BlockNumber, _: &[u8]) -> Result<(SimpleList, Option), ::error::Error> { Ok((self.validator.clone(), None)) } diff --git a/ethcore/src/engines/vote_collector.rs b/ethcore/src/engines/vote_collector.rs index b934fdb2ebff182ef90ccc0bb1e27ca3aaa2ef07..7af66b30c5d27e91d50b821401ae02e6e3757d63 100644 --- a/ethcore/src/engines/vote_collector.rs +++ b/ethcore/src/engines/vote_collector.rs @@ -19,7 +19,9 @@ use std::fmt::Debug; use std::collections::{BTreeMap, HashSet, HashMap}; use std::hash::Hash; -use util::*; +use ethereum_types::{H256, H520, Address}; +use parking_lot:: RwLock; +use bytes::Bytes; use rlp::{Encodable, RlpStream}; pub trait Message: Clone + PartialEq + Eq + Hash + Encodable + Debug { @@ -43,18 +45,18 @@ pub struct VoteCollector { #[derive(Debug, Default)] struct StepCollector { voted: HashMap, - pub block_votes: HashMap, HashMap>, + block_votes: HashMap, HashMap>, messages: HashSet, } #[derive(Debug)] -pub struct DoubleVote<'a, M: Message> { - pub author: &'a Address, +pub struct DoubleVote { + author: Address, vote_one: M, vote_two: M, } -impl<'a, M: Message> Encodable for DoubleVote<'a, M> { +impl Encodable for DoubleVote { fn rlp_append(&self, s: &mut RlpStream) { s.begin_list(2) .append(&self.vote_one) @@ -64,10 +66,10 @@ impl<'a, M: Message> Encodable for DoubleVote<'a, M> { impl StepCollector { /// Returns Some(&Address) when validator is double voting. - fn insert<'a>(&mut self, message: M, address: &'a Address) -> Option> { + fn insert(&mut self, message: M, address: Address) -> Option> { // Do nothing when message was seen. if self.messages.insert(message.clone()) { - if let Some(previous) = self.voted.insert(address.clone(), message.clone()) { + if let Some(previous) = self.voted.insert(address, message.clone()) { // Bad validator sent a different message. return Some(DoubleVote { author: address, @@ -79,7 +81,7 @@ impl StepCollector { .block_votes .entry(message.block_hash()) .or_insert_with(HashMap::new) - .insert(message.signature(), address.clone()); + .insert(message.signature(), address); } } None @@ -122,7 +124,7 @@ impl Default for VoteCollector { impl VoteCollector { /// Insert vote if it is newer than the oldest one. - pub fn vote<'a>(&self, message: M, voter: &'a Address) -> Option> { + pub fn vote(&self, message: M, voter: Address) -> Option> { self .votes .write() @@ -196,17 +198,12 @@ impl VoteCollector { let guard = self.votes.read(); guard.get(&message.round()).and_then(|c| c.block_votes.get(&message.block_hash())).and_then(|origins| origins.get(&message.signature()).cloned()) } - - /// Count the number of total rounds kept track of. - #[cfg(test)] - pub fn len(&self) -> usize { - self.votes.read().len() - } } #[cfg(test)] mod tests { - use util::*; + use hash::keccak; + use ethereum_types::{H160, H256}; use rlp::*; use super::*; @@ -241,17 +238,17 @@ mod tests { } fn random_vote(collector: &VoteCollector, signature: H520, step: TestStep, block_hash: Option) -> bool { - full_vote(collector, signature, step, block_hash, &H160::random()) + full_vote(collector, signature, step, block_hash, H160::random()) } - fn full_vote<'a>(collector: &VoteCollector, signature: H520, step: TestStep, block_hash: Option, address: &'a Address) -> bool { + fn full_vote(collector: &VoteCollector, signature: H520, step: TestStep, block_hash: Option, address: Address) -> bool { collector.vote(TestMessage { signature: signature, step: step, block_hash: block_hash }, address).is_none() } #[test] fn seal_retrieval() { let collector = VoteCollector::default(); - let bh = Some("1".sha3()); + let bh = Some(keccak("1")); let mut signatures = Vec::new(); for _ in 0..5 { signatures.push(H520::random()); @@ -263,9 +260,9 @@ mod tests { // Good proposal random_vote(&collector, signatures[0].clone(), propose_round.clone(), bh.clone()); // Wrong block proposal. - random_vote(&collector, signatures[0].clone(), propose_round.clone(), Some("0".sha3())); + random_vote(&collector, signatures[0].clone(), propose_round.clone(), Some(keccak("0"))); // Wrong block commit. - random_vote(&collector, signatures[3].clone(), commit_round.clone(), Some("0".sha3())); + random_vote(&collector, signatures[3].clone(), commit_round.clone(), Some(keccak("0"))); // Wrong round. random_vote(&collector, signatures[0].clone(), 6, bh.clone()); // Wrong round. @@ -291,22 +288,22 @@ mod tests { let round1 = 1; let round3 = 3; // good 1 - random_vote(&collector, H520::random(), round1, Some("0".sha3())); - random_vote(&collector, H520::random(), 0, Some("0".sha3())); + random_vote(&collector, H520::random(), round1, Some(keccak("0"))); + random_vote(&collector, H520::random(), 0, Some(keccak("0"))); // good 3 - random_vote(&collector, H520::random(), round3, Some("0".sha3())); - random_vote(&collector, H520::random(), 2, Some("0".sha3())); + random_vote(&collector, H520::random(), round3, Some(keccak("0"))); + random_vote(&collector, H520::random(), 2, Some(keccak("0"))); // good prevote - random_vote(&collector, H520::random(), round1, Some("1".sha3())); + random_vote(&collector, H520::random(), round1, Some(keccak("1"))); // good prevote let same_sig = H520::random(); - random_vote(&collector, same_sig.clone(), round1, Some("1".sha3())); - random_vote(&collector, same_sig, round1, Some("1".sha3())); + random_vote(&collector, same_sig.clone(), round1, Some(keccak("1"))); + random_vote(&collector, same_sig, round1, Some(keccak("1"))); // good precommit - random_vote(&collector, H520::random(), round3, Some("1".sha3())); + random_vote(&collector, H520::random(), round3, Some(keccak("1"))); // good prevote - random_vote(&collector, H520::random(), round1, Some("0".sha3())); - random_vote(&collector, H520::random(), 4, Some("2".sha3())); + random_vote(&collector, H520::random(), round1, Some(keccak("0"))); + random_vote(&collector, H520::random(), 4, Some(keccak("2"))); assert_eq!(collector.count_round_votes(&round1), 4); assert_eq!(collector.count_round_votes(&round3), 2); @@ -314,7 +311,7 @@ mod tests { let message = TestMessage { signature: H520::default(), step: round1, - block_hash: Some("1".sha3()) + block_hash: Some(keccak("1")) }; assert_eq!(collector.count_aligned_votes(&message), 2); } @@ -325,14 +322,18 @@ mod tests { let vote = |round, hash| { random_vote(&collector, H520::random(), round, hash); }; - vote(6, Some("0".sha3())); - vote(3, Some("0".sha3())); - vote(7, Some("0".sha3())); - vote(8, Some("1".sha3())); - vote(1, Some("1".sha3())); + vote(6, Some(keccak("0"))); + vote(3, Some(keccak("0"))); + vote(7, Some(keccak("0"))); + vote(8, Some(keccak("1"))); + vote(1, Some(keccak("1"))); collector.throw_out_old(&7); - assert_eq!(collector.len(), 2); + assert_eq!(collector.count_round_votes(&1), 0); + assert_eq!(collector.count_round_votes(&3), 0); + assert_eq!(collector.count_round_votes(&6), 0); + assert_eq!(collector.count_round_votes(&7), 1); + assert_eq!(collector.count_round_votes(&8), 1); } #[test] @@ -340,9 +341,9 @@ mod tests { let collector = VoteCollector::default(); let round = 3; // Vote is inserted fine. - assert!(full_vote(&collector, H520::random(), round, Some("0".sha3()), &Address::default())); + assert!(full_vote(&collector, H520::random(), round, Some(keccak("0")), Address::default())); // Returns the double voting address. - assert!(!full_vote(&collector, H520::random(), round, Some("1".sha3()), &Address::default())); + assert!(!full_vote(&collector, H520::random(), round, Some(keccak("1")), Address::default())); assert_eq!(collector.count_round_votes(&round), 1); } } diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 172323c0da4eb4a56841121ca86a6eadd82a2960..dd4cf498673eef5bd4d27d3d737884792a4d7e8d 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -17,99 +17,23 @@ //! General error types for use in ethcore. use std::fmt; -use util::*; +use kvdb; +use ethereum_types::{H256, U256, Address, Bloom}; +use util_error::UtilError; +use snappy::InvalidInput; +use unexpected::{Mismatch, OutOfBounds}; +use trie::TrieError; use io::*; use header::BlockNumber; -use basic_types::LogBloom; use client::Error as ClientError; -use ipc::binary::{BinaryConvertError, BinaryConvertable}; use snapshot::Error as SnapshotError; use engines::EngineError; use ethkey::Error as EthkeyError; use account_provider::SignError as AccountsError; +use transaction::Error as TransactionError; pub use executed::{ExecutionError, CallError}; -#[derive(Debug, PartialEq, Clone, Copy)] -/// Errors concerning transaction processing. -pub enum TransactionError { - /// Transaction is already imported to the queue - AlreadyImported, - /// Transaction is not valid anymore (state already has higher nonce) - Old, - /// Transaction has too low fee - /// (there is already a transaction with the same sender-nonce but higher gas price) - TooCheapToReplace, - /// Transaction was not imported to the queue because limit has been reached. - LimitReached, - /// Transaction's gas price is below threshold. - InsufficientGasPrice { - /// Minimal expected gas price - minimal: U256, - /// Transaction gas price - got: U256, - }, - /// Transaction's gas is below currently set minimal gas requirement. - InsufficientGas { - /// Minimal expected gas - minimal: U256, - /// Transaction gas - got: U256, - }, - /// Sender doesn't have enough funds to pay for this transaction - InsufficientBalance { - /// Senders balance - balance: U256, - /// Transaction cost - cost: U256, - }, - /// Transactions gas is higher then current gas limit - GasLimitExceeded { - /// Current gas limit - limit: U256, - /// Declared transaction gas - got: U256, - }, - /// Transaction's gas limit (aka gas) is invalid. - InvalidGasLimit(OutOfBounds), - /// Transaction sender is banned. - SenderBanned, - /// Transaction receipient is banned. - RecipientBanned, - /// Contract creation code is banned. - CodeBanned, - /// Invalid chain ID given. - InvalidChainId, -} - -impl fmt::Display for TransactionError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use self::TransactionError::*; - let msg = match *self { - AlreadyImported => "Already imported".into(), - Old => "No longer valid".into(), - TooCheapToReplace => "Gas price too low to replace".into(), - LimitReached => "Transaction limit reached".into(), - InsufficientGasPrice { minimal, got } => - format!("Insufficient gas price. Min={}, Given={}", minimal, got), - InsufficientGas { minimal, got } => - format!("Insufficient gas. Min={}, Given={}", minimal, got), - InsufficientBalance { balance, cost } => - format!("Insufficient balance for transaction. Balance={}, Cost={}", - balance, cost), - GasLimitExceeded { limit, got } => - format!("Gas limit exceeded. Limit={}, Given={}", limit, got), - InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), - SenderBanned => "Sender is temporarily banned.".into(), - RecipientBanned => "Recipient is temporarily banned.".into(), - CodeBanned => "Contract code is temporarily banned.".into(), - InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), - }; - - f.write_fmt(format_args!("Transaction error ({})", msg)) - } -} - #[derive(Debug, PartialEq, Clone, Copy, Eq)] /// Errors concerning block processing. pub enum BlockError { @@ -158,8 +82,10 @@ pub enum BlockError { InvalidReceiptsRoot(Mismatch), /// Timestamp header field is invalid. InvalidTimestamp(OutOfBounds), + /// Timestamp header field is too far in future. + TemporarilyInvalid(OutOfBounds), /// Log bloom header field is invalid. - InvalidLogBloom(Mismatch), + InvalidLogBloom(Mismatch), /// Parent hash field of header is invalid; this is an invalid error indicating a logic flaw in the codebase. /// TODO: remove and favour an assert!/panic!. InvalidParentHash(Mismatch), @@ -203,6 +129,7 @@ impl fmt::Display for BlockError { InvalidGasLimit(ref oob) => format!("Invalid gas limit: {}", oob), InvalidReceiptsRoot(ref mis) => format!("Invalid receipts trie root in header: {}", mis), InvalidTimestamp(ref oob) => format!("Invalid timestamp in header: {}", oob), + TemporarilyInvalid(ref oob) => format!("Future timestamp in header: {}", oob), InvalidLogBloom(ref oob) => format!("Invalid log bloom in header: {}", oob), InvalidParentHash(ref mis) => format!("Invalid parent hash: {}", mis), InvalidNumber(ref mis) => format!("Invalid number in header: {}", mis), @@ -260,15 +187,6 @@ impl From for BlockImportError { } } -/// Represents the result of importing transaction. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum TransactionImportResult { - /// Transaction was imported to current queue. - Current, - /// Transaction was imported to future queue. - Future -} - /// Api-level error for transaction import #[derive(Debug, Clone)] pub enum TransactionImportError { @@ -292,6 +210,8 @@ impl From for TransactionImportError { pub enum Error { /// Client configuration error. Client(ClientError), + /// Database error. + Database(kvdb::Error), /// Error concerning a utility. Util(UtilError), /// Error concerning block processing. @@ -315,7 +235,7 @@ pub enum Error { /// Standard io error. StdIo(::std::io::Error), /// Snappy error. - Snappy(::util::snappy::InvalidInput), + Snappy(InvalidInput), /// Snapshot error. Snapshot(SnapshotError), /// Consensus vote error. @@ -330,6 +250,7 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Client(ref err) => err.fmt(f), + Error::Database(ref err) => err.fmt(f), Error::Util(ref err) => err.fmt(f), Error::Io(ref err) => err.fmt(f), Error::Block(ref err) => err.fmt(f), @@ -363,6 +284,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: kvdb::Error) -> Error { + Error::Database(err) + } +} + impl From for Error { fn from(err: TransactionError) -> Error { Error::Transaction(err) @@ -389,7 +316,7 @@ impl From for Error { impl From<::rlp::DecoderError> for Error { fn from(err: ::rlp::DecoderError) -> Error { - Error::Util(UtilError::Decoder(err)) + Error::Util(UtilError::from(err)) } } @@ -422,13 +349,13 @@ impl From for Error { match err { BlockImportError::Block(e) => Error::Block(e), BlockImportError::Import(e) => Error::Import(e), - BlockImportError::Other(s) => Error::Util(UtilError::SimpleString(s)), + BlockImportError::Other(s) => Error::Util(UtilError::from(s)), } } } -impl From for Error { - fn from(err: snappy::InvalidInput) -> Error { +impl From<::snappy::InvalidInput> for Error { + fn from(err: ::snappy::InvalidInput) -> Error { Error::Snappy(err) } } @@ -467,21 +394,3 @@ impl From> for Error where Error: From { Error::from(*err) } } - -binary_fixed_size!(BlockError); -binary_fixed_size!(ImportError); -binary_fixed_size!(TransactionError); - -// TODO: uncomment below once https://github.com/rust-lang/rust/issues/27336 sorted. -/*#![feature(concat_idents)] -macro_rules! assimilate { - ($name:ident) => ( - impl From for Error { - fn from(err: concat_idents!($name, Error)) -> Error { - Error:: $name (err) - } - } - ) -} -assimilate!(FromHex); -assimilate!(BaseData);*/ diff --git a/ethcore/src/ethereum/denominations.rs b/ethcore/src/ethereum/denominations.rs index 789c803b965c0a984511640ec12c78f31c95e319..4892770df1e9dc3324e8a58485719810040888e5 100644 --- a/ethcore/src/ethereum/denominations.rs +++ b/ethcore/src/ethereum/denominations.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::*; +use ethereum_types::U256; #[inline] /// 1 Ether in Wei diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index fc7b274031213995d63e91ce6fe20076c4467ac1..68a07d0cda30f552e7fd6dea06f54a0dc2653889 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -16,26 +16,19 @@ use std::path::Path; use std::cmp; -use std::collections::{BTreeMap, HashMap}; +use std::collections::BTreeMap; use std::sync::Arc; -use ethash::{quick_get_difficulty, slow_get_seedhash, EthashManager}; -use util::*; +use hash::{KECCAK_EMPTY_LIST_RLP}; +use ethash::{quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor}; +use ethereum_types::{H256, H64, U256, Address}; +use unexpected::{OutOfBounds, Mismatch}; use block::*; -use builtin::Builtin; -use vm::EnvInfo; -use error::{BlockError, Error, TransactionError}; +use error::{BlockError, Error}; use header::{Header, BlockNumber}; -use state::CleanupMode; -use spec::CommonParams; -use transaction::UnverifiedTransaction; use engines::{self, Engine}; -use evm::Schedule; use ethjson; -use rlp::{self, UntrustedRlp}; -use vm::LastHashes; - -/// Parity tries to round block.gas_limit to multiple of this constant -pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); +use rlp::UntrustedRlp; +use machine::EthereumMachine; /// Number of blocks in an ethash snapshot. // make dependent on difficulty incrment divisor? @@ -43,6 +36,39 @@ const SNAPSHOT_BLOCKS: u64 = 5000; /// Maximum number of blocks allowed in an ethash snapshot. const MAX_SNAPSHOT_BLOCKS: u64 = 30000; +const DEFAULT_EIP649_DELAY: u64 = 3_000_000; + +/// Ethash specific seal +#[derive(Debug, PartialEq)] +pub struct Seal { + /// Ethash seal mix_hash + pub mix_hash: H256, + /// Ethash seal nonce + pub nonce: H64, +} + +impl Seal { + /// Tries to parse rlp as ethash seal. + pub fn parse_seal>(seal: &[T]) -> Result { + if seal.len() != 2 { + return Err(BlockError::InvalidSealArity( + Mismatch { + expected: 2, + found: seal.len() + } + ).into()); + } + + let mix_hash = UntrustedRlp::new(seal[0].as_ref()).as_val::()?; + let nonce = UntrustedRlp::new(seal[1].as_ref()).as_val::()?; + let seal = Seal { + mix_hash, + nonce, + }; + + Ok(seal) + } +} /// Ethash params. #[derive(Debug, PartialEq)] @@ -59,12 +85,6 @@ pub struct EthashParams { pub duration_limit: u64, /// Homestead transition block number. pub homestead_transition: u64, - /// DAO hard-fork transition block (X). - pub dao_hardfork_transition: u64, - /// DAO hard-fork refund contract address (C). - pub dao_hardfork_beneficiary: Address, - /// DAO hard-fork DAO accounts list (L) - pub dao_hardfork_accounts: Vec
, /// Transition block for a change of difficulty params (currently just bound_divisor). pub difficulty_hardfork_transition: u64, /// Difficulty param after the difficulty transition. @@ -73,30 +93,36 @@ pub struct EthashParams { pub bomb_defuse_transition: u64, /// Number of first block where EIP-100 rules begin. pub eip100b_transition: u64, - /// Number of first block where EIP-150 rules begin. - pub eip150_transition: u64, - /// Number of first block where EIP-160 rules begin. - pub eip160_transition: u64, - /// Number of first block where EIP-161.abc begin. - pub eip161abc_transition: u64, - /// Number of first block where EIP-161.d begins. - pub eip161d_transition: u64, /// Number of first block where ECIP-1010 begins. pub ecip1010_pause_transition: u64, /// Number of first block where ECIP-1010 ends. pub ecip1010_continue_transition: u64, /// Total block number for one ECIP-1017 era. pub ecip1017_era_rounds: u64, - /// Maximum amount of code that can be deploying into a contract. - pub max_code_size: u64, - /// Number of first block where the max gas limit becomes effective. - pub max_gas_limit_transition: u64, - /// Maximum valid block gas limit, - pub max_gas_limit: U256, - /// Number of first block where the minimum gas price becomes effective. - pub min_gas_price_transition: u64, - /// Do not alow transactions with lower gas price. - pub min_gas_price: U256, + /// Number of first block where MCIP-3 begins. + pub mcip3_transition: u64, + /// MCIP-3 Block reward coin-base for miners. + pub mcip3_miner_reward: U256, + /// MCIP-3 Block reward ubi-base for basic income. + pub mcip3_ubi_reward: U256, + /// MCIP-3 contract address for universal basic income. + pub mcip3_ubi_contract: Address, + /// MCIP-3 Block reward dev-base for dev funds. + pub mcip3_dev_reward: U256, + /// MCIP-3 contract address for the developer funds. + pub mcip3_dev_contract: Address, + /// Block reward in base units. + pub block_reward: U256, + /// EIP-649 transition block. + pub eip649_transition: u64, + /// EIP-649 bomb delay. + pub eip649_delay: u64, + /// EIP-649 base reward. + pub eip649_reward: Option, + /// EXPIP-2 block height + pub expip2_transition: u64, + /// EXPIP-2 duration limit + pub expip2_duration_limit: u64, } impl From for EthashParams { @@ -108,25 +134,25 @@ impl From for EthashParams { metropolis_difficulty_increment_divisor: p.metropolis_difficulty_increment_divisor.map_or(9, Into::into), duration_limit: p.duration_limit.map_or(0, Into::into), homestead_transition: p.homestead_transition.map_or(0, Into::into), - dao_hardfork_transition: p.dao_hardfork_transition.map_or(u64::max_value(), Into::into), - dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map_or_else(Address::new, Into::into), - dao_hardfork_accounts: p.dao_hardfork_accounts.unwrap_or_else(Vec::new).into_iter().map(Into::into).collect(), difficulty_hardfork_transition: p.difficulty_hardfork_transition.map_or(u64::max_value(), Into::into), difficulty_hardfork_bound_divisor: p.difficulty_hardfork_bound_divisor.map_or(p.difficulty_bound_divisor.into(), Into::into), bomb_defuse_transition: p.bomb_defuse_transition.map_or(u64::max_value(), Into::into), eip100b_transition: p.eip100b_transition.map_or(u64::max_value(), Into::into), - eip150_transition: p.eip150_transition.map_or(0, Into::into), - eip160_transition: p.eip160_transition.map_or(0, Into::into), - eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into), - eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into), ecip1010_pause_transition: p.ecip1010_pause_transition.map_or(u64::max_value(), Into::into), ecip1010_continue_transition: p.ecip1010_continue_transition.map_or(u64::max_value(), Into::into), ecip1017_era_rounds: p.ecip1017_era_rounds.map_or(u64::max_value(), Into::into), - max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), - max_gas_limit_transition: p.max_gas_limit_transition.map_or(u64::max_value(), Into::into), - max_gas_limit: p.max_gas_limit.map_or(U256::max_value(), Into::into), - min_gas_price_transition: p.min_gas_price_transition.map_or(u64::max_value(), Into::into), - min_gas_price: p.min_gas_price.map_or(U256::zero(), Into::into), + mcip3_transition: p.mcip3_transition.map_or(u64::max_value(), Into::into), + mcip3_miner_reward: p.mcip3_miner_reward.map_or_else(Default::default, Into::into), + mcip3_ubi_reward: p.mcip3_ubi_reward.map_or(U256::from(0), Into::into), + mcip3_ubi_contract: p.mcip3_ubi_contract.map_or_else(Address::new, Into::into), + mcip3_dev_reward: p.mcip3_dev_reward.map_or(U256::from(0), Into::into), + mcip3_dev_contract: p.mcip3_dev_contract.map_or_else(Address::new, Into::into), + block_reward: p.block_reward.map_or_else(Default::default, Into::into), + eip649_transition: p.eip649_transition.map_or(u64::max_value(), Into::into), + eip649_delay: p.eip649_delay.map_or(DEFAULT_EIP649_DELAY, Into::into), + eip649_reward: p.eip649_reward.map(Into::into), + expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into), + expip2_duration_limit: p.expip2_duration_limit.map_or(30, Into::into), } } } @@ -134,25 +160,23 @@ impl From for EthashParams { /// Engine using Ethash proof-of-work consensus algorithm, suitable for Ethereum /// mainnet chains in the Olympic, Frontier and Homestead eras. pub struct Ethash { - params: CommonParams, ethash_params: EthashParams, - builtins: BTreeMap, pow: EthashManager, + machine: EthereumMachine, } impl Ethash { /// Create a new instance of Ethash engine - pub fn new>( - cache_dir: T, - params: CommonParams, + pub fn new>>( + cache_dir: &Path, ethash_params: EthashParams, - builtins: BTreeMap, + machine: EthereumMachine, + optimize_for: T, ) -> Arc { Arc::new(Ethash { - params, ethash_params, - builtins, - pow: EthashManager::new(cache_dir), + machine, + pow: EthashManager::new(cache_dir.as_ref(), optimize_for.into()), }) } } @@ -165,170 +189,114 @@ impl Ethash { // for any block in the chain. // in the future, we might move the Ethash epoch // caching onto this mechanism as well. -impl engines::EpochVerifier for Arc { +impl engines::EpochVerifier for Arc { fn verify_light(&self, _header: &Header) -> Result<(), Error> { Ok(()) } fn verify_heavy(&self, header: &Header) -> Result<(), Error> { - self.verify_block_unordered(header, None) + self.verify_block_unordered(header) } } -impl Engine for Arc { +impl Engine for Arc { fn name(&self) -> &str { "Ethash" } - fn version(&self) -> SemanticVersion { SemanticVersion::new(1, 0, 0) } - // Two fields - mix - fn seal_fields(&self) -> usize { 2 } - - fn params(&self) -> &CommonParams { &self.params } - fn additional_params(&self) -> HashMap { hash_map!["registrar".to_owned() => self.params().registrar.hex()] } + fn machine(&self) -> &EthereumMachine { &self.machine } - fn builtins(&self) -> &BTreeMap { - &self.builtins - } + // Two fields - nonce and mix. + fn seal_fields(&self, _header: &Header) -> usize { 2 } /// Additional engine-specific information for the user/developer concerning `header`. fn extra_info(&self, header: &Header) -> BTreeMap { - if header.seal().len() == self.seal_fields() { - map![ - "nonce".to_owned() => format!("0x{}", header.nonce().hex()), - "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex()) - ] - } else { - BTreeMap::default() + match Seal::parse_seal(header.seal()) { + Ok(seal) => map![ + "nonce".to_owned() => format!("0x{:x}", seal.nonce), + "mixHash".to_owned() => format!("0x{:x}", seal.mix_hash) + ], + _ => BTreeMap::default() } } - fn schedule(&self, block_number: BlockNumber) -> Schedule { - trace!(target: "client", "Creating schedule. fCML={}, bGCML={}", self.ethash_params.homestead_transition, self.ethash_params.eip150_transition); - - if block_number < self.ethash_params.homestead_transition { - Schedule::new_frontier() - } else if block_number < self.ethash_params.eip150_transition { - Schedule::new_homestead() - } else { - let mut schedule = Schedule::new_post_eip150( - self.ethash_params.max_code_size as usize, - block_number >= self.ethash_params.eip160_transition, - block_number >= self.ethash_params.eip161abc_transition, - block_number >= self.ethash_params.eip161d_transition); - - self.params().update_schedule(block_number, &mut schedule); - schedule - } - } - - fn signing_chain_id(&self, env_info: &EnvInfo) -> Option { - if env_info.number >= self.params().eip155_transition { - Some(self.params().chain_id) - } else { - None - } - } + fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 } - fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, mut gas_ceil_target: U256) { + fn populate_from_parent(&self, header: &mut Header, parent: &Header) { let difficulty = self.calculate_difficulty(header, parent); - if header.number() >= self.ethash_params.max_gas_limit_transition && gas_ceil_target > self.ethash_params.max_gas_limit { - warn!("Gas limit target is limited to {}", self.ethash_params.max_gas_limit); - gas_ceil_target = self.ethash_params.max_gas_limit; - } - let gas_limit = { - let gas_limit = parent.gas_limit().clone(); - let bound_divisor = self.params().gas_limit_bound_divisor; - let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into(); - let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); - let gas_limit = if gas_limit < gas_floor_target { - let gas_limit = cmp::min(gas_floor_target, upper_limit); - round_block_gas_limit(gas_limit, lower_limit, upper_limit) - } else if gas_limit > gas_ceil_target { - let gas_limit = cmp::max(gas_ceil_target, lower_limit); - round_block_gas_limit(gas_limit, lower_limit, upper_limit) - } else { - let total_lower_limit = cmp::max(lower_limit, gas_floor_target); - let total_upper_limit = cmp::min(upper_limit, gas_ceil_target); - let gas_limit = cmp::max(gas_floor_target, cmp::min(total_upper_limit, - lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); - round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) - }; - // ensure that we are not violating protocol limits - debug_assert!(gas_limit >= lower_limit); - debug_assert!(gas_limit <= upper_limit); - gas_limit - }; header.set_difficulty(difficulty); - header.set_gas_limit(gas_limit); - if header.number() >= self.ethash_params.dao_hardfork_transition && - header.number() <= self.ethash_params.dao_hardfork_transition + 9 { - header.set_extra_data(b"dao-hard-fork"[..].to_owned()); - } - header.note_dirty(); -// info!("ethash: populate_from_parent #{}: difficulty={} and gas_limit={}", header.number(), header.difficulty(), header.gas_limit()); } fn on_new_block( &self, - block: &mut ExecutedBlock, - last_hashes: Arc, + _block: &mut ExecutedBlock, _begins_epoch: bool, ) -> Result<(), Error> { - let parent_hash = block.fields().header.parent_hash().clone(); - engines::common::push_last_hash(block, last_hashes, self, &parent_hash)?; - if block.fields().header.number() == self.ethash_params.dao_hardfork_transition { - let state = block.fields_mut().state; - for child in &self.ethash_params.dao_hardfork_accounts { - let beneficiary = &self.ethash_params.dao_hardfork_beneficiary; - state.balance(child) - .and_then(|b| state.transfer_balance(child, beneficiary, &b, CleanupMode::NoEmpty))?; - } - } Ok(()) } /// Apply the block reward on finalisation of the block. /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { - let reward = self.params().block_reward; - let fields = block.fields_mut(); + use std::ops::Shr; + use parity_machine::{LiveBlock, WithBalances}; + + let author = *LiveBlock::header(&*block).author(); + let number = LiveBlock::header(&*block).number(); + + // Applies EIP-649 reward. + let reward = if number >= self.ethash_params.eip649_transition { + self.ethash_params.eip649_reward.unwrap_or(self.ethash_params.block_reward) + } else { + self.ethash_params.block_reward + }; + + // Applies ECIP-1017 eras. let eras_rounds = self.ethash_params.ecip1017_era_rounds; - let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number()); - - // Bestow block reward - fields.state.add_balance( - fields.header.author(), - &(reward + reward / U256::from(32) * U256::from(fields.uncles.len())), - CleanupMode::NoEmpty - )?; - - // Bestow uncle rewards - let current_number = fields.header.number(); - for u in fields.uncles.iter() { - if eras == 0 { - fields.state.add_balance( - u.author(), - &(reward * U256::from(8 + u.number() - current_number) / U256::from(8)), - CleanupMode::NoEmpty - ) + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, number); + + let n_uncles = LiveBlock::uncles(&*block).len(); + + // Bestow block rewards. + let mut result_block_reward = reward + reward.shr(5) * U256::from(n_uncles); + let mut uncle_rewards = Vec::with_capacity(n_uncles); + + if number >= self.ethash_params.mcip3_transition { + result_block_reward = self.ethash_params.mcip3_miner_reward; + let ubi_contract = self.ethash_params.mcip3_ubi_contract; + let ubi_reward = self.ethash_params.mcip3_ubi_reward; + let dev_contract = self.ethash_params.mcip3_dev_contract; + let dev_reward = self.ethash_params.mcip3_dev_reward; + + self.machine.add_balance(block, &author, &result_block_reward)?; + self.machine.add_balance(block, &ubi_contract, &ubi_reward)?; + self.machine.add_balance(block, &dev_contract, &dev_reward)?; + } else { + self.machine.add_balance(block, &author, &result_block_reward)?; + } + + // Bestow uncle rewards. + for u in LiveBlock::uncles(&*block) { + let uncle_author = u.author(); + let result_uncle_reward = if eras == 0 { + (reward * U256::from(8 + u.number() - number)).shr(3) } else { - fields.state.add_balance( - u.author(), - &(reward / U256::from(32)), - CleanupMode::NoEmpty - ) - }?; + reward.shr(5) + }; + + uncle_rewards.push((*uncle_author, result_uncle_reward)); } - // Commit state so that we can actually figure out the state root. - fields.state.commit()?; - Ok(()) + for &(ref a, ref reward) in &uncle_rewards { + self.machine.add_balance(block, a, reward)?; + } + + // Note and trace. + self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards) } - fn verify_block_basic(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { + fn verify_local_seal(&self, header: &Header) -> Result<(), Error> { + self.verify_block_basic(header) + .and_then(|_| self.verify_block_unordered(header)) + } + + fn verify_block_basic(&self, header: &Header) -> Result<(), Error> { // check the seal fields. - if header.seal().len() != self.seal_fields() { - return Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal().len() } - ))); - } - UntrustedRlp::new(&header.seal()[0]).as_val::()?; - UntrustedRlp::new(&header.seal()[1]).as_val::()?; + let seal = Seal::parse_seal(header.seal())?; // TODO: consider removing these lines. let min_difficulty = self.ethash_params.minimum_difficulty; @@ -338,19 +306,14 @@ impl Engine for Arc { let difficulty = Ethash::boundary_to_difficulty(&H256(quick_get_difficulty( &header.bare_hash().0, - header.nonce().low_u64(), - &header.mix_hash().0 + seal.nonce.low_u64(), + &seal.mix_hash.0 ))); + if &difficulty < header.difficulty() { return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty }))); } - if header.number() >= self.ethash_params.dao_hardfork_transition && - header.number() <= self.ethash_params.dao_hardfork_transition + 9 && - header.extra_data()[..] != b"dao-hard-fork"[..] { - return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: None, found: 0 }))); - } - if header.gas_limit() > &0x7fffffffffffffffu64.into() { return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: None, max: Some(0x7fffffffffffffffu64.into()), found: header.gas_limit().clone() }))); } @@ -358,18 +321,21 @@ impl Engine for Arc { Ok(()) } - fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { - if header.seal().len() != self.seal_fields() { - return Err(From::from(BlockError::InvalidSealArity( - Mismatch { expected: self.seal_fields(), found: header.seal().len() } - ))); - } - let result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, header.nonce().low_u64()); + fn verify_block_unordered(&self, header: &Header) -> Result<(), Error> { + let seal = Seal::parse_seal(header.seal())?; + + let result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, seal.nonce.low_u64()); let mix = H256(result.mix_hash); let difficulty = Ethash::boundary_to_difficulty(&H256(result.value)); - trace!(target: "miner", "num: {}, seed: {}, h: {}, non: {}, mix: {}, res: {}" , header.number() as u64, H256(slow_get_seedhash(header.number() as u64)), header.bare_hash(), header.nonce().low_u64(), H256(result.mix_hash), H256(result.value)); - if mix != header.mix_hash() { - return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: header.mix_hash() }))); + trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}", + num = header.number() as u64, + seed = H256(slow_hash_block_number(header.number() as u64)), + h = header.bare_hash(), + non = seal.nonce.low_u64(), + mix = H256(result.mix_hash), + res = H256(result.value)); + if mix != seal.mix_hash { + return Err(From::from(BlockError::MismatchedH256SealElement(Mismatch { expected: mix, found: seal.mix_hash }))); } if &difficulty < header.difficulty() { return Err(From::from(BlockError::InvalidProofOfWork(OutOfBounds { min: Some(header.difficulty().clone()), max: None, found: difficulty }))); @@ -377,7 +343,7 @@ impl Engine for Arc { Ok(()) } - fn verify_block_family(&self, header: &Header, parent: &Header, _block: Option<&[u8]>) -> Result<(), Error> { + fn verify_block_family(&self, header: &Header, parent: &Header) -> Result<(), Error> { // we should not calculate difficulty for genesis blocks if header.number() == 0 { return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }))); @@ -388,31 +354,11 @@ impl Engine for Arc { if header.difficulty() != &expected_difficulty { return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty().clone() }))) } - let gas_limit_divisor = self.params().gas_limit_bound_divisor; - let parent_gas_limit = *parent.gas_limit(); - let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor; - let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor; - if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))); - } - if header.number() >= self.ethash_params.max_gas_limit_transition && header.gas_limit() > &self.ethash_params.max_gas_limit && header.gas_limit() > &parent_gas_limit { - return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(self.ethash_params.max_gas_limit), found: header.gas_limit().clone() }))); - } - Ok(()) - } - - fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> { - if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price { - return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into()); - } - let check_low_s = header.number() >= self.ethash_params.homestead_transition; - let chain_id = if header.number() >= self.params().eip155_transition { Some(self.params().chain_id) } else { None }; - t.verify_basic(check_low_s, chain_id, false)?; Ok(()) } - fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> engines::ConstructedVerifier<'a> { + fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> engines::ConstructedVerifier<'a, EthereumMachine> { engines::ConstructedVerifier::Trusted(Box::new(self.clone())) } @@ -421,44 +367,14 @@ impl Engine for Arc { } } -// Try to round gas_limit a bit so that: -// 1) it will still be in desired range -// 2) it will be a nearest (with tendency to increase) multiple of PARITY_GAS_LIMIT_DETERMINANT -fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { - let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); - if increased_gas_limit > upper_limit { - let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; - if decreased_gas_limit < lower_limit { - gas_limit - } else { - decreased_gas_limit - } - } else { - increased_gas_limit - } -} - -fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256){ - let eras = if block_number != 0 && block_number % era_rounds == 0 { - block_number / era_rounds - 1 - } else { - block_number / era_rounds - }; - for _ in 0..eras { - reward = reward / U256::from(5) * U256::from(4); - } - (eras, reward) -} - -#[cfg_attr(feature="dev", allow(wrong_self_convention))] impl Ethash { fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 { - const EXP_DIFF_PERIOD: u64 = 100000; + const EXP_DIFF_PERIOD: u64 = 100_000; if header.number() == 0 { panic!("Can't calculate genesis block difficulty"); } - let parent_has_uncles = parent.uncles_hash() != &sha3::SHA3_EMPTY_LIST_RLP; + let parent_has_uncles = parent.uncles_hash() != &KECCAK_EMPTY_LIST_RLP; let min_difficulty = self.ethash_params.minimum_difficulty; @@ -469,7 +385,13 @@ impl Ethash { self.ethash_params.difficulty_bound_divisor }; - let duration_limit = self.ethash_params.duration_limit; + let expip2_hardfork = header.number() >= self.ethash_params.expip2_transition; + let duration_limit = if expip2_hardfork { + self.ethash_params.expip2_duration_limit + } else { + self.ethash_params.duration_limit + }; + let frontier_limit = self.ethash_params.homestead_transition; let mut target = if header.number() < frontier_limit { @@ -478,8 +400,7 @@ impl Ethash { } else { *parent.difficulty() + (*parent.difficulty() / difficulty_bound_divisor) } - } - else { + } else { trace!(target: "ethash", "Calculating difficulty parent.difficulty={}, header.timestamp={}, parent.timestamp={}", parent.difficulty(), header.timestamp(), parent.timestamp()); //block_diff = parent_diff + parent_diff // 2048 * max(1 - (block_timestamp - parent_timestamp) // 10, -99) let (increment_divisor, threshold) = if header.number() < self.ethash_params.eip100b_transition { @@ -492,9 +413,9 @@ impl Ethash { let diff_inc = (header.timestamp() - parent.timestamp()) / increment_divisor; if diff_inc <= threshold { - *parent.difficulty() + *parent.difficulty() / difficulty_bound_divisor * (threshold - diff_inc).into() + *parent.difficulty() + *parent.difficulty() / difficulty_bound_divisor * U256::from(threshold - diff_inc) } else { - let multiplier = cmp::min(diff_inc - threshold, 99).into(); + let multiplier: U256 = cmp::min(diff_inc - threshold, 99).into(); parent.difficulty().saturating_sub( *parent.difficulty() / difficulty_bound_divisor * multiplier ) @@ -503,7 +424,11 @@ impl Ethash { target = cmp::max(min_difficulty, target); if header.number() < self.ethash_params.bomb_defuse_transition { if header.number() < self.ethash_params.ecip1010_pause_transition { - let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; + let mut number = header.number(); + if number >= self.ethash_params.eip649_transition { + number = number.saturating_sub(self.ethash_params.eip649_delay); + } + let period = (number / EXP_DIFF_PERIOD) as usize; if period > 1 { target = cmp::max(min_difficulty, target + (U256::from(1) << (period - 2))); } @@ -541,41 +466,70 @@ impl Ethash { } } -impl Header { - /// Get the none field of the header. - pub fn nonce(&self) -> H64 { - rlp::decode(&self.seal()[1]) - } - - /// Get the mix hash field of the header. - pub fn mix_hash(&self) -> H256 { - rlp::decode(&self.seal()[0]) - } - - /// Set the nonce and mix hash fields of the header. - pub fn set_nonce_and_mix_hash(&mut self, nonce: &H64, mix_hash: &H256) { - self.set_seal(vec![rlp::encode(mix_hash).into_vec(), rlp::encode(nonce).into_vec()]); +fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256) { + let eras = if block_number != 0 && block_number % era_rounds == 0 { + block_number / era_rounds - 1 + } else { + block_number / era_rounds + }; + let mut divi = U256::from(1); + for _ in 0..eras { + reward = reward * U256::from(4); + divi = divi * U256::from(5); } + reward = reward / divi; + (eras, reward) } #[cfg(test)] mod tests { use std::str::FromStr; - use std::collections::BTreeMap; use std::sync::Arc; - use util::*; + use ethereum_types::{H64, H256, U256, Address}; use block::*; - use tests::helpers::*; - use engines::Engine; + use tests::helpers::get_temp_state_db; use error::{BlockError, Error}; use header::Header; use spec::Spec; - use super::super::{new_morden, new_homestead_test}; - use super::{Ethash, EthashParams, PARITY_GAS_LIMIT_DETERMINANT, ecip1017_eras_block_reward}; + use engines::Engine; + use super::super::{new_morden, new_mcip3_test, new_homestead_test_machine}; + use super::{Ethash, EthashParams, ecip1017_eras_block_reward}; use rlp; + use tempdir::TempDir; fn test_spec() -> Spec { - new_morden(&::std::env::temp_dir()) + let tempdir = TempDir::new("").unwrap(); + new_morden(&tempdir.path()) + } + + fn get_default_ethash_params() -> EthashParams { + EthashParams { + minimum_difficulty: U256::from(131072), + difficulty_bound_divisor: U256::from(2048), + difficulty_increment_divisor: 10, + metropolis_difficulty_increment_divisor: 9, + homestead_transition: 1150000, + duration_limit: 13, + block_reward: 0.into(), + difficulty_hardfork_transition: u64::max_value(), + difficulty_hardfork_bound_divisor: U256::from(0), + bomb_defuse_transition: u64::max_value(), + eip100b_transition: u64::max_value(), + ecip1010_pause_transition: u64::max_value(), + ecip1010_continue_transition: u64::max_value(), + ecip1017_era_rounds: u64::max_value(), + mcip3_transition: u64::max_value(), + mcip3_miner_reward: 0.into(), + mcip3_ubi_reward: 0.into(), + mcip3_ubi_contract: "0000000000000000000000000000000000000001".into(), + mcip3_dev_reward: 0.into(), + mcip3_dev_contract: "0000000000000000000000000000000000000001".into(), + eip649_transition: u64::max_value(), + eip649_delay: 3_000_000, + eip649_reward: None, + expip2_transition: u64::max_value(), + expip2_duration_limit: 30, + } } #[test] @@ -590,6 +544,43 @@ mod tests { assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("4563918244f40000").unwrap()); } + #[test] + fn has_valid_ecip1017_eras_block_reward() { + let eras_rounds = 5000000; + + let start_reward: U256 = "4563918244F40000".parse().unwrap(); + + let block_number = 0; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); + assert_eq!(0, eras); + assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward); + + let block_number = 5000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); + assert_eq!(0, eras); + assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward); + + let block_number = 10000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); + assert_eq!(1, eras); + assert_eq!(U256::from_str("3782DACE9D900000").unwrap(), reward); + + let block_number = 20000000; + let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); + assert_eq!(3, eras); + assert_eq!(U256::from_str("2386F26FC1000000").unwrap(), reward); + + let block_number = 80000000; + 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); + assert_eq!(U256::from_str("51212FFBAF0A").unwrap(), reward); + } + #[test] fn on_close_block_with_uncle() { let spec = test_spec(); @@ -608,11 +599,27 @@ mod tests { assert_eq!(b.state().balance(&uncle_author).unwrap(), "3cb71f51fc558000".into()); } + #[test] + fn has_valid_mcip3_era_block_rewards() { + let spec = new_mcip3_test(); + let engine = &*spec.engine; + let genesis_header = spec.genesis_header(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let last_hashes = Arc::new(vec![genesis_header.hash()]); + let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![], false).unwrap(); + let b = b.close(); + + let ubi_contract: Address = "00efdd5883ec628983e9063c7d969fe268bbf310".into(); + let dev_contract: Address = "00756cf8159095948496617f5fb17ed95059f536".into(); + assert_eq!(b.state().balance(&Address::zero()).unwrap(), U256::from_str("d8d726b7177a80000").unwrap()); + assert_eq!(b.state().balance(&ubi_contract).unwrap(), U256::from_str("2b5e3af16b1880000").unwrap()); + assert_eq!(b.state().balance(&dev_contract).unwrap(), U256::from_str("c249fdd327780000").unwrap()); + } + #[test] fn has_valid_metadata() { let engine = test_spec().engine; assert!(!engine.name().is_empty()); - assert!(engine.version().major >= 1); } #[test] @@ -628,10 +635,9 @@ mod tests { #[test] fn can_do_seal_verification_fail() { let engine = test_spec().engine; - //let engine = Ethash::new_test(test_spec()); let header: Header = Header::default(); - let verify_result = engine.verify_block_basic(&header, None); + let verify_result = engine.verify_block_basic(&header); match verify_result { Err(Error::Block(BlockError::InvalidSealArity(_))) => {}, @@ -646,7 +652,7 @@ mod tests { let mut header: Header = Header::default(); header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]); - let verify_result = engine.verify_block_basic(&header, None); + let verify_result = engine.verify_block_basic(&header); match verify_result { Err(Error::Block(BlockError::DifficultyOutOfBounds(_))) => {}, @@ -662,7 +668,7 @@ mod tests { header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]); header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap()); - let verify_result = engine.verify_block_basic(&header, None); + let verify_result = engine.verify_block_basic(&header); match verify_result { Err(Error::Block(BlockError::InvalidProofOfWork(_))) => {}, @@ -674,9 +680,9 @@ mod tests { #[test] fn can_do_seal_unordered_verification_fail() { let engine = test_spec().engine; - let header: Header = Header::default(); + let header = Header::default(); - let verify_result = engine.verify_block_unordered(&header, None); + let verify_result = engine.verify_block_unordered(&header); match verify_result { Err(Error::Block(BlockError::InvalidSealArity(_))) => {}, @@ -685,12 +691,23 @@ mod tests { } } + #[test] + fn can_do_seal_unordered_verification_fail2() { + let engine = test_spec().engine; + let mut header = Header::default(); + header.set_seal(vec![vec![], vec![]]); + + let verify_result = engine.verify_block_unordered(&header); + // rlp error, shouldn't panic + assert!(verify_result.is_err()); + } + #[test] fn can_do_seal256_verification_fail() { let engine = test_spec().engine; let mut header: Header = Header::default(); header.set_seal(vec![rlp::encode(&H256::zero()).into_vec(), rlp::encode(&H64::zero()).into_vec()]); - let verify_result = engine.verify_block_unordered(&header, None); + let verify_result = engine.verify_block_unordered(&header); match verify_result { Err(Error::Block(BlockError::MismatchedH256SealElement(_))) => {}, @@ -706,7 +723,7 @@ mod tests { header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]); header.set_difficulty(U256::from_str("ffffffffffffffffffffffffffffffffffffffffffffaaaaaaaaaaaaaaaaaaaa").unwrap()); - let verify_result = engine.verify_block_unordered(&header, None); + let verify_result = engine.verify_block_unordered(&header); match verify_result { Err(Error::Block(BlockError::InvalidProofOfWork(_))) => {}, @@ -721,7 +738,7 @@ mod tests { let header: Header = Header::default(); let parent_header: Header = Header::default(); - let verify_result = engine.verify_block_family(&header, &parent_header, None); + let verify_result = engine.verify_block_family(&header, &parent_header); match verify_result { Err(Error::Block(BlockError::RidiculousNumber(_))) => {}, @@ -738,7 +755,7 @@ mod tests { let mut parent_header: Header = Header::default(); parent_header.set_number(1); - let verify_result = engine.verify_block_family(&header, &parent_header, None); + let verify_result = engine.verify_block_family(&header, &parent_header); match verify_result { Err(Error::Block(BlockError::InvalidDifficulty(_))) => {}, @@ -747,24 +764,6 @@ mod tests { } } - #[test] - fn can_verify_block_family_gas_fail() { - let engine = test_spec().engine; - let mut header: Header = Header::default(); - header.set_number(2); - header.set_difficulty(U256::from_str("0000000000000000000000000000000000000000000000000000000000020000").unwrap()); - let mut parent_header: Header = Header::default(); - parent_header.set_number(1); - - let verify_result = engine.verify_block_family(&header, &parent_header, None); - - match verify_result { - Err(Error::Block(BlockError::InvalidGasLimit(_))) => {}, - Err(_) => { panic!("should be invalid difficulty fail (got {:?})", verify_result); }, - _ => { panic!("Should be error, got Ok"); }, - } - } - #[test] fn test_difficulty_to_boundary() { // result of f(0) is undefined, so do not assert the result @@ -777,9 +776,10 @@ mod tests { #[test] fn difficulty_frontier() { - let spec = new_homestead_test(); + let machine = new_homestead_test_machine(); let ethparams = get_default_ethash_params(); - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); + let tempdir = TempDir::new("").unwrap(); + let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut parent_header = Header::default(); parent_header.set_number(1000000); @@ -795,9 +795,10 @@ mod tests { #[test] fn difficulty_homestead() { - let spec = new_homestead_test(); + let machine = new_homestead_test_machine(); let ethparams = get_default_ethash_params(); - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); + let tempdir = TempDir::new("").unwrap(); + let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut parent_header = Header::default(); parent_header.set_number(1500000); @@ -811,46 +812,15 @@ mod tests { assert_eq!(U256::from_str("1fc50f118efe").unwrap(), difficulty); } - #[test] - fn has_valid_ecip1017_eras_block_reward() { - let eras_rounds = 5000000; - - let start_reward: U256 = "4563918244F40000".parse().unwrap(); - - let block_number = 0; - let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); - assert_eq!(0, eras); - assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward); - - let block_number = 5000000; - let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); - assert_eq!(0, eras); - assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward); - - let block_number = 10000000; - let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); - assert_eq!(1, eras); - assert_eq!(U256::from_str("3782DACE9D900000").unwrap(), reward); - - let block_number = 20000000; - let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number); - assert_eq!(3, eras); - assert_eq!(U256::from_str("2386F26FC1000000").unwrap(), reward); - - let block_number = 80000000; - 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); - } - #[test] fn difficulty_classic_bomb_delay() { - let spec = new_homestead_test(); + let machine = new_homestead_test_machine(); let ethparams = EthashParams { ecip1010_pause_transition: 3000000, ..get_default_ethash_params() }; - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); + let tempdir = TempDir::new("").unwrap(); + let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut parent_header = Header::default(); parent_header.set_number(3500000); @@ -878,13 +848,14 @@ mod tests { #[test] fn test_difficulty_bomb_continue() { - let spec = new_homestead_test(); + let machine = new_homestead_test_machine(); let ethparams = EthashParams { ecip1010_pause_transition: 3000000, ecip1010_continue_transition: 5000000, ..get_default_ethash_params() }; - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); + let tempdir = TempDir::new("").unwrap(); + let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut parent_header = Header::default(); parent_header.set_number(5000102); @@ -926,55 +897,12 @@ mod tests { ); } - #[test] - fn gas_limit_is_multiple_of_determinant() { - let spec = new_homestead_test(); - let ethparams = get_default_ethash_params(); - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); - let mut parent = Header::new(); - let mut header = Header::new(); - header.set_number(1); - - // this test will work for this constant only - assert_eq!(PARITY_GAS_LIMIT_DETERMINANT, U256::from(37)); - - // when parent.gas_limit < gas_floor_target: - parent.set_gas_limit(U256::from(50_000)); - ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); - assert_eq!(*header.gas_limit(), U256::from(50_024)); - - // when parent.gas_limit > gas_ceil_target: - parent.set_gas_limit(U256::from(250_000)); - ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); - assert_eq!(*header.gas_limit(), U256::from(249_787)); - - // when parent.gas_limit is in miner's range - header.set_gas_used(U256::from(150_000)); - parent.set_gas_limit(U256::from(150_000)); - ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); - assert_eq!(*header.gas_limit(), U256::from(150_035)); - - // when parent.gas_limit is in miner's range - // && we can NOT increase it to be multiple of constant - header.set_gas_used(U256::from(150_000)); - parent.set_gas_limit(U256::from(150_000)); - ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(150_002)); - assert_eq!(*header.gas_limit(), U256::from(149_998)); - - // when parent.gas_limit is in miner's range - // && we can NOT increase it to be multiple of constant - // && we can NOT decrease it to be multiple of constant - header.set_gas_used(U256::from(150_000)); - parent.set_gas_limit(U256::from(150_000)); - ethash.populate_from_parent(&mut header, &parent, U256::from(150_000), U256::from(150_002)); - assert_eq!(*header.gas_limit(), U256::from(150_002)); - } - #[test] fn difficulty_max_timestamp() { - let spec = new_homestead_test(); + let machine = new_homestead_test_machine(); let ethparams = get_default_ethash_params(); - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); + let tempdir = TempDir::new("").unwrap(); + let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut parent_header = Header::default(); parent_header.set_number(1000000); @@ -989,80 +917,15 @@ mod tests { } #[test] - fn rejects_blocks_over_max_gas_limit() { - let spec = new_homestead_test(); - let mut ethparams = get_default_ethash_params(); - ethparams.max_gas_limit_transition = 10; - ethparams.max_gas_limit = 100_000.into(); - - let mut parent_header = Header::default(); - parent_header.set_number(1); - parent_header.set_gas_limit(100_000.into()); - let mut header = Header::default(); - header.set_number(parent_header.number() + 1); - header.set_gas_limit(100_001.into()); - header.set_difficulty(ethparams.minimum_difficulty); - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); - assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok()); - - parent_header.set_number(9); - header.set_number(parent_header.number() + 1); - - parent_header.set_gas_limit(99_999.into()); - header.set_gas_limit(100_000.into()); - assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok()); - - parent_header.set_gas_limit(200_000.into()); - header.set_gas_limit(200_000.into()); - assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok()); - - parent_header.set_gas_limit(100_000.into()); - header.set_gas_limit(100_001.into()); - assert!(ethash.verify_block_family(&header, &parent_header, None).is_err()); - - parent_header.set_gas_limit(200_000.into()); - header.set_gas_limit(200_001.into()); - assert!(ethash.verify_block_family(&header, &parent_header, None).is_err()); - } - - #[test] - fn rejects_transactions_below_min_gas_price() { - use ethkey::{Generator, Random}; - use transaction::{Transaction, Action}; - - let spec = new_homestead_test(); - let mut ethparams = get_default_ethash_params(); - ethparams.min_gas_price_transition = 10; - ethparams.min_gas_price = 100000.into(); - + fn test_extra_info() { + let machine = new_homestead_test_machine(); + let ethparams = get_default_ethash_params(); + let tempdir = TempDir::new("").unwrap(); + let ethash = Ethash::new(tempdir.path(), ethparams, machine, None); let mut header = Header::default(); - header.set_number(1); - - let keypair = Random.generate().unwrap(); - let tx1 = Transaction { - action: Action::Create, - value: U256::zero(), - data: Vec::new(), - gas: 100_000.into(), - gas_price: 100_000.into(), - nonce: U256::zero(), - }.sign(keypair.secret(), None).into(); - - let tx2 = Transaction { - action: Action::Create, - value: U256::zero(), - data: Vec::new(), - gas: 100_000.into(), - gas_price: 99_999.into(), - nonce: U256::zero(), - }.sign(keypair.secret(), None).into(); - - let ethash = Ethash::new(&::std::env::temp_dir(), spec.params().clone(), ethparams, BTreeMap::new()); - assert!(ethash.verify_transaction_basic(&tx1, &header).is_ok()); - assert!(ethash.verify_transaction_basic(&tx2, &header).is_ok()); - - header.set_number(10); - assert!(ethash.verify_transaction_basic(&tx1, &header).is_ok()); - assert!(ethash.verify_transaction_basic(&tx2, &header).is_err()); + header.set_seal(vec![rlp::encode(&H256::from("b251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d")).into_vec(), rlp::encode(&H64::zero()).into_vec()]); + let info = ethash.extra_info(&header); + assert_eq!(info["nonce"], "0x0000000000000000"); + assert_eq!(info["mixHash"], "0xb251bd2e0283d0658f2cadfdc8ca619b5de94eca5742725e2e757dd13ed7503d"); } } diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index dee86883b407a81db1320b8ab924fc645e6d5bfb..e892cf56a4b58d50710545b8bea9a56b7ba9909c 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -27,45 +27,64 @@ pub mod denominations; pub use self::ethash::{Ethash}; pub use self::denominations::*; -use std::path::Path; +use machine::EthereumMachine; use super::spec::*; -/// Most recent fork block that we support on Mainnet. -pub const FORK_SUPPORTED_FOUNDATION: u64 = 2675000; - -/// Most recent fork block that we support on Ropsten. -pub const FORK_SUPPORTED_ROPSTEN: u64 = 10; - -/// Most recent fork block that we support on Kovan. -pub const FORK_SUPPORTED_KOVAN: u64 = 0; - -fn load<'a, T: 'a + Into>>(cache_dir: T, b: &[u8]) -> Spec { - match cache_dir.into() { - Some(path) => Spec::load(path, b), +fn load<'a, T: Into>>>(params: T, b: &[u8]) -> Spec { + match params.into() { + Some(params) => Spec::load(params, b), None => Spec::load(&::std::env::temp_dir(), b) }.expect("chain spec is invalid") } +fn load_machine(b: &[u8]) -> EthereumMachine { + Spec::load_machine(b).expect("chain spec is invalid") +} + /// Create a new Foundation Olympic chain spec. -pub fn new_olympic(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/olympic.json")) } +pub fn new_olympic<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/olympic.json")) +} /// Create a new Foundation Mainnet chain spec. -pub fn new_foundation(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/foundation.json")) } +pub fn new_foundation<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/foundation.json")) +} /// Create a new Classic Mainnet chain spec without the DAO hardfork. -pub fn new_classic(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/classic.json")) } +pub fn new_classic<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/classic.json")) +} /// Create a new Expanse mainnet chain spec. -pub fn new_expanse(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/expanse.json")) } +pub fn new_expanse<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/expanse.json")) +} + +/// Create a new Musicoin mainnet chain spec. +pub fn new_musicoin<'a, T: Into>>(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>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/ellaism.json")) +} /// Create a new Kovan testnet chain spec. -pub fn new_kovan(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/kovan.json")) } +pub fn new_kovan<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/kovan.json")) +} /// Create a new Foundation Ropsten chain spec. -pub fn new_ropsten(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/ropsten.json")) } +pub fn new_ropsten<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/ropsten.json")) +} /// Create a new Morden chain spec. -pub fn new_morden(cache_dir: &Path) -> Spec { load(cache_dir, include_bytes!("../../res/ethereum/morden.json")) } +pub fn new_morden<'a, T: Into>>(params: T) -> Spec { + load(params.into(), include_bytes!("../../res/ethereum/morden.json")) +} // For tests @@ -87,15 +106,41 @@ pub fn new_transition_test() -> Spec { load(None, include_bytes!("../../res/ethe /// Create a new Foundation Mainnet chain spec without genesis accounts. pub fn new_mainnet_like() -> Spec { load(None, include_bytes!("../../res/ethereum/frontier_like_test.json")) } -/// Create a new Foundation Metropolis era spec. -pub fn new_metropolis_test() -> Spec { load(None, include_bytes!("../../res/ethereum/metropolis_test.json")) } +/// Create a new Foundation Byzantium era spec. +pub fn new_byzantium_test() -> Spec { load(None, include_bytes!("../../res/ethereum/byzantium_test.json")) } + +/// Create a new Foundation Constantinople era spec. +pub fn new_constantinople_test() -> Spec { load(None, include_bytes!("../../res/ethereum/constantinople_test.json")) } + +/// Create a new Musicoin-MCIP3-era spec. +pub fn new_mcip3_test() -> Spec { load(None, include_bytes!("../../res/ethereum/mcip3_test.json")) } + +// For tests + +/// Create a new Foundation Frontier-era chain spec as though it never changes to Homestead. +pub fn new_frontier_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/frontier_test.json")) } + +/// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier. +pub fn new_homestead_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/homestead_test.json")) } + +/// Create a new Foundation Byzantium era spec. +pub fn new_byzantium_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/byzantium_test.json")) } + +/// Create a new Foundation Constantinople era spec. +pub fn new_constantinople_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/constantinople_test.json")) } + +/// Create a new Musicoin-MCIP3-era spec. +pub fn new_mcip3_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/mcip3_test.json")) } + +/// Create new Kovan spec with wasm activated at certain block +pub fn new_kovan_wasm_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/kovan_wasm_test.json")) } #[cfg(test)] mod tests { - use util::*; + use ethereum_types::U256; use state::*; use super::*; - use tests::helpers::*; + use tests::helpers::get_temp_state_db; use views::BlockView; #[test] @@ -119,7 +164,7 @@ mod tests { assert_eq!(morden.state_root(), "f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9".into()); let genesis = morden.genesis_block(); - assert_eq!(BlockView::new(&genesis).header_view().sha3(), "0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303".into()); + assert_eq!(BlockView::new(&genesis).header_view().hash(), "0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303".into()); let _ = morden.engine; } @@ -130,7 +175,7 @@ mod tests { assert_eq!(frontier.state_root(), "d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544".into()); let genesis = frontier.genesis_block(); - assert_eq!(BlockView::new(&genesis).header_view().sha3(), "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3".into()); + assert_eq!(BlockView::new(&genesis).header_view().hash(), "d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3".into()); let _ = frontier.engine; } diff --git a/ethcore/src/executed.rs b/ethcore/src/executed.rs index 3154903ca0ff56ea6988b9051f8b99f69e5227b1..a787209326467ec900f369506acf34d612b9f9be 100644 --- a/ethcore/src/executed.rs +++ b/ethcore/src/executed.rs @@ -16,7 +16,9 @@ //! Transaction execution format module. -use util::{Bytes, U256, Address, U512, trie}; +use ethereum_types::{U256, U512, Address}; +use bytes::Bytes; +use trie; use vm; use trace::{VMTrace, FlatTrace}; use log_entry::LogEntry; @@ -26,7 +28,7 @@ use std::fmt; /// Transaction execution receipt. #[derive(Debug, PartialEq, Clone)] -pub struct Executed { +pub struct Executed { /// True if the outer call/create resulted in an exceptional exit. pub exception: Option, @@ -60,9 +62,9 @@ pub struct Executed { /// Transaction output. pub output: Bytes, /// The trace of this transaction. - pub trace: Vec, + pub trace: Vec, /// The VM trace of this transaction. - pub vm_trace: Option, + pub vm_trace: Option, /// The state diff, if we traced it. pub state_diff: Option, } diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 66a770243748a2ec9541f0a28aebf995015df61c..8e792f9e2e21e8d678c165843f6b421813015bc8 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -17,16 +17,19 @@ //! Transaction Execution environment. use std::cmp; use std::sync::Arc; -use util::*; +use hash::keccak; +use ethereum_types::{H256, U256, U512, Address}; +use bytes::{Bytes, BytesRef}; use state::{Backend as StateBackend, State, Substate, CleanupMode}; -use engines::Engine; -use vm::EnvInfo; +use machine::EthereumMachine as Machine; use error::ExecutionError; -use evm::{CallType, Factory, Finalize, FinalizationResult}; -use vm::{self, Ext, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, ActionValue}; -use wasm; +use evm::{CallType, Finalize, FinalizationResult}; +use vm::{ + self, Ext, EnvInfo, CreateContractAddress, ReturnData, CleanDustMode, ActionParams, + ActionValue, Schedule, +}; use externalities::*; -use trace::{self, FlatTrace, VMTrace, Tracer, VMTracer}; +use trace::{self, Tracer, VMTracer}; use transaction::{Action, SignedTransaction}; use crossbeam; pub use executed::{Executed, ExecutionResult}; @@ -36,8 +39,6 @@ pub use executed::{Executed, ExecutionResult}; /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` const STACK_SIZE_PER_DEPTH: usize = 24*1024; -const WASM_MAGIC_NUMBER: &'static [u8; 4] = b"\0asm"; - /// Returns new address created from address, nonce, and code hash pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code: &[u8]) -> (Address, Option) { use rlp::RlpStream; @@ -47,20 +48,20 @@ pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, let mut stream = RlpStream::new_list(2); stream.append(sender); stream.append(nonce); - (From::from(stream.as_raw().sha3()), None) + (From::from(keccak(stream.as_raw())), None) }, CreateContractAddress::FromCodeHash => { - let code_hash = code.sha3(); + let code_hash = keccak(code); let mut buffer = [0xffu8; 20 + 32]; &mut buffer[20..].copy_from_slice(&code_hash[..]); - (From::from((&buffer[..]).sha3()), Some(code_hash)) + (From::from(keccak(&buffer[..])), Some(code_hash)) }, CreateContractAddress::FromSenderAndCodeHash => { - let code_hash = code.sha3(); + let code_hash = keccak(code); let mut buffer = [0u8; 20 + 32]; &mut buffer[..20].copy_from_slice(&sender[..]); &mut buffer[20..].copy_from_slice(&code_hash[..]); - (From::from((&buffer[..]).sha3()), Some(code_hash)) + (From::from(keccak(&buffer[..])), Some(code_hash)) }, } } @@ -74,6 +75,8 @@ pub struct TransactOptions { pub vm_tracer: V, /// Check transaction nonce before execution. pub check_nonce: bool, + /// Records the output from init contract calls. + pub output_from_init_contract: bool, } impl TransactOptions { @@ -83,6 +86,7 @@ impl TransactOptions { tracer, vm_tracer, check_nonce: true, + output_from_init_contract: false, } } @@ -91,6 +95,12 @@ impl TransactOptions { self.check_nonce = false; self } + + /// Saves the output from contract creation. + pub fn save_output_from_contract(mut self) -> Self { + self.output_from_init_contract = true; + self + } } impl TransactOptions { @@ -100,6 +110,7 @@ impl TransactOptions { tracer: trace::ExecutiveTracer::default(), vm_tracer: trace::ExecutiveVMTracer::toplevel(), check_nonce: true, + output_from_init_contract: false, } } } @@ -111,6 +122,7 @@ impl TransactOptions { tracer: trace::ExecutiveTracer::default(), vm_tracer: trace::NoopVMTracer, check_nonce: true, + output_from_init_contract: false, } } } @@ -122,6 +134,7 @@ impl TransactOptions { tracer: trace::NoopTracer, vm_tracer: trace::ExecutiveVMTracer::toplevel(), check_nonce: true, + output_from_init_contract: false, } } } @@ -133,51 +146,38 @@ impl TransactOptions { tracer: trace::NoopTracer, vm_tracer: trace::NoopVMTracer, check_nonce: true, + output_from_init_contract: false, } } } -pub fn executor(engine: &E, vm_factory: &Factory, params: &ActionParams) - -> Box where E: Engine + ?Sized -{ - if engine.supports_wasm() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) { - Box::new( - wasm::WasmInterpreter::new() - // prefer to fail fast - .expect("Failed to create wasm runtime") - ) - } else { - vm_factory.create(params.gas) - } -} - /// Transaction executor. -pub struct Executive<'a, B: 'a + StateBackend, E: 'a + Engine + ?Sized> { +pub struct Executive<'a, B: 'a + StateBackend> { state: &'a mut State, info: &'a EnvInfo, - engine: &'a E, + machine: &'a Machine, depth: usize, static_flag: bool, } -impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { +impl<'a, B: 'a + StateBackend> Executive<'a, B> { /// Basic constructor. - pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a E) -> Self { + pub fn new(state: &'a mut State, info: &'a EnvInfo, machine: &'a Machine) -> Self { Executive { state: state, info: info, - engine: engine, + machine: machine, depth: 0, static_flag: false, } } /// Populates executive from parent properties. Increments executive depth. - pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a E, parent_depth: usize, static_flag: bool) -> Self { + pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, machine: &'a Machine, parent_depth: usize, static_flag: bool) -> Self { Executive { state: state, info: info, - engine: engine, + machine: machine, depth: parent_depth + 1, static_flag: static_flag, } @@ -192,23 +192,23 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { tracer: &'any mut T, vm_tracer: &'any mut V, static_call: bool, - ) -> Externalities<'any, T, V, B, E> where T: Tracer, V: VMTracer { + ) -> Externalities<'any, T, V, B> where T: Tracer, V: VMTracer { let is_static = self.static_flag || static_call; - Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static) + Externalities::new(self.state, self.info, self.machine, self.depth, origin_info, substate, output, tracer, vm_tracer, is_static) } /// This function should be used to execute transaction. pub fn transact(&'a mut self, t: &SignedTransaction, options: TransactOptions) - -> Result where T: Tracer, V: VMTracer, + -> Result, ExecutionError> where T: Tracer, V: VMTracer, { - self.transact_with_tracer(t, options.check_nonce, options.tracer, options.vm_tracer) + self.transact_with_tracer(t, options.check_nonce, options.output_from_init_contract, options.tracer, options.vm_tracer) } /// Execute a transaction in a "virtual" context. /// This will ensure the caller has enough balance to execute the desired transaction. /// Used for extra-block executions for things like consensus contracts and RPCs pub fn transact_virtual(&'a mut self, t: &SignedTransaction, options: TransactOptions) - -> Result where T: Tracer, V: VMTracer, + -> Result, ExecutionError> where T: Tracer, V: VMTracer, { let sender = t.sender(); let balance = self.state.balance(&sender)?; @@ -226,13 +226,14 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { &'a mut self, t: &SignedTransaction, check_nonce: bool, + output_from_create: bool, mut tracer: T, mut vm_tracer: V - ) -> Result where T: Tracer, V: VMTracer { + ) -> Result, ExecutionError> where T: Tracer, V: VMTracer { let sender = t.sender(); let nonce = self.state.nonce(&sender)?; - let schedule = self.engine.schedule(self.info.number); + let schedule = self.machine.schedule(self.info.number); let base_gas_required = U256::from(t.gas_required(&schedule)); if t.gas < base_gas_required { @@ -273,14 +274,14 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let mut substate = Substate::new(); // NOTE: there can be no invalid transactions from this point. - if !t.is_unsigned() { + if !schedule.eip86 || !t.is_unsigned() { self.state.inc_nonce(&sender)?; } self.state.sub_balance(&sender, &U256::from(gas_cost), &mut substate.to_cleanup_mode(&schedule))?; let (result, output) = match t.action { Action::Create => { - let (new_address, code_hash) = contract_address(self.engine.create_address_scheme(self.info.number), &sender, &nonce, &t.data); + let (new_address, code_hash) = contract_address(self.machine.create_address_scheme(self.info.number), &sender, &nonce, &t.data); let params = ActionParams { code_address: new_address.clone(), code_hash: code_hash, @@ -293,8 +294,10 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { code: Some(Arc::new(t.data.clone())), data: None, call_type: CallType::None, + params_type: vm::ParamsType::Embedded, }; - (self.create(params, &mut substate, &mut tracer, &mut vm_tracer), vec![]) + let mut out = if output_from_create { Some(vec![]) } else { None }; + (self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new)) }, Action::Call(ref address) => { let params = ActionParams { @@ -309,6 +312,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { code_hash: Some(self.state.code_hash(address)?), data: Some(t.data.clone()), call_type: CallType::Call, + params_type: vm::ParamsType::Separate, }; let mut out = vec![]; (self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out) @@ -321,6 +325,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { fn exec_vm( &mut self, + schedule: Schedule, params: ActionParams, unconfirmed_substate: &mut Substate, output_policy: OutputPolicy, @@ -336,19 +341,20 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let vm_factory = self.state.vm_factory(); let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); trace!(target: "executive", "ext.schedule.have_delegate_call: {}", ext.schedule().have_delegate_call); - return executor(self.engine, &vm_factory, ¶ms).exec(params, &mut ext).finalize(ext); + let mut vm = vm_factory.create(¶ms, &schedule); + return vm.exec(params, &mut ext).finalize(ext); } // Start in new thread to reset stack // TODO [todr] No thread builder yet, so we need to reset once for a while // https://github.com/aturon/crossbeam/issues/16 crossbeam::scope(|scope| { - let engine = self.engine; let vm_factory = self.state.vm_factory(); let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call); scope.spawn(move || { - executor(engine, &vm_factory, ¶ms).exec(params, &mut ext).finalize(ext) + let mut vm = vm_factory.create(¶ms, &schedule); + vm.exec(params, &mut ext).finalize(ext) }) }).join() } @@ -364,12 +370,12 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { mut output: BytesRef, tracer: &mut T, vm_tracer: &mut V - ) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { + ) -> vm::Result where T: Tracer, V: VMTracer { - trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); + trace!("Executive::call(params={:?}) self.env_info={:?}, static={}", params, self.info, self.static_flag); if (params.call_type == CallType::StaticCall || - ((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) && - self.static_flag)) + ((params.call_type == CallType::Call) && + self.static_flag)) && params.value.value() > 0.into() { return Err(vm::Error::MutableCallInStaticContext); } @@ -377,7 +383,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { // backup used in case of running out of gas self.state.checkpoint(); - let schedule = self.engine.schedule(self.info.number); + let schedule = self.machine.schedule(self.info.number); // at first, transfer value to destination if let ActionValue::Transfer(val) = params.value { @@ -385,7 +391,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { } // if destination is builtin, try to execute it - if let Some(builtin) = self.engine.builtin(¶ms.code_address, self.info.number) { + if let Some(builtin) = self.machine.builtin(¶ms.code_address, self.info.number) { // Engines aren't supposed to return builtins until activation, but // prefer to fail rather than silently break consensus. if !builtin.is_active(self.info.number) { @@ -399,18 +405,24 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let cost = builtin.cost(data); if cost <= params.gas { - if let Err(e) = builtin.execute(data, &mut output) { + let mut builtin_out_buffer = Vec::new(); + let result = { + let mut builtin_output = BytesRef::Flexible(&mut builtin_out_buffer); + builtin.execute(data, &mut builtin_output) + }; + if let Err(e) = result { self.state.revert_to_checkpoint(); let evm_err: vm::Error = e.into(); tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into()); Err(evm_err) } else { self.state.discard_checkpoint(); + output.write(0, &builtin_out_buffer); // trace only top level calls to builtins to avoid DDoS attacks if self.depth == 0 { let mut trace_output = tracer.prepare_trace_output(); - if let Some(mut out) = trace_output.as_mut() { + if let Some(out) = trace_output.as_mut() { *out = output.to_owned(); } @@ -422,7 +434,12 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { ); } - Ok((params.gas - cost, ReturnData::empty())) + let out_len = builtin_out_buffer.len(); + Ok(FinalizationResult { + gas_left: params.gas - cost, + return_data: ReturnData::new(builtin_out_buffer, 0, out_len), + apply_state: true, + }) } } else { // just drain the whole gas @@ -447,7 +464,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed")); let res = { - self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer) + self.exec_vm(schedule, params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer) }; vm_tracer.done_subtrace(subvmtracer); @@ -456,12 +473,13 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let traces = subtracer.drain(); match res { - Ok(ref res) => tracer.trace_call( + Ok(ref res) if res.apply_state => tracer.trace_call( trace_info, gas - res.gas_left, trace_output, traces ), + Ok(_) => tracer.trace_failed_call(trace_info, traces, vm::Error::Reverted.into()), Err(ref e) => tracer.trace_failed_call(trace_info, traces, e.into()), }; @@ -469,13 +487,17 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { self.enact_result(&res, substate, unconfirmed_substate); trace!(target: "executive", "enacted: substate={:?}\n", substate); - res.map(|r| (r.gas_left, r.return_data)) + res } else { // otherwise it's just a basic transaction, only do tracing, if necessary. self.state.discard_checkpoint(); tracer.trace_call(trace_info, U256::zero(), trace_output, vec![]); - Ok((params.gas, ReturnData::empty())) + Ok(FinalizationResult { + gas_left: params.gas, + return_data: ReturnData::empty(), + apply_state: true, + }) } } } @@ -487,15 +509,21 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { &mut self, params: ActionParams, substate: &mut Substate, + output: &mut Option, tracer: &mut T, vm_tracer: &mut V, - ) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { + ) -> vm::Result where T: Tracer, V: VMTracer { - let scheme = self.engine.create_address_scheme(self.info.number); - if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(¶ms.address)? { + // EIP-684: If a contract creation is attempted, due to either a creation transaction or the + // CREATE (or future CREATE2) opcode, and the destination address already has either + // nonzero nonce, or nonempty code, then the creation throws immediately, with exactly + // the same behavior as would arise if the first byte in the init code were an invalid + // opcode. This applies retroactively starting from genesis. + if self.state.exists_and_has_code_or_nonce(¶ms.address)? { return Err(vm::Error::OutOfGas); } + trace!("Executive::create(params={:?}) self.env_info={:?}, static={}", params, self.info, self.static_flag); if params.call_type == CallType::StaticCall || self.static_flag { let trace_info = tracer.prepare_trace_create(¶ms); tracer.trace_failed_create(trace_info, vec![], vm::Error::MutableCallInStaticContext.into()); @@ -509,7 +537,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let mut unconfirmed_substate = Substate::new(); // create contract and transfer value to it if necessary - let schedule = self.engine.schedule(self.info.number); + let schedule = self.machine.schedule(self.info.number); let nonce_offset = if schedule.no_empty {1} else {0}.into(); let prev_bal = self.state.balance(¶ms.address)?; if let ActionValue::Transfer(val) = params.value { @@ -527,38 +555,44 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed")); - let res = { - self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(trace_output.as_mut()), &mut subtracer, &mut subvmtracer) - }; + let res = self.exec_vm( + schedule, + params, + &mut unconfirmed_substate, + OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())), + &mut subtracer, + &mut subvmtracer + ); vm_tracer.done_subtrace(subvmtracer); match res { - Ok(ref res) => tracer.trace_create( + Ok(ref res) if res.apply_state => tracer.trace_create( trace_info, gas - res.gas_left, - trace_output, + trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)), created, subtracer.drain() ), + Ok(_) => tracer.trace_failed_create(trace_info, subtracer.drain(), vm::Error::Reverted.into()), Err(ref e) => tracer.trace_failed_create(trace_info, subtracer.drain(), e.into()) }; self.enact_result(&res, substate, unconfirmed_substate); - res.map(|r| (r.gas_left, r.return_data)) + res } /// Finalizes the transaction (does refunds and suicides). - fn finalize( + fn finalize( &mut self, t: &SignedTransaction, mut substate: Substate, - result: vm::Result<(U256, ReturnData)>, + result: vm::Result, output: Bytes, - trace: Vec, - vm_trace: Option - ) -> ExecutionResult { - let schedule = self.engine.schedule(self.info.number); + trace: Vec, + vm_trace: Option + ) -> Result, ExecutionError> { + let schedule = self.machine.schedule(self.info.number); // refunds from SSTORE nonzero -> zero let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count; @@ -567,7 +601,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let refunds_bound = sstore_refunds + suicide_refunds; // real ammount to refund - let gas_left_prerefund = match result { Ok((x, _)) => x, _ => 0.into() }; + let gas_left_prerefund = match result { Ok(FinalizationResult{ gas_left, .. }) => gas_left, _ => 0.into() }; let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) >> 1); let gas_left = gas_left_prerefund + refunded; @@ -611,9 +645,9 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { state_diff: None, }) }, - _ => { + Ok(r) => { Ok(Executed { - exception: None, + exception: if r.apply_state { None } else { Some(vm::Error::Reverted) }, gas: t.gas, gas_used: gas_used, refunded: refunded, @@ -639,6 +673,8 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { | Err(vm::Error::Wasm {..}) | Err(vm::Error::OutOfStack {..}) | Err(vm::Error::MutableCallInStaticContext) + | Err(vm::Error::OutOfBounds) + | Err(vm::Error::Reverted) | Ok(FinalizationResult { apply_state: false, .. }) => { self.state.revert_to_checkpoint(); }, @@ -658,18 +694,25 @@ mod tests { use rustc_hex::FromHex; use ethkey::{Generator, Random}; use super::*; - use util::{H256, U256, U512, Address}; - use util::bytes::BytesRef; + use ethereum_types::{H256, U256, U512, Address}; + use bytes::BytesRef; use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress}; use evm::{Factory, VMType}; use error::ExecutionError; + use machine::EthereumMachine; use state::{Substate, CleanupMode}; - use tests::helpers::*; + use tests::helpers::{get_temp_state_with_factory, get_temp_state}; use trace::trace; use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer}; use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer}; use transaction::{Action, Transaction}; + fn make_frontier_machine(max_depth: usize) -> EthereumMachine { + let mut machine = ::ethereum::new_frontier_test_machine(); + machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = max_depth)); + machine + } + #[test] fn test_contract_address() { let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); @@ -691,12 +734,12 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from(0x100u64), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let mut substate = Substate::new(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); - ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap() + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap() }; assert_eq!(gas_left, U256::from(79_975)); @@ -749,12 +792,12 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let mut substate = Substate::new(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); - ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap() + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap() }; assert_eq!(gas_left, U256::from(62_976)); @@ -805,13 +848,13 @@ mod tests { let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let mut substate = Substate::new(); let mut tracer = ExecutiveTracer::default(); let mut vm_tracer = ExecutiveVMTracer::toplevel(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); let output = BytesRef::Fixed(&mut[0u8;0]); ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap() }; @@ -885,6 +928,85 @@ mod tests { assert_eq!(vm_tracer.drain().unwrap(), expected_vm_trace); } + #[test] + fn test_trace_reverted_create() { + // code: + // + // 65 60016000fd - push 5 bytes + // 60 00 - push 0 + // 52 mstore + // 60 05 - push 5 + // 60 1b - push 27 + // 60 17 - push 23 + // f0 - create + // 60 00 - push 0 + // 55 sstore + // + // other code: + // + // 60 01 + // 60 00 + // fd - revert + + let code = "6460016000fd6000526005601b6017f0600055".from_hex().unwrap(); + + let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &[]).0; + let mut params = ActionParams::default(); + params.address = address.clone(); + params.code_address = address.clone(); + params.sender = sender.clone(); + params.origin = sender.clone(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.value = ActionValue::Transfer(U256::from(100)); + params.call_type = CallType::Call; + let mut state = get_temp_state(); + state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); + let info = EnvInfo::default(); + let machine = ::ethereum::new_byzantium_test_machine(); + let mut substate = Substate::new(); + let mut tracer = ExecutiveTracer::default(); + let mut vm_tracer = ExecutiveVMTracer::toplevel(); + + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + let output = BytesRef::Fixed(&mut[0u8;0]); + ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap() + }; + + assert_eq!(gas_left, U256::from(62967)); + + let expected_trace = vec![FlatTrace { + trace_address: Default::default(), + subtraces: 1, + action: trace::Action::Call(trace::Call { + from: "cd1722f3947def4cf144679da39c4c32bdc35681".into(), + to: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + value: 100.into(), + gas: 100_000.into(), + input: vec![], + call_type: CallType::Call, + }), + result: trace::Res::Call(trace::CallResult { + gas_used: U256::from(37_033), + output: vec![], + }), + }, FlatTrace { + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + action: trace::Action::Create(trace::Create { + from: "b010143a42d5980c7e5ef0e4a4416dc098a4fed3".into(), + value: 23.into(), + gas: 66_917.into(), + init: vec![0x60, 0x01, 0x60, 0x00, 0xfd] + }), + result: trace::Res::FailedCreate(vm::Error::Reverted.into()), + }]; + + assert_eq!(tracer.drain(), expected_trace); + } + #[test] fn test_create_contract() { // Tracing is not supported in JIT @@ -914,14 +1036,14 @@ mod tests { let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let mut substate = Substate::new(); let mut tracer = ExecutiveTracer::default(); let mut vm_tracer = ExecutiveVMTracer::toplevel(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); - ex.create(params.clone(), &mut substate, &mut tracer, &mut vm_tracer).unwrap() + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap() }; assert_eq!(gas_left, U256::from(96_776)); @@ -1001,12 +1123,12 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let mut substate = Substate::new(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); - ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap() + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap() }; assert_eq!(gas_left, U256::from(62_976)); @@ -1052,12 +1174,12 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(1024); + let machine = make_frontier_machine(1024); let mut substate = Substate::new(); { - let mut ex = Executive::new(&mut state, &info, &engine); - ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap(); + let mut ex = Executive::new(&mut state, &info, &machine); + ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap(); } assert_eq!(substate.contracts_created.len(), 1); @@ -1112,11 +1234,11 @@ mod tests { state.add_balance(&sender, &U256::from(100_000), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let mut substate = Substate::new(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -1156,11 +1278,11 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.init_code(&address, code).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let mut substate = Substate::new(); - let (gas_left, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); + let FinalizationResult { gas_left, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -1189,10 +1311,10 @@ mod tests { state.add_balance(&sender, &U256::from(18), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let executed = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &machine); let opts = TransactOptions::with_no_tracing(); ex.transact(&t, opts).unwrap() }; @@ -1226,10 +1348,10 @@ mod tests { state.add_balance(&sender, &U256::from(17), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &machine); let opts = TransactOptions::with_no_tracing(); ex.transact(&t, opts) }; @@ -1259,10 +1381,10 @@ mod tests { let mut info = EnvInfo::default(); info.gas_used = U256::from(20_000); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &machine); let opts = TransactOptions::with_no_tracing(); ex.transact(&t, opts) }; @@ -1292,10 +1414,10 @@ mod tests { state.add_balance(&sender, &U256::from(100_017), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let res = { - let mut ex = Executive::new(&mut state, &info, &engine); + let mut ex = Executive::new(&mut state, &info, &machine); let opts = TransactOptions::with_no_tracing(); ex.transact(&t, opts) }; @@ -1307,8 +1429,8 @@ mod tests { } } - evm_test!{test_sha3: test_sha3_jit, test_sha3_int} - fn test_sha3(factory: Factory) { + evm_test!{test_keccak: test_keccak_jit, test_keccak_int} + fn test_keccak(factory: Factory) { let code = "6064640fffffffff20600055".from_hex().unwrap(); let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); @@ -1325,12 +1447,12 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap(), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new(0); + let machine = make_frontier_machine(0); let mut substate = Substate::new(); let result = { - let mut ex = Executive::new(&mut state, &info, &engine); - ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) + let mut ex = Executive::new(&mut state, &info, &machine); + ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) }; match result { @@ -1357,15 +1479,13 @@ mod tests { params.gas = U256::from(20025); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::zero()); - let mut state = get_temp_state_with_factory(factory); - state.add_balance(&sender, &U256::from_str("152d02c7e14af68000000").unwrap(), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new_metropolis(); + let machine = ::ethereum::new_byzantium_test_machine(); let mut substate = Substate::new(); let mut output = [0u8; 14]; - let (result, _) = { - let mut ex = Executive::new(&mut state, &info, &engine); + let FinalizationResult { gas_left: result, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -1373,4 +1493,60 @@ mod tests { assert_eq!(output[..], returns[..]); assert_eq!(state.storage_at(&contract_address, &H256::from(&U256::zero())).unwrap(), H256::from(&U256::from(0))); } + + fn wasm_sample_code() -> Arc> { + Arc::new( + "0061736d01000000010d0360027f7f0060017f0060000002270303656e7603726574000003656e760673656e646572000103656e76066d656d6f727902010110030201020404017000000501000708010463616c6c00020901000ac10101be0102057f017e4100410028020441c0006b22043602042004412c6a41106a220041003602002004412c6a41086a22014200370200200441186a41106a22024100360200200441186a41086a220342003703002004420037022c2004410036021c20044100360218200441186a1001200020022802002202360200200120032903002205370200200441106a2002360200200441086a200537030020042004290318220537022c200420053703002004411410004100200441c0006a3602040b0b0a010041040b0410c00000" + .from_hex() + .unwrap() + ) + } + + #[test] + fn wasm_activated_test() { + let contract_address = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); + let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); + + let mut state = get_temp_state(); + state.add_balance(&sender, &U256::from(10000000000u64), CleanupMode::NoEmpty).unwrap(); + state.commit().unwrap(); + + let mut params = ActionParams::default(); + params.origin = sender.clone(); + params.sender = sender.clone(); + params.address = contract_address.clone(); + params.gas = U256::from(20025); + params.code = Some(wasm_sample_code()); + + let mut info = EnvInfo::default(); + + // 100 > 10 + info.number = 100; + + // Network with wasm activated at block 10 + let machine = ::ethereum::new_kovan_wasm_test_machine(); + + let mut output = [0u8; 20]; + let FinalizationResult { gas_left: result, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + ex.call(params.clone(), &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap() + }; + + assert_eq!(result, U256::from(18433)); + // Transaction successfully returned sender + assert_eq!(output[..], sender[..]); + + // 1 < 10 + info.number = 1; + + let mut output = [0u8; 20]; + let FinalizationResult { gas_left: result, .. } = { + let mut ex = Executive::new(&mut state, &info, &machine); + ex.call(params, &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap() + }; + + assert_eq!(result, U256::from(20025)); + // Since transaction errored due to wasm was not activated, result is just empty + assert_eq!(output[..], [0u8; 20][..]); + } } diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index eae981f1b06d2a1de7de67d71025b3a8a55edea5..732d3499a83b8ebec8105467af9d1cdc77269585 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -17,15 +17,17 @@ //! Transaction Execution environment. use std::cmp; use std::sync::Arc; -use util::*; +use ethereum_types::{H256, U256, Address}; +use bytes::{Bytes, BytesRef}; use state::{Backend as StateBackend, State, Substate, CleanupMode}; -use engines::Engine; +use machine::EthereumMachine as Machine; use executive::*; use vm::{ self, ActionParams, ActionValue, EnvInfo, CallType, Schedule, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData }; +use evm::FinalizationResult; use transaction::UNSIGNED_SENDER; use trace::{Tracer, VMTracer}; @@ -61,12 +63,12 @@ impl OriginInfo { } /// Implementation of evm Externalities. -pub struct Externalities<'a, T: 'a, V: 'a, B: 'a, E: 'a + Engine + ?Sized> +pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> where T: Tracer, V: VMTracer, B: StateBackend { state: &'a mut State, env_info: &'a EnvInfo, - engine: &'a E, + machine: &'a Machine, depth: usize, origin_info: OriginInfo, substate: &'a mut Substate, @@ -77,14 +79,13 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a, E: 'a + Engine + ?Sized> static_flag: bool, } -impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> - where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized +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, env_info: &'a EnvInfo, - engine: &'a E, + machine: &'a Machine, depth: usize, origin_info: OriginInfo, substate: &'a mut Substate, @@ -96,11 +97,11 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> Externalities { state: state, env_info: env_info, - engine: engine, + machine: machine, depth: depth, origin_info: origin_info, substate: substate, - schedule: engine.schedule(env_info.number), + schedule: machine.schedule(env_info.number), output: output, tracer: tracer, vm_tracer: vm_tracer, @@ -109,8 +110,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Externalities<'a, T, V, B, E> } } -impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> - where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized +impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> + where T: Tracer, V: VMTracer, B: StateBackend { fn storage_at(&self, key: &H256) -> vm::Result { self.state.storage_at(&self.origin_info.address, key).map_err(Into::into) @@ -124,6 +125,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> } } + fn is_static(&self) -> bool { + return self.static_flag + } + fn exists(&self, address: &Address) -> vm::Result { self.state.exists(address).map_err(Into::into) } @@ -141,8 +146,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> } fn blockhash(&mut self, number: &U256) -> H256 { - if self.env_info.number + 256 >= self.engine.params().eip210_transition { - let blockhash_contract_address = self.engine.params().eip210_contract_address; + if self.env_info.number + 256 >= self.machine.params().eip210_transition { + let blockhash_contract_address = self.machine.params().eip210_contract_address; let code_res = self.state.code(&blockhash_contract_address) .and_then(|code| self.state.code_hash(&blockhash_contract_address).map(|hash| (code, hash))); @@ -157,16 +162,17 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> value: ActionValue::Apparent(self.origin_info.value), code_address: blockhash_contract_address.clone(), origin: self.origin_info.origin.clone(), - gas: self.engine.params().eip210_contract_gas, + gas: self.machine.params().eip210_contract_gas, gas_price: 0.into(), code: code, code_hash: Some(code_hash), data: Some(H256::from(number).to_vec()), call_type: CallType::Call, + params_type: vm::ParamsType::Separate, }; let mut output = H256::new(); - let mut ex = Executive::new(self.state, self.env_info, self.engine); + let mut ex = Executive::new(self.state, self.env_info, self.machine); let r = ex.call(params, self.substate, BytesRef::Fixed(&mut output), self.tracer, self.vm_tracer); trace!("ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", number, r, output, self.env_info.number); output @@ -211,23 +217,29 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> code_hash: code_hash, data: None, call_type: CallType::None, + params_type: vm::ParamsType::Embedded, }; - if params.sender != UNSIGNED_SENDER { - if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { - debug!(target: "ext", "Database corruption encountered: {:?}", e); - return ContractCreateResult::Failed + if !self.static_flag { + if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER { + if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { + debug!(target: "ext", "Database corruption encountered: {:?}", e); + return ContractCreateResult::Failed + } } } - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag); + let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.depth, self.static_flag); // TODO: handle internal error separately - match ex.create(params, self.substate, self.tracer, self.vm_tracer) { - Ok((gas_left, _)) => { + match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) { + Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => { self.substate.contracts_created.push(address.clone()); ContractCreateResult::Created(address, gas_left) }, - _ => ContractCreateResult::Failed + Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => { + ContractCreateResult::Reverted(gas_left, return_data) + }, + _ => ContractCreateResult::Failed, } } @@ -263,16 +275,18 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> code_hash: Some(code_hash), data: Some(data.to_vec()), call_type: call_type, + params_type: vm::ParamsType::Separate, }; if let Some(value) = value { params.value = ActionValue::Transfer(value); } - let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag); + let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.depth, self.static_flag); match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) { - Ok((gas_left, return_data)) => MessageCallResult::Success(gas_left, return_data), + Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data), + Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data), _ => MessageCallResult::Failed } } @@ -285,8 +299,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> 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) -> vm::Result + fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result where Self: Sized { let handle_copy = |to: &mut Option<&mut Bytes>| { to.as_mut().map(|b| **b = data.to_vec()); @@ -306,7 +319,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> vec.extend_from_slice(&*data); Ok(*gas) }, - OutputPolicy::InitContract(ref mut copy) => { + OutputPolicy::InitContract(ref mut copy) if apply_state => { let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas); if return_cost > *gas || data.len() > self.schedule.create_data_limit { return match self.schedule.exceptional_failed_code_deposit { @@ -314,12 +327,13 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> false => Ok(*gas) } } - handle_copy(copy); - self.state.init_code(&self.origin_info.address, data.to_vec())?; Ok(*gas - return_cost) - } + }, + OutputPolicy::InitContract(_) => { + Ok(*gas) + }, } } @@ -382,8 +396,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one(); } - fn trace_next_instruction(&mut self, pc: usize, instruction: u8) -> bool { - self.vm_tracer.trace_next_instruction(pc, instruction) + fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { + self.vm_tracer.trace_next_instruction(pc, instruction, current_gas) } fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) { @@ -397,11 +411,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> #[cfg(test)] mod tests { - use util::*; - use engines::Engine; + use ethereum_types::{U256, Address}; use evm::{EnvInfo, Ext, CallType}; use state::{State, Substate}; - use tests::helpers::*; + use tests::helpers::get_temp_state; use super::*; use trace::{NoopTracer, NoopVMTracer}; @@ -428,7 +441,7 @@ mod tests { struct TestSetup { state: State<::state_db::StateDB>, - engine: Arc, + machine: ::machine::EthereumMachine, sub_state: Substate, env_info: EnvInfo } @@ -443,7 +456,7 @@ mod tests { fn new() -> Self { TestSetup { state: get_temp_state(), - engine: get_test_spec().engine, + machine: ::spec::Spec::new_test_machine(), sub_state: Substate::new(), env_info: get_test_env_info() } @@ -457,7 +470,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + let ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); assert_eq!(ext.env_info().number, 100); } @@ -469,7 +482,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::().unwrap()); @@ -493,7 +506,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::().unwrap()); @@ -508,7 +521,7 @@ mod tests { let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); let mut output = vec![]; @@ -536,7 +549,7 @@ mod tests { let mut vm_tracer = NoopVMTracer; { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); ext.log(log_topics, &log_data).unwrap(); } @@ -553,7 +566,7 @@ mod tests { let mut vm_tracer = NoopVMTracer; { - let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); ext.suicide(refund_account).unwrap(); } diff --git a/ethcore/src/factory.rs b/ethcore/src/factory.rs index e283491e16e62ef7def7b2969f3483a3f2ad90e1..68a15f164a6eb718f75ae32062eccc70bef93712 100644 --- a/ethcore/src/factory.rs +++ b/ethcore/src/factory.rs @@ -14,17 +14,47 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::trie::TrieFactory; -use evm::Factory as EvmFactory; +use trie::TrieFactory; use account_db::Factory as AccountFactory; +use evm::{Factory as EvmFactory, VMType}; +use vm::{Vm, ActionParams, Schedule}; +use wasm::WasmInterpreter; + +const WASM_MAGIC_NUMBER: &'static [u8; 4] = b"\0asm"; + +/// Virtual machine factory +#[derive(Default, Clone)] +pub struct VmFactory { + evm: EvmFactory, +} + +impl VmFactory { + pub fn create(&self, params: &ActionParams, schedule: &Schedule) -> Box { + if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) { + Box::new(WasmInterpreter) + } else { + self.evm.create(¶ms.gas) + } + } + + pub fn new(evm: VMType, cache_size: usize) -> Self { + VmFactory { evm: EvmFactory::new(evm, cache_size) } + } +} + +impl From for VmFactory { + fn from(evm: EvmFactory) -> Self { + VmFactory { evm: evm } + } +} /// Collection of factories. #[derive(Default, Clone)] pub struct Factories { /// factory for evm. - pub vm: EvmFactory, + pub vm: VmFactory, /// factory for tries. pub trie: TrieFactory, /// factory for account databases. pub accountdb: AccountFactory, -} \ No newline at end of file +} diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index a9a4f948d4ca90908529bbdc410db779b7377042..f6f5090ef841c3fe1eca652c044d62e1c847160b 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -18,15 +18,23 @@ use std::cmp; use std::cell::RefCell; -use util::*; -use basic_types::{LogBloom, ZERO_LOGBLOOM}; -use time::get_time; +use std::time::{SystemTime, UNIX_EPOCH}; +use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY_LIST_RLP, keccak}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, U256, Address, Bloom}; +use bytes::Bytes; use rlp::*; -pub use basic_types::Seal; - pub use types::BlockNumber; +/// Semantic boolean for when a seal/signature is included. +pub enum Seal { + /// The seal/signature is included. + With, + /// The seal/signature is not included. + Without, +} + /// A block header. /// /// Reflects the specific RLP fields of a block in the chain with additional room for the seal @@ -56,7 +64,7 @@ pub struct Header { /// Block receipts root. receipts_root: H256, /// Block bloom. - log_bloom: LogBloom, + log_bloom: Bloom, /// Gas used for contracts execution. gas_used: U256, /// Block gas limit. @@ -100,13 +108,13 @@ impl Default for Header { number: 0, author: Address::default(), - transactions_root: SHA3_NULL_RLP, - uncles_hash: SHA3_EMPTY_LIST_RLP, + transactions_root: KECCAK_NULL_RLP, + uncles_hash: KECCAK_EMPTY_LIST_RLP, extra_data: vec![], - state_root: SHA3_NULL_RLP, - receipts_root: SHA3_NULL_RLP, - log_bloom: ZERO_LOGBLOOM.clone(), + state_root: KECCAK_NULL_RLP, + receipts_root: KECCAK_NULL_RLP, + log_bloom: Bloom::default(), gas_used: U256::default(), gas_limit: U256::default(), @@ -143,7 +151,7 @@ impl Header { /// Get the receipts root field of the header. pub fn receipts_root(&self) -> &H256 { &self.receipts_root } /// Get the log bloom field of the header. - pub fn log_bloom(&self) -> &LogBloom { &self.log_bloom } + pub fn log_bloom(&self) -> &Bloom { &self.log_bloom } /// Get the transactions root field of the header. pub fn transactions_root(&self) -> &H256 { &self.transactions_root } /// Get the uncles hash field of the header. @@ -157,6 +165,12 @@ impl Header { pub fn difficulty(&self) -> &U256 { &self.difficulty } /// Get the seal field of the header. pub fn seal(&self) -> &[Bytes] { &self.seal } + /// Get the seal field with RLP-decoded values as bytes. + pub fn decode_seal<'a, T: ::std::iter::FromIterator<&'a [u8]>>(&'a self) -> Result { + self.seal.iter().map(|rlp| { + UntrustedRlp::new(rlp).data() + }).collect() + } // TODO: seal_at, set_seal_at &c. @@ -171,11 +185,11 @@ impl Header { /// Set the receipts root field of the header. pub fn set_receipts_root(&mut self, a: H256) { self.receipts_root = a; self.note_dirty() } /// Set the log bloom field of the header. - pub fn set_log_bloom(&mut self, a: LogBloom) { self.log_bloom = a; self.note_dirty() } + pub fn set_log_bloom(&mut self, a: Bloom) { self.log_bloom = a; self.note_dirty() } /// Set the timestamp field of the header. pub fn set_timestamp(&mut self, a: u64) { self.timestamp = a; self.note_dirty(); } /// Set the timestamp field of the header to the current time. - pub fn set_timestamp_now(&mut self, but_later_than: u64) { self.timestamp = cmp::max(get_time().sec as u64, but_later_than + 1); self.note_dirty(); } + pub fn set_timestamp_now(&mut self, but_later_than: u64) { let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default(); self.timestamp = cmp::max(now.as_secs() as u64, but_later_than + 1); self.note_dirty(); } /// Set the number field of the header. pub fn set_number(&mut self, a: BlockNumber) { self.number = a; self.note_dirty(); } /// Set the author field of the header. @@ -194,13 +208,13 @@ impl Header { /// Set the seal field of the header. pub fn set_seal(&mut self, a: Vec) { self.seal = a; self.note_dirty(); } - /// Get the hash of this header (sha3 of the RLP). + /// Get the hash of this header (keccak of the RLP). pub fn hash(&self) -> H256 { let mut hash = self.hash.borrow_mut(); match &mut *hash { &mut Some(ref h) => h.clone(), hash @ &mut None => { - let h = self.rlp_sha3(Seal::With); + let h = self.rlp_keccak(Seal::With); *hash = Some(h.clone()); h } @@ -213,7 +227,7 @@ impl Header { match &mut *hash { &mut Some(ref h) => h.clone(), hash @ &mut None => { - let h = self.rlp_sha3(Seal::Without); + let h = self.rlp_keccak(Seal::Without); *hash = Some(h.clone()); h } @@ -258,7 +272,12 @@ impl Header { } /// Get the SHA3 (Keccak) of this header, optionally `with_seal`. - pub fn rlp_sha3(&self, with_seal: Seal) -> H256 { self.rlp(with_seal).sha3() } + pub fn rlp_keccak(&self, with_seal: Seal) -> H256 { keccak(self.rlp(with_seal)) } + + /// Encode the header, getting a type-safe wrapper around the RLP. + pub fn encoded(&self) -> ::encoded::Header { + ::encoded::Header::new(self.rlp(Seal::With)) + } } impl Decodable for Header { @@ -278,7 +297,7 @@ impl Decodable for Header { timestamp: cmp::min(r.val_at::(11)?, u64::max_value().into()).as_u64(), extra_data: r.val_at(12)?, seal: vec![], - hash: RefCell::new(Some(r.as_raw().sha3())), + hash: RefCell::new(Some(keccak(r.as_raw()))), bare_hash: RefCell::new(None), }; @@ -302,6 +321,23 @@ impl HeapSizeOf for Header { } } +impl ::parity_machine::Header for Header { + fn bare_hash(&self) -> H256 { Header::bare_hash(self) } + + fn hash(&self) -> H256 { Header::hash(self) } + + fn seal(&self) -> &[Vec] { Header::seal(self) } + + fn author(&self) -> &Address { Header::author(self) } + + fn number(&self) -> BlockNumber { Header::number(self) } +} + +impl ::parity_machine::ScoredHeader for Header { + fn score(&self) -> &U256 { self.difficulty() } + fn set_score(&mut self, score: U256) { self.set_difficulty(score) } +} + #[cfg(test)] mod tests { use rustc_hex::FromHex; @@ -313,13 +349,20 @@ mod tests { // that's rlp of block header created with ethash engine. let header_rlp = "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".from_hex().unwrap(); let mix_hash = "a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap(); + let mix_hash_decoded = "a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd".from_hex().unwrap(); let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap(); + let nonce_decoded = "ab4e252a7e8c2a23".from_hex().unwrap(); let header: Header = rlp::decode(&header_rlp); - let seal_fields = header.seal; + let seal_fields = header.seal.clone(); assert_eq!(seal_fields.len(), 2); assert_eq!(seal_fields[0], mix_hash); assert_eq!(seal_fields[1], nonce); + + let decoded_seal = header.decode_seal::>().unwrap(); + assert_eq!(decoded_seal.len(), 2); + assert_eq!(decoded_seal[0], &*mix_hash_decoded); + assert_eq!(decoded_seal[1], &*nonce_decoded); } #[test] diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 7047c9882ce9a695fdadac3ec49720857e9b5a01..64414450bd5cb1babc242e94ecfd94fbd6dbc2e9 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -15,16 +15,14 @@ // along with Parity. If not, see . use std::sync::Arc; -use client::{BlockChainClient, Client, ClientConfig}; +use client::{EvmTestClient, Client, ClientConfig, ChainInfo, ImportBlock}; use block::Block; -use ethereum; -use tests::helpers::*; use spec::Genesis; use ethjson; use miner::Miner; use io::IoChannel; -pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { +pub fn json_chain_test(json_data: &[u8]) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); @@ -42,15 +40,16 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { flush!(" - {}...", name); let spec = { + let mut spec = match EvmTestClient::spec_from_json(&blockchain.network) { + Some(spec) => (*spec).clone(), + None => { + println!(" - {} | {:?} Ignoring tests because of missing spec", name, blockchain.network); + continue; + } + }; + let genesis = Genesis::from(blockchain.genesis()); let state = From::from(blockchain.pre_state.clone()); - let mut spec = match era { - ChainEra::Frontier => ethereum::new_frontier_test(), - ChainEra::Homestead => ethereum::new_homestead_test(), - ChainEra::Eip150 => ethereum::new_eip150_test(), - ChainEra::_Eip161 => ethereum::new_eip161_test(), - ChainEra::TransitionTest => ethereum::new_transition_test(), - }; spec.set_genesis_state(state).expect("Failed to overwrite genesis state"); spec.overwrite_genesis_params(genesis); assert!(spec.is_state_root_valid()); @@ -58,9 +57,11 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { }; { - let db = Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))); + let db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let mut config = ClientConfig::default(); + config.history = 8; let client = Client::new( - ClientConfig::default(), + config, &spec, db, Arc::new(Miner::with_spec(&spec)), @@ -86,67 +87,69 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { failed } -mod frontier_era_tests { - use tests::helpers::*; +mod block_tests { use super::json_chain_test; fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Frontier) + json_chain_test(json_data) } declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} - declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"} + declare_test!{BlockchainTests_bcExploitTest, "BlockchainTests/bcExploitTest"} + declare_test!{BlockchainTests_bcForgedTest, "BlockchainTests/bcForgedTest"} declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} - declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} - // TODO [ToDr] Ignored because of incorrect JSON (https://github.com/ethereum/tests/pull/113) - declare_test!{ignore => BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} - declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} - declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} + declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"} declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} - declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} + declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} - declare_test!{BlockchainTests_RandomTests_bl10251623GO, "BlockchainTests/RandomTests/bl10251623GO"} - declare_test!{BlockchainTests_RandomTests_bl201507071825GO, "BlockchainTests/RandomTests/bl201507071825GO"} + declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"} + declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"} + declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"} + declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"} + declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"} + declare_test!{BlockchainTests_GeneralStateTest_stEIP150Specific, "BlockchainTests/GeneralStateTests/stEIP150Specific/"} + declare_test!{BlockchainTests_GeneralStateTest_stEIP158Specific, "BlockchainTests/GeneralStateTests/stEIP158Specific/"} + declare_test!{BlockchainTests_GeneralStateTest_stExample, "BlockchainTests/GeneralStateTests/stExample/"} + declare_test!{BlockchainTests_GeneralStateTest_stHomesteadSpecific, "BlockchainTests/GeneralStateTests/stHomesteadSpecific/"} + declare_test!{BlockchainTests_GeneralStateTest_stInitCodeTest, "BlockchainTests/GeneralStateTests/stInitCodeTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stLogTests, "BlockchainTests/GeneralStateTests/stLogTests/"} + declare_test!{BlockchainTests_GeneralStateTest_stMemExpandingEIP150Calls, "BlockchainTests/GeneralStateTests/stMemExpandingEIP150Calls/"} + declare_test!{heavy => BlockchainTests_GeneralStateTest_stMemoryStressTest, "BlockchainTests/GeneralStateTests/stMemoryStressTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"} + declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"} + declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"} + declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"} + declare_test!{BlockchainTests_GeneralStateTest_stStaticCall, "BlockchainTests/GeneralStateTests/stStaticCall/"} + declare_test!{BlockchainTests_GeneralStateTest_stSystemOperationsTest, "BlockchainTests/GeneralStateTests/stSystemOperationsTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stTransactionTest, "BlockchainTests/GeneralStateTests/stTransactionTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stTransitionTest, "BlockchainTests/GeneralStateTests/stTransitionTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stWalletTest, "BlockchainTests/GeneralStateTests/stWalletTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"} + + declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"} + declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"} + declare_test!{BlockchainTests_TransitionTests_bcHomesteadToDao, "BlockchainTests/TransitionTests/bcHomesteadToDao/"} + declare_test!{BlockchainTests_TransitionTests_bcHomesteadToEIP150, "BlockchainTests/TransitionTests/bcHomesteadToEIP150/"} } -mod transition_tests { - use tests::helpers::*; - use super::json_chain_test; - - fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::TransitionTest) - } - - declare_test!{BlockchainTests_TestNetwork_bcSimpleTransitionTest, "BlockchainTests/TestNetwork/bcSimpleTransitionTest"} - declare_test!{BlockchainTests_TestNetwork_bcTheDaoTest, "BlockchainTests/TestNetwork/bcTheDaoTest"} - declare_test!{BlockchainTests_TestNetwork_bcEIP150Test, "BlockchainTests/TestNetwork/bcEIP150Test"} -} - -mod eip150_blockchain_tests { - use tests::helpers::*; - use super::json_chain_test; - - fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Eip150) - } - - declare_test!{BlockchainTests_EIP150_bcBlockGasLimitTest, "BlockchainTests/EIP150/bcBlockGasLimitTest"} - declare_test!{BlockchainTests_EIP150_bcForkStressTest, "BlockchainTests/EIP150/bcForkStressTest"} - declare_test!{BlockchainTests_EIP150_bcGasPricerTest, "BlockchainTests/EIP150/bcGasPricerTest"} - declare_test!{BlockchainTests_EIP150_bcInvalidHeaderTest, "BlockchainTests/EIP150/bcInvalidHeaderTest"} - declare_test!{BlockchainTests_EIP150_bcInvalidRLPTest, "BlockchainTests/EIP150/bcInvalidRLPTest"} - declare_test!{BlockchainTests_EIP150_bcMultiChainTest, "BlockchainTests/EIP150/bcMultiChainTest"} - declare_test!{BlockchainTests_EIP150_bcRPC_API_Test, "BlockchainTests/EIP150/bcRPC_API_Test"} - declare_test!{BlockchainTests_EIP150_bcStateTest, "BlockchainTests/EIP150/bcStateTest"} - declare_test!{BlockchainTests_EIP150_bcTotalDifficultyTest, "BlockchainTests/EIP150/bcTotalDifficultyTest"} - declare_test!{BlockchainTests_EIP150_bcUncleHeaderValiditiy, "BlockchainTests/EIP150/bcUncleHeaderValiditiy"} - declare_test!{BlockchainTests_EIP150_bcUncleTest, "BlockchainTests/EIP150/bcUncleTest"} - declare_test!{BlockchainTests_EIP150_bcValidBlockTest, "BlockchainTests/EIP150/bcValidBlockTest"} - declare_test!{BlockchainTests_EIP150_bcWalletTest, "BlockchainTests/EIP150/bcWalletTest"} -} diff --git a/ethcore/src/json_tests/difficulty.rs b/ethcore/src/json_tests/difficulty.rs new file mode 100644 index 0000000000000000000000000000000000000000..c0d03c810b467ef3fcd696800787274042d899ee --- /dev/null +++ b/ethcore/src/json_tests/difficulty.rs @@ -0,0 +1,73 @@ +// 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 . + +use ethjson; +use header::Header; +use ethereum_types::U256; +use spec::Spec; + +pub fn json_difficulty_test(json_data: &[u8], spec: Spec) -> Vec { + ::ethcore_logger::init_log(); + let tests = ethjson::test::DifficultyTest::load(json_data).unwrap(); + let engine = &spec.engine; + + for (name, test) in tests.into_iter() { + flush!(" - {}...", name); + println!(" - {}...", name); + + let mut parent_header = Header::new(); + let block_number: u64 = test.current_block_number.into(); + parent_header.set_number(block_number - 1); + parent_header.set_gas_limit(0x20000.into()); + parent_header.set_timestamp(test.parent_timestamp.into()); + parent_header.set_difficulty(test.parent_difficulty.into()); + parent_header.set_uncles_hash(test.parent_uncles.into()); + let mut header = Header::new(); + header.set_number(block_number); + header.set_timestamp(test.current_timestamp.into()); + engine.populate_from_parent(&mut header, &parent_header); + let expected_difficulty: U256 = test.current_difficulty.into(); + assert_eq!(header.difficulty(), &expected_difficulty); + flushln!("ok"); + } + vec![] +} + +mod difficulty_test_byzantium { + use super::json_difficulty_test; + + fn do_json_test(json_data: &[u8]) -> Vec { + json_difficulty_test(json_data, ::ethereum::new_byzantium_test()) + } + + declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"} +} + + +mod difficulty_test_foundation { + use super::json_difficulty_test; + use tempdir::TempDir; + + fn do_json_test(json_data: &[u8]) -> Vec { + let tempdir = TempDir::new("").unwrap(); + json_difficulty_test(json_data, ::ethereum::new_foundation(&tempdir.path())) + } + + declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"} +} + + + diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index f7b4bbe81d9c4d618bce7df5cecf2cc93bbf4614..0ec60d49319f22e05f5b7f30108236280f9f66d0 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -18,7 +18,6 @@ use std::sync::Arc; use super::test_common::*; use state::{Backend as StateBackend, State, Substate}; use executive::*; -use engines::Engine; use evm::{VMType, Finalize}; use vm::{ self, ActionParams, CallType, Schedule, Ext, @@ -26,10 +25,15 @@ use vm::{ CreateContractAddress, ReturnData, }; use externalities::*; -use tests::helpers::*; +use tests::helpers::get_temp_state; use ethjson; use trace::{Tracer, NoopTracer}; use trace::{VMTracer, NoopVMTracer}; +use bytes::{Bytes, BytesRef}; +use trie; +use rlp::RlpStream; +use hash::keccak; +use machine::EthereumMachine as Machine; #[derive(Debug, PartialEq, Clone)] struct CallCreate { @@ -53,22 +57,22 @@ impl From for CallCreate { /// Tiny wrapper around executive externalities. /// Stores callcreates. -struct TestExt<'a, T: 'a, V: 'a, B: 'a, E: 'a> - where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized +struct TestExt<'a, T: 'a, V: 'a, B: 'a> + where T: Tracer, V: VMTracer, B: StateBackend { - ext: Externalities<'a, T, V, B, E>, + ext: Externalities<'a, T, V, B>, callcreates: Vec, nonce: U256, sender: Address, } -impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> TestExt<'a, T, V, B, E> - where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized +impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B> + where T: Tracer, V: VMTracer, B: StateBackend, { fn new( state: &'a mut State, info: &'a EnvInfo, - engine: &'a E, + machine: &'a Machine, depth: usize, origin_info: OriginInfo, substate: &'a mut Substate, @@ -80,15 +84,15 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> TestExt<'a, T, V, B, E> let static_call = false; Ok(TestExt { nonce: state.nonce(&address)?, - ext: Externalities::new(state, info, engine, depth, origin_info, substate, output, tracer, vm_tracer, static_call), + ext: Externalities::new(state, info, machine, depth, origin_info, substate, output, tracer, vm_tracer, static_call), callcreates: vec![], sender: address, }) } } -impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> - where T: Tracer, V: VMTracer, B: StateBackend, E: Engine + ?Sized +impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> + where T: Tracer, V: VMTracer, B: StateBackend { fn storage_at(&self, key: &H256) -> vm::Result { self.ext.storage_at(key) @@ -160,8 +164,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> self.ext.log(topics, data) } - fn ret(self, gas: &U256, data: &ReturnData) -> Result { - self.ext.ret(gas, data) + fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> Result { + self.ext.ret(gas, data, apply_state) } fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> { @@ -180,6 +184,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> 0 } + fn is_static(&self) -> bool { + false + } + fn inc_sstore_clears(&mut self) { self.ext.inc_sstore_clears() } @@ -223,7 +231,12 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { let mut state = get_temp_state(); state.populate_from(From::from(vm.pre_state.clone())); let info = From::from(vm.env); - let engine = TestEngine::new(1); + let machine = { + let mut machine = ::ethereum::new_frontier_test_machine(); + machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = 1)); + machine + }; + let params = ActionParams::from(vm.transaction); let mut substate = Substate::new(); @@ -237,7 +250,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { let mut ex = try_fail!(TestExt::new( &mut state, &info, - &engine, + &machine, 0, OriginInfo::from(¶ms), &mut substate, @@ -246,13 +259,21 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { &mut tracer, &mut vm_tracer, )); - let mut evm = vm_factory.create(params.gas); + let mut evm = vm_factory.create(¶ms, &machine.schedule(0u64.into())); let res = evm.exec(params, &mut ex); // a return in finalize will not alter callcreates let callcreates = ex.callcreates.clone(); (res.finalize(ex), callcreates) }; + let log_hash = { + let mut rlp = RlpStream::new_list(substate.logs.len()); + for l in &substate.logs { + rlp.append(l); + } + keccak(&rlp.drain()) + }; + match res { Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."), Ok(res) => { @@ -260,6 +281,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { fail_unless(Some(res.gas_left) == vm.gas_left.map(Into::into), "gas_left is incorrect"); let vm_output: Option> = vm.output.map(Into::into); fail_unless(Some(output) == vm_output, "output is incorrect"); + fail_unless(Some(log_hash) == vm.logs.map(|h| h.0), "logs are incorrect"); for (address, account) in vm.post_state.unwrap().into_iter() { let address = address.into(); @@ -293,15 +315,15 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { } declare_test!{ExecutiveTests_vmArithmeticTest, "VMTests/vmArithmeticTest"} -declare_test!{ExecutiveTests_vmBitwiseLogicOperationTest, "VMTests/vmBitwiseLogicOperationTest"} +declare_test!{ExecutiveTests_vmBitwiseLogicOperationTest, "VMTests/vmBitwiseLogicOperation"} declare_test!{ExecutiveTests_vmBlockInfoTest, "VMTests/vmBlockInfoTest"} // TODO [todr] Fails with Signal 11 when using JIT -declare_test!{ExecutiveTests_vmEnvironmentalInfoTest, "VMTests/vmEnvironmentalInfoTest"} -declare_test!{ExecutiveTests_vmIOandFlowOperationsTest, "VMTests/vmIOandFlowOperationsTest"} -declare_test!{heavy => ExecutiveTests_vmInputLimits, "VMTests/vmInputLimits"} +declare_test!{ExecutiveTests_vmEnvironmentalInfoTest, "VMTests/vmEnvironmentalInfo"} +declare_test!{ExecutiveTests_vmIOandFlowOperationsTest, "VMTests/vmIOandFlowOperations"} declare_test!{ExecutiveTests_vmLogTest, "VMTests/vmLogTest"} -declare_test!{ExecutiveTests_vmPerformanceTest, "VMTests/vmPerformanceTest"} +declare_test!{heavy => ExecutiveTests_vmPerformance, "VMTests/vmPerformance"} declare_test!{ExecutiveTests_vmPushDupSwapTest, "VMTests/vmPushDupSwapTest"} +declare_test!{ExecutiveTests_vmRandomTest, "VMTests/vmRandomTest"} declare_test!{ExecutiveTests_vmSha3Test, "VMTests/vmSha3Test"} -declare_test!{ExecutiveTests_vmSystemOperationsTest, "VMTests/vmSystemOperationsTest"} -declare_test!{ExecutiveTests_vmtests, "VMTests/vmtests"} +declare_test!{ExecutiveTests_vmSystemOperationsTest, "VMTests/vmSystemOperations"} +declare_test!{ExecutiveTests_vmTests, "VMTests/vmTests"} diff --git a/ethcore/src/json_tests/homestead_chain.rs b/ethcore/src/json_tests/homestead_chain.rs deleted file mode 100644 index 5f0fe5769ee9385eecd919356737005b04fe39fe..0000000000000000000000000000000000000000 --- a/ethcore/src/json_tests/homestead_chain.rs +++ /dev/null @@ -1,39 +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 . - -use super::chain::json_chain_test; -use tests::helpers::*; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Homestead) -} - -declare_test!{BlockchainTests_Homestead_bcBlockGasLimitTest, "BlockchainTests/Homestead/bcBlockGasLimitTest"} -declare_test!{BlockchainTests_Homestead_bcForkStressTest, "BlockchainTests/Homestead/bcForkStressTest"} -declare_test!{BlockchainTests_Homestead_bcGasPricerTest, "BlockchainTests/Homestead/bcGasPricerTest"} -declare_test!{BlockchainTests_Homestead_bcInvalidHeaderTest, "BlockchainTests/Homestead/bcInvalidHeaderTest"} -declare_test!{BlockchainTests_Homestead_bcInvalidRLPTest, "BlockchainTests/Homestead/bcInvalidRLPTest"} -declare_test!{BlockchainTests_Homestead_bcMultiChainTest, "BlockchainTests/Homestead/bcMultiChainTest"} -declare_test!{BlockchainTests_Homestead_bcRPC_API_Test, "BlockchainTests/Homestead/bcRPC_API_Test"} -declare_test!{BlockchainTests_Homestead_bcStateTest, "BlockchainTests/Homestead/bcStateTest"} -declare_test!{BlockchainTests_Homestead_bcTotalDifficultyTest, "BlockchainTests/Homestead/bcTotalDifficultyTest"} -declare_test!{BlockchainTests_Homestead_bcUncleHeaderValiditiy, "BlockchainTests/Homestead/bcUncleHeaderValiditiy"} -declare_test!{BlockchainTests_Homestead_bcUncleTest, "BlockchainTests/Homestead/bcUncleTest"} -declare_test!{BlockchainTests_Homestead_bcValidBlockTest, "BlockchainTests/Homestead/bcValidBlockTest"} -declare_test!{BlockchainTests_Homestead_bcWalletTest, "BlockchainTests/Homestead/bcWalletTest"} -declare_test!{BlockchainTests_Homestead_bcShanghaiLove, "BlockchainTests/Homestead/bcShanghaiLove"} -declare_test!{BlockchainTests_Homestead_bcSuicideIssue, "BlockchainTests/Homestead/bcSuicideIssue"} -declare_test!{BlockchainTests_Homestead_bcExploitTest, "BlockchainTests/Homestead/bcExploitTest"} diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index 40678207259f652511cd052f0336fba18d90dc06..a0966a2d29e8856196deb60a3d41332698d91e6b 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -21,5 +21,5 @@ mod transaction; mod executive; mod state; mod chain; -mod homestead_chain; mod trie; +mod difficulty; diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 51961a2bbebd416c4987af655d5344aae5612c83..a55ab18443dad30fe20d5c56d6c58fd7fee8d224 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -51,7 +51,7 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec { let result = || -> Result<_, EvmTestError> { Ok(EvmTestClient::from_pod_state(spec, pre.clone())? - .transact(&env, transaction, trace::NoopVMTracer)) + .transact(&env, transaction, trace::NoopTracer, trace::NoopVMTracer)) }; match result() { Err(err) => { @@ -97,9 +97,8 @@ mod state_tests { } declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"} - declare_test!{GeneralStateTest_stBoundsTest, "GeneralStateTests/stBoundsTest/"} + declare_test!{GeneralStateTest_stBadOpcodeTest, "GeneralStateTests/stBadOpcode/"} declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"} - declare_test!{skip => [ "createJS_ExampleContract" ], GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} @@ -108,6 +107,7 @@ mod state_tests { declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} + declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"} declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} @@ -121,15 +121,18 @@ mod state_tests { declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"} declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} - declare_test!{skip => [ "RevertDepthCreateAddressCollision" ], GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} + declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"} + declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"} declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"} declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"} + declare_test!{GeneralStateTest_stStaticCall, "GeneralStateTests/stStaticCall/"} declare_test!{GeneralStateTest_stSystemOperationsTest, "GeneralStateTests/stSystemOperationsTest/"} declare_test!{GeneralStateTest_stTransactionTest, "GeneralStateTests/stTransactionTest/"} declare_test!{GeneralStateTest_stTransitionTest, "GeneralStateTests/stTransitionTest/"} declare_test!{GeneralStateTest_stWalletTest, "GeneralStateTests/stWalletTest/"} declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} + declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"} } diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index fa107877635d40ded20a43017bfc8e538c56adb7..83f6b55272d5e87e2ca6afdff3dc56e500f735a2 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -14,12 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -pub use util::*; use std::collections::HashSet; use std::io::Read; use std::fs::{File, read_dir}; use std::path::Path; use std::ffi::OsString; +pub use ethereum_types::{H256, U256, Address}; pub fn run_test_path(p: &Path, skip: &[&'static str], runner: fn (json_data: &[u8]) -> Vec) { let path = Path::new(p); @@ -50,7 +50,8 @@ pub fn run_test_file(path: &Path, runner: fn (json_data: &[u8]) -> Vec) let mut file = File::open(&path).expect("Error opening test file"); file.read_to_end(&mut data).expect("Error reading test file"); let results = runner(&data); - assert!(results.is_empty()); + let empty: [String; 0] = []; + assert_eq!(results, empty); } macro_rules! test { diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index 3d71a5fafde9e2b7c55a930ef77fde05126747be..b7445c51ad3adca47889535008ddc08aceb0c019 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -25,7 +25,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { let mut failed = Vec::new(); let frontier_schedule = evm::Schedule::new_frontier(); let homestead_schedule = evm::Schedule::new_homestead(); - let metropolis_schedule = evm::Schedule::new_metropolis(); + let byzantium_schedule = evm::Schedule::new_byzantium(); for (name, test) in tests.into_iter() { let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); }; @@ -34,7 +34,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { None => &frontier_schedule, Some(x) if x < 1_150_000 => &frontier_schedule, Some(x) if x < 3_000_000 => &homestead_schedule, - Some(_) => &metropolis_schedule + Some(_) => &byzantium_schedule }; let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000); let allow_unsigned = number.map_or(false, |n| n >= 3_000_000); @@ -42,8 +42,10 @@ fn do_json_test(json_data: &[u8]) -> Vec { let rlp: Vec = test.rlp.into(); let res = UntrustedRlp::new(&rlp) .as_val() - .map_err(From::from) - .and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned)); + .map_err(::error::Error::from) + .and_then(|t: UnverifiedTransaction| { + t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned).map_err(Into::into) + }); fail_unless(test.transaction.is_none() == res.is_err(), "Validity different"); if let (Some(tx), Some(sender)) = (test.transaction, test.sender) { @@ -75,18 +77,13 @@ fn do_json_test(json_data: &[u8]) -> Vec { failed } -declare_test!{TransactionTests_ttTransactionTest, "TransactionTests/ttTransactionTest"} -declare_test!{heavy => TransactionTests_tt10mbDataField, "TransactionTests/tt10mbDataField"} -declare_test!{TransactionTests_ttWrongRLPTransaction, "TransactionTests/ttWrongRLPTransaction"} -declare_test!{TransactionTests_Homestead_ttTransactionTest, "TransactionTests/Homestead/ttTransactionTest"} -declare_test!{heavy => TransactionTests_Homestead_tt10mbDataField, "TransactionTests/Homestead/tt10mbDataField"} -declare_test!{TransactionTests_Homestead_ttWrongRLPTransaction, "TransactionTests/Homestead/ttWrongRLPTransaction"} -declare_test!{TransactionTests_RandomTests_tr201506052141PYTHON, "TransactionTests/RandomTests/tr201506052141PYTHON"} -declare_test!{TransactionTests_Homestead_ttTransactionTestEip155VitaliksTests, "TransactionTests/Homestead/ttTransactionTestEip155VitaliksTests"} -declare_test!{TransactionTests_EIP155_ttTransactionTest, "TransactionTests/EIP155/ttTransactionTest"} -declare_test!{TransactionTests_EIP155_ttTransactionTestEip155VitaliksTests, "TransactionTests/EIP155/ttTransactionTestEip155VitaliksTests"} -declare_test!{TransactionTests_EIP155_ttTransactionTestVRule, "TransactionTests/EIP155/ttTransactionTestVRule"} - -declare_test!{TransactionTests_Metropolis_ttMetropolisTest, "TransactionTests/Metropolis/ttMetropolisTest"} -declare_test!{TransactionTests_Metropolis_ttTransactionTest, "TransactionTests/Metropolis/ttTransactionTest"} -declare_test!{TransactionTests_Metropolis_ttTransactionTestZeroSig, "TransactionTests/Metropolis/ttTransactionTestZeroSig"} +declare_test!{TransactionTests_ttEip155VitaliksHomesead, "TransactionTests/ttEip155VitaliksHomesead"} +declare_test!{TransactionTests_ttEip155VitaliksEip158, "TransactionTests/ttEip155VitaliksEip158"} +declare_test!{TransactionTests_ttEip158, "TransactionTests/ttEip158"} +declare_test!{TransactionTests_ttFrontier, "TransactionTests/ttFrontier"} +declare_test!{TransactionTests_ttHomestead, "TransactionTests/ttHomestead"} +declare_test!{TransactionTests_ttVRuleEip158, "TransactionTests/ttVRuleEip158"} +declare_test!{TransactionTests_ttWrongRLPFrontier, "TransactionTests/ttWrongRLPFrontier"} +declare_test!{TransactionTests_ttWrongRLPHomestead, "TransactionTests/ttWrongRLPHomestead"} +declare_test!{TransactionTests_ttConstantinople, "TransactionTests/ttConstantinople"} +declare_test!{TransactionTests_ttSpecConstantinople, "TransactionTests/ttSpecConstantinople"} diff --git a/ethcore/src/json_tests/trie.rs b/ethcore/src/json_tests/trie.rs index 0b1fd949ae851a0566ea2e9de9560afae57e163a..f5803d2d372e5274f0833c6bde0e6977ee8275a2 100644 --- a/ethcore/src/json_tests/trie.rs +++ b/ethcore/src/json_tests/trie.rs @@ -15,9 +15,9 @@ // along with Parity. If not, see . use ethjson; -use util::trie::{TrieFactory, TrieSpec}; -use util::hash::H256; -use util::memorydb::MemoryDB; +use trie::{TrieFactory, TrieSpec}; +use ethereum_types::H256; +use memorydb::MemoryDB; fn test_trie(json: &[u8], trie: TrieSpec) -> Vec { let tests = ethjson::trie::Test::load(json).unwrap(); @@ -49,7 +49,7 @@ fn test_trie(json: &[u8], trie: TrieSpec) -> Vec { } mod generic { - use util::trie::TrieSpec; + use trie::TrieSpec; fn do_json_test(json: &[u8]) -> Vec { super::test_trie(json, TrieSpec::Generic) @@ -60,7 +60,7 @@ mod generic { } mod secure { - use util::trie::TrieSpec; + use trie::TrieSpec; fn do_json_test(json: &[u8]) -> Vec { super::test_trie(json, TrieSpec::Secure) diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 15d44626b2f246b7519229299b6ccf8becc770ea..343cef9f4165760cbb6e6490d33d8c4e5f3abcb5 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -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 when implementing From> -#![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 //! @@ -71,58 +54,79 @@ //! cargo build --release //! ``` -extern crate bit_set; extern crate bloomchain; extern crate bn; extern crate byteorder; extern crate crossbeam; extern crate common_types as types; extern crate crypto; -extern crate env_logger; -extern crate ethabi; extern crate ethash; extern crate ethcore_bloom_journal as bloom_journal; -extern crate ethcore_devtools as devtools; extern crate ethcore_io as io; -extern crate ethcore_ipc_nano as nanoipc; +extern crate ethcore_bytes as bytes; extern crate ethcore_logger; +extern crate ethcore_miner; extern crate ethcore_stratum; +extern crate ethcore_transaction as transaction; +extern crate ethereum_types; extern crate ethjson; extern crate ethkey; -extern crate futures; +extern crate futures_cpupool; extern crate hardware_wallet; -extern crate hyper; +extern crate hashdb; extern crate itertools; -extern crate linked_hash_map; extern crate lru_cache; -extern crate native_contracts; extern crate num_cpus; extern crate num; +extern crate parity_machine; +extern crate parking_lot; extern crate price_info; extern crate rand; +extern crate rayon; extern crate rlp; +extern crate rlp_compress; +extern crate keccak_hash as hash; +extern crate heapsize; +extern crate memorydb; +extern crate patricia_trie as trie; +extern crate triehash; +extern crate ansi_term; +extern crate unexpected; +extern crate kvdb; +extern crate kvdb_rocksdb; +extern crate kvdb_memorydb; +extern crate util_error; +extern crate snappy; +extern crate migration; + +extern crate ethabi; +#[macro_use] +extern crate ethabi_derive; +#[macro_use] +extern crate ethabi_contract; #[macro_use] extern crate rlp_derive; extern crate rustc_hex; -extern crate semver; extern crate stats; -extern crate time; -extern crate transient_hashmap; +extern crate stop_guard; extern crate using_queue; extern crate table; -extern crate bloomable; extern crate vm; extern crate wasm; +extern crate memory_cache; +extern crate journaldb; +#[cfg(test)] +extern crate tempdir; #[macro_use] -extern crate log; +extern crate macros; #[macro_use] -extern crate ethcore_util as util; +extern crate log; #[macro_use] extern crate lazy_static; #[macro_use] -extern crate ethcore_ipc as ipc; +extern crate trace_time; #[cfg_attr(test, macro_use)] extern crate evm; @@ -141,29 +145,27 @@ pub mod error; pub mod ethereum; pub mod executed; pub mod header; -pub mod migrations; +pub mod machine; pub mod miner; pub mod pod_state; -pub mod service; pub mod snapshot; pub mod spec; pub mod state; +pub mod state_db; pub mod trace; -pub mod transaction; pub mod verification; pub mod views; mod cache_manager; mod blooms; -mod basic_types; mod pod_account; -mod state_db; mod account_db; mod builtin; mod executive; mod externalities; mod blockchain; mod factory; +mod tx_filter; #[cfg(test)] mod tests; diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs new file mode 100644 index 0000000000000000000000000000000000000000..ad36aa69d795736fd81aa351c28d436b496fc9b7 --- /dev/null +++ b/ethcore/src/machine.rs @@ -0,0 +1,540 @@ +// 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 . + +//! Ethereum-like state machine definition. + +use std::collections::{BTreeMap, HashMap}; +use std::cmp; +use std::sync::Arc; + +use block::{ExecutedBlock, IsBlock}; +use builtin::Builtin; +use client::{BlockInfo, CallContract}; +use error::Error; +use executive::Executive; +use header::{BlockNumber, Header}; +use spec::CommonParams; +use state::{CleanupMode, Substate}; +use trace::{NoopTracer, NoopVMTracer, Tracer, ExecutiveTracer, RewardType, Tracing}; +use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction}; +use tx_filter::TransactionFilter; + +use ethereum_types::{U256, Address}; +use bytes::BytesRef; +use vm::{CallType, ActionParams, ActionValue, ParamsType}; +use vm::{EnvInfo, Schedule, CreateContractAddress}; + +/// Parity tries to round block.gas_limit to multiple of this constant +pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); + +/// Ethash-specific extensions. +#[derive(Debug, Clone)] +pub struct EthashExtensions { + /// Homestead transition block number. + pub homestead_transition: BlockNumber, + /// EIP150 transition block number. + pub eip150_transition: BlockNumber, + /// Number of first block where EIP-160 rules begin. + pub eip160_transition: u64, + /// Number of first block where EIP-161.abc begin. + pub eip161abc_transition: u64, + /// Number of first block where EIP-161.d begins. + pub eip161d_transition: u64, + /// DAO hard-fork transition block (X). + pub dao_hardfork_transition: u64, + /// DAO hard-fork refund contract address (C). + pub dao_hardfork_beneficiary: Address, + /// DAO hard-fork DAO accounts list (L) + pub dao_hardfork_accounts: Vec
, +} + +impl From<::ethjson::spec::EthashParams> for EthashExtensions { + fn from(p: ::ethjson::spec::EthashParams) -> Self { + EthashExtensions { + homestead_transition: p.homestead_transition.map_or(0, Into::into), + eip150_transition: p.eip150_transition.map_or(0, Into::into), + eip160_transition: p.eip160_transition.map_or(0, Into::into), + eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into), + eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into), + dao_hardfork_transition: p.dao_hardfork_transition.map_or(u64::max_value(), Into::into), + dao_hardfork_beneficiary: p.dao_hardfork_beneficiary.map_or_else(Address::new, Into::into), + dao_hardfork_accounts: p.dao_hardfork_accounts.unwrap_or_else(Vec::new).into_iter().map(Into::into).collect(), + } + } +} + +/// Special rules to be applied to the schedule. +pub type ScheduleCreationRules = Fn(&mut Schedule, BlockNumber) + Sync + Send; + +/// An ethereum-like state machine. +pub struct EthereumMachine { + params: CommonParams, + builtins: Arc>, + tx_filter: Option>, + ethash_extensions: Option, + schedule_rules: Option>, +} + +impl EthereumMachine { + /// Regular ethereum machine. + pub fn regular(params: CommonParams, builtins: BTreeMap) -> EthereumMachine { + let tx_filter = TransactionFilter::from_params(¶ms).map(Arc::new); + EthereumMachine { + params: params, + builtins: Arc::new(builtins), + tx_filter: tx_filter, + ethash_extensions: None, + schedule_rules: None, + } + } + + /// Ethereum machine with ethash extensions. + // TODO: either unify or specify to mainnet specifically and include other specific-chain HFs? + pub fn with_ethash_extensions(params: CommonParams, builtins: BTreeMap, extensions: EthashExtensions) -> EthereumMachine { + let mut machine = EthereumMachine::regular(params, builtins); + machine.ethash_extensions = Some(extensions); + machine + } + + /// Attach special rules to the creation of schedule. + pub fn set_schedule_creation_rules(&mut self, rules: Box) { + self.schedule_rules = Some(rules); + } + + /// Get a reference to the ethash-specific extensions. + pub fn ethash_extensions(&self) -> Option<&EthashExtensions> { + self.ethash_extensions.as_ref() + } +} + +impl EthereumMachine { + /// Execute a call as the system address. + pub fn execute_as_system( + &self, + block: &mut ExecutedBlock, + contract_address: Address, + gas: U256, + data: Option>, + ) -> Result, Error> { + let env_info = { + let mut env_info = block.env_info(); + env_info.gas_limit = env_info.gas_used + gas; + env_info + }; + + let mut state = block.state_mut(); + let params = ActionParams { + code_address: contract_address.clone(), + address: contract_address.clone(), + sender: SYSTEM_ADDRESS.clone(), + origin: SYSTEM_ADDRESS.clone(), + gas: gas, + gas_price: 0.into(), + value: ActionValue::Transfer(0.into()), + code: state.code(&contract_address)?, + code_hash: Some(state.code_hash(&contract_address)?), + data: data, + call_type: CallType::Call, + params_type: ParamsType::Separate, + }; + let mut ex = Executive::new(&mut state, &env_info, self); + let mut substate = Substate::new(); + let mut output = Vec::new(); + if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) { + warn!("Encountered error on making system call: {}", e); + } + + Ok(output) + } + + /// Push last known block hash to the state. + fn push_last_hash(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + let params = self.params(); + if block.header().number() == params.eip210_transition { + let state = block.state_mut(); + state.init_code(¶ms.eip210_contract_address, params.eip210_contract_code.clone())?; + } + if block.header().number() >= params.eip210_transition { + let parent_hash = block.header().parent_hash().clone(); + let _ = self.execute_as_system( + block, + params.eip210_contract_address, + params.eip210_contract_gas, + Some(parent_hash.to_vec()), + )?; + } + Ok(()) + } + + /// Logic to perform on a new block: updating last hashes and the DAO + /// fork, for ethash. + pub fn on_new_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { + self.push_last_hash(block)?; + + if let Some(ref ethash_params) = self.ethash_extensions { + if block.header().number() == ethash_params.dao_hardfork_transition { + let state = block.state_mut(); + for child in ðash_params.dao_hardfork_accounts { + let beneficiary = ðash_params.dao_hardfork_beneficiary; + state.balance(child) + .and_then(|b| state.transfer_balance(child, beneficiary, &b, CleanupMode::NoEmpty))?; + } + } + } + + Ok(()) + } + + /// Populate a header's fields based on its parent's header. + /// Usually implements the chain scoring rule based on weight. + /// The gas floor target must not be lower than the engine's minimum gas limit. + pub fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, gas_ceil_target: U256) { + header.set_difficulty(parent.difficulty().clone()); + + if let Some(ref ethash_params) = self.ethash_extensions { + let gas_limit = { + let gas_limit = parent.gas_limit().clone(); + let bound_divisor = self.params().gas_limit_bound_divisor; + let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into(); + let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); + let gas_limit = if gas_limit < gas_floor_target { + let gas_limit = cmp::min(gas_floor_target, upper_limit); + round_block_gas_limit(gas_limit, lower_limit, upper_limit) + } else if gas_limit > gas_ceil_target { + let gas_limit = cmp::max(gas_ceil_target, lower_limit); + round_block_gas_limit(gas_limit, lower_limit, upper_limit) + } else { + let total_lower_limit = cmp::max(lower_limit, gas_floor_target); + let total_upper_limit = cmp::min(upper_limit, gas_ceil_target); + let gas_limit = cmp::max(gas_floor_target, cmp::min(total_upper_limit, + lower_limit + (header.gas_used().clone() * 6u32 / 5.into()) / bound_divisor)); + round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) + }; + // ensure that we are not violating protocol limits + debug_assert!(gas_limit >= lower_limit); + debug_assert!(gas_limit <= upper_limit); + gas_limit + }; + + header.set_gas_limit(gas_limit); + if header.number() >= ethash_params.dao_hardfork_transition && + header.number() <= ethash_params.dao_hardfork_transition + 9 { + header.set_extra_data(b"dao-hard-fork"[..].to_owned()); + } + return + } + + header.set_gas_limit({ + let gas_limit = parent.gas_limit().clone(); + let bound_divisor = self.params().gas_limit_bound_divisor; + if gas_limit < gas_floor_target { + cmp::min(gas_floor_target, gas_limit + gas_limit / bound_divisor - 1.into()) + } else { + cmp::max(gas_floor_target, gas_limit - gas_limit / bound_divisor + 1.into()) + } + }); + } + + /// Get the general parameters of the chain. + pub fn params(&self) -> &CommonParams { + &self.params + } + + /// Get the EVM schedule for the given block number. + pub fn schedule(&self, block_number: BlockNumber) -> Schedule { + let mut schedule = match self.ethash_extensions { + None => self.params.schedule(block_number), + Some(ref ext) => { + if block_number < ext.homestead_transition { + Schedule::new_frontier() + } else if block_number < ext.eip150_transition { + Schedule::new_homestead() + } else { + let max_code_size = self.params.max_code_size(block_number); + let mut schedule = Schedule::new_post_eip150( + max_code_size as _, + block_number >= ext.eip160_transition, + block_number >= ext.eip161abc_transition, + block_number >= ext.eip161d_transition + ); + + self.params.update_schedule(block_number, &mut schedule); + schedule + } + } + }; + + if let Some(ref rules) = self.schedule_rules { + (rules)(&mut schedule, block_number) + } + + schedule + } + + /// Builtin-contracts for the chain.. + pub fn builtins(&self) -> &BTreeMap { + &*self.builtins + } + + /// Attempt to get a handle to a built-in contract. + /// Only returns references to activated built-ins. + // TODO: builtin contract routing - to do this properly, it will require removing the built-in configuration-reading logic + // from Spec into here and removing the Spec::builtins field. + pub fn builtin(&self, a: &Address, block_number: BlockNumber) -> Option<&Builtin> { + self.builtins() + .get(a) + .and_then(|b| if b.is_active(block_number) { Some(b) } else { None }) + } + + /// Some intrinsic operation parameters; by default they take their value from the `spec()`'s `engine_params`. + pub fn maximum_extra_data_size(&self) -> usize { self.params().maximum_extra_data_size } + + /// The nonce with which accounts begin at given block. + pub fn account_start_nonce(&self, block: u64) -> U256 { + let params = self.params(); + + if block >= params.dust_protection_transition { + U256::from(params.nonce_cap_increment) * U256::from(block) + } else { + params.account_start_nonce + } + } + + /// The network ID that transactions should be signed with. + pub fn signing_chain_id(&self, env_info: &EnvInfo) -> Option { + let params = self.params(); + + if env_info.number >= params.eip155_transition { + Some(params.chain_id) + } else { + None + } + } + + /// Returns new contract address generation scheme at given block number. + pub fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress { + if number >= self.params().eip86_transition { + CreateContractAddress::FromCodeHash + } else { + CreateContractAddress::FromSenderAndNonce + } + } + + /// Verify a particular transaction is valid, regardless of order. + pub fn verify_transaction_unordered(&self, t: UnverifiedTransaction, _header: &Header) -> Result { + Ok(SignedTransaction::new(t)?) + } + + /// Does basic verification of the transaction. + pub fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> Result<(), Error> { + let check_low_s = match self.ethash_extensions { + Some(ref ext) => header.number() >= ext.homestead_transition, + None => true, + }; + + let chain_id = if header.number() < self.params().validate_chain_id_transition { + t.chain_id() + } else if header.number() >= self.params().eip155_transition { + Some(self.params().chain_id) + } else { + None + }; + t.verify_basic(check_low_s, chain_id, false)?; + + Ok(()) + } + + /// Does verification of the transaction against the parent state. + // TODO: refine the bound here to be a "state provider" or similar as opposed + // to full client functionality. + pub fn verify_transaction(&self, t: &SignedTransaction, header: &Header, client: &C) -> Result<(), Error> { + if let Some(ref filter) = self.tx_filter.as_ref() { + if !filter.transaction_allowed(header.parent_hash(), t, client) { + return Err(transaction::Error::NotAllowed.into()) + } + } + + Ok(()) + } + + /// Additional params. + pub fn additional_params(&self) -> HashMap { + hash_map![ + "registrar".to_owned() => format!("{:x}", self.params.registrar) + ] + } +} + +/// Auxiliary data fetcher for an Ethereum machine. In Ethereum-like machines +/// there are two kinds of auxiliary data: bodies and receipts. +#[derive(Default, Clone)] +pub struct AuxiliaryData<'a> { + /// The full block bytes, including the header. + pub bytes: Option<&'a [u8]>, + /// The block receipts. + pub receipts: Option<&'a [::receipt::Receipt]>, +} + +/// Type alias for a function we can make calls through synchronously. +/// Returns the call result and state proof for each call. +pub type Call<'a> = Fn(Address, Vec) -> Result<(Vec, Vec>), String> + 'a; + +/// Request for auxiliary data of a block. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum AuxiliaryRequest { + /// Needs the body. + Body, + /// Needs the receipts. + Receipts, + /// Needs both body and receipts. + Both, +} + +impl ::parity_machine::Machine for EthereumMachine { + type Header = Header; + + type LiveBlock = ExecutedBlock; + type EngineClient = ::client::EngineClient; + type AuxiliaryRequest = AuxiliaryRequest; + + type Error = Error; +} + +impl<'a> ::parity_machine::LocalizedMachine<'a> for EthereumMachine { + type StateContext = Call<'a>; + type AuxiliaryData = AuxiliaryData<'a>; +} + +impl ::parity_machine::WithBalances for EthereumMachine { + fn balance(&self, live: &ExecutedBlock, address: &Address) -> Result { + live.state().balance(address).map_err(Into::into) + } + + fn add_balance(&self, live: &mut ExecutedBlock, address: &Address, amount: &U256) -> Result<(), Error> { + live.state_mut().add_balance(address, amount, CleanupMode::NoEmpty).map_err(Into::into) + } + + fn note_rewards( + &self, + live: &mut Self::LiveBlock, + direct: &[(Address, U256)], + indirect: &[(Address, U256)], + ) -> Result<(), Self::Error> { + if let Tracing::Enabled(ref mut traces) = *live.traces_mut() { + let mut tracer = ExecutiveTracer::default(); + + for &(address, amount) in direct { + tracer.trace_reward(address, amount, RewardType::Block); + } + + for &(address, amount) in indirect { + tracer.trace_reward(address, amount, RewardType::Uncle); + } + + traces.push(tracer.drain().into()); + } + + Ok(()) + } +} + +// Try to round gas_limit a bit so that: +// 1) it will still be in desired range +// 2) it will be a nearest (with tendency to increase) multiple of PARITY_GAS_LIMIT_DETERMINANT +fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { + let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); + if increased_gas_limit > upper_limit { + let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; + if decreased_gas_limit < lower_limit { + gas_limit + } else { + decreased_gas_limit + } + } else { + increased_gas_limit + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + fn get_default_ethash_extensions() -> EthashExtensions { + EthashExtensions { + homestead_transition: 1150000, + eip150_transition: u64::max_value(), + eip160_transition: u64::max_value(), + eip161abc_transition: u64::max_value(), + eip161d_transition: u64::max_value(), + dao_hardfork_transition: u64::max_value(), + dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(), + dao_hardfork_accounts: Vec::new(), + } + } + + #[test] + fn ethash_gas_limit_is_multiple_of_determinant() { + use ethereum_types::U256; + + let spec = ::ethereum::new_homestead_test(); + let ethparams = get_default_ethash_extensions(); + + let machine = EthereumMachine::with_ethash_extensions( + spec.params().clone(), + Default::default(), + ethparams, + ); + + let mut parent = ::header::Header::new(); + let mut header = ::header::Header::new(); + header.set_number(1); + + // this test will work for this constant only + assert_eq!(PARITY_GAS_LIMIT_DETERMINANT, U256::from(37)); + + // when parent.gas_limit < gas_floor_target: + parent.set_gas_limit(U256::from(50_000)); + machine.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); + assert_eq!(*header.gas_limit(), U256::from(50_024)); + + // when parent.gas_limit > gas_ceil_target: + parent.set_gas_limit(U256::from(250_000)); + machine.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); + assert_eq!(*header.gas_limit(), U256::from(249_787)); + + // when parent.gas_limit is in miner's range + header.set_gas_used(U256::from(150_000)); + parent.set_gas_limit(U256::from(150_000)); + machine.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); + assert_eq!(*header.gas_limit(), U256::from(150_035)); + + // when parent.gas_limit is in miner's range + // && we can NOT increase it to be multiple of constant + header.set_gas_used(U256::from(150_000)); + parent.set_gas_limit(U256::from(150_000)); + machine.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(150_002)); + assert_eq!(*header.gas_limit(), U256::from(149_998)); + + // when parent.gas_limit is in miner's range + // && we can NOT increase it to be multiple of constant + // && we can NOT decrease it to be multiple of constant + header.set_gas_used(U256::from(150_000)); + parent.set_gas_limit(U256::from(150_000)); + machine.populate_from_parent(&mut header, &parent, U256::from(150_000), U256::from(150_002)); + assert_eq!(*header.gas_limit(), U256::from(150_002)); + } +} diff --git a/ethcore/src/migrations/blocks/v8.rs b/ethcore/src/migrations/blocks/v8.rs deleted file mode 100644 index ddade6847dfbd1c64b40f831bcdce33029501dd3..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/blocks/v8.rs +++ /dev/null @@ -1,37 +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 . - -//! This migration compresses the state db. - -use util::migration::{SimpleMigration, Progress}; -use rlp::{Compressible, UntrustedRlp, RlpType}; - -/// Compressing migration. -#[derive(Default)] -pub struct V8(Progress); - -impl SimpleMigration for V8 { - fn version(&self) -> u32 { - 8 - } - - fn columns(&self) -> Option { None } - - fn simple_migrate(&mut self, key: Vec, value: Vec) -> Option<(Vec, Vec)> { - self.0.tick(); - Some((key,UntrustedRlp::new(&value).compress(RlpType::Blocks).into_vec())) - } -} diff --git a/ethcore/src/migrations/extras/mod.rs b/ethcore/src/migrations/extras/mod.rs deleted file mode 100644 index 01fddc66af184d5b64b106e3c01ea07e8e64a369..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/extras/mod.rs +++ /dev/null @@ -1,21 +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 . - -//! Extras database migrations. - -mod v6; - -pub use self::v6::ToV6; \ No newline at end of file diff --git a/ethcore/src/migrations/extras/v6.rs b/ethcore/src/migrations/extras/v6.rs deleted file mode 100644 index 638a64a838b66ed63c0d6db55c04fda2632b6b9e..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/extras/v6.rs +++ /dev/null @@ -1,102 +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 . - -use util::migration::SimpleMigration; - -/// This migration reduces the sizes of keys and moves `ExtrasIndex` byte from back to the front. -pub struct ToV6; - -impl ToV6 { - fn migrate_old_key(&self, old_key: Vec, index: u8, len: usize) -> Vec { - let mut result = vec![]; - result.reserve(len); - unsafe { - result.set_len(len); - } - result[0] = index; - let old_key_start = 33 - len; - result[1..].clone_from_slice(&old_key[old_key_start..32]); - result - } -} - -impl SimpleMigration for ToV6 { - - fn columns(&self) -> Option { None } - - fn version(&self) -> u32 { 6 } - - fn simple_migrate(&mut self, mut key: Vec, value: Vec) -> Option<(Vec, Vec)> { - //// at this version all extras keys are 33 bytes long. - if key.len() == 33 { - // block details key changes: - // - index is moved to the front - if key[32] == 0 { - return Some((self.migrate_old_key(key, 0, 33), value)); - } - - // block hash key changes: - // - key is shorter 33 -> 5 bytes - // - index is moved to the front - if key[32] == 1 { - return Some((self.migrate_old_key(key, 1, 5), value)); - } - - // transaction addresses changes: - // - index is moved to the front - if key[32] == 2 { - return Some((self.migrate_old_key(key, 2, 33), value)); - } - - // block log blooms are removed - if key[32] == 3 { - return None; - } - - // blocks blooms key changes: - // - key is shorter 33 -> 6 bytes - // - index is moved to the front - // - index is changed 4 -> 3 - if key[32] == 4 { - key.reverse(); - // i have no idea why it was reversed - let reverse = key; - let result = vec![ - // new extras index is 3 - 3, - // 9th (+ prefix) byte was the level. Now it's second. - reverse[9], - reverse[4], - reverse[3], - reverse[2], - reverse[1], - ]; - - return Some((result, value)); - } - - // blocks receipts key changes: - // - index is moved to the front - // - index is changed 5 -> 4 - if key[32] == 5 { - return Some((self.migrate_old_key(key, 4, 33), value)); - } - } - - Some((key, value)) - } -} - diff --git a/ethcore/src/migrations/state/mod.rs b/ethcore/src/migrations/state/mod.rs deleted file mode 100644 index da4ef24846e149973e9f89e75104377b48afc7c6..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/state/mod.rs +++ /dev/null @@ -1,21 +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 . - -//! State database migrations. - -mod v7; - -pub use self::v7::{ArchiveV7, OverlayRecentV7}; \ No newline at end of file diff --git a/ethcore/src/migrations/state/v7.rs b/ethcore/src/migrations/state/v7.rs deleted file mode 100644 index 9a9a65d7b3a17a3fae29d0f508c1ca000d70a202..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/state/v7.rs +++ /dev/null @@ -1,263 +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 . - -//! This migration migrates the state db to use an accountdb which ensures uniqueness -//! using an address' hash as opposed to the address itself. - -use std::collections::HashMap; - -use util::Bytes; -use util::{Address, H256}; -use util::kvdb::Database; -use util::migration::{Batch, Config, Error, Migration, SimpleMigration, Progress}; -use util::sha3::Hashable; -use std::sync::Arc; - -use rlp::{decode, Rlp, RlpStream}; - -// attempt to migrate a key, value pair. None if migration not possible. -fn attempt_migrate(mut key_h: H256, val: &[u8]) -> Option { - let val_hash = val.sha3(); - - if key_h != val_hash { - // this is a key which has been xor'd with an address. - // recover the address. - let address = key_h ^ val_hash; - - // check that the address is actually a 20-byte value. - // the leftmost 12 bytes should be zero. - if &address[0..12] != &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] { - return None; - } - - let address_hash = Address::from(address).sha3(); - - // create the xor'd key in place. - key_h.copy_from_slice(&*val_hash); - assert_eq!(key_h, val_hash); - - { - let last_src: &[u8] = &*address_hash; - let last_dst: &mut [u8] = &mut *key_h; - for (k, a) in last_dst[12..].iter_mut().zip(&last_src[12..]) { - *k ^= *a; - } - } - - Some(key_h) - } else { - None - } -} - -/// Version for `ArchiveDB`. -#[derive(Default)] -pub struct ArchiveV7(Progress); - -impl SimpleMigration for ArchiveV7 { - - fn columns(&self) -> Option { None } - - fn version(&self) -> u32 { 7 } - - fn simple_migrate(&mut self, key: Vec, value: Vec) -> Option<(Vec, Vec)> { - self.0.tick(); - - if key.len() != 32 { - // metadata key, ignore. - return Some((key, value)); - } - - let key_h = H256::from_slice(&key[..]); - if let Some(new_key) = attempt_migrate(key_h, &value[..]) { - Some((new_key[..].to_owned(), value)) - } else { - Some((key, value)) - } - } -} - -// magic numbers and constants for overlay-recent at v6. -// re-written here because it may change in the journaldb module. -const V7_LATEST_ERA_KEY: &'static [u8] = &[ b'l', b'a', b's', b't', 0, 0, 0, 0, 0, 0, 0, 0 ]; -const V7_VERSION_KEY: &'static [u8] = &[ b'j', b'v', b'e', b'r', 0, 0, 0, 0, 0, 0, 0, 0 ]; -const DB_VERSION: u32 = 0x203; -const PADDING : [u8; 10] = [0u8; 10]; - -/// Version for `OverlayRecent` database. -/// more involved than the archive version because of journaling. -#[derive(Default)] -pub struct OverlayRecentV7 { - migrated_keys: HashMap, -} - -impl OverlayRecentV7 { - // walk all journal entries in the database backwards. - // find migrations for any possible inserted keys. - fn walk_journal(&mut self, source: Arc) -> Result<(), Error> { - if let Some(val) = source.get(None, V7_LATEST_ERA_KEY).map_err(Error::Custom)? { - let mut era = decode::(&val); - loop { - let mut index: usize = 0; - loop { - let entry_key = { - let mut r = RlpStream::new_list(3); - r.append(&era).append(&index).append(&&PADDING[..]); - r.out() - }; - - if let Some(journal_raw) = source.get(None, &entry_key).map_err(Error::Custom)? { - let rlp = Rlp::new(&journal_raw); - - // migrate all inserted keys. - for r in rlp.at(1).iter() { - let key: H256 = r.val_at(0); - let v: Bytes = r.val_at(1); - - if self.migrated_keys.get(&key).is_none() { - if let Some(new_key) = attempt_migrate(key, &v) { - self.migrated_keys.insert(key, new_key); - } - } - } - index += 1; - } else { - break; - } - } - - if index == 0 || era == 0 { - break; - } - era -= 1; - } - } - Ok(()) - } - - // walk all journal entries in the database backwards. - // replace all possible inserted/deleted keys with their migrated counterparts - // and commit the altered entries. - fn migrate_journal(&self, source: Arc, mut batch: Batch, dest: &mut Database) -> Result<(), Error> { - if let Some(val) = source.get(None, V7_LATEST_ERA_KEY).map_err(Error::Custom)? { - batch.insert(V7_LATEST_ERA_KEY.into(), val.clone().into_vec(), dest)?; - - let mut era = decode::(&val); - loop { - let mut index: usize = 0; - loop { - let entry_key = { - let mut r = RlpStream::new_list(3); - r.append(&era).append(&index).append(&&PADDING[..]); - r.out() - }; - - if let Some(journal_raw) = source.get(None, &entry_key).map_err(Error::Custom)? { - let rlp = Rlp::new(&journal_raw); - let id: H256 = rlp.val_at(0); - let mut inserted_keys: Vec<(H256, Bytes)> = Vec::new(); - - // migrate all inserted keys. - for r in rlp.at(1).iter() { - let mut key: H256 = r.val_at(0); - let v: Bytes = r.val_at(1); - - if let Some(new_key) = self.migrated_keys.get(&key) { - key = *new_key; - } - - inserted_keys.push((key, v)); - } - - // migrate all deleted keys. - let mut deleted_keys: Vec = rlp.list_at(2); - for old_key in &mut deleted_keys { - if let Some(new) = self.migrated_keys.get(&*old_key) { - *old_key = new.clone(); - } - } - - // rebuild the journal entry rlp. - let mut stream = RlpStream::new_list(3); - stream.append(&id); - stream.begin_list(inserted_keys.len()); - for (k, v) in inserted_keys { - stream.begin_list(2).append(&k).append(&v); - } - - stream.append_list(&deleted_keys); - - // and insert it into the new database. - batch.insert(entry_key, stream.out(), dest)?; - - index += 1; - } else { - break; - } - } - - if index == 0 || era == 0 { - break; - } - era -= 1; - } - } - batch.commit(dest) - } -} - -impl Migration for OverlayRecentV7 { - - fn columns(&self) -> Option { None } - - fn version(&self) -> u32 { 7 } - - // walk all records in the database, attempting to migrate any possible and - // keeping records of those that we do. then migrate the journal using - // this information. - fn migrate(&mut self, source: Arc, config: &Config, dest: &mut Database, col: Option) -> Result<(), Error> { - let mut batch = Batch::new(config, col); - - // check version metadata. - match source.get(None, V7_VERSION_KEY).map_err(Error::Custom)? { - Some(ref version) if decode::(&*version) == DB_VERSION => {} - _ => return Err(Error::MigrationImpossible), // missing or wrong version - } - - let mut count = 0; - for (key, value) in source.iter(None).into_iter().flat_map(|inner| inner) { - count += 1; - if count == 100_000 { - count = 0; - flush!("."); - } - - let mut key = key.into_vec(); - if key.len() == 32 { - let key_h = H256::from_slice(&key[..]); - if let Some(new_key) = attempt_migrate(key_h.clone(), &value) { - self.migrated_keys.insert(key_h, new_key); - key.copy_from_slice(&new_key[..]); - } - } - - batch.insert(key, value.into_vec(), dest)?; - } - - self.walk_journal(source.clone())?; - self.migrate_journal(source, batch, dest) - } -} diff --git a/ethcore/src/migrations/v10.rs b/ethcore/src/migrations/v10.rs deleted file mode 100644 index 7982279cf5e81258a2abff62a15d00281c767c72..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/v10.rs +++ /dev/null @@ -1,117 +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 . - -//! Bloom upgrade - -use std::sync::Arc; -use db::{COL_EXTRA, COL_HEADERS, COL_STATE}; -use state_db::{ACCOUNT_BLOOM_SPACE, DEFAULT_ACCOUNT_PRESET, StateDB}; -use util::trie::TrieDB; -use views::HeaderView; -use bloom_journal::Bloom; -use util::migration::{Error, Migration, Progress, Batch, Config}; -use util::journaldb; -use util::{H256, Trie}; -use util::{Database, DBTransaction}; - -/// Account bloom upgrade routine. If bloom already present, does nothing. -/// If database empty (no best block), does nothing. -/// Can be called on upgraded database with no issues (will do nothing). -pub fn generate_bloom(source: Arc, dest: &mut Database) -> Result<(), Error> { - trace!(target: "migration", "Account bloom upgrade started"); - let best_block_hash = match source.get(COL_EXTRA, b"best")? { - // no migration needed - None => { - trace!(target: "migration", "No best block hash, skipping"); - return Ok(()); - }, - Some(hash) => hash, - }; - let best_block_header = match source.get(COL_HEADERS, &best_block_hash)? { - // no best block, nothing to do - None => { - trace!(target: "migration", "No best block header, skipping"); - return Ok(()) - }, - Some(x) => x, - }; - let state_root = HeaderView::new(&best_block_header).state_root(); - - trace!("Adding accounts bloom (one-time upgrade)"); - let bloom_journal = { - let mut bloom = Bloom::new(ACCOUNT_BLOOM_SPACE, DEFAULT_ACCOUNT_PRESET); - // no difference what algorithm is passed, since there will be no writes - let state_db = journaldb::new( - source.clone(), - journaldb::Algorithm::OverlayRecent, - COL_STATE); - let account_trie = TrieDB::new(state_db.as_hashdb(), &state_root).map_err(|e| Error::Custom(format!("Cannot open trie: {:?}", e)))?; - for item in account_trie.iter().map_err(|_| Error::MigrationImpossible)? { - let (ref account_key, _) = item.map_err(|_| Error::MigrationImpossible)?; - let account_key_hash = H256::from_slice(account_key); - bloom.set(&*account_key_hash); - } - - bloom.drain_journal() - }; - - trace!(target: "migration", "Generated {} bloom updates", bloom_journal.entries.len()); - - let mut batch = DBTransaction::new(); - StateDB::commit_bloom(&mut batch, bloom_journal).map_err(|_| Error::Custom("Failed to commit bloom".to_owned()))?; - dest.write(batch)?; - - trace!(target: "migration", "Finished bloom update"); - - - Ok(()) -} - -/// Account bloom migration. -#[derive(Default)] -pub struct ToV10 { - progress: Progress, -} - -impl ToV10 { - /// New v10 migration - pub fn new() -> ToV10 { ToV10 { progress: Progress::default() } } -} - -impl Migration for ToV10 { - fn version(&self) -> u32 { - 10 - } - - fn pre_columns(&self) -> Option { Some(5) } - - fn columns(&self) -> Option { Some(6) } - - fn migrate(&mut self, source: Arc, config: &Config, dest: &mut Database, col: Option) -> Result<(), Error> { - let mut batch = Batch::new(config, col); - for (key, value) in source.iter(col).into_iter().flat_map(|inner| inner) { - self.progress.tick(); - batch.insert(key.into_vec(), value.into_vec(), dest)?; - } - batch.commit(dest)?; - - if col == COL_STATE { - generate_bloom(source, dest)?; - } - - Ok(()) - } -} diff --git a/ethcore/src/migrations/v9.rs b/ethcore/src/migrations/v9.rs deleted file mode 100644 index 08f83f1320fcdc3bc7df0b2e832ee5f62f52606b..0000000000000000000000000000000000000000 --- a/ethcore/src/migrations/v9.rs +++ /dev/null @@ -1,82 +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 . - - -//! This migration consolidates all databases into single one using Column Families. - -use rlp::{Rlp, RlpStream}; -use util::kvdb::Database; -use util::migration::{Batch, Config, Error, Migration, Progress}; -use std::sync::Arc; - -/// Which part of block to preserve -pub enum Extract { - /// Extract block header RLP. - Header, - /// Extract block body RLP. - Body, - /// Don't change the value. - All, -} - -/// Consolidation of extras/block/state databases into single one. -pub struct ToV9 { - progress: Progress, - column: Option, - extract: Extract, -} - -impl ToV9 { - /// Creates new V9 migration and assigns all `(key,value)` pairs from `source` DB to given Column Family - pub fn new(column: Option, extract: Extract) -> Self { - ToV9 { - progress: Progress::default(), - column: column, - extract: extract, - } - } -} - -impl Migration for ToV9 { - fn columns(&self) -> Option { Some(5) } - - fn version(&self) -> u32 { 9 } - - fn migrate(&mut self, source: Arc, config: &Config, dest: &mut Database, col: Option) -> Result<(), Error> { - let mut batch = Batch::new(config, self.column); - - for (key, value) in source.iter(col).into_iter().flat_map(|inner| inner) { - self.progress.tick(); - match self.extract { - Extract::Header => { - batch.insert(key.into_vec(), Rlp::new(&value).at(0).as_raw().to_vec(), dest)? - }, - Extract::Body => { - let mut body = RlpStream::new_list(2); - let block_rlp = Rlp::new(&value); - body.append_raw(block_rlp.at(1).as_raw(), 1); - body.append_raw(block_rlp.at(2).as_raw(), 1); - batch.insert(key.into_vec(), body.out(), dest)? - }, - Extract::All => { - batch.insert(key.into_vec(), value.into_vec(), dest)? - } - } - } - - batch.commit(dest) - } -} diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index 0639c645fa478e162f75283bb28735844b84bbde..58111cd741ad70c109f16593a7d87d8793cd32be 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -18,28 +18,49 @@ use std::time::{Instant, Duration}; use std::collections::{BTreeMap, HashSet}; use std::sync::Arc; -use util::*; -use using_queue::{UsingQueue, GetAction}; use account_provider::{AccountProvider, SignError as AccountError}; -use state::State; -use client::{MiningBlockChainClient, BlockId, TransactionId}; -use client::TransactionImportResult; -use executive::contract_address; -use block::{ClosedBlock, IsBlock, Block}; +use ansi_term::Colour; +use ethereum_types::{H256, U256, Address}; +use parking_lot::{Mutex, RwLock}; +use bytes::Bytes; +use engines::{EthEngine, Seal}; use error::*; -use transaction::{Action, UnverifiedTransaction, PendingTransaction, SignedTransaction, Condition as TransactionCondition}; -use receipt::{Receipt, RichReceipt}; -use spec::Spec; -use engines::{Engine, Seal}; -use miner::{MinerService, MinerStatus, TransactionQueue, RemovalReason, TransactionQueueDetailsProvider, PrioritizationStrategy, - AccountDetails, TransactionOrigin}; -use miner::banning_queue::{BanningTransactionQueue, Threshold}; -use miner::work_notify::{WorkPoster, NotifyWork}; -use miner::local_transactions::{Status as LocalTransactionStatus}; +use ethcore_miner::banning_queue::{BanningTransactionQueue, Threshold}; +use ethcore_miner::local_transactions::{Status as LocalTransactionStatus}; +use ethcore_miner::transaction_queue::{ + TransactionQueue, + RemovalReason, + TransactionDetailsProvider as TransactionQueueDetailsProvider, + PrioritizationStrategy, + AccountDetails, + TransactionOrigin, +}; +use futures_cpupool::CpuPool; +use ethcore_miner::work_notify::{WorkPoster, NotifyWork}; use miner::service_transaction_checker::ServiceTransactionChecker; -use price_info::{Client as PriceInfoClient, PriceInfo}; +use miner::{MinerService, MinerStatus}; use price_info::fetch::Client as FetchClient; +use price_info::{Client as PriceInfoClient, PriceInfo}; +use transaction::{ + Action, + UnverifiedTransaction, + PendingTransaction, + SignedTransaction, + Condition as TransactionCondition, + ImportResult as TransactionImportResult, + Error as TransactionError, +}; +use using_queue::{UsingQueue, GetAction}; +use block::{ClosedBlock, IsBlock, Block}; +use client::{ + AccountData, BlockChain, RegistryInfo, ScheduleInfo, CallContract, BlockProducer, SealedBlockImporter +}; +use client::{BlockId, TransactionId, MiningBlockChainClient}; +use executive::contract_address; use header::{Header, BlockNumber}; +use receipt::{Receipt, RichReceipt}; +use spec::Spec; +use state::State; /// Different possible definitions for pending transaction set. #[derive(Debug, PartialEq)] @@ -117,6 +138,10 @@ pub struct MinerOptions { pub tx_queue_banning: Banning, /// Do we refuse to accept service transactions even if sender is certified. pub refuse_service_transactions: bool, + /// Create a pending block with maximal possible gas limit. + /// NOTE: Such block will contain all pending transactions but + /// will be invalid if mined. + pub infinite_pending_block: bool, } impl Default for MinerOptions { @@ -139,6 +164,7 @@ impl Default for MinerOptions { enable_resubmission: true, tx_queue_banning: Banning::Disabled, refuse_service_transactions: false, + infinite_pending_block: false, } } } @@ -193,11 +219,11 @@ pub enum GasPricer { impl GasPricer { /// Create a new Calibrated `GasPricer`. - pub fn new_calibrated(options: GasPriceCalibratorOptions, fetch: FetchClient) -> GasPricer { + pub fn new_calibrated(options: GasPriceCalibratorOptions, fetch: FetchClient, p: CpuPool) -> GasPricer { GasPricer::Calibrated(GasPriceCalibrator { options: options, next_calibration: Instant::now(), - price_info: PriceInfoClient::new(fetch), + price_info: PriceInfoClient::new(fetch, p), }) } @@ -224,6 +250,7 @@ struct SealingWork { pub struct Miner { // NOTE [ToDr] When locking always lock in this order! transaction_queue: Arc>, + transaction_listener: RwLock>>, sealing_work: Mutex, next_allowed_reseal: Mutex, next_mandatory_reseal: RwLock, @@ -234,7 +261,7 @@ pub struct Miner { gas_range_target: RwLock<(U256, U256)>, author: RwLock
, extra_data: RwLock, - engine: Arc, + engine: Arc, accounts: Option>, notifiers: RwLock>>, @@ -290,6 +317,7 @@ impl Miner { Miner { transaction_queue: Arc::new(RwLock::new(txq)), + transaction_listener: RwLock::new(vec![]), next_allowed_reseal: Mutex::new(Instant::now()), next_mandatory_reseal: RwLock::new(Instant::now() + options.reseal_max_period), sealing_block_last_request: Mutex::new(0), @@ -345,6 +373,11 @@ impl Miner { self.map_pending_block(|b| b.header().clone(), latest_block_number) } + /// Set a callback to be notified about imported transactions' hashes. + pub fn add_transactions_listener(&self, f: Box) { + self.transaction_listener.write().push(f); + } + fn map_pending_block(&self, f: F, latest_block_number: BlockNumber) -> Option where F: FnOnce(&ClosedBlock) -> T, { @@ -355,10 +388,9 @@ 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) { - let _timer = PerfTimer::new("prepare_block"); + fn prepare_block(&self, chain: &C) -> (ClosedBlock, Option) { + trace_time!("prepare_block"); let chain_info = chain.chain_info(); let (transactions, mut open_block, original_work_hash) = { let nonce_cap = if chain_info.best_block_number + 1 >= self.engine.params().dust_protection_transition { @@ -366,17 +398,16 @@ impl Miner { } else { None }; let transactions = {self.transaction_queue.read().top_transactions_at(chain_info.best_block_number, chain_info.best_block_timestamp, nonce_cap)}; let mut sealing_work = self.sealing_work.lock(); - let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash()); + let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().header().hash()); let best_hash = chain_info.best_block_hash; -/* + // check to see if last ClosedBlock in would_seals is actually same parent block. // if so // duplicate, re-open and push any new transactions. // if at least one was pushed successfully, close and enqueue new ClosedBlock; // otherwise, leave everything alone. // otherwise, author a fresh block. -*/ - let open_block = match sealing_work.queue.pop_if(|b| b.block().fields().header.parent_hash() == &best_hash) { + let mut open_block = match sealing_work.queue.pop_if(|b| b.block().header().parent_hash() == &best_hash) { Some(old_block) => { trace!(target: "miner", "prepare_block: Already have previous work; updating and returning"); // add transactions to old_block @@ -392,19 +423,33 @@ impl Miner { ) } }; + + if self.options.infinite_pending_block { + open_block.remove_gas_limit(); + } + (transactions, open_block, last_work_hash) }; let mut invalid_transactions = HashSet::new(); + let mut non_allowed_transactions = HashSet::new(); let mut transactions_to_penalize = HashSet::new(); - let block_number = open_block.block().fields().header.number(); + let block_number = open_block.block().header().number(); let mut tx_count: usize = 0; let tx_total = transactions.len(); for tx in transactions { let hash = tx.hash(); let start = Instant::now(); - let result = open_block.push_transaction(tx, None); + // Check whether transaction type is allowed for sender + let result = match self.engine.machine().verify_transaction(&tx, open_block.header(), chain) { + Err(Error::Transaction(TransactionError::NotAllowed)) => { + Err(TransactionError::NotAllowed.into()) + } + _ => { + open_block.push_transaction(tx, None) + } + }; let took = start.elapsed(); // Check for heavy transactions @@ -445,6 +490,12 @@ impl Miner { }, // already have transaction - ignore Err(Error::Transaction(TransactionError::AlreadyImported)) => {}, + Err(Error::Transaction(TransactionError::NotAllowed)) => { + non_allowed_transactions.insert(hash); + debug!(target: "miner", + "Skipping non-allowed transaction for sender {:?}", + hash); + }, Err(e) => { invalid_transactions.insert(hash); debug!(target: "miner", @@ -467,6 +518,9 @@ impl Miner { for hash in invalid_transactions { queue.remove(&hash, &fetch_nonce, RemovalReason::Invalid); } + for hash in non_allowed_transactions { + queue.remove(&hash, &fetch_nonce, RemovalReason::NotAllowed); + } for hash in transactions_to_penalize { queue.penalize(&hash); } @@ -516,10 +570,18 @@ impl Miner { } /// Attempts to perform internal sealing (one that does not require work) and handles the result depending on the type of Seal. - fn seal_and_import_block_internally(&self, chain: &MiningBlockChainClient, block: ClosedBlock) -> bool { + fn seal_and_import_block_internally(&self, chain: &C, block: ClosedBlock) -> bool + where C: BlockChain + SealedBlockImporter + { 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."); @@ -561,14 +623,14 @@ impl Miner { fn prepare_work(&self, block: ClosedBlock, original_work_hash: Option) { let (work, is_new) = { let mut sealing_work = self.sealing_work.lock(); - let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().fields().header.hash()); - trace!(target: "miner", "prepare_work: Checking whether we need to reseal: orig={:?} last={:?}, this={:?}", original_work_hash, last_work_hash, block.block().fields().header.hash()); - let (work, is_new) = if last_work_hash.map_or(true, |h| h != block.block().fields().header.hash()) { - trace!(target: "miner", "prepare_work: Pushing a new, refreshed or borrowed pending {}...", block.block().fields().header.hash()); - let pow_hash = block.block().fields().header.hash(); - let number = block.block().fields().header.number(); - let difficulty = *block.block().fields().header.difficulty(); - let is_new = original_work_hash.map_or(true, |h| block.block().fields().header.hash() != h); + let last_work_hash = sealing_work.queue.peek_last_ref().map(|pb| pb.block().header().hash()); + trace!(target: "miner", "prepare_work: Checking whether we need to reseal: orig={:?} last={:?}, this={:?}", original_work_hash, last_work_hash, block.block().header().hash()); + let (work, is_new) = if last_work_hash.map_or(true, |h| h != block.block().header().hash()) { + trace!(target: "miner", "prepare_work: Pushing a new, refreshed or borrowed pending {}...", block.block().header().hash()); + let pow_hash = block.block().header().hash(); + let number = block.block().header().number(); + let difficulty = *block.block().header().difficulty(); + let is_new = original_work_hash.map_or(true, |h| block.block().header().hash() != h); sealing_work.queue.push(block); // If push notifications are enabled we assume all work items are used. if !self.notifiers.read().is_empty() && is_new { @@ -578,7 +640,7 @@ impl Miner { } else { (None, false) }; - trace!(target: "miner", "prepare_work: leaving (last={:?})", sealing_work.queue.peek_last_ref().map(|b| b.block().fields().header.hash())); + trace!(target: "miner", "prepare_work: leaving (last={:?})", sealing_work.queue.peek_last_ref().map(|b| b.block().header().hash())); (work, is_new) }; if is_new { @@ -590,18 +652,18 @@ impl Miner { } } - fn update_gas_limit(&self, client: &MiningBlockChainClient) { + fn update_gas_limit(&self, client: &C) { let gas_limit = client.best_block_header().gas_limit(); let mut queue = self.transaction_queue.write(); queue.set_gas_limit(gas_limit); if let GasLimit::Auto = self.options.tx_queue_gas_limit { // Set total tx queue gas limit to be 20x the block gas limit. - queue.set_total_gas_limit(gas_limit * 20.into()); + queue.set_total_gas_limit(gas_limit * 20u32); } } /// Returns true if we had to prepare new pending block. - fn prepare_work_sealing(&self, client: &MiningBlockChainClient) -> bool { + fn prepare_work_sealing(&self, client: &C) -> bool { trace!(target: "miner", "prepare_work_sealing: entering"); let prepare_new = { let mut sealing_work = self.sealing_work.lock(); @@ -633,22 +695,19 @@ impl Miner { prepare_new } - fn add_transactions_to_queue( + fn add_transactions_to_queue( &self, - client: &MiningBlockChainClient, + client: &C, transactions: Vec, default_origin: TransactionOrigin, condition: Option, transaction_queue: &mut BanningTransactionQueue, ) -> Vec> { - let accounts = self.accounts.as_ref() - .and_then(|provider| provider.accounts().ok()) - .map(|accounts| accounts.into_iter().collect::>()); - let best_block_header = client.best_block_header().decode(); let insertion_time = client.chain_info().best_block_number; + let mut inserted = Vec::with_capacity(transactions.len()); - transactions.into_iter() + let results = transactions.into_iter() .map(|tx| { let hash = tx.hash(); if client.transaction_block(TransactionId::Hash(hash)).is_some() { @@ -656,43 +715,51 @@ impl Miner { return Err(Error::Transaction(TransactionError::AlreadyImported)); } match self.engine.verify_transaction_basic(&tx, &best_block_header) - .and_then(|_| self.engine.verify_transaction(tx, &best_block_header)) + .and_then(|_| self.engine.verify_transaction_unordered(tx, &best_block_header)) { Err(e) => { debug!(target: "miner", "Rejected tx {:?} with invalid signature: {:?}", hash, e); Err(e) }, Ok(transaction) => { - let origin = accounts.as_ref().and_then(|accounts| { - match accounts.contains(&transaction.sender()) { + // This check goes here because verify_transaction takes SignedTransaction parameter + self.engine.machine().verify_transaction(&transaction, &best_block_header, client)?; + + let origin = self.accounts.as_ref().and_then(|accounts| { + match accounts.has_account(transaction.sender()).unwrap_or(false) { true => Some(TransactionOrigin::Local), false => None, } }).unwrap_or(default_origin); - // try to install service transaction checker before appending transactions - self.service_transaction_action.update_from_chain_client(client); - let details_provider = TransactionDetailsProvider::new(client, &self.service_transaction_action); - match origin { + let hash = transaction.hash(); + let result = match origin { TransactionOrigin::Local | TransactionOrigin::RetractedBlock => { - transaction_queue.add(transaction, origin, insertion_time, condition.clone(), &details_provider) + transaction_queue.add(transaction, origin, insertion_time, condition.clone(), &details_provider)? }, TransactionOrigin::External => { - transaction_queue.add_with_banlist(transaction, insertion_time, &details_provider) + transaction_queue.add_with_banlist(transaction, insertion_time, &details_provider)? }, - } + }; + + inserted.push(hash); + Ok(result) }, } }) - .collect() + .collect(); + + for listener in &*self.transaction_listener.read() { + listener(&inserted); + } + + results } /// 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(&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(); @@ -712,8 +779,9 @@ impl Miner { const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; impl MinerService for Miner { + type State = State<::state_db::StateDB>; - fn clear_and_reset(&self, chain: &MiningBlockChainClient) { + fn clear_and_reset(&self, chain: &C) { self.transaction_queue.write().clear(); // -------------------------------------------------------------------------- // | NOTE Code below requires transaction_queue and sealing_work locks. | @@ -790,7 +858,7 @@ impl MinerService for Miner { fn sensible_gas_price(&self) -> U256 { // 10% above our minimum. - *self.transaction_queue.read().minimal_gas_price() * 110.into() / 100.into() + *self.transaction_queue.read().minimal_gas_price() * 110u32 / 100.into() } fn sensible_gas_limit(&self) -> U256 { @@ -829,16 +897,16 @@ impl MinerService for Miner { self.gas_range_target.read().1 } - fn import_external_transactions( + fn import_external_transactions( &self, - chain: &MiningBlockChainClient, + client: &C, transactions: Vec ) -> Vec> { trace!(target: "external_tx", "Importing external transactions"); let results = { let mut transaction_queue = self.transaction_queue.write(); self.add_transactions_to_queue( - chain, transactions, TransactionOrigin::External, None, &mut transaction_queue + client, transactions, TransactionOrigin::External, None, &mut transaction_queue ) }; @@ -847,15 +915,14 @@ impl MinerService for Miner { // | NOTE Code below requires transaction_queue and sealing_work locks. | // | Make sure to release the locks before calling that method. | // -------------------------------------------------------------------------- - self.update_sealing(chain); + self.update_sealing(client); } results } - #[cfg_attr(feature="dev", allow(collapsible_if))] - fn import_own_transaction( + fn import_own_transaction( &self, - chain: &MiningBlockChainClient, + chain: &C, pending: PendingTransaction, ) -> Result { @@ -979,7 +1046,7 @@ impl MinerService for Miner { } } - fn remove_pending_transaction(&self, chain: &MiningBlockChainClient, hash: &H256) -> Option { + fn remove_pending_transaction(&self, chain: &C, hash: &H256) -> Option { let mut queue = self.transaction_queue.write(); let tx = queue.find(hash); if tx.is_some() { @@ -1016,7 +1083,7 @@ impl MinerService for Miner { }, logs: receipt.logs.clone(), log_bloom: receipt.log_bloom, - state_root: receipt.state_root, + outcome: receipt.outcome.clone(), } }) } @@ -1049,7 +1116,10 @@ impl MinerService for Miner { /// Update sealing if required. /// Prepare the block and work if the Engine does not seal internally. - fn update_sealing(&self, chain: &MiningBlockChainClient) { + fn update_sealing(&self, chain: &C) + where C: AccountData + BlockChain + RegistryInfo + + CallContract + BlockProducer + SealedBlockImporter + { trace!(target: "miner", "update_sealing"); const NO_NEW_CHAIN_WITH_FORKS: &str = "Your chain specification contains one or more hard forks which are required to be \ on by default. Please remove these forks and start your chain again."; @@ -1064,7 +1134,7 @@ impl MinerService for Miner { // refuse to seal the first block of the chain if it contains hard forks // which should be on by default. - if block.block().fields().header.number() == 1 && self.engine.params().contains_bugfix_hard_fork() { + if block.block().header().number() == 1 && self.engine.params().contains_bugfix_hard_fork() { warn!("{}", NO_NEW_CHAIN_WITH_FORKS); return; } @@ -1089,17 +1159,20 @@ impl MinerService for Miner { self.sealing_work.lock().queue.is_in_use() } - fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option where F: FnOnce(&ClosedBlock) -> T { + fn map_sealing_work(&self, client: &C, f: F) -> Option + where C: AccountData + BlockChain + BlockProducer + CallContract, + F: FnOnce(&ClosedBlock) -> T + { trace!(target: "miner", "map_sealing_work: entering"); - self.prepare_work_sealing(chain); + self.prepare_work_sealing(client); trace!(target: "miner", "map_sealing_work: sealing prepared"); let mut sealing_work = self.sealing_work.lock(); let ret = sealing_work.queue.use_last_ref(); - trace!(target: "miner", "map_sealing_work: leaving use_last_ref={:?}", ret.as_ref().map(|b| b.block().fields().header.hash())); + trace!(target: "miner", "map_sealing_work: leaving use_last_ref={:?}", ret.as_ref().map(|b| b.block().header().hash())); ret.map(f) } - fn submit_seal(&self, chain: &MiningBlockChainClient, block_hash: H256, seal: Vec) -> Result<(), Error> { + fn submit_seal(&self, chain: &C, block_hash: H256, seal: Vec) -> Result<(), Error> { let result = if let Some(b) = self.sealing_work.lock().queue.get_used_if( if self.options.enable_resubmission { @@ -1122,12 +1195,15 @@ impl MinerService for Miner { let n = sealed.header().number(); let h = sealed.header().hash(); chain.import_sealed_block(sealed)?; - info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(h.hex())); + info!(target: "miner", "Submitted block imported OK. #{}: {}", Colour::White.bold().paint(format!("{}", n)), Colour::White.bold().paint(format!("{:x}", h))); Ok(()) }) } - fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) { + fn chain_new_blocks(&self, chain: &C, imported: &[H256], _invalid: &[H256], enacted: &[H256], retracted: &[H256]) + where C: AccountData + BlockChain + CallContract + RegistryInfo + + BlockProducer + ScheduleInfo + SealedBlockImporter + { trace!(target: "miner", "chain_new_blocks"); // 1. We ignore blocks that were `imported` unless resealing on new uncles is enabled. @@ -1173,6 +1249,18 @@ impl MinerService for Miner { self.update_sealing(chain); } } + + fn pending_state(&self, latest_block_number: BlockNumber) -> Option { + Miner::pending_state(self, latest_block_number) + } + + fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option
{ + Miner::pending_block_header(self, latest_block_number) + } + + fn pending_block(&self, latest_block_number: BlockNumber) -> Option { + Miner::pending_block(self, latest_block_number) + } } /// Action when service transaction is received @@ -1184,13 +1272,8 @@ enum ServiceTransactionAction { } impl ServiceTransactionAction { - pub fn update_from_chain_client(&self, client: &MiningBlockChainClient) { - if let ServiceTransactionAction::Check(ref checker) = *self { - checker.update_from_chain_client(client); - } - } - - pub fn check(&self, client: &MiningBlockChainClient, tx: &SignedTransaction) -> Result { + pub fn check(&self, client: &C, tx: &SignedTransaction) -> Result + { match *self { ServiceTransactionAction::Refuse => Err("configured to refuse service transactions".to_owned()), ServiceTransactionAction::Check(ref checker) => checker.check(client, tx), @@ -1198,13 +1281,13 @@ impl ServiceTransactionAction { } } -struct TransactionDetailsProvider<'a> { - client: &'a MiningBlockChainClient, +struct TransactionDetailsProvider<'a, C: 'a> { + client: &'a C, service_transaction_action: &'a ServiceTransactionAction, } -impl<'a> TransactionDetailsProvider<'a> { - pub fn new(client: &'a MiningBlockChainClient, service_transaction_action: &'a ServiceTransactionAction) -> Self { +impl<'a, C> TransactionDetailsProvider<'a, C> { + pub fn new(client: &'a C, service_transaction_action: &'a ServiceTransactionAction) -> Self { TransactionDetailsProvider { client: client, service_transaction_action: service_transaction_action, @@ -1212,7 +1295,9 @@ impl<'a> TransactionDetailsProvider<'a> { } } -impl<'a> TransactionQueueDetailsProvider for TransactionDetailsProvider<'a> { +impl<'a, C> TransactionQueueDetailsProvider for TransactionDetailsProvider<'a, C> + where C: AccountData + CallContract + RegistryInfo + ScheduleInfo +{ fn fetch_account(&self, address: &Address) -> AccountDetails { AccountDetails { nonce: self.client.latest_nonce(address), @@ -1231,19 +1316,18 @@ impl<'a> TransactionQueueDetailsProvider for TransactionDetailsProvider<'a> { #[cfg(test)] mod tests { - - use std::sync::Arc; - use std::time::Duration; - use rustc_hex::FromHex; - use super::super::{MinerService, PrioritizationStrategy}; use super::*; - use block::IsBlock; - use util::U256; + use ethcore_miner::transaction_queue::PrioritizationStrategy; + use ethereum_types::U256; use ethkey::{Generator, Random}; - use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; + use client::{TestBlockChainClient, EachBlockWith, ChainInfo}; + use hash::keccak; use header::BlockNumber; - use transaction::{SignedTransaction, Transaction, PendingTransaction, Action}; + use rustc_hex::FromHex; use spec::Spec; + use transaction::{SignedTransaction, Transaction, PendingTransaction, Action}; + use miner::MinerService; + use tests::helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts}; #[test] @@ -1263,16 +1347,16 @@ mod tests { let client = TestBlockChainClient::default(); let miner = Miner::with_spec(&Spec::new_test()); - let res = miner.map_sealing_work(&client, |b| b.block().fields().header.hash()); + let res = miner.map_sealing_work(&client, |b| b.block().header().hash()); assert!(res.is_some()); assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok()); // two more blocks mined, work requested. client.add_blocks(1, EachBlockWith::Uncle); - miner.map_sealing_work(&client, |b| b.block().fields().header.hash()); + miner.map_sealing_work(&client, |b| b.block().header().hash()); client.add_blocks(1, EachBlockWith::Uncle); - miner.map_sealing_work(&client, |b| b.block().fields().header.hash()); + miner.map_sealing_work(&client, |b| b.block().header().hash()); // solution to original work submitted. assert!(miner.submit_seal(&client, res.unwrap(), vec![]).is_ok()); @@ -1298,6 +1382,7 @@ mod tests { enable_resubmission: true, tx_queue_banning: Banning::Disabled, refuse_service_transactions: false, + infinite_pending_block: false, }, GasPricer::new_fixed(0u64.into()), &Spec::new_test(), @@ -1418,7 +1503,7 @@ mod tests { fn should_fail_setting_engine_signer_on_pow() { let spec = Spec::new_pow_test_spec; let tap = Arc::new(AccountProvider::transient_provider()); - let addr = tap.insert_account("1".sha3().into(), "").unwrap(); + let addr = tap.insert_account(keccak("1").into(), "").unwrap(); let client = generate_dummy_client_with_spec_and_accounts(spec, Some(tap.clone())); assert!(match client.miner().set_engine_signer(addr, "".into()) { Err(AccountError::InappropriateChain) => true, _ => false }) } @@ -1427,7 +1512,7 @@ mod tests { fn should_fail_setting_engine_signer_without_account_provider() { let spec = Spec::new_instant; let tap = Arc::new(AccountProvider::transient_provider()); - let addr = tap.insert_account("1".sha3().into(), "").unwrap(); + let addr = tap.insert_account(keccak("1").into(), "").unwrap(); let client = generate_dummy_client_with_spec_and_accounts(spec, None); assert!(match client.miner().set_engine_signer(addr, "".into()) { Err(AccountError::NotFound) => true, _ => false }); } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index b4cb065fd1e5f031062e449edff77d53bacd68de..5f451fdc2a630779342d1ea4098cfb027ff40659 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -15,8 +15,6 @@ // along with Parity. If not, see . #![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. @@ -24,7 +22,6 @@ //! Usage example: //! //! ```rust -//! extern crate ethcore_util as util; //! extern crate ethcore; //! use std::env; //! use ethcore::ethereum; @@ -41,36 +38,34 @@ //! } //! ``` -mod banning_queue; -mod external; -mod local_transactions; mod miner; -mod service_transaction_checker; -mod transaction_queue; -mod work_notify; mod stratum; - -pub use self::external::{ExternalMiner, ExternalMinerService}; +mod service_transaction_checker; pub use self::miner::{Miner, MinerOptions, Banning, PendingSet, GasPricer, GasPriceCalibratorOptions, GasLimit}; -pub use self::transaction_queue::{TransactionQueue, RemovalReason, TransactionDetailsProvider as TransactionQueueDetailsProvider, - PrioritizationStrategy, AccountDetails, TransactionOrigin}; -pub use self::local_transactions::{Status as LocalTransactionStatus}; -pub use client::TransactionImportResult; -pub use self::work_notify::NotifyWork; pub use self::stratum::{Stratum, Error as StratumError, Options as StratumOptions}; +pub use ethcore_miner::local_transactions::Status as LocalTransactionStatus; + use std::collections::BTreeMap; -use util::{H256, U256, Address, Bytes}; -use client::{MiningBlockChainClient}; -use block::ClosedBlock; -use header::BlockNumber; -use receipt::{RichReceipt, Receipt}; + +use block::{ClosedBlock, Block}; +use bytes::Bytes; +use client::{ + MiningBlockChainClient, CallContract, RegistryInfo, ScheduleInfo, + BlockChain, AccountData, BlockProducer, SealedBlockImporter +}; use error::{Error}; -use transaction::{UnverifiedTransaction, PendingTransaction}; +use ethereum_types::{H256, U256, Address}; +use header::{BlockNumber, Header}; +use receipt::{RichReceipt, Receipt}; +use transaction::{UnverifiedTransaction, PendingTransaction, ImportResult as TransactionImportResult}; +use state::StateInfo; /// Miner client API pub trait MinerService : Send + Sync { + /// Type representing chain state + type State: StateInfo + 'static; /// Returns miner's status. fn status(&self) -> MinerStatus; @@ -119,42 +114,46 @@ pub trait MinerService : Send + Sync { fn set_tx_gas_limit(&self, limit: U256); /// Imports transactions to transaction queue. - fn import_external_transactions(&self, chain: &MiningBlockChainClient, transactions: Vec) -> + fn import_external_transactions(&self, client: &C, transactions: Vec) -> Vec>; /// Imports own (node owner) transaction to queue. - fn import_own_transaction(&self, chain: &MiningBlockChainClient, transaction: PendingTransaction) -> + fn import_own_transaction(&self, chain: &C, transaction: PendingTransaction) -> Result; /// Returns hashes of transactions currently in pending fn pending_transactions_hashes(&self, best_block: BlockNumber) -> Vec; /// Removes all transactions from the queue and restart mining operation. - fn clear_and_reset(&self, chain: &MiningBlockChainClient); + fn clear_and_reset(&self, chain: &C); /// Called when blocks are imported to chain, updates transactions queue. - fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); + fn chain_new_blocks(&self, chain: &C, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]) + where C: AccountData + BlockChain + CallContract + RegistryInfo + BlockProducer + ScheduleInfo + SealedBlockImporter; /// PoW chain - can produce work package fn can_produce_work_package(&self) -> bool; /// New chain head event. Restart mining operation. - fn update_sealing(&self, chain: &MiningBlockChainClient); + fn update_sealing(&self, chain: &C) + where C: AccountData + BlockChain + RegistryInfo + CallContract + BlockProducer + SealedBlockImporter; /// Submit `seal` as a valid solution for the header of `pow_hash`. /// Will check the seal, but not actually insert the block into the chain. - fn submit_seal(&self, chain: &MiningBlockChainClient, pow_hash: H256, seal: Vec) -> Result<(), Error>; + fn submit_seal(&self, chain: &C, pow_hash: H256, seal: Vec) -> Result<(), Error>; /// Get the sealing work package and if `Some`, apply some transform. - fn map_sealing_work(&self, chain: &MiningBlockChainClient, f: F) -> Option - where F: FnOnce(&ClosedBlock) -> T, Self: Sized; + fn map_sealing_work(&self, client: &C, f: F) -> Option + where C: AccountData + BlockChain + BlockProducer + CallContract, + F: FnOnce(&ClosedBlock) -> T, + Self: Sized; /// Query pending transactions for hash. fn transaction(&self, best_block: BlockNumber, hash: &H256) -> Option; /// Removes transaction from the queue. /// NOTE: The transaction is not removed from pending block if mining. - fn remove_pending_transaction(&self, chain: &MiningBlockChainClient, hash: &H256) -> Option; + fn remove_pending_transaction(&self, chain: &C, hash: &H256) -> Option; /// Get a list of all pending transactions in the queue. fn pending_transactions(&self) -> Vec; @@ -185,6 +184,15 @@ pub trait MinerService : Send + Sync { /// Suggested gas limit. fn sensible_gas_limit(&self) -> U256 { 21000.into() } + + /// Get `Some` `clone()` of the current pending block's state or `None` if we're not sealing. + fn pending_state(&self, latest_block_number: BlockNumber) -> Option; + + /// Get `Some` `clone()` of the current pending block header or `None` if we're not sealing. + fn pending_block_header(&self, latest_block_number: BlockNumber) -> Option
; + + /// Get `Some` `clone()` of the current pending block or `None` if we're not sealing. + fn pending_block(&self, latest_block_number: BlockNumber) -> Option; } /// Mining status diff --git a/ethcore/src/miner/service_transaction_checker.rs b/ethcore/src/miner/service_transaction_checker.rs index d21643772ac319710c71f0c80a7f8e705b29ccf1..a555829c5f2d1fddb60ba90ec60cc5e9bb6bafb0 100644 --- a/ethcore/src/miner/service_transaction_checker.rs +++ b/ethcore/src/miner/service_transaction_checker.rs @@ -14,47 +14,35 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use client::MiningBlockChainClient; +//! A service transactions contract checker. + +use client::{RegistryInfo, CallContract}; use transaction::SignedTransaction; use types::ids::BlockId; -use futures::{future, Future}; -use native_contracts::ServiceTransactionChecker as Contract; -use util::{U256, Mutex}; +use_contract!(service_transaction, "ServiceTransaction", "res/contracts/service_transaction.json"); const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker"; /// Service transactions checker. #[derive(Default)] pub struct ServiceTransactionChecker { - contract: Mutex>, + contract: service_transaction::ServiceTransaction, } impl ServiceTransactionChecker { - /// Try to create instance, reading contract address from given chain client. - pub fn update_from_chain_client(&self, client: &MiningBlockChainClient) { - let mut contract = self.contract.lock(); - if contract.is_none() { - *contract = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned()) - .and_then(|contract_addr| { - trace!(target: "txqueue", "Configuring for service transaction checker contract from {}", contract_addr); - - Some(Contract::new(contract_addr)) - }) - } - } - /// Checks if service transaction can be appended to the transaction queue. - pub fn check(&self, client: &MiningBlockChainClient, tx: &SignedTransaction) -> Result { - debug_assert_eq!(tx.gas_price, U256::zero()); - - if let Some(ref contract) = *self.contract.lock() { - contract.certified( - |addr, data| future::done(client.call_contract(BlockId::Latest, addr, data)), - tx.sender() - ).wait() - } else { - Err("contract is not configured".to_owned()) - } + pub fn check(&self, client: &C, tx: &SignedTransaction) -> Result { + assert!(tx.gas_price.is_zero()); + + let address = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest) + .ok_or_else(|| "contract is not configured")?; + + trace!(target: "txqueue", "Checking service transaction checker contract from {}", address); + + self.contract.functions() + .certified() + .call(tx.sender(), &|data| client.call_contract(BlockId::Latest, address, data)) + .map_err(|e| e.to_string()) } } diff --git a/ethcore/src/miner/stratum.rs b/ethcore/src/miner/stratum.rs index 0031bb715d8945a8f8afa8bce62f17c925ad20ff..c8c387e51066912c25ee6badb373ccdd6059b656 100644 --- a/ethcore/src/miner/stratum.rs +++ b/ethcore/src/miner/stratum.rs @@ -16,22 +16,22 @@ //! Client-side stratum job dispatcher and mining notifier handler -use ethcore_stratum::{ - JobDispatcher, PushWorkHandler, - Stratum as StratumService, Error as StratumServiceError, -}; - use std::sync::{Arc, Weak}; use std::net::{SocketAddr, AddrParseError}; use std::fmt; -use util::{H256, U256, H64, clean_0x}; +use block::IsBlock; +use client::Client; +use ethereum_types::{H64, H256, clean_0x, U256}; use ethereum::ethash::Ethash; use ethash::SeedHashCompute; -use util::Mutex; +use ethcore_miner::work_notify::NotifyWork; +use ethcore_stratum::{ + JobDispatcher, PushWorkHandler, + Stratum as StratumService, Error as StratumServiceError, +}; use miner::{self, Miner, MinerService}; -use client::Client; -use block::IsBlock; +use parking_lot::Mutex; use rlp::encode; /// Configures stratum server options. @@ -170,11 +170,11 @@ impl StratumJobDispatcher { fn payload(&self, pow_hash: H256, difficulty: U256, number: u64) -> String { // TODO: move this to engine let target = Ethash::difficulty_to_boundary(&difficulty); - let seed_hash = &self.seed_compute.lock().get_seedhash(number); + let seed_hash = &self.seed_compute.lock().hash_block_number(number); let seed_hash = H256::from_slice(&seed_hash[..]); format!( - r#"["0x", "0x{}","0x{}","0x{}","0x{:x}"]"#, - pow_hash.hex(), seed_hash.hex(), target.hex(), number + r#"["0x", "0x{:x}","0x{:x}","0x{:x}","0x{:x}"]"#, + pow_hash, seed_hash, target, number ) } @@ -213,7 +213,7 @@ impl From for Error { fn from(err: AddrParseError) -> Error { Error::Address(err) } } -impl super::work_notify::NotifyWork for Stratum { +impl NotifyWork for Stratum { fn notify(&self, pow_hash: H256, difficulty: U256, number: u64) { trace!(target: "stratum", "Notify work"); @@ -248,7 +248,7 @@ impl Stratum { /// Start STRATUM job dispatcher and register it in the miner pub fn register(cfg: &Options, miner: Arc, client: Weak) -> Result<(), Error> { let stratum = miner::Stratum::start(cfg, Arc::downgrade(&miner.clone()), client)?; - miner.push_notifier(Box::new(stratum) as Box); + miner.push_notifier(Box::new(stratum) as Box); Ok(()) } } diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 4204b591df67010c21fb183317377c1f5f41644e..027e2765fff2074f6c9412e86e3869af584a5334 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -17,7 +17,12 @@ use std::fmt; use std::collections::BTreeMap; use itertools::Itertools; -use util::*; +use hash::{keccak}; +use ethereum_types::{H256, U256}; +use hashdb::HashDB; +use triehash::sec_trie_root; +use bytes::Bytes; +use trie::TrieFactory; use state::Account; use ethjson; use types::account_diff::*; @@ -38,12 +43,6 @@ pub struct PodAccount { } impl PodAccount { - /// Construct new object. - #[cfg(test)] - pub fn new(balance: U256, nonce: U256, code: Bytes, storage: BTreeMap) -> PodAccount { - PodAccount { balance: balance, nonce: nonce, code: Some(code), storage: storage } - } - /// Convert Account to a PodAccount. /// NOTE: This will silently fail unless the account is fully cached. pub fn from_account(acc: &Account) -> PodAccount { @@ -60,8 +59,8 @@ impl PodAccount { let mut stream = RlpStream::new_list(4); stream.append(&self.nonce); stream.append(&self.balance); - stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k.to_vec(), rlp::encode(&U256::from(&**v)).to_vec())).collect())); - stream.append(&self.code.as_ref().unwrap_or(&vec![]).sha3()); + stream.append(&sec_trie_root(self.storage.iter().map(|(k, v)| (k, rlp::encode(&U256::from(&**v)))))); + stream.append(&keccak(&self.code.as_ref().unwrap_or(&vec![]))); stream.out() } @@ -117,7 +116,7 @@ impl fmt::Display for PodAccount { self.balance, self.nonce, self.code.as_ref().map_or(0, |c| c.len()), - self.code.as_ref().map_or_else(H256::new, |c| c.sha3()), + self.code.as_ref().map_or_else(H256::new, |c| keccak(c)), self.storage.len(), ) } diff --git a/ethcore/src/pod_state.rs b/ethcore/src/pod_state.rs index 5a0265dc18ed91f634afbf38ec77d8966259b564..1bbabc98060b6c1030a240a2ae836168e1d453c9 100644 --- a/ethcore/src/pod_state.rs +++ b/ethcore/src/pod_state.rs @@ -19,7 +19,8 @@ use std::fmt; use std::collections::BTreeMap; use itertools::Itertools; -use util::*; +use ethereum_types::{H256, Address}; +use triehash::sec_trie_root; use pod_account::{self, PodAccount}; use types::state_diff::StateDiff; use ethjson; @@ -40,7 +41,7 @@ impl PodState { /// Get the root hash of the trie of the RLP of this. pub fn root(&self) -> H256 { - sec_trie_root(self.0.iter().map(|(k, v)| (k.to_vec(), v.rlp())).collect()) + sec_trie_root(self.0.iter().map(|(k, v)| (k, v.rlp()))) } /// Drain object to get the underlying map. @@ -75,7 +76,12 @@ impl fmt::Display for PodState { /// Calculate and return diff between `pre` state and `post` state. pub fn diff_pod(pre: &PodState, post: &PodState) -> StateDiff { - StateDiff { raw: pre.get().keys().merge(post.get().keys()).filter_map(|acc| pod_account::diff_pod(pre.get().get(acc), post.get().get(acc)).map(|d|(acc.clone(), d))).collect() } + StateDiff { + raw: pre.get().keys() + .merge(post.get().keys()) + .filter_map(|acc| pod_account::diff_pod(pre.get().get(acc), post.get().get(acc)).map(|d| (acc.clone(), d))) + .collect() + } } #[cfg(test)] @@ -88,7 +94,14 @@ mod test { #[test] fn create_delete() { - let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); + let a = PodState::from(map![ + 1.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + } + ]); assert_eq!(super::diff_pod(&a, &PodState::new()), StateDiff { raw: map![ 1.into() => AccountDiff{ balance: Diff::Died(69.into()), @@ -109,10 +122,27 @@ mod test { #[test] fn create_delete_with_unchanged() { - let a = PodState::from(map![ 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) ]); + let a = PodState::from(map![ + 1.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + } + ]); let b = PodState::from(map![ - 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), - 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) + 1.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + }, + 2.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + } ]); assert_eq!(super::diff_pod(&a, &b), StateDiff { raw: map![ 2.into() => AccountDiff{ @@ -135,12 +165,32 @@ mod test { #[test] fn change_with_unchanged() { let a = PodState::from(map![ - 1.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]), - 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) + 1.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + }, + 2.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + } ]); let b = PodState::from(map![ - 1.into() => PodAccount::new(69.into(), 1.into(), vec![], map![]), - 2.into() => PodAccount::new(69.into(), 0.into(), vec![], map![]) + 1.into() => PodAccount { + balance: 69.into(), + nonce: 1.into(), + code: Some(Vec::new()), + storage: map![], + }, + 2.into() => PodAccount { + balance: 69.into(), + nonce: 0.into(), + code: Some(Vec::new()), + storage: map![], + } ]); assert_eq!(super::diff_pod(&a, &b), StateDiff { raw: map![ 1.into() => AccountDiff{ diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index a9f2ba593b5155f7aee225f40452e829825a8611..b85f8f4013f65dd72a04b45246dd8e2941d442c2 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -19,9 +19,12 @@ use account_db::{AccountDB, AccountDBMut}; use basic_account::BasicAccount; use snapshot::Error; +use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP}; -use util::{U256, H256, Bytes, HashDB, SHA3_EMPTY, SHA3_NULL_RLP}; -use util::trie::{TrieDB, Trie}; +use ethereum_types::{H256, U256}; +use hashdb::HashDB; +use bytes::Bytes; +use trie::{TrieDB, Trie}; use rlp::{RlpStream, UntrustedRlp}; use std::collections::HashSet; @@ -30,8 +33,8 @@ use std::collections::HashSet; const ACC_EMPTY: BasicAccount = BasicAccount { nonce: U256([0, 0, 0, 0]), balance: U256([0, 0, 0, 0]), - storage_root: SHA3_NULL_RLP, - code_hash: SHA3_EMPTY, + storage_root: KECCAK_NULL_RLP, + code_hash: KECCAK_EMPTY, }; // whether an encoded account has code and how it is referred to. @@ -78,7 +81,7 @@ pub fn to_fat_rlps(account_hash: &H256, acc: &BasicAccount, acct_db: &AccountDB, .append(&acc.balance); // [has_code, code_hash]. - if acc.code_hash == SHA3_EMPTY { + if acc.code_hash == KECCAK_EMPTY { account_stream.append(&CodeState::Empty.raw()).append_empty_data(); } else if used_code.contains(&acc.code_hash) { account_stream.append(&CodeState::Hash.raw()).append(&acc.code_hash); @@ -148,7 +151,7 @@ pub fn from_fat_rlp( rlp: UntrustedRlp, mut storage_root: H256, ) -> Result<(BasicAccount, Option), Error> { - use util::{TrieDBMut, TrieMut}; + use trie::{TrieDBMut, TrieMut}; // check for special case of empty account. if rlp.is_empty() { @@ -164,7 +167,7 @@ pub fn from_fat_rlp( // load the code if it exists. let (code_hash, new_code) = match code_state { - CodeState::Empty => (SHA3_EMPTY, None), + CodeState::Empty => (KECCAK_EMPTY, None), CodeState::Inline => { let code: Bytes = rlp.val_at(3)?; let code_hash = acct_db.insert(&code); @@ -210,8 +213,10 @@ mod tests { use tests::helpers::get_temp_state_db; use snapshot::tests::helpers::fill_storage; - use util::sha3::{SHA3_EMPTY, SHA3_NULL_RLP}; - use util::{Address, H256, HashDB, DBValue, Hashable}; + use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; + use ethereum_types::{H256, Address}; + use hashdb::HashDB; + use kvdb::DBValue; use rlp::UntrustedRlp; use std::collections::HashSet; @@ -226,14 +231,14 @@ mod tests { let account = BasicAccount { nonce: 50.into(), balance: 123456789.into(), - storage_root: SHA3_NULL_RLP, - code_hash: SHA3_EMPTY, + storage_root: KECCAK_NULL_RLP, + code_hash: KECCAK_EMPTY, }; let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp), account); - let fat_rlps = to_fat_rlps(&addr.sha3(), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); + let fat_rlps = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); let fat_rlp = UntrustedRlp::new(&fat_rlps[0]).at(1).unwrap(); assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); } @@ -245,20 +250,20 @@ mod tests { let account = { let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr); - let mut root = SHA3_NULL_RLP; + let mut root = KECCAK_NULL_RLP; fill_storage(acct_db, &mut root, &mut H256::zero()); BasicAccount { nonce: 25.into(), balance: 987654321.into(), storage_root: root, - code_hash: SHA3_EMPTY, + code_hash: KECCAK_EMPTY, } }; let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp), account); - let fat_rlp = to_fat_rlps(&addr.sha3(), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); + let fat_rlp = to_fat_rlps(&keccak(&addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), usize::max_value(), usize::max_value()).unwrap(); let fat_rlp = UntrustedRlp::new(&fat_rlp[0]).at(1).unwrap(); assert_eq!(from_fat_rlp(&mut AccountDBMut::new(db.as_hashdb_mut(), &addr), fat_rlp, H256::zero()).unwrap().0, account); } @@ -270,21 +275,21 @@ mod tests { let account = { let acct_db = AccountDBMut::new(db.as_hashdb_mut(), &addr); - let mut root = SHA3_NULL_RLP; + let mut root = KECCAK_NULL_RLP; fill_storage(acct_db, &mut root, &mut H256::zero()); BasicAccount { nonce: 25.into(), balance: 987654321.into(), storage_root: root, - code_hash: SHA3_EMPTY, + code_hash: KECCAK_EMPTY, } }; let thin_rlp = ::rlp::encode(&account); assert_eq!(::rlp::decode::(&thin_rlp), account); - let fat_rlps = to_fat_rlps(&addr.sha3(), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap(); - let mut root = SHA3_NULL_RLP; + let fat_rlps = to_fat_rlps(&keccak(addr), &account, &AccountDB::new(db.as_hashdb(), &addr), &mut Default::default(), 500, 1000).unwrap(); + let mut root = KECCAK_NULL_RLP; let mut restored_account = None; for rlp in fat_rlps { let fat_rlp = UntrustedRlp::new(&rlp).at(1).unwrap(); @@ -314,21 +319,21 @@ mod tests { let account1 = BasicAccount { nonce: 50.into(), balance: 123456789.into(), - storage_root: SHA3_NULL_RLP, + storage_root: KECCAK_NULL_RLP, code_hash: code_hash, }; let account2 = BasicAccount { nonce: 400.into(), balance: 98765432123456789usize.into(), - storage_root: SHA3_NULL_RLP, + storage_root: KECCAK_NULL_RLP, code_hash: code_hash, }; let mut used_code = HashSet::new(); - let fat_rlp1 = to_fat_rlps(&addr1.sha3(), &account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); - let fat_rlp2 = to_fat_rlps(&addr2.sha3(), &account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); + let fat_rlp1 = to_fat_rlps(&keccak(&addr1), &account1, &AccountDB::new(db.as_hashdb(), &addr1), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); + let fat_rlp2 = to_fat_rlps(&keccak(&addr2), &account2, &AccountDB::new(db.as_hashdb(), &addr2), &mut used_code, usize::max_value(), usize::max_value()).unwrap(); assert_eq!(used_code.len(), 1); let fat_rlp1 = UntrustedRlp::new(&fat_rlp1[0]).at(1).unwrap(); diff --git a/ethcore/src/snapshot/block.rs b/ethcore/src/snapshot/block.rs index e7b100f690516c4748d5c33a0e2c205b26c3dced..98215b3244d9f1bca80252e6792181cf21892688 100644 --- a/ethcore/src/snapshot/block.rs +++ b/ethcore/src/snapshot/block.rs @@ -18,11 +18,13 @@ use block::Block; use header::Header; +use hash::keccak; use views::BlockView; use rlp::{DecoderError, RlpStream, UntrustedRlp}; -use util::{Bytes, Hashable, H256}; -use util::triehash::ordered_trie_root; +use ethereum_types::H256; +use bytes::Bytes; +use triehash::ordered_trie_root; const HEADER_FIELDS: usize = 8; const BLOCK_FIELDS: usize = 2; @@ -105,13 +107,13 @@ impl AbridgedBlock { let uncles: Vec
= rlp.list_at(9)?; header.set_transactions_root(ordered_trie_root( - rlp.at(8)?.iter().map(|r| r.as_raw().to_owned()) + rlp.at(8)?.iter().map(|r| r.as_raw()) )); header.set_receipts_root(receipts_root); let mut uncles_rlp = RlpStream::new(); uncles_rlp.append_list(&uncles); - header.set_uncles_hash(uncles_rlp.as_raw().sha3()); + header.set_uncles_hash(keccak(uncles_rlp.as_raw())); let mut seal_fields = Vec::new(); for i in (HEADER_FIELDS + BLOCK_FIELDS)..rlp.item_count()? { @@ -133,13 +135,15 @@ impl AbridgedBlock { mod tests { use views::BlockView; use block::Block; + use header::Seal; use super::AbridgedBlock; use transaction::{Action, Transaction}; - use util::{Address, H256, U256, Bytes}; + use ethereum_types::{H256, U256, Address}; + use bytes::Bytes; fn encode_block(b: &Block) -> Bytes { - b.rlp_bytes(::basic_types::Seal::With) + b.rlp_bytes(Seal::With) } #[test] @@ -189,8 +193,8 @@ mod tests { b.transactions.push(t2.into()); let receipts_root = b.header.receipts_root().clone(); - b.header.set_transactions_root(::util::triehash::ordered_trie_root( - b.transactions.iter().map(::rlp::encode).map(|out| out.into_vec()) + b.header.set_transactions_root(::triehash::ordered_trie_root( + b.transactions.iter().map(::rlp::encode) )); let encoded = encode_block(&b); diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 1a1215522dedec51be97eb52292c42c7f8c991d5..46f433c00503e8992179758a1d2a73fa7787e0c7 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -25,15 +25,18 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use blockchain::{BlockChain, BlockProvider}; -use engines::{Engine, EpochVerifier, EpochTransition}; +use engines::{EthEngine, EpochVerifier, EpochTransition}; +use machine::EthereumMachine; use ids::BlockId; -use header::Header; +use header::{Header, Seal}; use receipt::Receipt; use snapshot::{Error, ManifestData}; use itertools::{Position, Itertools}; use rlp::{RlpStream, UntrustedRlp}; -use util::{Bytes, H256, KeyValueDB}; +use ethereum_types::{H256, U256}; +use kvdb::KeyValueDB; +use bytes::Bytes; /// Snapshot creation and restoration for PoA chains. /// Chunk format: @@ -166,7 +169,7 @@ struct ChunkRebuilder { // and epoch data from last blocks in chunks. // verification for these will be done at the end. unverified_firsts: Vec<(Header, Bytes, H256)>, - last_epochs: Vec<(Header, Box)>, + last_epochs: Vec<(Header, Box>)>, } // verified data. @@ -178,9 +181,9 @@ struct Verified { impl ChunkRebuilder { fn verify_transition( &mut self, - last_verifier: &mut Option>, + last_verifier: &mut Option>>, transition_rlp: UntrustedRlp, - engine: &Engine, + engine: &EthEngine, ) -> Result { use engines::ConstructedVerifier; @@ -236,7 +239,7 @@ impl Rebuilder for ChunkRebuilder { fn feed( &mut self, chunk: &[u8], - engine: &Engine, + engine: &EthEngine, abort_flag: &AtomicBool, ) -> Result<(), ::error::Error> { let rlp = UntrustedRlp::new(chunk); @@ -321,7 +324,7 @@ impl Rebuilder for ChunkRebuilder { transactions: last_rlp.list_at(1)?, uncles: last_rlp.list_at(2)?, }; - let block_data = block.rlp_bytes(::basic_types::Seal::With); + let block_data = block.rlp_bytes(Seal::With); let receipts: Vec = last_rlp.list_at(3)?; { @@ -332,7 +335,7 @@ impl Rebuilder for ChunkRebuilder { } } - let parent_td: ::util::U256 = last_rlp.val_at(4)?; + let parent_td: U256 = last_rlp.val_at(4)?; let mut batch = self.db.transaction(); self.chain.insert_unordered_block(&mut batch, &block_data, receipts, Some(parent_td), true, false); @@ -344,7 +347,7 @@ impl Rebuilder for ChunkRebuilder { Ok(()) } - fn finalize(&mut self, _engine: &Engine) -> Result<(), ::error::Error> { + fn finalize(&mut self, _engine: &EthEngine) -> Result<(), ::error::Error> { if !self.had_genesis { return Err(Error::WrongChunkFormat("No genesis transition included.".into()).into()); } diff --git a/ethcore/src/snapshot/consensus/mod.rs b/ethcore/src/snapshot/consensus/mod.rs index 3f583893beb25f2889a5c7d485d15d0b0f83c67d..712c245ff37d1ca1cf4f763c3c1e971dc3dc24cb 100644 --- a/ethcore/src/snapshot/consensus/mod.rs +++ b/ethcore/src/snapshot/consensus/mod.rs @@ -21,11 +21,11 @@ use std::sync::atomic::AtomicBool; use std::sync::Arc; use blockchain::BlockChain; -use engines::Engine; +use engines::EthEngine; use snapshot::{Error, ManifestData}; -use util::H256; -use util::kvdb::KeyValueDB; +use ethereum_types::H256; +use kvdb::KeyValueDB; mod authority; mod work; @@ -84,7 +84,7 @@ pub trait Rebuilder: Send { fn feed( &mut self, chunk: &[u8], - engine: &Engine, + engine: &EthEngine, abort_flag: &AtomicBool, ) -> Result<(), ::error::Error>; @@ -93,5 +93,5 @@ pub trait Rebuilder: Send { /// /// This should apply the necessary "glue" between chunks, /// and verify against the restored state. - fn finalize(&mut self, engine: &Engine) -> Result<(), ::error::Error>; + fn finalize(&mut self, engine: &EthEngine) -> Result<(), ::error::Error>; } diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index 2bf154fc48a9c0b6f8529ffef79a3b6b7a78d8ea..5b4ff4888935501fb71f54632e1349b33f682954 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -27,10 +27,12 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use blockchain::{BlockChain, BlockProvider}; -use engines::Engine; +use engines::EthEngine; use snapshot::{Error, ManifestData}; use snapshot::block::AbridgedBlock; -use util::{Bytes, H256, KeyValueDB}; +use ethereum_types::H256; +use kvdb::KeyValueDB; +use bytes::Bytes; use rlp::{RlpStream, UntrustedRlp}; use rand::OsRng; @@ -217,12 +219,12 @@ impl PowRebuilder { impl Rebuilder for PowRebuilder { /// Feed the rebuilder an uncompressed block chunk. /// Returns the number of blocks fed or any errors. - fn feed(&mut self, chunk: &[u8], engine: &Engine, abort_flag: &AtomicBool) -> Result<(), ::error::Error> { - use basic_types::Seal::With; + fn feed(&mut self, chunk: &[u8], engine: &EthEngine, abort_flag: &AtomicBool) -> Result<(), ::error::Error> { + use header::Seal; use views::BlockView; use snapshot::verify_old_block; - use util::U256; - use util::triehash::ordered_trie_root; + use ethereum_types::U256; + use triehash::ordered_trie_root; let rlp = UntrustedRlp::new(chunk); let item_count = rlp.item_count()?; @@ -246,12 +248,10 @@ impl Rebuilder for PowRebuilder { let abridged_rlp = pair.at(0)?.as_raw().to_owned(); let abridged_block = AbridgedBlock::from_raw(abridged_rlp); let receipts: Vec<::receipt::Receipt> = pair.list_at(1)?; - let receipts_root = ordered_trie_root( - pair.at(1)?.iter().map(|r| r.as_raw().to_owned()) - ); + let receipts_root = ordered_trie_root(pair.at(1)?.iter().map(|r| r.as_raw())); let block = abridged_block.to_block(parent_hash, cur_number, receipts_root)?; - let block_bytes = block.rlp_bytes(With); + let block_bytes = block.rlp_bytes(Seal::With); let is_best = cur_number == self.best_number; if is_best { @@ -269,7 +269,6 @@ impl Rebuilder for PowRebuilder { &block.header, engine, &self.chain, - Some(&block_bytes), is_best )?; @@ -296,7 +295,7 @@ impl Rebuilder for PowRebuilder { } /// Glue together any disconnected chunks and check that the chain is complete. - fn finalize(&mut self, _: &Engine) -> Result<(), ::error::Error> { + fn finalize(&mut self, _: &EthEngine) -> Result<(), ::error::Error> { let mut batch = self.db.transaction(); for (first_num, first_hash) in self.disconnected.drain(..) { diff --git a/ethcore/src/snapshot/error.rs b/ethcore/src/snapshot/error.rs index 56be84c96479a8e9cb81ac679b04f590c1ee873a..2741f648a2b917f65ce602c7f53725d61c611fc4 100644 --- a/ethcore/src/snapshot/error.rs +++ b/ethcore/src/snapshot/error.rs @@ -20,8 +20,8 @@ use std::fmt; use ids::BlockId; -use util::H256; -use util::trie::TrieError; +use ethereum_types::H256; +use trie::TrieError; use rlp::DecoderError; /// Snapshot-related errors. @@ -57,6 +57,8 @@ pub enum Error { VersionNotSupported(u64), /// Max chunk size is to small to fit basic account data. ChunkTooSmall, + /// Oversized chunk + ChunkTooLarge, /// Snapshots not supported by the consensus engine. SnapshotsUnsupported, /// Bad epoch transition. @@ -85,6 +87,7 @@ impl fmt::Display for Error { Error::Trie(ref err) => err.fmt(f), Error::VersionNotSupported(ref ver) => write!(f, "Snapshot version {} is not supprted.", ver), Error::ChunkTooSmall => write!(f, "Chunk size is too small."), + Error::ChunkTooLarge => write!(f, "Chunk size is too large."), Error::SnapshotsUnsupported => write!(f, "Snapshots unsupported by consensus engine."), Error::BadEpochProof(i) => write!(f, "Bad epoch proof for transition to epoch {}", i), Error::WrongChunkFormat(ref msg) => write!(f, "Wrong chunk format: {}", msg), diff --git a/ethcore/src/snapshot/io.rs b/ethcore/src/snapshot/io.rs index f28adcf7f26d7919c9804a4d538d203cb11360e6..7e38177ea526f955cd080ab63fee5583a3a679dd 100644 --- a/ethcore/src/snapshot/io.rs +++ b/ethcore/src/snapshot/io.rs @@ -25,8 +25,8 @@ use std::io::{self, Read, Seek, SeekFrom, Write}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use util::Bytes; -use util::hash::H256; +use bytes::Bytes; +use ethereum_types::H256; use rlp::{RlpStream, UntrustedRlp}; use super::ManifestData; @@ -156,12 +156,9 @@ impl LooseWriter { // writing logic is the same for both kinds of chunks. fn write_chunk(&mut self, hash: H256, chunk: &[u8]) -> io::Result<()> { - let mut file_path = self.dir.clone(); - file_path.push(hash.hex()); - + let file_path = self.dir.join(format!("{:x}", hash)); let mut file = File::create(file_path)?; file.write_all(chunk)?; - Ok(()) } } @@ -327,22 +324,18 @@ impl SnapshotReader for LooseReader { } fn chunk(&self, hash: H256) -> io::Result { - let mut path = self.dir.clone(); - path.push(hash.hex()); - + let path = self.dir.join(format!("{:x}", hash)); let mut buf = Vec::new(); let mut file = File::open(&path)?; - file.read_to_end(&mut buf)?; - Ok(buf) } } #[cfg(test)] mod tests { - use devtools::RandomTempPath; - use util::sha3::Hashable; + use tempdir::TempDir; + use hash::keccak; use snapshot::ManifestData; use super::{SnapshotWriter, SnapshotReader, PackedWriter, PackedReader, LooseWriter, LooseReader, SNAPSHOT_VERSION}; @@ -352,36 +345,37 @@ mod tests { #[test] fn packed_write_and_read() { - let path = RandomTempPath::new(); - let mut writer = PackedWriter::new(path.as_path()).unwrap(); + let tempdir = TempDir::new("").unwrap(); + let path = tempdir.path().join("packed"); + let mut writer = PackedWriter::new(&path).unwrap(); let mut state_hashes = Vec::new(); let mut block_hashes = Vec::new(); for chunk in STATE_CHUNKS { - let hash = chunk.sha3(); + let hash = keccak(&chunk); state_hashes.push(hash.clone()); writer.write_state_chunk(hash, chunk).unwrap(); } for chunk in BLOCK_CHUNKS { - let hash = chunk.sha3(); + let hash = keccak(&chunk); block_hashes.push(hash.clone()); - writer.write_block_chunk(chunk.sha3(), chunk).unwrap(); + writer.write_block_chunk(keccak(&chunk), chunk).unwrap(); } let manifest = ManifestData { version: SNAPSHOT_VERSION, state_hashes: state_hashes, block_hashes: block_hashes, - state_root: b"notarealroot".sha3(), + state_root: keccak(b"notarealroot"), block_number: 12345678987654321, - block_hash: b"notarealblock".sha3(), + block_hash: keccak(b"notarealblock"), }; writer.finish(manifest.clone()).unwrap(); - let reader = PackedReader::new(path.as_path()).unwrap().unwrap(); + let reader = PackedReader::new(&path).unwrap().unwrap(); assert_eq!(reader.manifest(), &manifest); for hash in manifest.state_hashes.iter().chain(&manifest.block_hashes) { @@ -391,36 +385,36 @@ mod tests { #[test] fn loose_write_and_read() { - let path = RandomTempPath::new(); - let mut writer = LooseWriter::new(path.as_path().into()).unwrap(); + let tempdir = TempDir::new("").unwrap(); + let mut writer = LooseWriter::new(tempdir.path().into()).unwrap(); let mut state_hashes = Vec::new(); let mut block_hashes = Vec::new(); for chunk in STATE_CHUNKS { - let hash = chunk.sha3(); + let hash = keccak(&chunk); state_hashes.push(hash.clone()); writer.write_state_chunk(hash, chunk).unwrap(); } for chunk in BLOCK_CHUNKS { - let hash = chunk.sha3(); + let hash = keccak(&chunk); block_hashes.push(hash.clone()); - writer.write_block_chunk(chunk.sha3(), chunk).unwrap(); + writer.write_block_chunk(keccak(&chunk), chunk).unwrap(); } let manifest = ManifestData { version: SNAPSHOT_VERSION, state_hashes: state_hashes, block_hashes: block_hashes, - state_root: b"notarealroot".sha3(), + state_root: keccak(b"notarealroot"), block_number: 12345678987654321, - block_hash: b"notarealblock".sha3(), + block_hash: keccak(b"notarealblock)"), }; writer.finish(manifest.clone()).unwrap(); - let reader = LooseReader::new(path.as_path().into()).unwrap(); + let reader = LooseReader::new(tempdir.path().into()).unwrap(); assert_eq!(reader.manifest(), &manifest); for hash in manifest.state_hashes.iter().chain(&manifest.block_hashes) { diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index a15c15566ab2c0625bd234bd7e5c06a4356295db..f9a513dd17868c1a0d025dc64ed19f5e1478c873 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -22,20 +22,23 @@ use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use hash::{keccak, KECCAK_NULL_RLP, KECCAK_EMPTY}; use account_db::{AccountDB, AccountDBMut}; use blockchain::{BlockChain, BlockProvider}; -use engines::Engine; +use engines::EthEngine; use header::Header; use ids::BlockId; -use util::{Bytes, Hashable, HashDB, DBValue, snappy, U256}; -use util::Mutex; -use util::hash::{H256}; -use util::journaldb::{self, Algorithm, JournalDB}; -use util::kvdb::KeyValueDB; -use util::trie::{TrieDB, TrieDBMut, Trie, TrieMut}; -use util::sha3::SHA3_NULL_RLP; +use ethereum_types::{H256, U256}; +use hashdb::HashDB; +use kvdb::DBValue; +use snappy; +use bytes::Bytes; +use parking_lot::Mutex; +use journaldb::{self, Algorithm, JournalDB}; +use kvdb::KeyValueDB; +use trie::{TrieDB, TrieDBMut, Trie, TrieMut}; use rlp::{RlpStream, UntrustedRlp}; use bloom_journal::Bloom; @@ -69,20 +72,16 @@ mod watcher; #[cfg(test)] mod tests; -/// IPC interfaces -#[cfg(feature="ipc")] -pub mod remote { - pub use super::traits::RemoteSnapshotService; -} - -mod traits { - #![allow(dead_code, unused_assignments, unused_variables, missing_docs)] // codegen issues - include!(concat!(env!("OUT_DIR"), "/snapshot_service_trait.rs")); -} +mod traits; // Try to have chunks be around 4MB (before compression) const PREFERRED_CHUNK_SIZE: usize = 4 * 1024 * 1024; +// Maximal chunk size (decompressed) +// Snappy::decompressed_len estimation may sometimes yield results greater +// than PREFERRED_CHUNK_SIZE so allow some threshold here. +const MAX_CHUNK_SIZE: usize = PREFERRED_CHUNK_SIZE / 4 * 5; + // Minimum supported state chunk version. const MIN_SUPPORTED_STATE_CHUNK_VERSION: u64 = 1; // current state chunk version. @@ -124,7 +123,7 @@ impl Progress { } /// Take a snapshot using the given blockchain, starting block hash, and database, writing into the given writer. pub fn take_snapshot( - engine: &Engine, + engine: &EthEngine, chain: &BlockChain, block_at: H256, state_db: &HashDB, @@ -183,12 +182,12 @@ pub fn chunk_secondary<'a>(mut chunker: Box, chain: &'a Bloc let mut chunk_sink = |raw_data: &[u8]| { let compressed_size = snappy::compress_into(raw_data, &mut snappy_buffer); let compressed = &snappy_buffer[..compressed_size]; - let hash = compressed.sha3(); + let hash = keccak(&compressed); let size = compressed.len(); writer.lock().write_block_chunk(hash, compressed)?; - trace!(target: "snapshot", "wrote secondary chunk. hash: {}, size: {}, uncompressed size: {}", - hash.hex(), size, raw_data.len()); + trace!(target: "snapshot", "wrote secondary chunk. hash: {:x}, size: {}, uncompressed size: {}", + hash, size, raw_data.len()); progress.size.fetch_add(size, Ordering::SeqCst); chunk_hashes.push(hash); @@ -240,7 +239,7 @@ impl<'a> StateChunker<'a> { let compressed_size = snappy::compress_into(&raw_data, &mut self.snappy_buffer); let compressed = &self.snappy_buffer[..compressed_size]; - let hash = compressed.sha3(); + let hash = keccak(&compressed); self.writer.lock().write_state_chunk(hash, compressed)?; trace!(target: "snapshot", "wrote state chunk. size: {}, uncompressed size: {}", compressed_size, raw_data.len()); @@ -318,7 +317,7 @@ impl StateRebuilder { pub fn new(db: Arc, pruning: Algorithm) -> Self { StateRebuilder { db: journaldb::new(db.clone(), pruning, ::db::COL_STATE), - state_root: SHA3_NULL_RLP, + state_root: KECCAK_NULL_RLP, known_code: HashMap::new(), missing_code: HashMap::new(), bloom: StateDB::load_bloom(&*db), @@ -362,7 +361,7 @@ impl StateRebuilder { // batch trie writes { - let mut account_trie = if self.state_root != SHA3_NULL_RLP { + let mut account_trie = if self.state_root != KECCAK_NULL_RLP { TrieDBMut::from_existing(self.db.as_hashdb_mut(), &mut self.state_root)? } else { TrieDBMut::new(self.db.as_hashdb_mut(), &mut self.state_root) @@ -443,7 +442,7 @@ fn rebuild_accounts( // new inline code Some(code) => status.new_code.push((code_hash, code, hash)), None => { - if code_hash != ::util::SHA3_EMPTY { + if code_hash != KECCAK_EMPTY { // see if this code has already been included inline match known_code.get(&code_hash) { Some(&first_with) => { @@ -482,13 +481,13 @@ const POW_VERIFY_RATE: f32 = 0.02; /// Verify an old block with the given header, engine, blockchain, body. If `always` is set, it will perform /// the fullest verification possible. If not, it will take a random sample to determine whether it will /// do heavy or light verification. -pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &Engine, chain: &BlockChain, body: Option<&[u8]>, always: bool) -> Result<(), ::error::Error> { - engine.verify_block_basic(header, body)?; +pub fn verify_old_block(rng: &mut OsRng, header: &Header, engine: &EthEngine, chain: &BlockChain, always: bool) -> Result<(), ::error::Error> { + engine.verify_block_basic(header)?; if always || rng.gen::() <= POW_VERIFY_RATE { - engine.verify_block_unordered(header, body)?; + engine.verify_block_unordered(header)?; match chain.block_header(header.parent_hash()) { - Some(parent) => engine.verify_block_family(header, &parent, body), + Some(parent) => engine.verify_block_family(header, &parent), None => Ok(()), } } else { diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 47bbb59975d3d08b223a9e821d246e85829a0c84..7def518f35723b207ce314b74f311a6d915f69a4 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -23,22 +23,24 @@ use std::path::PathBuf; use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; -use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService}; +use super::{ManifestData, StateRebuilder, Rebuilder, RestorationStatus, SnapshotService, MAX_CHUNK_SIZE}; use super::io::{SnapshotReader, LooseReader, SnapshotWriter, LooseWriter}; use blockchain::BlockChain; -use client::{BlockChainClient, Client}; -use engines::Engine; +use client::{Client, ChainInfo, ClientIoMessage}; +use engines::EthEngine; use error::Error; use ids::BlockId; -use service::ClientIoMessage; use io::IoChannel; -use util::{Bytes, H256, Mutex, RwLock, RwLockReadGuard, UtilError}; -use util::journaldb::Algorithm; -use util::kvdb::{Database, DatabaseConfig}; -use util::snappy; +use ethereum_types::H256; +use parking_lot::{Mutex, RwLock, RwLockReadGuard}; +use util_error::UtilError; +use bytes::Bytes; +use journaldb::Algorithm; +use kvdb_rocksdb::{Database, DatabaseConfig}; +use snappy; /// Helper for removing directories in case of error. struct Guard(bool, PathBuf); @@ -88,7 +90,7 @@ struct RestorationParams<'a> { writer: Option, // writer for recovered snapshot. genesis: &'a [u8], // genesis block of the chain. guard: Guard, // guard for the restoration directory. - engine: &'a Engine, + engine: &'a EthEngine, } impl Restoration { @@ -100,7 +102,7 @@ impl Restoration { let block_chunks = manifest.block_hashes.iter().cloned().collect(); let raw_db = Arc::new(Database::open(params.db_config, &*params.db_path.to_string_lossy()) - .map_err(UtilError::SimpleString)?); + .map_err(UtilError::from)?); let chain = BlockChain::new(Default::default(), params.genesis, raw_db.clone()); let components = params.engine.snapshot_components() @@ -127,6 +129,11 @@ impl Restoration { // feeds a state chunk, aborts early if `flag` becomes false. fn feed_state(&mut self, hash: H256, chunk: &[u8], flag: &AtomicBool) -> Result<(), Error> { if self.state_chunks_left.contains(&hash) { + let expected_len = snappy::decompressed_len(chunk)?; + if expected_len > MAX_CHUNK_SIZE { + trace!(target: "snapshot", "Discarding large chunk: {} vs {}", expected_len, MAX_CHUNK_SIZE); + return Err(::snapshot::Error::ChunkTooLarge.into()); + } let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?; self.state.feed(&self.snappy_buffer[..len], flag)?; @@ -142,8 +149,13 @@ impl Restoration { } // feeds a block chunk - fn feed_blocks(&mut self, hash: H256, chunk: &[u8], engine: &Engine, flag: &AtomicBool) -> Result<(), Error> { + fn feed_blocks(&mut self, hash: H256, chunk: &[u8], engine: &EthEngine, flag: &AtomicBool) -> Result<(), Error> { if self.block_chunks_left.contains(&hash) { + let expected_len = snappy::decompressed_len(chunk)?; + if expected_len > MAX_CHUNK_SIZE { + trace!(target: "snapshot", "Discarding large chunk: {} vs {}", expected_len, MAX_CHUNK_SIZE); + return Err(::snapshot::Error::ChunkTooLarge.into()); + } let len = snappy::decompress_into(chunk, &mut self.snappy_buffer)?; self.secondary.feed(&self.snappy_buffer[..len], engine, flag)?; @@ -158,8 +170,8 @@ impl Restoration { } // finish up restoration. - fn finalize(mut self, engine: &Engine) -> Result<(), Error> { - use util::trie::TrieError; + fn finalize(mut self, engine: &EthEngine) -> Result<(), Error> { + use trie::TrieError; if !self.is_done() { return Ok(()) } @@ -196,7 +208,7 @@ pub type Channel = IoChannel; /// Snapshot service parameters. pub struct ServiceParams { /// The consensus engine this is built on. - pub engine: Arc, + pub engine: Arc, /// The chain's genesis block. pub genesis_block: Bytes, /// Database configuration options. @@ -222,7 +234,7 @@ pub struct Service { pruning: Algorithm, status: Mutex, reader: RwLock>, - engine: Arc, + engine: Arc, genesis_block: Bytes, state_chunks: AtomicUsize, block_chunks: AtomicUsize, @@ -517,7 +529,7 @@ impl Service { match is_done { true => { - db.flush().map_err(::util::UtilError::SimpleString)?; + db.flush().map_err(UtilError::from)?; drop(db); return self.finalize_restoration(&mut *restoration); }, @@ -530,7 +542,7 @@ impl Service { } } }; - result.and_then(|_| db.flush().map_err(|e| ::util::UtilError::SimpleString(e).into())) + result.and_then(|_| db.flush().map_err(|e| UtilError::from(e).into())) } /// Feed a state chunk to be processed synchronously. @@ -618,14 +630,14 @@ impl Drop for Service { #[cfg(test)] mod tests { use std::sync::Arc; - use service::ClientIoMessage; + use client::ClientIoMessage; use io::{IoService}; - use devtools::RandomTempPath; - use tests::helpers::get_test_spec; - use util::journaldb::Algorithm; + use spec::Spec; + use journaldb::Algorithm; use error::Error; use snapshot::{ManifestData, RestorationStatus, SnapshotService}; use super::*; + use tempdir::TempDir; struct NoopDBRestore; impl DatabaseRestore for NoopDBRestore { @@ -637,13 +649,10 @@ mod tests { #[test] fn sends_async_messages() { let service = IoService::::start().unwrap(); - let spec = get_test_spec(); + let spec = Spec::new_test(); - let dir = RandomTempPath::new(); - let mut dir = dir.as_path().to_owned(); - let mut client_db = dir.clone(); - dir.push("snapshot"); - client_db.push("client"); + let tempdir = TempDir::new("").unwrap(); + let dir = tempdir.path().join("snapshot"); let snapshot_params = ServiceParams { engine: spec.engine.clone(), @@ -678,11 +687,11 @@ mod tests { #[test] fn cannot_finish_with_invalid_chunks() { - use util::H256; - use util::kvdb::DatabaseConfig; + use ethereum_types::H256; + use kvdb_rocksdb::DatabaseConfig; - let spec = get_test_spec(); - let dir = RandomTempPath::new(); + let spec = Spec::new_test(); + let tempdir = TempDir::new("").unwrap(); let state_hashes: Vec<_> = (0..5).map(|_| H256::random()).collect(); let block_hashes: Vec<_> = (0..5).map(|_| H256::random()).collect(); @@ -700,7 +709,7 @@ mod tests { block_hash: H256::default(), }, pruning: Algorithm::Archive, - db_path: dir.as_path().to_owned(), + db_path: tempdir.path().to_owned(), db_config: &db_config, writer: None, genesis: &gb, diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index 6429667f584781ccca988393ccddddec8922e1a0..51f417149bf7ac7e09407227b0e0f37cb6a3f5a8 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -17,26 +17,28 @@ //! Snapshot test helpers. These are used to build blockchains and state tries //! which can be queried before and after a full snapshot/restore cycle. +extern crate trie_standardmap; + use std::sync::Arc; +use hash::{KECCAK_NULL_RLP}; use account_db::AccountDBMut; use basic_account::BasicAccount; use blockchain::BlockChain; -use client::{BlockChainClient, Client}; -use engines::Engine; +use client::{Client, ChainInfo}; +use engines::EthEngine; use snapshot::{StateRebuilder}; use snapshot::io::{SnapshotReader, PackedWriter, PackedReader}; -use devtools::{RandomTempPath, GuardedTempResult}; +use tempdir::TempDir; use rand::Rng; -use util::{DBValue, KeyValueDB}; -use util::hash::H256; -use util::hashdb::HashDB; -use util::journaldb; -use util::trie::{Alphabet, StandardMap, SecTrieDBMut, TrieMut, ValueMode}; -use util::trie::{TrieDB, TrieDBMut, Trie}; -use util::sha3::SHA3_NULL_RLP; +use kvdb::{KeyValueDB, DBValue}; +use ethereum_types::H256; +use hashdb::HashDB; +use journaldb; +use trie::{SecTrieDBMut, TrieMut, TrieDB, TrieDBMut, Trie}; +use self::trie_standardmap::{Alphabet, StandardMap, ValueMode}; // the proportion of accounts we will alter each tick. const ACCOUNT_CHURN: f32 = 0.01; @@ -51,12 +53,11 @@ impl StateProducer { /// Create a new `StateProducer`. pub fn new() -> Self { StateProducer { - state_root: SHA3_NULL_RLP, + state_root: KECCAK_NULL_RLP, storage_seed: H256::zero(), } } - #[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(&mut self, rng: &mut R, db: &mut HashDB) { @@ -115,7 +116,7 @@ pub fn fill_storage(mut db: AccountDBMut, root: &mut H256, seed: &mut H256) { count: 100, }; { - let mut trie = if *root == SHA3_NULL_RLP { + let mut trie = if *root == KECCAK_NULL_RLP { SecTrieDBMut::new(&mut db, root) } else { SecTrieDBMut::from_existing(&mut db, root).unwrap() @@ -138,34 +139,32 @@ pub fn compare_dbs(one: &HashDB, two: &HashDB) { /// Take a snapshot from the given client into a temporary file. /// Return a snapshot reader for it. -pub fn snap(client: &Client) -> GuardedTempResult> { +pub fn snap(client: &Client) -> (Box, TempDir) { use ids::BlockId; - let dir = RandomTempPath::new(); - let writer = PackedWriter::new(dir.as_path()).unwrap(); + let tempdir = TempDir::new("").unwrap(); + let path = tempdir.path().join("file"); + let writer = PackedWriter::new(&path).unwrap(); let progress = Default::default(); let hash = client.chain_info().best_block_hash; client.take_snapshot(writer, BlockId::Hash(hash), &progress).unwrap(); - let reader = PackedReader::new(dir.as_path()).unwrap().unwrap(); + let reader = PackedReader::new(&path).unwrap().unwrap(); - GuardedTempResult { - result: Some(Box::new(reader)), - _temp: dir, - } + (Box::new(reader), tempdir) } /// Restore a snapshot into a given database. This will read chunks from the given reader /// write into the given database. pub fn restore( db: Arc, - engine: &Engine, + engine: &EthEngine, reader: &SnapshotReader, genesis: &[u8], ) -> Result<(), ::error::Error> { use std::sync::atomic::AtomicBool; - use util::snappy; + use snappy; let flag = AtomicBool::new(true); let components = engine.snapshot_components().unwrap(); diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 7c44ec20a3af75cef2e9fe6b121bd44c7ff19401..101de5c586cbf6e4210d06d2d5bd758da82480c7 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -21,31 +21,32 @@ use std::sync::Arc; use std::str::FromStr; use account_provider::AccountProvider; -use client::{Client, BlockChainClient}; +use client::{Client, BlockChainClient, ChainInfo}; use ethkey::Secret; -use futures::Future; -use native_contracts::test_contracts::ValidatorSet; use snapshot::tests::helpers as snapshot_helpers; use spec::Spec; use tests::helpers; use transaction::{Transaction, Action, SignedTransaction}; +use tempdir::TempDir; -use util::{Address, Hashable}; -use util::kvdb; +use ethereum_types::Address; +use kvdb_memorydb; + +use_contract!(test_validator_set, "ValidatorSet", "res/contracts/test_validator_set.json"); const PASS: &'static str = ""; const TRANSITION_BLOCK_1: usize = 2; // block at which the contract becomes activated. const TRANSITION_BLOCK_2: usize = 10; // block at which the second contract activates. macro_rules! secret { - ($e: expr) => { Secret::from_slice(&$e.sha3()) } + ($e: expr) => { Secret::from_slice(&$crate::hash::keccak($e)) } } lazy_static! { // contract addresses. static ref CONTRACT_ADDR_1: Address = Address::from_str("0000000000000000000000000000000000000005").unwrap(); static ref CONTRACT_ADDR_2: Address = Address::from_str("0000000000000000000000000000000000000006").unwrap(); - // secret: `sha3(1)`, and initial validator. + // secret: `keccak(1)`, and initial validator. static ref RICH_ADDR: Address = Address::from_str("7d577a597b2742b498cb5cf0c26cdcd726d39e6e").unwrap(); // rich address' secret. static ref RICH_SECRET: Secret = secret!("1"); @@ -53,13 +54,14 @@ lazy_static! { /// Contract code used here: https://gist.github.com/anonymous/2a43783647e0f0dfcc359bd6fd81d6d9 -/// Account with secrets "1".sha3() is initially the validator. +/// Account with secrets keccak("1") is initially the validator. /// Transitions to the contract at block 2, initially same validator set. /// Create a new Spec with AuthorityRound which uses a contract at address 5 to determine the current validators using `getValidators`. -/// `native_contracts::test_contracts::ValidatorSet` provides a native wrapper for the ABi. +/// `test_validator_set::ValidatorSet` provides a native wrapper for the ABi. fn spec_fixed_to_contract() -> Spec { let data = include_bytes!("test_validator_contract.json"); - Spec::load(&::std::env::temp_dir(), &data[..]).unwrap() + let tempdir = TempDir::new("").unwrap(); + Spec::load(&tempdir.path(), &data[..]).unwrap() } // creates an account provider, filling it with accounts from all the given @@ -93,7 +95,7 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: let mut cur_signers = vec![*RICH_ADDR]; { let engine = client.engine(); - engine.register_client(Arc::downgrade(&client)); + engine.register_client(Arc::downgrade(&client) as _); } { @@ -136,8 +138,7 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: vec![transaction] }; - let contract_1 = ValidatorSet::new(*CONTRACT_ADDR_1); - let contract_2 = ValidatorSet::new(*CONTRACT_ADDR_2); + let contract = test_validator_set::ValidatorSet::default(); // apply all transitions. for transition in transitions { @@ -160,34 +161,24 @@ fn make_chain(accounts: Arc, blocks_beyond: usize, transitions: let pending = if manual { trace!(target: "snapshot", "applying set transition at block #{}", num); - let contract = match num >= TRANSITION_BLOCK_2 { - true => &contract_2, - false => &contract_1, + let address = match num >= TRANSITION_BLOCK_2 { + true => &CONTRACT_ADDR_2 as &Address, + false => &CONTRACT_ADDR_1 as &Address, }; - let mut pending = Vec::new(); - { - let mut exec = |addr, data| { - let mut nonce = nonce.borrow_mut(); - let transaction = Transaction { - nonce: *nonce, - gas_price: 0.into(), - gas: 1_000_000.into(), - action: Action::Call(addr), - value: 0.into(), - data: data, - }.sign(&*RICH_SECRET, client.signing_chain_id()); - - pending.push(transaction); - - *nonce = *nonce + 1.into(); - Ok(Vec::new()) - }; - - contract.set_validators(&mut exec, new_set.clone()).wait().unwrap(); - } - - pending + let data = contract.functions().set_validators().input(new_set.clone()); + let mut nonce = nonce.borrow_mut(); + let transaction = Transaction { + nonce: *nonce, + gas_price: 0.into(), + gas: 1_000_000.into(), + action: Action::Call(*address), + value: 0.into(), + data, + }.sign(&*RICH_SECRET, client.signing_chain_id()); + + *nonce = *nonce + 1.into(); + vec![transaction] } else { make_useless_transactions() }; @@ -236,14 +227,14 @@ fn fixed_to_contract_only() { // 6, 7, 8 prove finality for transition at 6. // 3 beyond gets us to 11. assert_eq!(client.chain_info().best_block_number, 11); - let reader = snapshot_helpers::snap(&*client); + let (reader, _tempdir) = snapshot_helpers::snap(&*client); - let new_db = kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)); + let new_db = kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)); let spec = spec_fixed_to_contract(); // ensure fresh engine's step matches. for _ in 0..11 { spec.engine.step() } - snapshot_helpers::restore(Arc::new(new_db), &*spec.engine, &**reader, &spec.genesis_block()).unwrap(); + snapshot_helpers::restore(Arc::new(new_db), &*spec.engine, &*reader, &spec.genesis_block()).unwrap(); } #[test] @@ -269,10 +260,10 @@ fn fixed_to_contract_to_contract() { ]); assert_eq!(client.chain_info().best_block_number, 16); - let reader = snapshot_helpers::snap(&*client); - let new_db = kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)); + let (reader, _tempdir) = snapshot_helpers::snap(&*client); + let new_db = kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0)); let spec = spec_fixed_to_contract(); for _ in 0..16 { spec.engine.step() } - snapshot_helpers::restore(Arc::new(new_db), &*spec.engine, &**reader, &spec.genesis_block()).unwrap(); + snapshot_helpers::restore(Arc::new(new_db), &*spec.engine, &*reader, &spec.genesis_block()).unwrap(); } diff --git a/ethcore/src/snapshot/tests/proof_of_work.rs b/ethcore/src/snapshot/tests/proof_of_work.rs index a6c0166f53c2d9a3659e659618f65d216f94cdb0..e41b61e6e068d9ece97dc6f817aa22c6fae8861c 100644 --- a/ethcore/src/snapshot/tests/proof_of_work.rs +++ b/ethcore/src/snapshot/tests/proof_of_work.rs @@ -16,40 +16,40 @@ //! PoW block chunker and rebuilder tests. -use devtools::RandomTempPath; +use std::sync::Arc; +use std::sync::atomic::AtomicBool; +use tempdir::TempDir; use error::Error; -use blockchain::generator::{ChainGenerator, ChainIterator, BlockFinalizer}; +use blockchain::generator::{BlockGenerator, BlockBuilder}; use blockchain::BlockChain; use snapshot::{chunk_secondary, Error as SnapshotError, Progress, SnapshotComponents}; use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter}; -use util::{Mutex, snappy}; -use util::kvdb::{self, KeyValueDB, DBTransaction}; - -use std::sync::Arc; -use std::sync::atomic::AtomicBool; +use parking_lot::Mutex; +use snappy; +use kvdb::{KeyValueDB, DBTransaction}; +use kvdb_memorydb; const SNAPSHOT_MODE: ::snapshot::PowSnapshot = ::snapshot::PowSnapshot { blocks: 30000, max_restore_blocks: 30000 }; fn chunk_and_restore(amount: u64) { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - let genesis = canon_chain.generate(&mut finalizer).unwrap(); + let genesis = BlockBuilder::genesis(); + let rest = genesis.add_blocks(amount as usize); + let generator = BlockGenerator::new(vec![rest]); + let genesis = genesis.last(); - let engine = Arc::new(::engines::NullEngine::default()); - let new_path = RandomTempPath::create_dir(); - let mut snapshot_path = new_path.as_path().to_owned(); - snapshot_path.push("SNAP"); + let engine = ::spec::Spec::new_test().engine; + let tempdir = TempDir::new("").unwrap(); + let snapshot_path = tempdir.path().join("SNAP"); - let old_db = Arc::new(kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))); - let bc = BlockChain::new(Default::default(), &genesis, old_db.clone()); + let old_db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let bc = BlockChain::new(Default::default(), &genesis.encoded(), old_db.clone()); // build the blockchain. let mut batch = DBTransaction::new(); - for _ in 0..amount { - let block = canon_chain.generate(&mut finalizer).unwrap(); - bc.insert_block(&mut batch, &block, vec![]); + for block in generator { + bc.insert_block(&mut batch, &block.encoded(), vec![]); bc.commit(); } @@ -71,7 +71,7 @@ fn chunk_and_restore(amount: u64) { version: 2, state_hashes: Vec::new(), block_hashes: block_hashes, - state_root: ::util::sha3::SHA3_NULL_RLP, + state_root: ::hash::KECCAK_NULL_RLP, block_number: amount, block_hash: best_hash, }; @@ -79,8 +79,8 @@ fn chunk_and_restore(amount: u64) { writer.into_inner().finish(manifest.clone()).unwrap(); // restore it. - let new_db = Arc::new(kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))); - let new_chain = BlockChain::new(Default::default(), &genesis, new_db.clone()); + let new_db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let new_chain = BlockChain::new(Default::default(), &genesis.encoded(), new_db.clone()); let mut rebuilder = SNAPSHOT_MODE.rebuilder(new_chain, new_db.clone(), &manifest).unwrap(); let reader = PackedReader::new(&snapshot_path).unwrap().unwrap(); @@ -95,20 +95,24 @@ fn chunk_and_restore(amount: u64) { drop(rebuilder); // and test it. - let new_chain = BlockChain::new(Default::default(), &genesis, new_db); + let new_chain = BlockChain::new(Default::default(), &genesis.encoded(), new_db); assert_eq!(new_chain.best_block_hash(), best_hash); } #[test] -fn chunk_and_restore_500() { chunk_and_restore(500) } +fn chunk_and_restore_500() { + chunk_and_restore(500) +} #[test] -fn chunk_and_restore_40k() { chunk_and_restore(40000) } +fn chunk_and_restore_4k() { + chunk_and_restore(4000) +} #[test] fn checks_flag() { use rlp::RlpStream; - use util::H256; + use ethereum_types::H256; let mut stream = RlpStream::new_list(5); @@ -118,23 +122,18 @@ fn checks_flag() { stream.append_empty_data().append_empty_data(); - let genesis = { - let mut canon_chain = ChainGenerator::default(); - let mut finalizer = BlockFinalizer::default(); - canon_chain.generate(&mut finalizer).unwrap() - }; - + let genesis = BlockBuilder::genesis(); let chunk = stream.out(); - let db = Arc::new(kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))); - let engine = Arc::new(::engines::NullEngine::default()); - let chain = BlockChain::new(Default::default(), &genesis, db.clone()); + let db = Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + let engine = ::spec::Spec::new_test().engine; + let chain = BlockChain::new(Default::default(), &genesis.last().encoded(), db.clone()); let manifest = ::snapshot::ManifestData { version: 2, state_hashes: Vec::new(), block_hashes: Vec::new(), - state_root: ::util::sha3::SHA3_NULL_RLP, + state_root: ::hash::KECCAK_NULL_RLP, block_number: 102, block_hash: H256::default(), }; diff --git a/ethcore/src/snapshot/tests/service.rs b/ethcore/src/snapshot/tests/service.rs index 64a8407aa94ac44a38a349872a8ee562a9e108dc..52b4b3cc979f7c9d77035d46c9a3b59fefb56cb4 100644 --- a/ethcore/src/snapshot/tests/service.rs +++ b/ethcore/src/snapshot/tests/service.rs @@ -18,16 +18,16 @@ use std::sync::Arc; -use client::{BlockChainClient, Client}; +use tempdir::TempDir; +use client::{Client, BlockInfo}; use ids::BlockId; use snapshot::service::{Service, ServiceParams}; use snapshot::{self, ManifestData, SnapshotService}; use spec::Spec; use tests::helpers::generate_dummy_client_with_spec_and_data; -use devtools::RandomTempPath; use io::IoChannel; -use util::kvdb::{Database, DatabaseConfig}; +use kvdb_rocksdb::{Database, DatabaseConfig}; struct NoopDBRestore; @@ -46,12 +46,9 @@ fn restored_is_equivalent() { let client = generate_dummy_client_with_spec_and_data(Spec::new_null, NUM_BLOCKS, TX_PER, &gas_prices); - let path = RandomTempPath::create_dir(); - let mut path = path.as_path().clone(); - let mut client_db = path.clone(); - - client_db.push("client_db"); - path.push("snapshot"); + let tempdir = TempDir::new("").unwrap(); + let client_db = tempdir.path().join("client_db"); + let path = tempdir.path().join("snapshot"); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); let client_db = Database::open(&db_config, client_db.to_str().unwrap()).unwrap(); @@ -69,7 +66,7 @@ fn restored_is_equivalent() { engine: spec.engine.clone(), genesis_block: spec.genesis_block(), db_config: db_config, - pruning: ::util::journaldb::Algorithm::Archive, + pruning: ::journaldb::Algorithm::Archive, channel: IoChannel::disconnected(), snapshot_root: path, db_restore: client2.clone(), @@ -106,20 +103,19 @@ fn restored_is_equivalent() { #[test] fn guards_delete_folders() { let spec = Spec::new_null(); - let path = RandomTempPath::create_dir(); - let mut path = path.as_path().clone(); + let tempdir = TempDir::new("").unwrap(); let service_params = ServiceParams { engine: spec.engine.clone(), genesis_block: spec.genesis_block(), db_config: DatabaseConfig::with_columns(::db::NUM_COLUMNS), - pruning: ::util::journaldb::Algorithm::Archive, + pruning: ::journaldb::Algorithm::Archive, channel: IoChannel::disconnected(), - snapshot_root: path.clone(), + snapshot_root: tempdir.path().to_owned(), db_restore: Arc::new(NoopDBRestore), }; let service = Service::new(service_params).unwrap(); - path.push("restoration"); + let path = tempdir.path().join("restoration"); let manifest = ManifestData { version: 2, diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index 744b86577f9c79c0ed6067b61b7a92379be7569d..f61c799933cef9771acb75c6aa8a7e227350a51d 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -16,6 +16,10 @@ //! State snapshotting tests. +use std::sync::Arc; +use std::sync::atomic::AtomicBool; +use hash::{KECCAK_NULL_RLP, keccak}; + use basic_account::BasicAccount; use snapshot::account; use snapshot::{chunk_state, Error as SnapshotError, Progress, StateRebuilder}; @@ -25,17 +29,12 @@ use super::helpers::{compare_dbs, StateProducer}; use error::Error; use rand::{XorShiftRng, SeedableRng}; -use util::hash::H256; -use util::journaldb::{self, Algorithm}; -use util::kvdb::{Database, DatabaseConfig}; -use util::memorydb::MemoryDB; -use util::Mutex; -use devtools::RandomTempPath; - -use util::sha3::SHA3_NULL_RLP; - -use std::sync::Arc; -use std::sync::atomic::AtomicBool; +use ethereum_types::H256; +use journaldb::{self, Algorithm}; +use kvdb_rocksdb::{Database, DatabaseConfig}; +use memorydb::MemoryDB; +use parking_lot::Mutex; +use tempdir::TempDir; #[test] fn snap_and_restore() { @@ -48,9 +47,8 @@ fn snap_and_restore() { producer.tick(&mut rng, &mut old_db); } - let snap_dir = RandomTempPath::create_dir(); - let mut snap_file = snap_dir.as_path().to_owned(); - snap_file.push("SNAP"); + let tempdir = TempDir::new("").unwrap(); + let snap_file = tempdir.path().join("SNAP"); let state_root = producer.state_root(); let writer = Mutex::new(PackedWriter::new(&snap_file).unwrap()); @@ -66,8 +64,7 @@ fn snap_and_restore() { block_hash: H256::default(), }).unwrap(); - let mut db_path = snap_dir.as_path().to_owned(); - db_path.push("db"); + let db_path = tempdir.path().join("db"); let db = { let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); @@ -77,7 +74,7 @@ fn snap_and_restore() { for chunk_hash in &reader.manifest().state_hashes { let raw = reader.chunk(*chunk_hash).unwrap(); - let chunk = ::util::snappy::decompress(&raw).unwrap(); + let chunk = ::snappy::decompress(&raw).unwrap(); rebuilder.feed(&chunk, &flag).unwrap(); } @@ -98,7 +95,8 @@ fn snap_and_restore() { fn get_code_from_prev_chunk() { use std::collections::HashSet; use rlp::RlpStream; - use util::{HashDB, H256, U256, Hashable}; + use ethereum_types::{H256, U256}; + use hashdb::HashDB; use account_db::{AccountDBMut, AccountDB}; @@ -107,8 +105,8 @@ fn get_code_from_prev_chunk() { let mut acc_stream = RlpStream::new_list(4); acc_stream.append(&U256::default()) .append(&U256::default()) - .append(&SHA3_NULL_RLP) - .append(&code.sha3()); + .append(&KECCAK_NULL_RLP) + .append(&keccak(code)); let (h1, h2) = (H256::random(), H256::random()); @@ -131,9 +129,9 @@ fn get_code_from_prev_chunk() { let chunk1 = make_chunk(acc.clone(), h1); let chunk2 = make_chunk(acc, h2); - let db_path = RandomTempPath::create_dir(); + let tempdir = TempDir::new("").unwrap(); let db_cfg = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); + let new_db = Arc::new(Database::open(&db_cfg, tempdir.path().to_str().unwrap()).unwrap()); { let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); @@ -160,9 +158,8 @@ fn checks_flag() { producer.tick(&mut rng, &mut old_db); } - let snap_dir = RandomTempPath::create_dir(); - let mut snap_file = snap_dir.as_path().to_owned(); - snap_file.push("SNAP"); + let tempdir = TempDir::new("").unwrap(); + let snap_file = tempdir.path().join("SNAP"); let state_root = producer.state_root(); let writer = Mutex::new(PackedWriter::new(&snap_file).unwrap()); @@ -178,8 +175,8 @@ fn checks_flag() { block_hash: H256::default(), }).unwrap(); - let mut db_path = snap_dir.as_path().to_owned(); - db_path.push("db"); + let tempdir = TempDir::new("").unwrap(); + let db_path = tempdir.path().join("db"); { let new_db = Arc::new(Database::open(&db_cfg, &db_path.to_string_lossy()).unwrap()); let mut rebuilder = StateRebuilder::new(new_db.clone(), Algorithm::OverlayRecent); @@ -189,7 +186,7 @@ fn checks_flag() { for chunk_hash in &reader.manifest().state_hashes { let raw = reader.chunk(*chunk_hash).unwrap(); - let chunk = ::util::snappy::decompress(&raw).unwrap(); + let chunk = ::snappy::decompress(&raw).unwrap(); match rebuilder.feed(&chunk, &flag) { Err(Error::Snapshot(SnapshotError::RestorationAborted)) => {}, diff --git a/ethcore/src/snapshot/snapshot_service_trait.rs b/ethcore/src/snapshot/traits.rs similarity index 94% rename from ethcore/src/snapshot/snapshot_service_trait.rs rename to ethcore/src/snapshot/traits.rs index 9df3662507030c6be62cafbadf79378e3fe5a26d..a81c14f08d58937d78b2815d2d7aad620ce99d94 100644 --- a/ethcore/src/snapshot/snapshot_service_trait.rs +++ b/ethcore/src/snapshot/traits.rs @@ -15,14 +15,13 @@ // along with Parity. If not, see . use super::{ManifestData, RestorationStatus}; -use util::{Bytes, H256}; -use ipc::IpcConfig; +use ethereum_types::H256; +use bytes::Bytes; /// The interface for a snapshot network service. /// This handles: /// - restoration of snapshots to temporary databases. /// - responding to queries for snapshot manifests and chunks -#[ipc(client_ident="RemoteSnapshotService")] pub trait SnapshotService : Sync + Send { /// Query the most recent manifest data. fn manifest(&self) -> Option; @@ -53,5 +52,3 @@ pub trait SnapshotService : Sync + Send { /// no-op if currently restoring. fn restore_block_chunk(&self, hash: H256, chunk: Bytes); } - -impl IpcConfig for SnapshotService { } diff --git a/ethcore/src/snapshot/watcher.rs b/ethcore/src/snapshot/watcher.rs index cff9be18cdc548f32f15e207aa42becdbd84bb5d..841fa1982acdc8488994b4936dea6633a816647a 100644 --- a/ethcore/src/snapshot/watcher.rs +++ b/ethcore/src/snapshot/watcher.rs @@ -16,13 +16,13 @@ //! Watcher for snapshot-related chain events. -use util::Mutex; -use client::{BlockChainClient, Client, ChainNotify}; +use parking_lot::Mutex; +use client::{BlockInfo, Client, ChainNotify, ClientIoMessage}; use ids::BlockId; -use service::ClientIoMessage; use io::IoChannel; -use util::{H256, Bytes}; +use ethereum_types::H256; +use bytes::Bytes; use std::sync::Arc; @@ -133,7 +133,7 @@ mod tests { use client::ChainNotify; - use util::{H256, U256}; + use ethereum_types::{H256, U256}; use std::collections::HashMap; diff --git a/ethcore/src/spec/genesis.rs b/ethcore/src/spec/genesis.rs index b7db9aa90eaac72ec70237ff4bc43a83518fa25d..937d7ed8737460747973003794fa4f5f23de6c66 100644 --- a/ethcore/src/spec/genesis.rs +++ b/ethcore/src/spec/genesis.rs @@ -14,10 +14,10 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::{Address, H256, U256}; -use util::sha3::SHA3_NULL_RLP; +use ethereum_types::{H256, U256, Address}; use ethjson; -use super::seal::Seal; +use hash::KECCAK_NULL_RLP; +use spec::seal::Seal; /// Genesis components. pub struct Genesis { @@ -54,8 +54,8 @@ impl From for Genesis { timestamp: g.timestamp.map_or(0, Into::into), parent_hash: g.parent_hash.map_or_else(H256::zero, Into::into), gas_limit: g.gas_limit.into(), - transactions_root: g.transactions_root.map_or_else(|| SHA3_NULL_RLP.clone(), Into::into), - receipts_root: g.receipts_root.map_or_else(|| SHA3_NULL_RLP.clone(), Into::into), + transactions_root: g.transactions_root.map_or_else(|| KECCAK_NULL_RLP.clone(), Into::into), + receipts_root: g.receipts_root.map_or_else(|| KECCAK_NULL_RLP.clone(), Into::into), state_root: g.state_root.map(Into::into), gas_used: g.gas_used.map_or_else(U256::zero, Into::into), extra_data: g.extra_data.map_or_else(Vec::new, Into::into), diff --git a/ethcore/src/spec/mod.rs b/ethcore/src/spec/mod.rs index 2658858a50badc51ea25119c827ab3e932d0f5f2..fb60e1cc858efa28746b190b9f025befd95c5131 100644 --- a/ethcore/src/spec/mod.rs +++ b/ethcore/src/spec/mod.rs @@ -18,7 +18,7 @@ mod genesis; mod seal; -pub mod spec; +mod spec; -pub use self::spec::*; pub use self::genesis::Genesis; +pub use self::spec::{Spec, SpecHardcodedSync, SpecParams, CommonParams, OptimizeFor}; diff --git a/ethcore/src/spec/seal.rs b/ethcore/src/spec/seal.rs index a1e929604e3105cdc56858bcfa125d9901737baf..2a07e69c43f37b6eb0ff7bef44a32a422bceb9cc 100644 --- a/ethcore/src/spec/seal.rs +++ b/ethcore/src/spec/seal.rs @@ -16,8 +16,8 @@ //! Spec seal. -use rlp::*; -use util::hash::{H64, H256, H520}; +use rlp::RlpStream; +use ethereum_types::{H64, H256, H520}; use ethjson; /// Classic ethereum seal. diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 4d10a90adf3a7270ee87cd0da2e550c482d1b04d..f0b3b9203bb26a7d41f975aad411af9714c3f5b7 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -16,30 +16,42 @@ //! Parameters for a block chain. -use std::io::Read; use std::collections::BTreeMap; +use std::io::Read; use std::path::Path; use std::sync::Arc; -use rustc_hex::FromHex; -use super::genesis::Genesis; -use super::seal::Generic as GenericSeal; + +use bytes::Bytes; +use ethereum_types::{H256, Bloom, U256, Address}; +use ethjson; +use hash::{KECCAK_NULL_RLP, keccak}; +use memorydb::MemoryDB; +use parking_lot::RwLock; +use rlp::{Rlp, RlpStream}; +use rustc_hex::{FromHex, ToHex}; +use vm::{EnvInfo, CallType, ActionValue, ActionParams, ParamsType}; use builtin::Builtin; -use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT}; -use vm::{EnvInfo, CallType, ActionValue, ActionParams}; +use encoded; +use engines::{EthEngine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT}; use error::Error; -use ethereum; -use ethjson; use executive::Executive; use factory::Factories; use header::{BlockNumber, Header}; -use pod_state::*; -use rlp::{Rlp, RlpStream}; -use state_db::StateDB; -use state::{Backend, State, Substate}; +use machine::EthereumMachine; +use pod_state::PodState; +use spec::Genesis; +use spec::seal::Generic as GenericSeal; use state::backend::Basic as BasicBackend; +use state::{Backend, State, Substate}; use trace::{NoopTracer, NoopVMTracer}; -use util::*; + +pub use ethash::OptimizeFor; + +// helper for formatting errors. +fn fmt_err(f: F) -> String { + format!("Spec json is invalid: {}", f) +} /// Parameters common to ethereum-like blockchains. /// NOTE: when adding bugfix hard-fork parameters, @@ -66,10 +78,14 @@ pub struct CommonParams { pub fork_block: Option<(BlockNumber, H256)>, /// Number of first block where EIP-98 rules begin. pub eip98_transition: BlockNumber, + /// Number of first block where EIP-658 rules begin. + pub eip658_transition: BlockNumber, /// Number of first block where EIP-155 rules begin. pub eip155_transition: BlockNumber, /// Validate block receipts root. pub validate_receipts_transition: BlockNumber, + /// Validate transaction chain id. + pub validate_chain_id_transition: BlockNumber, /// Number of first block where EIP-86 (Metropolis) rules begin. pub eip86_transition: BlockNumber, /// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin. @@ -82,7 +98,8 @@ pub struct CommonParams { pub eip210_contract_code: Bytes, /// Gas allocated for EIP-210 blockhash update. pub eip210_contract_gas: U256, - /// Number of first block where EIP-211 (Metropolis: RETURNDATASIZE/RETURNDATACOPY) rules begin. + /// Number of first block where EIP-211 (Metropolis: RETURNDATASIZE/RETURNDATACOPY) rules + /// begin. pub eip211_transition: BlockNumber, /// Number of first block where EIP-214 rules begin. pub eip214_transition: BlockNumber, @@ -92,34 +109,47 @@ pub struct CommonParams { pub nonce_cap_increment: u64, /// Enable dust cleanup for contracts. pub remove_dust_contracts: bool, - /// Wasm support - pub wasm: bool, + /// Wasm activation blocknumber, if any disabled initially. + pub wasm_activation_transition: BlockNumber, /// Gas limit bound divisor (how much gas limit can change per block) pub gas_limit_bound_divisor: U256, - /// Block reward in wei. - pub block_reward: U256, /// Registrar contract address. pub registrar: Address, /// Node permission managing contract address. pub node_permission_contract: Option
, + /// Maximum contract code size that can be deployed. + pub max_code_size: u64, + /// Number of first block where max code size limit is active. + pub max_code_size_transition: BlockNumber, + /// Transaction permission managing contract address. + pub transaction_permission_contract: Option
, } impl CommonParams { /// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net. pub fn schedule(&self, block_number: u64) -> ::vm::Schedule { - let mut schedule = ::vm::Schedule::new_post_eip150(usize::max_value(), true, true, true); + let mut schedule = ::vm::Schedule::new_post_eip150(self.max_code_size(block_number) as _, true, true, true); self.update_schedule(block_number, &mut schedule); schedule } + /// Returns max code size at given block. + pub fn max_code_size(&self, block_number: u64) -> u64 { + if block_number >= self.max_code_size_transition { + self.max_code_size + } else { + u64::max_value() + } + } + /// Apply common spec config parameters to the schedule. - pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) { + pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) { schedule.have_create2 = block_number >= self.eip86_transition; schedule.have_revert = block_number >= self.eip140_transition; schedule.have_static_call = block_number >= self.eip214_transition; schedule.have_return_data = block_number >= self.eip211_transition; if block_number >= self.eip210_transition { - schedule.blockhash_gas = 350; + schedule.blockhash_gas = 800; } if block_number >= self.dust_protection_transition { schedule.kill_dust = match self.remove_dust_contracts { @@ -127,19 +157,18 @@ impl CommonParams { false => ::vm::CleanDustMode::BasicOnly, }; } + if block_number >= self.wasm_activation_transition { + schedule.wasm = Some(Default::default()); + } } /// Whether these params contain any bug-fix hard forks. pub fn contains_bugfix_hard_fork(&self) -> bool { - self.eip98_transition != 0 && - self.eip155_transition != 0 && - self.validate_receipts_transition != 0 && - self.eip86_transition != 0 && - self.eip140_transition != 0 && - self.eip210_transition != 0 && - self.eip211_transition != 0 && - self.eip214_transition != 0 && - self.dust_protection_transition != 0 + self.eip98_transition != 0 && self.eip155_transition != 0 && + self.validate_receipts_transition != 0 && self.eip86_transition != 0 && + self.eip140_transition != 0 && self.eip210_transition != 0 && + self.eip211_transition != 0 && self.eip214_transition != 0 && + self.validate_chain_id_transition != 0 && self.dust_protection_transition != 0 } } @@ -149,42 +178,121 @@ impl From for CommonParams { account_start_nonce: p.account_start_nonce.map_or_else(U256::zero, Into::into), maximum_extra_data_size: p.maximum_extra_data_size.into(), network_id: p.network_id.into(), - chain_id: if let Some(n) = p.chain_id { n.into() } else { p.network_id.into() }, + chain_id: if let Some(n) = p.chain_id { + n.into() + } else { + p.network_id.into() + }, subprotocol_name: p.subprotocol_name.unwrap_or_else(|| "eth".to_owned()), min_gas_limit: p.min_gas_limit.into(), - fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None }, + fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { + Some((n.into(), h.into())) + } else { + None + }, eip98_transition: p.eip98_transition.map_or(0, Into::into), eip155_transition: p.eip155_transition.map_or(0, Into::into), validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into), - eip86_transition: p.eip86_transition.map_or(BlockNumber::max_value(), Into::into), - eip140_transition: p.eip140_transition.map_or(BlockNumber::max_value(), Into::into), - eip210_transition: p.eip210_transition.map_or(BlockNumber::max_value(), Into::into), + validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into), + eip86_transition: p.eip86_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), + eip140_transition: p.eip140_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), + eip210_transition: p.eip210_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), eip210_contract_address: p.eip210_contract_address.map_or(0xf0.into(), Into::into), eip210_contract_code: p.eip210_contract_code.map_or_else( - || DEFAULT_BLOCKHASH_CONTRACT.from_hex().expect("Default BLOCKHASH contract is valid"), - Into::into), + || { + DEFAULT_BLOCKHASH_CONTRACT.from_hex().expect( + "Default BLOCKHASH contract is valid", + ) + }, + Into::into, + ), eip210_contract_gas: p.eip210_contract_gas.map_or(1000000.into(), Into::into), - eip211_transition: p.eip211_transition.map_or(BlockNumber::max_value(), Into::into), - eip214_transition: p.eip214_transition.map_or(BlockNumber::max_value(), Into::into), - dust_protection_transition: p.dust_protection_transition.map_or(BlockNumber::max_value(), Into::into), + eip211_transition: p.eip211_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), + eip214_transition: p.eip214_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), + eip658_transition: p.eip658_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), + dust_protection_transition: p.dust_protection_transition.map_or( + BlockNumber::max_value(), + Into::into, + ), nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), - wasm: p.wasm.unwrap_or(false), gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), - block_reward: p.block_reward.map_or_else(U256::zero, Into::into), registrar: p.registrar.map_or_else(Address::new, Into::into), node_permission_contract: p.node_permission_contract.map(Into::into), + max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), + max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into), + transaction_permission_contract: p.transaction_permission_contract.map(Into::into), + wasm_activation_transition: p.wasm_activation_transition.map_or( + BlockNumber::max_value(), + Into::into + ), + } + } +} + +/// Runtime parameters for the spec that are related to how the software should run the chain, +/// rather than integral properties of the chain itself. +#[derive(Debug, Clone, Copy)] +pub struct SpecParams<'a> { + /// The path to the folder used to cache nodes. This is typically /tmp/ on Unix-like systems + pub cache_dir: &'a Path, + /// Whether to run slower at the expense of better memory usage, or run faster while using + /// more + /// memory. This may get more fine-grained in the future but for now is simply a binary + /// option. + pub optimization_setting: Option, +} + +impl<'a> SpecParams<'a> { + /// Create from a cache path, with null values for the other fields + pub fn from_path(path: &'a Path) -> Self { + SpecParams { + cache_dir: path, + optimization_setting: None, + } + } + + /// Create from a cache path and an optimization setting + pub fn new(path: &'a Path, optimization: OptimizeFor) -> Self { + SpecParams { + cache_dir: path, + optimization_setting: Some(optimization), } } } +impl<'a, T: AsRef> From<&'a T> for SpecParams<'a> { + fn from(path: &'a T) -> Self { + Self::from_path(path.as_ref()) + } +} + + /// Parameters for a block chain; includes both those intrinsic to the design of the /// chain and those to be interpreted by the active chain engine. pub struct Spec { /// User friendly spec name pub name: String, /// What engine are we using for this? - pub engine: Arc, + pub engine: Arc, /// Name of the subdir inside the main data dir to use for chain data and settings. pub data_dir: String, @@ -203,15 +311,18 @@ pub struct Spec { pub gas_used: U256, /// The genesis block's timestamp field. pub timestamp: u64, - /// Transactions root of the genesis block. Should be SHA3_NULL_RLP. + /// Transactions root of the genesis block. Should be KECCAK_NULL_RLP. pub transactions_root: H256, - /// Receipts root of the genesis block. Should be SHA3_NULL_RLP. + /// Receipts root of the genesis block. Should be KECCAK_NULL_RLP. pub receipts_root: H256, /// The genesis block's extra data field. pub extra_data: Bytes, /// Each seal field, expressed as RLP, concatenated. pub seal_rlp: Bytes, + /// Hardcoded synchronization. Allows the light client to immediately jump to a specific block. + pub hardcoded_sync: Option, + /// Contract constructors to be executed on genesis. constructors: Vec<(Address, Bytes)>, @@ -222,15 +333,109 @@ pub struct Spec { genesis_state: PodState, } -fn load_from>(cache_dir: T, s: ethjson::spec::Spec) -> Result { +#[cfg(test)] +impl Clone for Spec { + fn clone(&self) -> Spec { + Spec { + name: self.name.clone(), + engine: self.engine.clone(), + data_dir: self.data_dir.clone(), + nodes: self.nodes.clone(), + parent_hash: self.parent_hash.clone(), + transactions_root: self.transactions_root.clone(), + receipts_root: self.receipts_root.clone(), + author: self.author.clone(), + difficulty: self.difficulty.clone(), + gas_limit: self.gas_limit.clone(), + gas_used: self.gas_used.clone(), + timestamp: self.timestamp.clone(), + extra_data: self.extra_data.clone(), + seal_rlp: self.seal_rlp.clone(), + hardcoded_sync: self.hardcoded_sync.clone(), + constructors: self.constructors.clone(), + state_root_memo: RwLock::new(*self.state_root_memo.read()), + genesis_state: self.genesis_state.clone(), + } + } +} + +/// Part of `Spec`. Describes the hardcoded synchronization parameters. +pub struct SpecHardcodedSync { + /// Header of the block to jump to for hardcoded sync, and total difficulty. + pub header: encoded::Header, + /// Total difficulty of the block to jump to. + pub total_difficulty: U256, + /// List of hardcoded CHTs, in order. If `hardcoded_sync` is set, the CHTs should include the + /// header of `hardcoded_sync`. + pub chts: Vec, +} + +impl SpecHardcodedSync { + /// Turns this specifications back into JSON. Useful for pretty printing. + pub fn to_json(self) -> ethjson::spec::HardcodedSync { + self.into() + } +} + +#[cfg(test)] +impl Clone for SpecHardcodedSync { + fn clone(&self) -> SpecHardcodedSync { + SpecHardcodedSync { + header: self.header.clone(), + total_difficulty: self.total_difficulty.clone(), + chts: self.chts.clone(), + } + } +} + +impl From for ethjson::spec::HardcodedSync { + fn from(sync: SpecHardcodedSync) -> ethjson::spec::HardcodedSync { + ethjson::spec::HardcodedSync { + header: sync.header.into_inner().to_hex(), + total_difficulty: ethjson::uint::Uint(sync.total_difficulty), + chts: sync.chts.into_iter().map(Into::into).collect(), + } + } +} + +fn load_machine_from(s: ethjson::spec::Spec) -> EthereumMachine { let builtins = s.accounts.builtins().into_iter().map(|p| (p.0.into(), From::from(p.1))).collect(); + let params = CommonParams::from(s.params); + + Spec::machine(&s.engine, params, builtins) +} + +/// Load from JSON object. +fn load_from(spec_params: SpecParams, s: ethjson::spec::Spec) -> Result { + let builtins = s.accounts + .builtins() + .into_iter() + .map(|p| (p.0.into(), From::from(p.1))) + .collect(); let g = Genesis::from(s.genesis); let GenericSeal(seal_rlp) = g.seal.into(); let params = CommonParams::from(s.params); + let hardcoded_sync = if let Some(ref hs) = s.hardcoded_sync { + if let Ok(header) = hs.header.from_hex() { + Some(SpecHardcodedSync { + header: encoded::Header::new(header), + total_difficulty: hs.total_difficulty.into(), + chts: s.hardcoded_sync + .as_ref() + .map(|s| s.chts.iter().map(|c| c.clone().into()).collect()) + .unwrap_or(Vec::new()), + }) + } else { + None + } + } else { + None + }; + let mut s = Spec { name: s.name.clone().into(), - engine: Spec::engine(cache_dir, s.engine, params, builtins), + engine: Spec::engine(spec_params, s.engine, params, builtins), data_dir: s.data_dir.unwrap_or(s.name).into(), nodes: s.nodes.unwrap_or_else(Vec::new), parent_hash: g.parent_hash, @@ -243,7 +448,12 @@ fn load_from>(cache_dir: T, s: ethjson::spec::Spec) -> Result>(cache_dir: T, s: ethjson::spec::Spec) -> Result *s.state_root_memo.get_mut() = root, - None => { let _ = s.run_constructors(&Default::default(), BasicBackend(MemoryDB::new()))?; }, + None => { + let _ = s.run_constructors( + &Default::default(), + BasicBackend(MemoryDB::new()), + )?; + } } Ok(s) @@ -266,28 +481,54 @@ macro_rules! load_bundled { }; } +macro_rules! load_machine_bundled { + ($e:expr) => { + Spec::load_machine( + include_bytes!(concat!("../../res/", $e, ".json")) as &[u8] + ).expect(concat!("Chain spec ", $e, " is invalid.")) + }; +} + impl Spec { + // create an instance of an Ethereum state machine, minus consensus logic. + fn machine( + engine_spec: ðjson::spec::Engine, + params: CommonParams, + builtins: BTreeMap, + ) -> EthereumMachine { + if let ethjson::spec::Engine::Ethash(ref ethash) = *engine_spec { + EthereumMachine::with_ethash_extensions(params, builtins, ethash.params.clone().into()) + } else { + EthereumMachine::regular(params, builtins) + } + } + /// Convert engine spec into a arc'd Engine of the right underlying type. /// TODO avoid this hard-coded nastiness - use dynamic-linked plugin framework instead. - fn engine>( - cache_dir: T, + fn engine( + spec_params: SpecParams, engine_spec: ethjson::spec::Engine, params: CommonParams, builtins: BTreeMap, - ) -> Arc { + ) -> Arc { + let machine = Self::machine(&engine_spec, params, builtins); + match engine_spec { - ethjson::spec::Engine::Null => Arc::new(NullEngine::new(params, builtins)), - ethjson::spec::Engine::InstantSeal => Arc::new(InstantSeal::new(params, builtins)), - ethjson::spec::Engine::Ethash(ethash) => Arc::new(ethereum::Ethash::new(cache_dir, params, From::from(ethash.params), builtins)), - ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(params, From::from(basic_authority.params), builtins)), - ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(params, From::from(authority_round.params), builtins).expect("Failed to start AuthorityRound consensus engine."), - ethjson::spec::Engine::Tendermint(tendermint) => Tendermint::new(params, From::from(tendermint.params), builtins).expect("Failed to start the Tendermint consensus engine."), + ethjson::spec::Engine::Null(null) => Arc::new(NullEngine::new(null.params.into(), machine)), + ethjson::spec::Engine::Ethash(ethash) => Arc::new(::ethereum::Ethash::new(spec_params.cache_dir, ethash.params.into(), machine, spec_params.optimization_setting)), + ethjson::spec::Engine::InstantSeal => Arc::new(InstantSeal::new(machine)), + ethjson::spec::Engine::BasicAuthority(basic_authority) => Arc::new(BasicAuthority::new(basic_authority.params.into(), machine)), + ethjson::spec::Engine::AuthorityRound(authority_round) => AuthorityRound::new(authority_round.params.into(), machine) + .expect("Failed to start AuthorityRound consensus engine."), + ethjson::spec::Engine::Tendermint(tendermint) => Tendermint::new(tendermint.params.into(), machine) + .expect("Failed to start the Tendermint consensus engine."), } } - // given a pre-constructor state, run all the given constructors and produce a new state and state root. + // given a pre-constructor state, run all the given constructors and produce a new state and + // state root. fn run_constructors(&self, factories: &Factories, mut db: T) -> Result { - let mut root = SHA3_NULL_RLP; + let mut root = KECCAK_NULL_RLP; // basic accounts in spec. { @@ -301,20 +542,18 @@ impl Spec { for (address, account) in self.genesis_state.get().iter() { db.note_non_null_account(address); account.insert_additional( - &mut *factories.accountdb.create(db.as_hashdb_mut(), address.sha3()), - &factories.trie + &mut *factories.accountdb.create( + db.as_hashdb_mut(), + keccak(address), + ), + &factories.trie, ); } let start_nonce = self.engine.account_start_nonce(0); let (root, db) = { - let mut state = State::from_existing( - db, - root, - start_nonce, - factories.clone(), - )?; + let mut state = State::from_existing(db, root, start_nonce, factories.clone())?; // Execute contract constructors. let env_info = EnvInfo { @@ -333,7 +572,7 @@ impl Spec { trace!(target: "spec", " .. root before = {}", state.root()); let params = ActionParams { code_address: address.clone(), - code_hash: Some(constructor.sha3()), + code_hash: Some(keccak(constructor)), address: address.clone(), sender: from.clone(), origin: from.clone(), @@ -343,14 +582,14 @@ impl Spec { code: Some(Arc::new(constructor.clone())), data: None, call_type: CallType::None, + params_type: ParamsType::Embedded, }; let mut substate = Substate::new(); - state.kill_account(&address); { - let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref()); - if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) { + let mut exec = Executive::new(&mut state, &env_info, self.engine.machine()); + if let Err(e) = exec.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) { warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e); } } @@ -375,22 +614,34 @@ impl Spec { } /// Get common blockchain parameters. - pub fn params(&self) -> &CommonParams { &self.engine.params() } + pub fn params(&self) -> &CommonParams { + &self.engine.params() + } /// Get the known knodes of the network in enode format. - pub fn nodes(&self) -> &[String] { &self.nodes } + pub fn nodes(&self) -> &[String] { + &self.nodes + } /// Get the configured Network ID. - pub fn network_id(&self) -> u64 { self.params().network_id } + pub fn network_id(&self) -> u64 { + self.params().network_id + } /// Get the chain ID used for signing. - pub fn chain_id(&self) -> u64 { self.params().chain_id } + pub fn chain_id(&self) -> u64 { + self.params().chain_id + } /// Get the configured subprotocol name. - pub fn subprotocol_name(&self) -> String { self.params().subprotocol_name.clone() } + pub fn subprotocol_name(&self) -> String { + self.params().subprotocol_name.clone() + } /// Get the configured network fork block. - pub fn fork_block(&self) -> Option<(BlockNumber, H256)> { self.params().fork_block } + pub fn fork_block(&self) -> Option<(BlockNumber, H256)> { + self.params().fork_block + } /// Get the header of the genesis block. pub fn genesis_header(&self) -> Header { @@ -400,11 +651,11 @@ impl Spec { header.set_number(0); header.set_author(self.author.clone()); header.set_transactions_root(self.transactions_root.clone()); - header.set_uncles_hash(RlpStream::new_list(0).out().sha3()); + header.set_uncles_hash(keccak(RlpStream::new_list(0).out())); header.set_extra_data(self.extra_data.clone()); header.set_state_root(self.state_root()); header.set_receipts_root(self.receipts_root.clone()); - header.set_log_bloom(H2048::new().clone()); + header.set_log_bloom(Bloom::default()); header.set_gas_used(self.gas_used.clone()); header.set_gas_limit(self.gas_limit.clone()); header.set_difficulty(self.difficulty.clone()); @@ -445,7 +696,10 @@ impl Spec { /// Alter the value of the genesis state. pub fn set_genesis_state(&mut self, s: PodState) -> Result<(), Error> { self.genesis_state = s; - let _ = self.run_constructors(&Default::default(), BasicBackend(MemoryDB::new()))?; + let _ = self.run_constructors( + &Default::default(), + BasicBackend(MemoryDB::new()), + )?; Ok(()) } @@ -459,9 +713,9 @@ impl Spec { } /// Ensure that the given state DB has the trie nodes in for the genesis state. - pub fn ensure_db_good(&self, db: StateDB, factories: &Factories) -> Result { + pub fn ensure_db_good(&self, db: T, factories: &Factories) -> Result { if db.as_hashdb().contains(&self.state_root()) { - return Ok(db) + return Ok(db); } // TODO: could optimize so we don't re-run, but `ensure_db_good` is barely ever @@ -470,87 +724,216 @@ impl Spec { Ok(db) } + /// Loads just the state machine from a json file. + pub fn load_machine(reader: R) -> Result { + ethjson::spec::Spec::load(reader) + .map_err(fmt_err) + .map(load_machine_from) + + } + /// Loads spec from json file. Provide factories for executing contracts and ensuring /// storage goes to the right place. - pub fn load, R>(cache_dir: T, reader: R) -> Result where R: Read { - fn fmt(f: F) -> String { - format!("Spec json is invalid: {}", f) - } + pub fn load<'a, T: Into>, R>(params: T, reader: R) -> Result + where + R: Read, + { + ethjson::spec::Spec::load(reader).map_err(fmt_err).and_then( + |x| { + load_from(params.into(), x).map_err(fmt_err) + }, + ) + } + + /// initialize genesis epoch data, using in-memory database for + /// constructor. + pub fn genesis_epoch_data(&self) -> Result, String> { + use transaction::{Action, Transaction}; + use journaldb; + use kvdb_memorydb; + + let genesis = self.genesis_header(); + + let factories = Default::default(); + let mut db = journaldb::new( + Arc::new(kvdb_memorydb::create(0)), + journaldb::Algorithm::Archive, + None, + ); + + self.ensure_db_good(BasicBackend(db.as_hashdb_mut()), &factories) + .map_err(|e| format!("Unable to initialize genesis state: {}", e))?; - ethjson::spec::Spec::load(reader).map_err(fmt) - .and_then(|x| load_from(cache_dir, x).map_err(fmt)) + let call = |a, d| { + let mut db = db.boxed_clone(); + let env_info = ::evm::EnvInfo { + number: 0, + author: *genesis.author(), + timestamp: genesis.timestamp(), + difficulty: *genesis.difficulty(), + gas_limit: *genesis.gas_limit(), + last_hashes: Arc::new(Vec::new()), + gas_used: 0.into(), + }; + + let from = Address::default(); + let tx = Transaction { + nonce: self.engine.account_start_nonce(0), + action: Action::Call(a), + gas: U256::from(50_000_000), // TODO: share with client. + gas_price: U256::default(), + value: U256::default(), + data: d, + }.fake_sign(from); + + let res = ::state::prove_transaction( + db.as_hashdb_mut(), + *genesis.state_root(), + &tx, + self.engine.machine(), + &env_info, + factories.clone(), + true, + ); + + res.map(|(out, proof)| { + (out, proof.into_iter().map(|x| x.into_vec()).collect()) + }).ok_or_else(|| "Failed to prove call: insufficient state".into()) + }; + + self.engine.genesis_epoch_data(&genesis, &call) + } + + /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a + /// NullEngine consensus. + pub fn new_test() -> Spec { + load_bundled!("null_morden") } - /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus. - pub fn new_test() -> Spec { load_bundled!("null_morden") } + /// Create the EthereumMachine corresponding to Spec::new_test. + pub fn new_test_machine() -> EthereumMachine { load_machine_bundled!("null_morden") } - /// Create a new Spec which is a NullEngine consensus with a premine of address whose secret is sha3(''). - pub fn new_null() -> Spec { load_bundled!("null") } + + /// Create a new Spec which conforms to the Frontier-era Morden chain except that it's a NullEngine consensus with applying reward on block close. + pub fn new_test_with_reward() -> Spec { load_bundled!("null_morden_with_reward") } + + /// Create a new Spec which is a NullEngine consensus with a premine of address whose + /// secret is keccak(''). + pub fn new_null() -> Spec { + load_bundled!("null") + } /// Create a new Spec which constructs a contract at address 5 with storage at 0 equal to 1. - pub fn new_test_constructor() -> Spec { load_bundled!("constructor") } + pub fn new_test_constructor() -> Spec { + load_bundled!("constructor") + } - /// Create a new Spec with InstantSeal consensus which does internal sealing (not requiring work). - pub fn new_instant() -> Spec { load_bundled!("instant_seal") } + /// Create a new Spec with InstantSeal consensus which does internal sealing (not requiring + /// work). + pub fn new_instant() -> Spec { + load_bundled!("instant_seal") + } - /// Create a new Spec with AuthorityRound consensus which does internal sealing (not requiring work). - /// Accounts with secrets "0".sha3() and "1".sha3() are the validators. - pub fn new_test_round() -> Self { load_bundled!("authority_round") } + /// Create a new Spec with AuthorityRound consensus which does internal sealing (not + /// requiring work). + /// Accounts with secrets keccak("0") and keccak("1") are the validators. + pub fn new_test_round() -> Self { + load_bundled!("authority_round") + } - /// Create a new Spec with Tendermint consensus which does internal sealing (not requiring work). - /// Account "0".sha3() and "1".sha3() are a authorities. - pub fn new_test_tendermint() -> Self { load_bundled!("tendermint") } + /// Create a new Spec with AuthorityRound consensus which does internal sealing (not + /// requiring work) with empty step messages enabled. + /// Accounts with secrets keccak("0") and keccak("1") are the validators. + pub fn new_test_round_empty_steps() -> Self { + load_bundled!("authority_round_empty_steps") + } + + /// Create a new Spec with Tendermint consensus which does internal sealing (not requiring + /// work). + /// Account keccak("0") and keccak("1") are a authorities. + pub fn new_test_tendermint() -> Self { + load_bundled!("tendermint") + } /// TestList.sol used in both specs: https://github.com/paritytech/contracts/pull/30/files - /// Accounts with secrets "0".sha3() and "1".sha3() are initially the validators. - /// Create a new Spec with BasicAuthority which uses a contract at address 5 to determine the current validators using `getValidators`. - /// Second validator can be removed with "0xbfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1" and added back in using "0x4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1". - pub fn new_validator_safe_contract() -> Self { load_bundled!("validator_safe_contract") } + /// Accounts with secrets keccak("0") and keccak("1") are initially the validators. + /// Create a new Spec with BasicAuthority which uses a contract at address 5 to determine + /// the current validators using `getValidators`. + /// Second validator can be removed with + /// "0xbfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1" and added + /// back in using + /// "0x4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1". + pub fn new_validator_safe_contract() -> Self { + load_bundled!("validator_safe_contract") + } /// The same as the `safeContract`, but allows reporting and uses AuthorityRound. /// Account is marked with `reportBenign` it can be checked as disliked with "0xd8f2e0bf". /// Validator can be removed with `reportMalicious`. - pub fn new_validator_contract() -> Self { load_bundled!("validator_contract") } + pub fn new_validator_contract() -> Self { + load_bundled!("validator_contract") + } - /// Create a new Spec with BasicAuthority which uses multiple validator sets changing with height. - /// Account with secrets "0".sha3() is the validator for block 1 and with "1".sha3() onwards. - pub fn new_validator_multi() -> Self { load_bundled!("validator_multi") } + /// Create a new Spec with BasicAuthority which uses multiple validator sets changing with + /// height. + /// Account with secrets keccak("0") is the validator for block 1 and with keccak("1") + /// onwards. + pub fn new_validator_multi() -> Self { + load_bundled!("validator_multi") + } /// Create a new spec for a PoW chain - pub fn new_pow_test_spec() -> Self { load_bundled!("ethereum/olympic") } + pub fn new_pow_test_spec() -> Self { + load_bundled!("ethereum/olympic") + } } #[cfg(test)] mod tests { - use std::str::FromStr; - use util::*; - use views::*; - use tests::helpers::get_temp_state_db; - use state::State; use super::*; + use state::State; + use tests::helpers::get_temp_state_db; + use views::BlockView; + use tempdir::TempDir; // https://github.com/paritytech/parity/issues/1840 #[test] fn test_load_empty() { - assert!(Spec::load(::std::env::temp_dir(), &[] as &[u8]).is_err()); + let tempdir = TempDir::new("").unwrap(); + assert!(Spec::load(&tempdir.path(), &[] as &[u8]).is_err()); } #[test] fn test_chain() { let test_spec = Spec::new_test(); - assert_eq!(test_spec.state_root(), H256::from_str("f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9").unwrap()); + assert_eq!( + test_spec.state_root(), + "f3f4696bbf3b3b07775128eb7a3763279a394e382130f27c21e70233e04946a9".into() + ); let genesis = test_spec.genesis_block(); - assert_eq!(BlockView::new(&genesis).header_view().sha3(), H256::from_str("0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303").unwrap()); + assert_eq!( + BlockView::new(&genesis).header_view().hash(), + "0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303".into() + ); } #[test] fn genesis_constructor() { ::ethcore_logger::init_log(); let spec = Spec::new_test_constructor(); - let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); - let state = State::from_existing(db.boxed_clone(), spec.state_root(), spec.engine.account_start_nonce(0), Default::default()).unwrap(); - let expected = H256::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - assert_eq!(state.storage_at(&Address::from_str("0000000000000000000000000000000000000005").unwrap(), &H256::zero()).unwrap(), expected); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()) + .unwrap(); + let state = State::from_existing( + db.boxed_clone(), + spec.state_root(), + spec.engine.account_start_nonce(0), + Default::default(), + ).unwrap(); + let expected = "0000000000000000000000000000000000000000000000000000000000000001".into(); + let address = "0000000000000000000000000000000000001337".into(); + + assert_eq!(state.storage_at(&address, &H256::zero()).unwrap(), expected); + assert_eq!(state.balance(&address).unwrap(), 1.into()); } } diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs old mode 100644 new mode 100755 index 1235fd289682b83da1810c16e5acac1d121d72fe..f70b3eb6a816ac85088e68c394ae033904aee695 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -18,8 +18,14 @@ use std::fmt; use std::sync::Arc; -use std::collections::HashMap; -use util::*; +use std::collections::{HashMap, BTreeMap}; +use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; +use ethereum_types::{H256, U256, Address}; +use hashdb::HashDB; +use kvdb::DBValue; +use bytes::{Bytes, ToPretty}; +use trie; +use trie::{SecTrieDB, Trie, TrieFactory, TrieError}; use pod_account::*; use rlp::*; use lru_cache::LruCache; @@ -29,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` @@ -47,7 +62,7 @@ pub struct Account { storage_changes: HashMap, // Code hash of the account. code_hash: H256, - // Size of the accoun code. + // Size of the account code. code_size: Option, // Code cache of the account. code_cache: Arc, @@ -81,10 +96,10 @@ impl Account { Account { balance: balance, nonce: nonce, - storage_root: SHA3_NULL_RLP, + storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), storage_changes: storage, - code_hash: code.sha3(), + code_hash: keccak(&code), code_size: Some(code.len()), code_cache: Arc::new(code), code_filth: Filth::Dirty, @@ -101,10 +116,10 @@ impl Account { Account { balance: pod.balance, nonce: pod.nonce, - storage_root: SHA3_NULL_RLP, + storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), storage_changes: pod.storage.into_iter().collect(), - code_hash: pod.code.as_ref().map_or(SHA3_EMPTY, |c| c.sha3()), + code_hash: pod.code.as_ref().map_or(KECCAK_EMPTY, |c| keccak(c)), code_filth: Filth::Dirty, code_size: Some(pod.code.as_ref().map_or(0, |c| c.len())), code_cache: Arc::new(pod.code.map_or_else(|| { warn!("POD account with unknown code is being created! Assuming no code."); vec![] }, |c| c)), @@ -117,10 +132,10 @@ impl Account { Account { balance: balance, nonce: nonce, - storage_root: SHA3_NULL_RLP, + storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), storage_changes: HashMap::new(), - code_hash: SHA3_EMPTY, + code_hash: KECCAK_EMPTY, code_cache: Arc::new(vec![]), code_size: Some(0), code_filth: Filth::Clean, @@ -140,10 +155,10 @@ impl Account { Account { balance: balance, nonce: nonce, - storage_root: SHA3_NULL_RLP, + storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), storage_changes: HashMap::new(), - code_hash: SHA3_EMPTY, + code_hash: KECCAK_EMPTY, code_cache: Arc::new(vec![]), code_size: None, code_filth: Filth::Clean, @@ -154,7 +169,7 @@ impl Account { /// Set this account's code to the given code. /// NOTE: Account should have been created with `new_contract()` pub fn init_code(&mut self, code: Bytes) { - self.code_hash = code.sha3(); + self.code_hash = keccak(&code); self.code_cache = Arc::new(code); self.code_size = Some(self.code_cache.len()); self.code_filth = Filth::Dirty; @@ -171,7 +186,7 @@ impl Account { } /// Get (and cache) the contents of the trie's storage at `key`. - /// Takes modifed storage into account. + /// Takes modified storage into account. pub fn storage_at(&self, db: &HashDB, key: &H256) -> trie::Result { if let Some(value) = self.cached_storage_at(key) { return Ok(value); @@ -211,7 +226,7 @@ impl Account { pub fn address_hash(&self, address: &Address) -> H256 { let hash = self.address_hash.get(); hash.unwrap_or_else(|| { - let hash = address.sha3(); + let hash = keccak(address); self.address_hash.set(Some(hash.clone())); hash }) @@ -220,7 +235,7 @@ impl Account { /// returns the account's code. If `None` then the code cache isn't available - /// get someone who knows to call `note_code`. pub fn code(&self) -> Option> { - if self.code_hash != SHA3_EMPTY && self.code_cache.is_empty() { + if self.code_hash != KECCAK_EMPTY && self.code_cache.is_empty() { return None; } Some(self.code_cache.clone()) @@ -235,7 +250,7 @@ impl Account { #[cfg(test)] /// Provide a byte array which hashes to the `code_hash`. returns the hash as a result. pub fn note_code(&mut self, code: Bytes) -> Result<(), H256> { - let h = code.sha3(); + let h = keccak(&code); if self.code_hash == h { self.code_cache = Arc::new(code); self.code_size = Some(self.code_cache.len()); @@ -247,7 +262,7 @@ impl Account { /// Is `code_cache` valid; such that code is going to return Some? pub fn is_cached(&self) -> bool { - !self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == SHA3_EMPTY) + !self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == KECCAK_EMPTY) } /// Provide a database to get `code_hash`. Should not be called if it is a contract without code. @@ -284,7 +299,7 @@ impl Account { // TODO: fill out self.code_cache; trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); self.code_size.is_some() || - if self.code_hash != SHA3_EMPTY { + if self.code_hash != KECCAK_EMPTY { match db.get(&self.code_hash) { Some(x) => { self.code_size = Some(x.len()); @@ -308,19 +323,19 @@ impl Account { /// NOTE: Will panic if `!self.storage_is_clean()` pub fn is_empty(&self) -> bool { assert!(self.storage_is_clean(), "Account::is_empty() may only legally be called when storage is clean."); - self.is_null() && self.storage_root == SHA3_NULL_RLP + self.is_null() && self.storage_root == KECCAK_NULL_RLP } /// Check if account has zero nonce, balance, no code. pub fn is_null(&self) -> bool { self.balance.is_zero() && self.nonce.is_zero() && - self.code_hash == SHA3_EMPTY + self.code_hash == KECCAK_EMPTY } /// Check if account is basic (Has no code). pub fn is_basic(&self) -> bool { - self.code_hash == SHA3_EMPTY + self.code_hash == KECCAK_EMPTY } /// Return the storage root associated with this account or None if it has been altered via the overlay. @@ -447,8 +462,8 @@ impl Account { /// `storage_key` is the hash of the desired storage key, meaning /// this will only work correctly under a secure trie. pub fn prove_storage(&self, db: &HashDB, storage_key: H256) -> Result<(Vec, H256), Box> { - use util::trie::{Trie, TrieDB}; - use util::trie::recorder::Recorder; + use trie::{Trie, TrieDB}; + use trie::recorder::Recorder; let mut recorder = Recorder::new(); @@ -464,24 +479,30 @@ impl Account { impl fmt::Debug for Account { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{:?}", PodAccount::from_account(self)) + f.debug_struct("Account") + .field("balance", &self.balance) + .field("nonce", &self.nonce) + .field("code", &self.code()) + .field("storage", &self.storage_changes.iter().collect::>()) + .finish() } } #[cfg(test)] mod tests { - use rlp::{UntrustedRlp, RlpType, Compressible}; - use util::*; + use rlp_compress::{compress, decompress, snapshot_swapper}; + use ethereum_types::{H256, Address}; + use memorydb::MemoryDB; + use bytes::Bytes; use super::*; use account_db::*; #[test] fn account_compress() { let raw = Account::new_basic(2.into(), 4.into()).rlp(); - let rlp = UntrustedRlp::new(&raw); - let compact_vec = rlp.compress(RlpType::Snapshot).into_vec(); + let compact_vec = compress(&raw, snapshot_swapper()); assert!(raw.len() > compact_vec.len()); - let again_raw = UntrustedRlp::new(&compact_vec).decompress(RlpType::Snapshot); + let again_raw = decompress(&compact_vec, snapshot_swapper()); assert_eq!(raw, again_raw.into_vec()); } @@ -491,7 +512,7 @@ mod tests { let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { let mut a = Account::new_contract(69.into(), 0.into()); - a.set_storage(H256::from(&U256::from(0x00u64)), H256::from(&U256::from(0x1234u64))); + a.set_storage(0x00u64.into(), 0x1234u64.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); a.init_code(vec![]); a.commit_code(&mut db); @@ -499,9 +520,9 @@ mod tests { }; let a = Account::from_rlp(&rlp); - assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); - assert_eq!(a.storage_at(&db.immutable(), &H256::from(&U256::from(0x00u64))).unwrap(), H256::from(&U256::from(0x1234u64))); - assert_eq!(a.storage_at(&db.immutable(), &H256::from(&U256::from(0x01u64))).unwrap(), H256::new()); + assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into()); + assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default()); } #[test] @@ -531,7 +552,7 @@ mod tests { a.set_storage(0.into(), 0x1234.into()); assert_eq!(a.storage_root(), None); a.commit_storage(&Default::default(), &mut db).unwrap(); - assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); + assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); } #[test] @@ -545,7 +566,7 @@ mod tests { a.commit_storage(&Default::default(), &mut db).unwrap(); a.set_storage(1.into(), 0.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); - assert_eq!(a.storage_root().unwrap().hex(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2"); + assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); } #[test] @@ -557,7 +578,7 @@ mod tests { assert_eq!(a.code_filth, Filth::Dirty); assert_eq!(a.code_size(), Some(3)); a.commit_code(&mut db); - assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb"); + assert_eq!(a.code_hash(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb".into()); } #[test] @@ -569,16 +590,16 @@ mod tests { assert_eq!(a.code_filth, Filth::Dirty); a.commit_code(&mut db); assert_eq!(a.code_filth, Filth::Clean); - assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb"); + assert_eq!(a.code_hash(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb".into()); a.reset_code(vec![0x55]); assert_eq!(a.code_filth, Filth::Dirty); a.commit_code(&mut db); - assert_eq!(a.code_hash().hex(), "37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be"); + assert_eq!(a.code_hash(), "37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be".into()); } #[test] fn rlpio() { - let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); + let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new()); let b = Account::from_rlp(&a.rlp()); assert_eq!(a.balance(), b.balance()); assert_eq!(a.nonce(), b.nonce()); @@ -588,17 +609,17 @@ mod tests { #[test] fn new_account() { - let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); + let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new()); assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); - assert_eq!(a.balance(), &U256::from(69u8)); - assert_eq!(a.nonce(), &U256::from(0u8)); - assert_eq!(a.code_hash(), SHA3_EMPTY); - assert_eq!(a.storage_root().unwrap(), &SHA3_NULL_RLP); + assert_eq!(*a.balance(), 69u8.into()); + assert_eq!(*a.nonce(), 0u8.into()); + assert_eq!(a.code_hash(), KECCAK_EMPTY); + assert_eq!(a.storage_root().unwrap(), &KECCAK_NULL_RLP); } #[test] fn create_account() { - let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); + let a = Account::new(69u8.into(), 0u8.into(), HashMap::new(), Bytes::new()); assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); } diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index ea172b5afefdd039334aa204a233b953467fb774..1e761506d95703afaac0df33f2468578f775b9ed 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -25,8 +25,10 @@ use std::collections::{HashSet, HashMap}; use std::sync::Arc; use state::Account; -use util::{Address, MemoryDB, Mutex, H256}; -use util::hashdb::{AsHashDB, HashDB, DBValue}; +use parking_lot::Mutex; +use ethereum_types::{Address, H256}; +use memorydb::MemoryDB; +use hashdb::{AsHashDB, HashDB, DBValue}; /// State backend. See module docs for more details. pub trait Backend: Send { diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs old mode 100644 new mode 100755 index 1b36c91ec206e1459964b4eca1c873c86ef6aa4e..1fe4dd4d6d990ea12dd7abe3461e195001cc3971 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -24,9 +24,10 @@ use std::collections::hash_map::Entry; use std::collections::{HashMap, BTreeMap, HashSet}; use std::fmt; use std::sync::Arc; +use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY}; -use receipt::Receipt; -use engines::Engine; +use receipt::{Receipt, TransactionOutcome}; +use machine::EthereumMachine as Machine; use vm::EnvInfo; use error::Error; use executive::{Executive, TransactOptions}; @@ -39,12 +40,17 @@ use executed::{Executed, ExecutionError}; use types::state_diff::StateDiff; use transaction::SignedTransaction; use state_db::StateDB; -use evm::{Factory as EvmFactory}; +use factory::VmFactory; -use util::*; +use ethereum_types::{H256, U256, Address}; +use hashdb::{HashDB, AsHashDB}; +use kvdb::DBValue; +use bytes::Bytes; + +use trie; +use trie::{Trie, TrieError, TrieDB}; +use trie::recorder::Recorder; -use util::trie; -use util::trie::recorder::Recorder; mod account; mod substate; @@ -56,19 +62,19 @@ pub use self::backend::Backend; pub use self::substate::Substate; /// Used to return information about an `State::apply` operation. -pub struct ApplyOutcome { +pub struct ApplyOutcome { /// The receipt for the applied transaction. pub receipt: Receipt, /// The output of the applied transaction. pub output: Bytes, /// The trace for the applied transaction, empty if tracing was not produced. - pub trace: Vec, + pub trace: Vec, /// The VM trace for the applied transaction, None if tracing was not produced. - pub vm_trace: Option + pub vm_trace: Option } /// Result type for the execution ("application") of a transaction. -pub type ApplyResult = Result; +pub type ApplyResult = Result, Error>; /// Return type of proof validity check. #[derive(Debug, Clone)] @@ -187,10 +193,10 @@ impl AccountEntry { /// `Err(ExecutionError::Internal)` indicates failure, everything else indicates /// a successful proof (as the transaction itself may be poorly chosen). pub fn check_proof( - proof: &[::util::DBValue], + proof: &[DBValue], root: H256, transaction: &SignedTransaction, - engine: &Engine, + machine: &Machine, env_info: &EnvInfo, ) -> ProvedExecution { let backend = self::backend::ProofCheck::new(proof); @@ -200,7 +206,7 @@ pub fn check_proof( let res = State::from_existing( backend, root, - engine.account_start_nonce(env_info.number), + machine.account_start_nonce(env_info.number), factories ); @@ -209,13 +215,52 @@ pub fn check_proof( Err(_) => return ProvedExecution::BadProof, }; - match state.execute(env_info, engine, transaction, TransactOptions::with_no_tracing(), true) { + let options = TransactOptions::with_no_tracing().save_output_from_contract(); + match state.execute(env_info, machine, transaction, options, true) { Ok(executed) => ProvedExecution::Complete(executed), Err(ExecutionError::Internal(_)) => ProvedExecution::BadProof, Err(e) => ProvedExecution::Failed(e), } } +/// Prove a transaction on the given state. +/// Returns `None` when the transacion could not be proved, +/// and a proof otherwise. +pub fn prove_transaction( + db: H, + root: H256, + transaction: &SignedTransaction, + machine: &Machine, + env_info: &EnvInfo, + factories: Factories, + virt: bool, +) -> Option<(Bytes, Vec)> { + use self::backend::Proving; + + let backend = Proving::new(db); + let res = State::from_existing( + backend, + root, + machine.account_start_nonce(env_info.number), + factories, + ); + + let mut state = match res { + Ok(state) => state, + Err(_) => return None, + }; + + let options = TransactOptions::with_no_tracing().dont_check_nonce().save_output_from_contract(); + match state.execute(env_info, machine, transaction, options, virt) { + Err(ExecutionError::Internal(_)) => None, + Err(e) => { + trace!(target: "state", "Proved call failed: {}", e); + Some((Vec::new(), state.drop().1.extract_proof())) + } + Ok(res) => Some((res.output, state.drop().1.extract_proof())), + } +} + /// Representation of the entire state of all accounts in the system. /// /// `State` can work together with `StateDB` to share account cache. @@ -289,6 +334,28 @@ pub enum CleanupMode<'a> { TrackTouched(&'a mut HashSet
), } +/// Provides subset of `State` methods to query state information +pub trait StateInfo { + /// Get the nonce of account `a`. + fn nonce(&self, a: &Address) -> trie::Result; + + /// Get the balance of account `a`. + fn balance(&self, a: &Address) -> trie::Result; + + /// Mutate storage of account `address` so that it is `value` for `key`. + fn storage_at(&self, address: &Address, key: &H256) -> trie::Result; + + /// Get accounts' code. + fn code(&self, a: &Address) -> trie::Result>>; +} + +impl StateInfo for State { + fn nonce(&self, a: &Address) -> trie::Result { State::nonce(self, a) } + fn balance(&self, a: &Address) -> trie::Result { State::balance(self, a) } + fn storage_at(&self, address: &Address, key: &H256) -> trie::Result { State::storage_at(self, address, key) } + fn code(&self, address: &Address) -> trie::Result>> { State::code(self, address) } +} + const SEC_TRIE_DB_UNWRAP_STR: &'static str = "A state can only be created with valid root. Creating a SecTrieDB with a valid root will not fail. \ Therefore creating a SecTrieDB with this state's root will not fail."; @@ -298,7 +365,7 @@ impl State { pub fn new(mut db: B, account_start_nonce: U256, factories: Factories) -> State { let mut root = H256::new(); { - // init trie and reset root too null + // init trie and reset root to null let _ = factories.trie.create(db.as_hashdb_mut(), &mut root); } @@ -331,7 +398,7 @@ impl State { } /// Get a VM factory that can execute on this state. - pub fn vm_factory(&self) -> EvmFactory { + pub fn vm_factory(&self) -> VmFactory { self.factories.vm.clone() } @@ -405,22 +472,19 @@ impl State { // // In all other cases account is read as clean first, and after that made // dirty in and added to the checkpoint with `note_cache`. - if account.is_dirty() { + let is_dirty = account.is_dirty(); + let old_value = self.cache.borrow_mut().insert(*address, account); + if is_dirty { if let Some(ref mut checkpoint) = self.checkpoints.borrow_mut().last_mut() { - if !checkpoint.contains_key(address) { - checkpoint.insert(address.clone(), self.cache.borrow_mut().insert(address.clone(), account)); - return; - } + checkpoint.entry(*address).or_insert(old_value); } } - self.cache.borrow_mut().insert(address.clone(), account); } fn note_cache(&self, address: &Address) { if let Some(ref mut checkpoint) = self.checkpoints.borrow_mut().last_mut() { - if !checkpoint.contains_key(address) { - checkpoint.insert(address.clone(), self.cache.borrow().get(address).map(AccountEntry::clone_dirty)); - } + checkpoint.entry(*address) + .or_insert_with(|| self.cache.borrow().get(address).map(AccountEntry::clone_dirty)); } } @@ -458,9 +522,10 @@ impl State { self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null())) } - /// Determine whether an account exists and has code. - pub fn exists_and_has_code(&self, a: &Address) -> trie::Result { - self.ensure_cached(a, RequireCache::CodeSize, false, |a| a.map_or(false, |a| a.code_size().map_or(false, |size| size != 0))) + /// Determine whether an account exists and has code or non-zero nonce. + pub fn exists_and_has_code_or_nonce(&self, a: &Address) -> trie::Result { + self.ensure_cached(a, RequireCache::CodeSize, false, + |a| a.map_or(false, |a| a.code_hash() != KECCAK_EMPTY || *a.nonce() != self.account_start_nonce)) } /// Get the balance of account `a`. @@ -488,8 +553,8 @@ impl State { // 2. If there's an entry for the account in the global cache check for the key or load it into that account. // 3. If account is missing in the global cache load it into the local cache and cache the key there. - // check local cache first without updating { + // check local cache first without updating let local_cache = self.cache.borrow_mut(); let mut local_account = None; if let Some(maybe_acc) = local_cache.get(address) { @@ -513,9 +578,8 @@ impl State { } }); - match trie_res { - None => {} - Some(res) => return res, + if let Some(res) = trie_res { + return res; } // otherwise cache the account localy and cache storage key there. @@ -552,7 +616,7 @@ impl State { /// Get an account's code hash. pub fn code_hash(&self, a: &Address) -> trie::Result { self.ensure_cached(a, RequireCache::None, true, - |a| a.as_ref().map_or(SHA3_EMPTY, |a| a.code_hash())) + |a| a.as_ref().map_or(KECCAK_EMPTY, |a| a.code_hash())) } /// Get accounts' code size. @@ -562,7 +626,6 @@ impl State { } /// 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(); @@ -603,7 +666,7 @@ impl State { /// Mutate storage of account `a` so that it is `value` for `key`. pub fn set_storage(&mut self, a: &Address, key: H256, value: H256) -> trie::Result<()> { - trace!(target: "state", "set_storage({}:{} to {})", a, key.hex(), value.hex()); + trace!(target: "state", "set_storage({}:{:x} to {:x})", a, key, value); if self.storage_at(a, &key)? != value { self.require(a, false)?.set_storage(key, value) } @@ -626,13 +689,13 @@ impl State { /// Execute a given transaction, producing a receipt and an optional trace. /// This will change the state accordingly. - pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult { + pub fn apply(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, tracing: bool) -> ApplyResult { if tracing { let options = TransactOptions::with_tracing(); - self.apply_with_tracing(env_info, engine, t, options.tracer, options.vm_tracer) + self.apply_with_tracing(env_info, machine, t, options.tracer, options.vm_tracer) } else { let options = TransactOptions::with_no_tracing(); - self.apply_with_tracing(env_info, engine, t, options.tracer, options.vm_tracer) + self.apply_with_tracing(env_info, machine, t, options.tracer, options.vm_tracer) } } @@ -641,26 +704,36 @@ impl State { pub fn apply_with_tracing( &mut self, env_info: &EnvInfo, - engine: &Engine, + machine: &Machine, t: &SignedTransaction, tracer: T, vm_tracer: V, - ) -> ApplyResult where + ) -> ApplyResult where T: trace::Tracer, V: trace::VMTracer, { let options = TransactOptions::new(tracer, vm_tracer); - let e = self.execute(env_info, engine, t, options, false)?; - - let state_root = if env_info.number < engine.params().eip98_transition || env_info.number < engine.params().validate_receipts_transition { - self.commit()?; - Some(self.root().clone()) + let e = self.execute(env_info, machine, t, options, false)?; + let params = machine.params(); + + let eip658 = env_info.number >= params.eip658_transition; + let no_intermediate_commits = + eip658 || + (env_info.number >= params.eip98_transition && env_info.number >= params.validate_receipts_transition); + + let outcome = if no_intermediate_commits { + if eip658 { + TransactionOutcome::StatusCode(if e.exception.is_some() { 0 } else { 1 }) + } else { + TransactionOutcome::Unknown + } } else { - None + self.commit()?; + TransactionOutcome::StateRoot(self.root().clone()) }; let output = e.output; - let receipt = Receipt::new(state_root, e.cumulative_gas_used, e.logs); + let receipt = Receipt::new(outcome, e.cumulative_gas_used, e.logs); trace!(target: "state", "Transaction receipt: {:?}", receipt); Ok(ApplyOutcome { @@ -675,10 +748,10 @@ impl State { // // `virt` signals that we are executing outside of a block set and restrictions like // gas limits and gas costs should be lifted. - fn execute(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, options: TransactOptions, virt: bool) - -> Result where T: trace::Tracer, V: trace::VMTracer, + fn execute(&mut self, env_info: &EnvInfo, machine: &Machine, t: &SignedTransaction, options: TransactOptions, virt: bool) + -> Result, ExecutionError> where T: trace::Tracer, V: trace::VMTracer, { - let mut e = Executive::new(self, env_info, engine); + let mut e = Executive::new(self, env_info, machine); match virt { true => e.transact_virtual(t, options), @@ -692,8 +765,6 @@ impl State { } /// 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(); @@ -811,27 +882,29 @@ impl State { // load required account data from the databases. fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB) { - match (account.is_cached(), require) { - (true, _) | (false, RequireCache::None) => {} - (false, require) => { - // if there's already code in the global cache, always cache it - // locally. - let hash = account.code_hash(); - match state_db.get_cached_code(&hash) { - Some(code) => account.cache_given_code(code), - None => match require { - RequireCache::None => {}, - RequireCache::Code => { - if let Some(code) = account.cache_code(db) { - // propagate code loaded from the database to - // the global code cache. - state_db.cache_code(hash, code) - } - } - RequireCache::CodeSize => { - account.cache_code_size(db); - } + if let RequireCache::None = require { + return; + } + + if account.is_cached() { + return; + } + + // if there's already code in the global cache, always cache it localy + let hash = account.code_hash(); + match state_db.get_cached_code(&hash) { + Some(code) => account.cache_given_code(code), + None => match require { + RequireCache::None => {}, + RequireCache::Code => { + if let Some(code) = account.cache_code(db) { + // propagate code loaded from the database to + // the global code cache. + state_db.cache_code(hash, code) } + }, + RequireCache::CodeSize => { + account.cache_code_size(db); } } } @@ -881,7 +954,7 @@ impl State { /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. fn require<'a>(&'a self, a: &Address, require_code: bool) -> trie::Result> { - self.require_or_from(a, require_code, || Account::new_basic(U256::from(0u8), self.account_start_nonce), |_|{}) + self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_|{}) } /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. @@ -908,7 +981,7 @@ impl State { // at this point the entry is guaranteed to be in the cache. Ok(RefMut::map(self.cache.borrow_mut(), |c| { - let mut entry = c.get_mut(a).expect("entry known to exist in the cache; qed"); + let entry = c.get_mut(a).expect("entry known to exist in the cache; qed"); match &mut entry.account { &mut Some(ref mut acc) => not_default(acc), @@ -938,7 +1011,7 @@ impl State { /// Returns a merkle proof of the account's trie node omitted or an encountered trie error. /// If the account doesn't exist in the trie, prove that and return defaults. /// Requires a secure trie to be used for accurate results. - /// `account_key` == sha3(address) + /// `account_key` == keccak(address) pub fn prove_account(&self, account_key: H256) -> trie::Result<(Vec, BasicAccount)> { let mut recorder = Recorder::new(); let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; @@ -949,8 +1022,8 @@ impl State { let account = maybe_account.unwrap_or_else(|| BasicAccount { balance: 0.into(), nonce: self.account_start_nonce, - code_hash: SHA3_EMPTY, - storage_root: ::util::sha3::SHA3_NULL_RLP, + code_hash: KECCAK_EMPTY, + storage_root: KECCAK_NULL_RLP, }); Ok((recorder.drain().into_iter().map(|r| r.data).collect(), account)) @@ -959,11 +1032,11 @@ impl State { /// Prove an account's storage key's existence or nonexistence in the state. /// Returns a merkle proof of the account's storage trie. /// Requires a secure trie to be used for correctness. - /// `account_key` == sha3(address) - /// `storage_key` == sha3(key) + /// `account_key` == keccak(address) + /// `storage_key` == keccak(key) pub fn prove_storage(&self, account_key: H256, storage_key: H256) -> trie::Result<(Vec, H256)> { // TODO: probably could look into cache somehow but it's keyed by - // address, not sha3(address). + // address, not keccak(address). let trie = TrieDB::new(self.db.as_hashdb(), &self.root)?; let acc = match trie.get_with(&account_key, Account::from_rlp)? { Some(acc) => acc, @@ -1008,14 +1081,15 @@ impl Clone for State { #[cfg(test)] mod tests { - use std::sync::Arc; use std::str::FromStr; use rustc_hex::FromHex; + use hash::keccak; use super::*; use ethkey::Secret; - use util::{U256, H256, Address, Hashable}; - use tests::helpers::*; + use ethereum_types::{H256, U256, Address}; + use tests::helpers::{get_temp_state, get_temp_state_db}; + use machine::EthereumMachine; use vm::EnvInfo; use spec::*; use transaction::*; @@ -1024,7 +1098,13 @@ mod tests { use evm::CallType; fn secret() -> Secret { - "".sha3().into() + keccak("").into() + } + + fn make_frontier_machine(max_depth: usize) -> EthereumMachine { + let mut machine = ::ethereum::new_frontier_test_machine(); + machine.set_schedule_creation_rules(Box::new(move |s, _| s.max_depth = max_depth)); + machine } #[test] @@ -1035,7 +1115,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1047,7 +1127,7 @@ mod tests { }.sign(&secret(), None); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), subtraces: 0, @@ -1093,7 +1173,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1105,7 +1185,7 @@ mod tests { }.sign(&secret(), None); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Create(trace::Create { @@ -1129,7 +1209,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1142,7 +1222,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("6000").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { @@ -1171,7 +1251,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1183,7 +1263,7 @@ mod tests { }.sign(&secret(), None); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { @@ -1212,7 +1292,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = &*Spec::new_test().engine; + let machine = Spec::new_test_machine(); let t = Transaction { nonce: 0.into(), @@ -1223,7 +1303,7 @@ mod tests { data: vec![], }.sign(&secret(), None); - let result = state.apply(&info, engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), @@ -1253,7 +1333,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = &*Spec::new_test().engine; + let machine = Spec::new_test_machine(); let t = Transaction { nonce: 0.into(), @@ -1265,7 +1345,7 @@ mod tests { }.sign(&secret(), None); state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060006001610be0f1").unwrap()).unwrap(); - let result = state.apply(&info, engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), @@ -1278,7 +1358,7 @@ mod tests { call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(28_061), + gas_used: U256::from(3_721), // in post-eip150 output: vec![] }), subtraces: 0, @@ -1295,7 +1375,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = &*Spec::new_test().engine; + let machine = Spec::new_test_machine(); let t = Transaction { nonce: 0.into(), @@ -1308,7 +1388,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b611000f2").unwrap()).unwrap(); state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()).unwrap(); - let result = state.apply(&info, engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), @@ -1322,7 +1402,7 @@ mod tests { call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: 64.into(), + gas_used: 724.into(), // in post-eip150 output: vec![] }), }, FlatTrace { @@ -1346,7 +1426,7 @@ mod tests { } #[test] - fn should_not_trace_delegatecall() { + fn should_trace_delegatecall_properly() { init_log(); let mut state = get_temp_state(); @@ -1354,9 +1434,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); info.number = 0x789b0; - let engine = &*Spec::new_test().engine; - - println!("schedule.have_delegate_call: {:?}", engine.schedule(info.number).have_delegate_call); + let machine = Spec::new_test_machine(); let t = Transaction { nonce: 0.into(), @@ -1368,8 +1446,8 @@ mod tests { }.sign(&secret(), None); state.init_code(&0xa.into(), FromHex::from_hex("6000600060006000600b618000f4").unwrap()).unwrap(); - state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()).unwrap(); - let result = state.apply(&info, engine, &t, true).unwrap(); + state.init_code(&0xb.into(), FromHex::from_hex("60056000526001601ff3").unwrap()).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), @@ -1383,23 +1461,23 @@ mod tests { call_type: CallType::Call, }), result: trace::Res::Call(trace::CallResult { - gas_used: U256::from(61), + gas_used: U256::from(736), // in post-eip150 output: vec![] }), }, FlatTrace { trace_address: vec![0].into_iter().collect(), subtraces: 0, action: trace::Action::Call(trace::Call { - from: "9cce34f7ab185c7aba1b7c8140d620b4bda941d6".into(), - to: 0xa.into(), + from: 0xa.into(), + to: 0xb.into(), value: 0.into(), gas: 32768.into(), input: vec![], call_type: CallType::DelegateCall, }), result: trace::Res::Call(trace::CallResult { - gas_used: 3.into(), - output: vec![], + gas_used: 18.into(), + output: vec![5], }), }]; @@ -1414,7 +1492,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1427,7 +1505,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("5b600056").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), action: trace::Action::Call(trace::Call { @@ -1453,7 +1531,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1467,7 +1545,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()).unwrap(); state.init_code(&0xb.into(), FromHex::from_hex("6000").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), @@ -1512,7 +1590,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1525,7 +1603,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006045600b6000f1").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), subtraces: 1, @@ -1566,7 +1644,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1579,7 +1657,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("600060006000600060ff600b6000f1").unwrap()).unwrap(); // not enough funds. state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), subtraces: 0, @@ -1608,7 +1686,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1622,7 +1700,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("60006000600060006000600b602b5a03f1").unwrap()).unwrap(); state.init_code(&0xb.into(), FromHex::from_hex("5b600056").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), subtraces: 1, @@ -1663,7 +1741,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1678,7 +1756,7 @@ mod tests { state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1").unwrap()).unwrap(); state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), subtraces: 1, @@ -1737,7 +1815,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1752,7 +1830,7 @@ mod tests { state.init_code(&0xb.into(), FromHex::from_hex("60006000600060006000600c602b5a03f1505b601256").unwrap()).unwrap(); state.init_code(&0xc.into(), FromHex::from_hex("6000").unwrap()).unwrap(); state.add_balance(&t.sender(), &(100.into()), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), @@ -1809,7 +1887,7 @@ mod tests { let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); - let engine = TestEngine::new(5); + let machine = make_frontier_machine(5); let t = Transaction { nonce: 0.into(), @@ -1823,7 +1901,7 @@ mod tests { state.init_code(&0xa.into(), FromHex::from_hex("73000000000000000000000000000000000000000bff").unwrap()).unwrap(); state.add_balance(&0xa.into(), &50.into(), CleanupMode::NoEmpty).unwrap(); state.add_balance(&t.sender(), &100.into(), CleanupMode::NoEmpty).unwrap(); - let result = state.apply(&info, &engine, &t, true).unwrap(); + let result = state.apply(&info, &machine, &t, true).unwrap(); let expected_trace = vec![FlatTrace { trace_address: Default::default(), subtraces: 1, @@ -2029,7 +2107,7 @@ mod tests { let a = Address::zero(); state.require(&a, false).unwrap(); state.commit().unwrap(); - assert_eq!(state.root().hex(), "0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785"); + assert_eq!(*state.root(), "0ce23f3c809de377b008a4a3ee94a0834aac8bec1f86e28ffe4fdb5a15b0c785".into()); } #[test] @@ -2066,7 +2144,7 @@ mod tests { fn create_empty() { let mut state = get_temp_state(); state.commit().unwrap(); - assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); + assert_eq!(*state.root(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".into()); } #[test] diff --git a/ethcore/src/state/substate.rs b/ethcore/src/state/substate.rs index 76f6eaed7165e91c394b65861f55db42f9edb96e..e70178a36255133565b01c84a031850ebed66a44 100644 --- a/ethcore/src/state/substate.rs +++ b/ethcore/src/state/substate.rs @@ -16,7 +16,7 @@ //! Execution environment substate. use std::collections::HashSet; -use util::{Address, U256}; +use ethereum_types::{U256, Address}; use log_entry::LogEntry; use evm::{Schedule, CleanDustMode}; use super::CleanupMode; @@ -49,15 +49,14 @@ impl Substate { /// Merge secondary substate `s` into self, accruing each element correspondingly. pub fn accrue(&mut self, s: Substate) { - self.suicides.extend(s.suicides.into_iter()); - self.touched.extend(s.touched.into_iter()); - self.logs.extend(s.logs.into_iter()); + self.suicides.extend(s.suicides); + self.touched.extend(s.touched); + self.logs.extend(s.logs); self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count; - self.contracts_created.extend(s.contracts_created.into_iter()); + self.contracts_created.extend(s.contracts_created); } /// 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, diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs old mode 100644 new mode 100755 index e2f6fdaf0380a2046a0994010cc617a1903ecd1e..346ad9cc2a69f9a282c431e0d6cd30d9504c4360 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -14,24 +14,36 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +//! State database abstraction. For more info, see the doc for `StateDB` + use std::collections::{VecDeque, HashSet}; use std::sync::Arc; use lru_cache::LruCache; -use util::cache::MemoryLruCache; -use util::journaldb::JournalDB; -use util::kvdb::KeyValueDB; -use util::hash::{H256}; -use util::hashdb::HashDB; +use memory_cache::MemoryLruCache; +use journaldb::JournalDB; +use kvdb::{KeyValueDB, DBTransaction}; +use ethereum_types::{H256, Address}; +use hashdb::HashDB; use state::{self, Account}; use header::BlockNumber; -use util::{Address, DBTransaction, UtilError, Mutex, Hashable}; +use hash::keccak; +use parking_lot::Mutex; +use util_error::UtilError; use bloom_journal::{Bloom, BloomJournal}; use db::COL_ACCOUNT_BLOOM; use byteorder::{LittleEndian, ByteOrder}; +/// Value used to initialize bloom bitmap size. +/// +/// Bitmap size is the size in bytes (not bits) that will be allocated in memory. pub const ACCOUNT_BLOOM_SPACE: usize = 1048576; + +/// Value used to initialize bloom items count. +/// +/// Items count is an estimation of the maximum number of items to store. pub const DEFAULT_ACCOUNT_PRESET: usize = 1000000; +/// Key for a value storing amount of hashes pub const ACCOUNT_BLOOM_HASHCOUNT_KEY: &'static [u8] = b"account_hash_count"; const STATE_CACHE_BLOCKS: usize = 12; @@ -55,7 +67,7 @@ struct CacheQueueItem { /// Account address. address: Address, /// Acccount data or `None` if account does not exist. - account: Option, + account: SyncAccount, /// Indicates that the account was modified before being /// added to the cache. modified: bool, @@ -167,6 +179,7 @@ impl StateDB { bloom } + /// Commit blooms journal to the database transaction pub fn commit_bloom(batch: &mut DBTransaction, journal: BloomJournal) -> Result<(), UtilError> { assert!(journal.hash_functions <= 255); batch.put(COL_ACCOUNT_BLOOM, ACCOUNT_BLOOM_HASHCOUNT_KEY, &[journal.hash_functions as u8]); @@ -208,7 +221,7 @@ impl StateDB { pub fn sync_cache(&mut self, enacted: &[H256], retracted: &[H256], is_best: bool) { trace!("sync_cache id = (#{:?}, {:?}), parent={:?}, best={}", self.commit_number, self.commit_hash, self.parent_hash, is_best); let mut cache = self.account_cache.lock(); - let mut cache = &mut *cache; + let cache = &mut *cache; // Purge changes from re-enacted and retracted blocks. // Filter out commiting block if any. @@ -265,15 +278,16 @@ impl StateDB { modifications.insert(account.address.clone()); } if is_best { + let acc = account.account.0; if let Some(&mut Some(ref mut existing)) = cache.accounts.get_mut(&account.address) { - if let Some(new) = account.account { + if let Some(new) = acc { if account.modified { existing.overwrite_with(new); } continue; } } - cache.accounts.insert(account.address, account.account); + cache.accounts.insert(account.address, acc); } } @@ -295,10 +309,12 @@ impl StateDB { } } + /// Conversion method to interpret self as `HashDB` reference pub fn as_hashdb(&self) -> &HashDB { self.db.as_hashdb() } + /// Conversion method to interpret self as mutable `HashDB` reference pub fn as_hashdb_mut(&mut self) -> &mut HashDB { self.db.as_hashdb_mut() } @@ -405,7 +421,7 @@ impl state::Backend for StateDB { fn add_to_account_cache(&mut self, addr: Address, data: Option, modified: bool) { self.local_cache.push(CacheQueueItem { address: addr, - account: data, + account: SyncAccount(data), modified: modified, }) } @@ -424,13 +440,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>> { - let mut cache = self.code_cache.lock(); - - cache.get_mut(hash).map(|code| code.clone()) - } - fn get_cached(&self, a: &Address, f: F) -> Option where F: FnOnce(Option<&mut Account>) -> U { let mut cache = self.account_cache.lock(); @@ -440,24 +449,38 @@ impl state::Backend for StateDB { cache.accounts.get_mut(a).map(|c| f(c.as_mut())) } + fn get_cached_code(&self, hash: &H256) -> Option>> { + let mut cache = self.code_cache.lock(); + + cache.get_mut(hash).map(|code| code.clone()) + } + fn note_non_null_account(&self, address: &Address) { trace!(target: "account_bloom", "Note account bloom: {:?}", address); let mut bloom = self.account_bloom.lock(); - bloom.set(&*address.sha3()); + bloom.set(&*keccak(address)); } fn is_known_null(&self, address: &Address) -> bool { trace!(target: "account_bloom", "Check account bloom: {:?}", address); let bloom = self.account_bloom.lock(); - let is_null = !bloom.check(&*address.sha3()); + let is_null = !bloom.check(&*keccak(address)); is_null } } +/// Sync wrapper for the account. +struct SyncAccount(Option); +/// That implementation is safe because account is never modified or accessed in any way. +/// We only need `Sync` here to allow `StateDb` to be kept in a `RwLock`. +/// `Account` is `!Sync` by default because of `RefCell`s inside it. +unsafe impl Sync for SyncAccount {} + #[cfg(test)] mod tests { - use util::{U256, H256, Address, DBTransaction}; - use tests::helpers::*; + use ethereum_types::{H256, U256, Address}; + use kvdb::DBTransaction; + use tests::helpers::{get_temp_state_db}; use state::{Account, Backend}; use ethcore_logger::init_log; diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index ea7dd32f5d9cac6dceee0b9870919bebcadf7cc5..2fee61412f21c1c8740c0de9d8b83b9e2821eafa 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -16,29 +16,34 @@ use std::str::FromStr; use std::sync::Arc; +use hash::keccak; use io::IoChannel; -use client::{BlockChainClient, MiningBlockChainClient, Client, ClientConfig, BlockId}; +use client::{BlockChainClient, Client, ClientConfig, BlockId, ChainInfo, BlockInfo, PrepareOpenBlock, ImportSealedBlock, ImportBlock}; use state::{self, State, CleanupMode}; use executive::{Executive, TransactOptions}; use ethereum; use block::IsBlock; -use tests::helpers::*; +use tests::helpers::{ + generate_dummy_client, push_blocks_to_client, get_test_client_with_blocks, get_good_dummy_block_seq, + generate_dummy_client_with_data, get_good_dummy_block, get_bad_state_dummy_block +}; use types::filter::Filter; -use util::*; -use devtools::*; +use ethereum_types::{U256, Address}; +use kvdb_rocksdb::{Database, DatabaseConfig}; use miner::Miner; use spec::Spec; use views::BlockView; use ethkey::KeyPair; use transaction::{PendingTransaction, Transaction, Action, Condition}; use miner::MinerService; +use tempdir::TempDir; #[test] fn imports_from_empty() { - let dir = RandomTempPath::new(); - let spec = get_test_spec(); + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::new_test(); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -53,10 +58,10 @@ fn imports_from_empty() { #[test] fn should_return_registrar() { - let dir = RandomTempPath::new(); - let spec = ethereum::new_morden(&dir); + let tempdir = TempDir::new("").unwrap(); + let spec = ethereum::new_morden(&tempdir.path().to_owned()); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -75,7 +80,7 @@ fn should_return_registrar() { #[test] fn returns_state_root_basic() { let client = generate_dummy_client(6); - let test_spec = get_test_spec(); + let test_spec = Spec::new_test(); let genesis_header = test_spec.genesis_header(); assert!(client.state_data(genesis_header.state_root()).is_some()); @@ -83,10 +88,10 @@ fn returns_state_root_basic() { #[test] fn imports_good_block() { - let dir = RandomTempPath::new(); - let spec = get_test_spec(); + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::new_test(); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -108,10 +113,10 @@ fn imports_good_block() { #[test] fn query_none_block() { - let dir = RandomTempPath::new(); - let spec = get_test_spec(); + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::new_test(); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); let client = Client::new( ClientConfig::default(), @@ -192,7 +197,7 @@ fn imports_block_sequence() { #[test] fn can_collect_garbage() { let client = generate_dummy_client(100); - client.tick(); + client.tick(true); assert!(client.blockchain_cache_info().blocks < 100 * 1024); } @@ -254,16 +259,16 @@ fn can_mine() { let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).close(); - assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().sha3()); + assert_eq!(*b.block().header().parent_hash(), BlockView::new(&dummy_blocks[0]).header_view().hash()); } #[test] fn change_history_size() { - let dir = RandomTempPath::new(); + let tempdir = TempDir::new("").unwrap(); let test_spec = Spec::new_null(); let mut config = ClientConfig::default(); let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); config.history = 2; let address = Address::random(); @@ -278,8 +283,8 @@ fn change_history_size() { for _ in 0..20 { let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]); - b.block_mut().fields_mut().state.add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap(); - b.block_mut().fields_mut().state.commit().unwrap(); + b.block_mut().state_mut().add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap(); + b.block_mut().state_mut().commit().unwrap(); let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap(); client.import_sealed_block(b).unwrap(); // account change is in the journal overlay } @@ -298,7 +303,7 @@ fn change_history_size() { #[test] fn does_not_propagate_delayed_transactions() { - let key = KeyPair::from_secret("test".sha3().into()).unwrap(); + let key = KeyPair::from_secret(keccak("test").into()).unwrap(); let secret = key.secret(); let tx0 = PendingTransaction::new(Transaction { nonce: 0.into(), @@ -337,8 +342,8 @@ fn transaction_proof() { let test_spec = Spec::new_test(); for _ in 0..20 { let mut b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]); - b.block_mut().fields_mut().state.add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap(); - b.block_mut().fields_mut().state.commit().unwrap(); + b.block_mut().state_mut().add_balance(&address, &5.into(), CleanupMode::NoEmpty).unwrap(); + b.block_mut().state_mut().commit().unwrap(); let b = b.close_and_lock().seal(&*test_spec.engine, vec![]).unwrap(); client.import_sealed_block(b).unwrap(); // account change is in the journal overlay } @@ -360,7 +365,7 @@ fn transaction_proof() { let root = client.best_block_header().state_root(); let mut state = State::from_existing(backend, root, 0.into(), factories.clone()).unwrap(); - Executive::new(&mut state, &client.latest_env_info(), &*test_spec.engine) + Executive::new(&mut state, &client.latest_env_info(), test_spec.engine.machine()) .transact(&transaction, TransactOptions::with_no_tracing().dont_check_nonce()).unwrap(); assert_eq!(state.balance(&Address::default()).unwrap(), 5.into()); diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 7b0e03d249cb3c9ac545ea6a13065b6c8a1bbe5c..39feb1364438d7b299b69ddc186d3bca7adb6bd6 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -1,27 +1,45 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + //! Tests of EVM integration with transaction execution. use std::sync::Arc; -use vm::{EnvInfo, ActionParams, ActionValue, CallType}; +use hash::keccak; +use vm::{EnvInfo, ActionParams, ActionValue, CallType, ParamsType}; use evm::{Factory, VMType}; use executive::Executive; use state::Substate; -use tests::helpers::*; +use tests::helpers::get_temp_state_with_factory; use trace::{NoopVMTracer, NoopTracer}; use transaction::SYSTEM_ADDRESS; use rustc_hex::FromHex; -use util::*; +use ethereum_types::{H256, Address}; +use bytes::BytesRef; evm_test!{test_blockhash_eip210: test_blockhash_eip210_jit, test_blockhash_eip210_int} fn test_blockhash_eip210(factory: Factory) { let get_prev_hash_code = Arc::new("600143034060205260206020f3".from_hex().unwrap()); // this returns previous block hash - let get_prev_hash_code_hash = get_prev_hash_code.sha3(); + let get_prev_hash_code_hash = keccak(get_prev_hash_code.as_ref()); // This is same as DEFAULT_BLOCKHASH_CONTRACT except for metropolis transition block check removed. let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b"; let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap()); - let blockhash_contract_code_hash = blockhash_contract_code.sha3(); - let engine = TestEngine::new_metropolis(); + let blockhash_contract_code_hash = keccak(blockhash_contract_code.as_ref()); + let machine = ::ethereum::new_constantinople_test_machine(); let mut env_info = EnvInfo::default(); // populate state with 256 last hashes @@ -42,8 +60,9 @@ fn test_blockhash_eip210(factory: Factory) { code_hash: Some(blockhash_contract_code_hash), data: Some(H256::from(i - 1).to_vec()), call_type: CallType::Call, + params_type: ParamsType::Separate, }; - let mut ex = Executive::new(&mut state, &env_info, &engine); + let mut ex = Executive::new(&mut state, &env_info, &machine); let mut substate = Substate::new(); let mut output = []; if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) { @@ -64,8 +83,9 @@ fn test_blockhash_eip210(factory: Factory) { code_hash: Some(get_prev_hash_code_hash), data: None, call_type: CallType::Call, + params_type: ParamsType::Separate, }; - let mut ex = Executive::new(&mut state, &env_info, &engine); + let mut ex = Executive::new(&mut state, &env_info, &machine); let mut substate = Substate::new(); let mut output = H256::new(); if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) { diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index d8ba8313e917347691b480e312b38de67dd59e53..fd37164dcbbd71b3d88300187db6011e4f3d35dc 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -14,85 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use std::collections::BTreeMap; -use std::sync::Arc; -use ethkey::KeyPair; -use io::*; -use client::{BlockChainClient, Client, ClientConfig}; -use util::*; -use spec::*; use account_provider::AccountProvider; -use state_db::StateDB; +use ethereum_types::{H256, U256}; use block::{OpenBlock, Drain}; use blockchain::{BlockChain, Config as BlockChainConfig}; -use builtin::Builtin; -use state::*; -use evm::{Schedule, Factory as EvmFactory}; +use bytes::Bytes; +use client::{Client, ClientConfig, ChainInfo, ImportBlock, ChainNotify}; +use ethkey::KeyPair; +use evm::Factory as EvmFactory; use factory::Factories; -use engines::Engine; -use ethereum; -use ethereum::ethash::EthashParams; -use miner::Miner; +use hash::keccak; use header::Header; -use transaction::{Action, Transaction, SignedTransaction}; +use io::*; +use miner::Miner; +use parking_lot::RwLock; use rlp::{self, RlpStream}; +use spec::Spec; +use state_db::StateDB; +use state::*; +use std::sync::Arc; +use transaction::{Action, Transaction, SignedTransaction}; use views::BlockView; -#[cfg(feature = "json-tests")] -pub enum ChainEra { - Frontier, - Homestead, - Eip150, - _Eip161, - TransitionTest, -} - -pub struct TestEngine { - engine: Arc, - max_depth: usize, -} - -impl TestEngine { - pub fn new(max_depth: usize) -> TestEngine { - TestEngine { - engine: ethereum::new_frontier_test().engine, - max_depth: max_depth, - } - } - - pub fn new_metropolis() -> TestEngine { - TestEngine { - engine: ethereum::new_metropolis_test().engine, - max_depth: 0, - } - } -} - -impl Engine for TestEngine { - fn name(&self) -> &str { - "TestEngine" - } - - fn params(&self) -> &CommonParams { - self.engine.params() - } - - fn builtins(&self) -> &BTreeMap { - self.engine.builtins() - } - - fn schedule(&self, _block_number: u64) -> Schedule { - let mut schedule = self.engine.schedule(0); - schedule.max_depth = self.max_depth; - schedule - } -} - -// TODO: move everything over to get_null_spec. -pub fn get_test_spec() -> Spec { - Spec::new_test() -} - pub fn create_test_block(header: &Header) -> Bytes { let mut rlp = RlpStream::new_list(3); rlp.append(header); @@ -150,16 +93,16 @@ pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, } -pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { - generate_dummy_client_with_spec_accounts_and_data(get_test_spec, None, block_number, txs_per_block, tx_gas_prices) +pub fn generate_dummy_client_with_spec_and_data(test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { + generate_dummy_client_with_spec_accounts_and_data(test_spec, None, block_number, txs_per_block, tx_gas_prices) } -pub fn generate_dummy_client_with_spec_and_accounts(get_test_spec: F, accounts: Option>) -> Arc where F: Fn()->Spec { - generate_dummy_client_with_spec_accounts_and_data(get_test_spec, accounts, 0, 0, &[]) +pub fn generate_dummy_client_with_spec_and_accounts(test_spec: F, accounts: Option>) -> Arc where F: Fn()->Spec { + generate_dummy_client_with_spec_accounts_and_data(test_spec, accounts, 0, 0, &[]) } -pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, accounts: Option>, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { - let test_spec = get_test_spec(); +pub fn generate_dummy_client_with_spec_accounts_and_data(test_spec: F, accounts: Option>, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { + let test_spec = test_spec(); let client_db = new_db(); let client = Client::new( @@ -178,7 +121,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac let mut last_hashes = vec![]; let mut last_header = genesis_header.clone(); - let kp = KeyPair::from_secret_slice(&"".sha3()).unwrap(); + let kp = KeyPair::from_secret_slice(&keccak("")).unwrap(); let author = kp.address(); let mut n = 0; @@ -198,7 +141,6 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac vec![], false, ).unwrap(); - b.set_difficulty(U256::from(0x20000)); rolling_timestamp += 10; b.set_timestamp(rolling_timestamp); @@ -230,10 +172,10 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac } pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting_number: usize, block_number: usize) { - let test_spec = get_test_spec(); - let test_engine = &test_spec.engine; - //let test_engine = test_spec.to_engine().unwrap(); + let test_spec = Spec::new_test(); let state_root = test_spec.genesis_header().state_root().clone(); + let genesis_gas = test_spec.genesis_header().gas_limit().clone(); + let mut rolling_hash = client.chain_info().best_block_hash; let mut rolling_block_number = starting_number as u64; let mut rolling_timestamp = timestamp_salt + starting_number as u64 * 10; @@ -241,7 +183,7 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting for _ in 0..block_number { let mut header = Header::new(); - header.set_gas_limit(test_engine.params().min_gas_limit); + header.set_gas_limit(genesis_gas); header.set_difficulty(U256::from(0x20000)); header.set_timestamp(rolling_timestamp); header.set_number(rolling_block_number); @@ -259,7 +201,7 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting } pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { - let test_spec = get_test_spec(); + let test_spec = Spec::new_test(); let client_db = new_db(); let client = Client::new( @@ -270,9 +212,9 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { IoChannel::disconnected(), ).unwrap(); - for block in &blocks { - if client.import_block(block.clone()).is_err() { - panic!("panic importing block which is well-formed"); + for block in blocks { + if let Err(e) = client.import_block(block) { + panic!("error importing block which is well-formed: {:?}", e); } } client.flush_queue(); @@ -280,8 +222,8 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { client } -fn new_db() -> Arc { - Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))) +fn new_db() -> Arc<::kvdb::KeyValueDB> { + Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) } pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { @@ -325,30 +267,30 @@ pub fn get_temp_state() -> State<::state_db::StateDB> { pub fn get_temp_state_with_factory(factory: EvmFactory) -> State<::state_db::StateDB> { let journal_db = get_temp_state_db(); let mut factories = Factories::default(); - factories.vm = factory; + factories.vm = factory.into(); State::new(journal_db, U256::from(0), factories) } pub fn get_temp_state_db() -> StateDB { let db = new_db(); - let journal_db = journaldb::new(db, journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); + let journal_db = ::journaldb::new(db, ::journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); StateDB::new(journal_db, 5 * 1024 * 1024) } pub fn get_good_dummy_block_seq(count: usize) -> Vec { - let test_spec = get_test_spec(); + let test_spec = Spec::new_test(); get_good_dummy_block_fork_seq(1, count, &test_spec.genesis_header().hash()) } pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_hash: &H256) -> Vec { - let test_spec = get_test_spec(); - let test_engine = &test_spec.engine; + let test_spec = Spec::new_test(); + let genesis_gas = test_spec.genesis_header().gas_limit().clone(); let mut rolling_timestamp = start_number as u64 * 10; let mut parent = *parent_hash; let mut r = Vec::new(); for i in start_number .. start_number + count + 1 { let mut block_header = Header::new(); - block_header.set_gas_limit(test_engine.params().min_gas_limit); + block_header.set_gas_limit(genesis_gas); block_header.set_difficulty(U256::from(i) * U256([0, 1, 0, 0])); block_header.set_timestamp(rolling_timestamp); block_header.set_number(i as u64); @@ -365,9 +307,9 @@ pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_h pub fn get_good_dummy_block_hash() -> (H256, Bytes) { let mut block_header = Header::new(); - let test_spec = get_test_spec(); - let test_engine = &test_spec.engine; - block_header.set_gas_limit(test_engine.params().min_gas_limit); + let test_spec = Spec::new_test(); + let genesis_gas = test_spec.genesis_header().gas_limit().clone(); + block_header.set_gas_limit(genesis_gas); block_header.set_difficulty(U256::from(0x20000)); block_header.set_timestamp(40); block_header.set_number(1); @@ -384,9 +326,10 @@ pub fn get_good_dummy_block() -> Bytes { pub fn get_bad_state_dummy_block() -> Bytes { let mut block_header = Header::new(); - let test_spec = get_test_spec(); - let test_engine = &test_spec.engine; - block_header.set_gas_limit(test_engine.params().min_gas_limit); + let test_spec = Spec::new_test(); + let genesis_gas = test_spec.genesis_header().gas_limit().clone(); + + block_header.set_gas_limit(genesis_gas); block_header.set_difficulty(U256::from(0x20000)); block_header.set_timestamp(40); block_header.set_number(1); @@ -396,32 +339,13 @@ pub fn get_bad_state_dummy_block() -> Bytes { create_test_block(&block_header) } -pub fn get_default_ethash_params() -> EthashParams { - EthashParams { - minimum_difficulty: U256::from(131072), - difficulty_bound_divisor: U256::from(2048), - difficulty_increment_divisor: 10, - metropolis_difficulty_increment_divisor: 9, - duration_limit: 13, - homestead_transition: 1150000, - dao_hardfork_transition: u64::max_value(), - dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(), - dao_hardfork_accounts: vec![], - difficulty_hardfork_transition: u64::max_value(), - difficulty_hardfork_bound_divisor: U256::from(0), - bomb_defuse_transition: u64::max_value(), - eip100b_transition: u64::max_value(), - eip150_transition: u64::max_value(), - eip160_transition: u64::max_value(), - eip161abc_transition: u64::max_value(), - eip161d_transition: u64::max_value(), - ecip1010_pause_transition: u64::max_value(), - ecip1010_continue_transition: u64::max_value(), - ecip1017_era_rounds: u64::max_value(), - max_code_size: u64::max_value(), - max_gas_limit_transition: u64::max_value(), - max_gas_limit: U256::max_value(), - min_gas_price_transition: u64::max_value(), - min_gas_price: U256::zero(), +#[derive(Default)] +pub struct TestNotify { + pub messages: RwLock>, +} + +impl ChainNotify for TestNotify { + fn broadcast(&self, data: Vec) { + self.messages.write().push(data); } } diff --git a/ethcore/src/tests/mod.rs b/ethcore/src/tests/mod.rs index 31f195725b65a10efc20a548ce34c095c07b228e..eec71efafbfc10355679f2c456223f96a8acb312 100644 --- a/ethcore/src/tests/mod.rs +++ b/ethcore/src/tests/mod.rs @@ -17,7 +17,4 @@ pub mod helpers; mod client; mod evm; - -#[cfg(feature="ipc")] -mod rpc; - +mod trace; diff --git a/ethcore/src/tests/rpc.rs b/ethcore/src/tests/rpc.rs deleted file mode 100644 index 6444daa56b5d156b262a2021b4a58a73930f6c75..0000000000000000000000000000000000000000 --- a/ethcore/src/tests/rpc.rs +++ /dev/null @@ -1,78 +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 . - -//! Client RPC tests - -use nanoipc; -use std::sync::Arc; -use std::sync::atomic::{Ordering, AtomicBool}; -use client::{Client, BlockChainClient, ClientConfig, BlockId}; -use client::remote::RemoteClient; -use tests::helpers::*; -use devtools::*; -use miner::Miner; -use crossbeam; -use io::IoChannel; -use util::kvdb::DatabaseConfig; - -pub fn run_test_worker(scope: &crossbeam::Scope, stop: Arc, socket_path: &str) { - let socket_path = socket_path.to_owned(); - scope.spawn(move || { - let temp = RandomTempPath::create_dir(); - let spec = get_test_spec(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - - let client = Client::new( - ClientConfig::default(), - &spec, - temp.as_path(), - Arc::new(Miner::with_spec(&spec)), - IoChannel::disconnected(), - &db_config - ).unwrap(); - let mut worker = nanoipc::Worker::new(&(client as Arc)); - worker.add_reqrep(&socket_path).unwrap(); - while !stop.load(Ordering::Relaxed) { - worker.poll(); - } - }); -} - -#[test] -fn can_handshake() { - crossbeam::scope(|scope| { - let stop_guard = StopGuard::new(); - let socket_path = "ipc:///tmp/parity-client-rpc-10.ipc"; - run_test_worker(scope, stop_guard.share(), socket_path); - let remote_client = nanoipc::generic_client::>(socket_path).unwrap(); - - assert!(remote_client.handshake().is_ok()); - }) -} - -#[test] -fn can_query_block() { - crossbeam::scope(|scope| { - let stop_guard = StopGuard::new(); - let socket_path = "ipc:///tmp/parity-client-rpc-20.ipc"; - run_test_worker(scope, stop_guard.share(), socket_path); - let remote_client = nanoipc::generic_client::>(socket_path).unwrap(); - - let non_existant_block = remote_client.block_header(BlockId::Number(999)); - - assert!(non_existant_block.is_none()); - }) -} diff --git a/ethcore/src/tests/trace.rs b/ethcore/src/tests/trace.rs new file mode 100644 index 0000000000000000000000000000000000000000..5483c626342f60f7d2afb672da02991615a75b95 --- /dev/null +++ b/ethcore/src/tests/trace.rs @@ -0,0 +1,208 @@ +// 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 . + +//! Client tests of tracing + +use tempdir::TempDir; +use ethkey::KeyPair; +use hash::keccak; +use block::*; +use ethereum_types::{U256, Address}; +use io::*; +use spec::*; +use client::*; +use tests::helpers::get_temp_state_db; +use client::{BlockChainClient, Client, ClientConfig}; +use kvdb_rocksdb::{Database, DatabaseConfig}; +use std::sync::Arc; +use header::Header; +use miner::Miner; +use transaction::{Action, Transaction}; +use views::BlockView; +use trace::{RewardType, LocalizedTrace}; +use trace::trace::Action::Reward; + +#[test] +fn can_trace_block_and_uncle_reward() { + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::new_test_with_reward(); + let engine = &*spec.engine; + + // Create client + let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); + let mut client_config = ClientConfig::default(); + client_config.tracing.enabled = true; + let client_db = Arc::new(Database::open(&db_config, tempdir.path().to_str().unwrap()).unwrap()); + let client = Client::new( + client_config, + &spec, + client_db, + Arc::new(Miner::with_spec(&spec)), + IoChannel::disconnected(), + ).unwrap(); + + // Create test data: + // genesis + // | + // root_block + // | + // parent_block + // | + // block with transaction and uncle + + let genesis_header = spec.genesis_header(); + let genesis_gas = genesis_header.gas_limit().clone(); + + let mut db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let mut rolling_timestamp = 40; + let mut last_hashes = vec![]; + let mut last_header = genesis_header.clone(); + last_hashes.push(last_header.hash()); + + let kp = KeyPair::from_secret_slice(&keccak("")).unwrap(); + let author = kp.address(); + + // Add root block first + let mut root_block = OpenBlock::new( + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + rolling_timestamp += 10; + root_block.set_timestamp(rolling_timestamp); + + let root_block = root_block.close_and_lock().seal(engine, vec![]).unwrap(); + + if let Err(e) = client.import_block(root_block.rlp_bytes()) { + panic!("error importing block which is valid by definition: {:?}", e); + } + + last_header = BlockView::new(&root_block.rlp_bytes()).header(); + let root_header = last_header.clone(); + db = root_block.drain(); + + last_hashes.push(last_header.hash()); + + // Add parent block + let mut parent_block = OpenBlock::new( + engine, + Default::default(), + false, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false, + ).unwrap(); + rolling_timestamp += 10; + parent_block.set_timestamp(rolling_timestamp); + + let parent_block = parent_block.close_and_lock().seal(engine, vec![]).unwrap(); + + if let Err(e) = client.import_block(parent_block.rlp_bytes()) { + panic!("error importing block which is valid by definition: {:?}", e); + } + + last_header = BlockView::new(&parent_block.rlp_bytes()).header(); + db = parent_block.drain(); + + last_hashes.push(last_header.hash()); + + // Add testing block with transaction and uncle + let mut block = OpenBlock::new( + engine, + Default::default(), + true, + db, + &last_header, + Arc::new(last_hashes.clone()), + author.clone(), + (3141562.into(), 31415620.into()), + vec![], + false + ).unwrap(); + rolling_timestamp += 10; + block.set_timestamp(rolling_timestamp); + + let mut n = 0; + for _ in 0..1 { + block.push_transaction(Transaction { + nonce: n.into(), + gas_price: 10000.into(), + gas: 100000.into(), + action: Action::Create, + data: vec![], + value: U256::zero(), + }.sign(kp.secret(), Some(spec.network_id())), None).unwrap(); + n += 1; + } + + let mut uncle = Header::new(); + let uncle_author: Address = "ef2d6d194084c2de36e0dabfce45d046b37d1106".into(); + uncle.set_author(uncle_author); + uncle.set_parent_hash(root_header.hash()); + uncle.set_gas_limit(genesis_gas); + uncle.set_number(root_header.number() + 1); + uncle.set_timestamp(rolling_timestamp); + block.push_uncle(uncle).unwrap(); + + let block = block.close_and_lock().seal(engine, vec![]).unwrap(); + + let res = client.import_block(block.rlp_bytes()); + if res.is_err() { + panic!("error importing block: {:#?}", res.err().unwrap()); + } + + block.drain(); + client.flush_queue(); + client.import_verified_blocks(); + + // Test0. Check overall filter + let filter = TraceFilter { + range: (BlockId::Number(1)..BlockId::Number(3)), + from_address: vec![], + to_address: vec![], + after: None, + count: None, + }; + + let traces = client.filter_traces(filter); + assert!(traces.is_some(), "Filtered traces should be present"); + let traces_vec = traces.unwrap(); + let block_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { + Reward(ref a) => a.reward_type == RewardType::Block, + _ => false, + }).collect(); + assert_eq!(block_reward_traces.len(), 3); + let uncle_reward_traces: Vec = traces_vec.clone().into_iter().filter(|trace| match (trace).action { + Reward(ref a) => a.reward_type == RewardType::Uncle, + _ => false, + }).collect(); + assert_eq!(uncle_reward_traces.len(), 1); + + // Test1. Check block filter + let traces = client.block_traces(BlockId::Number(3)); + assert_eq!(traces.unwrap().len(), 3); +} diff --git a/ethcore/src/trace/bloom.rs b/ethcore/src/trace/bloom.rs deleted file mode 100644 index ed34d650510c98e68657131d923f5799ff22ef95..0000000000000000000000000000000000000000 --- a/ethcore/src/trace/bloom.rs +++ /dev/null @@ -1,77 +0,0 @@ -use bloomchain::Bloom; -use bloomchain::group::{BloomGroup, GroupPosition}; -use basic_types::LogBloom; - -/// Helper structure representing bloom of the trace. -#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)] -pub struct BlockTracesBloom(LogBloom); - -impl From for BlockTracesBloom { - fn from(bloom: LogBloom) -> BlockTracesBloom { - BlockTracesBloom(bloom) - } -} - -impl From for BlockTracesBloom { - fn from(bloom: Bloom) -> BlockTracesBloom { - let bytes: [u8; 256] = bloom.into(); - BlockTracesBloom(LogBloom::from(bytes)) - } -} - -impl Into for BlockTracesBloom { - fn into(self) -> Bloom { - let log = self.0; - Bloom::from(log.0) - } -} - -/// Represents group of X consecutive blooms. -#[derive(Clone, RlpEncodableWrapper, RlpDecodableWrapper)] -pub struct BlockTracesBloomGroup { - blooms: Vec, -} - -impl From for BlockTracesBloomGroup { - fn from(group: BloomGroup) -> Self { - let blooms = group.blooms - .into_iter() - .map(From::from) - .collect(); - - BlockTracesBloomGroup { - blooms: blooms - } - } -} - -impl Into for BlockTracesBloomGroup { - fn into(self) -> BloomGroup { - let blooms = self.blooms - .into_iter() - .map(Into::into) - .collect(); - - BloomGroup { - blooms: blooms - } - } -} - -/// Represents `BloomGroup` position in database. -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -pub struct TraceGroupPosition { - /// Bloom level. - pub level: u8, - /// Group index. - pub index: u32, -} - -impl From for TraceGroupPosition { - fn from(p: GroupPosition) -> Self { - TraceGroupPosition { - level: p.level as u8, - index: p.index as u32, - } - } -} diff --git a/ethcore/src/trace/db.rs b/ethcore/src/trace/db.rs index fe90ffe418c00ce8dde9b8a5725f26ba1ea79056..45b9ebc150acf02c4606edf029dd51129be00d13 100644 --- a/ethcore/src/trace/db.rs +++ b/ethcore/src/trace/db.rs @@ -20,7 +20,10 @@ use std::collections::{HashMap, VecDeque}; use std::sync::Arc; use bloomchain::{Number, Config as BloomConfig}; use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup}; -use util::{H256, H264, KeyValueDB, DBTransaction, RwLock, HeapSizeOf}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, H264}; +use kvdb::{KeyValueDB, DBTransaction}; +use parking_lot::RwLock; use header::BlockNumber; use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras}; use db::{self, Key, Writable, Readable, CacheUpdatePolicy}; @@ -31,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, @@ -99,7 +101,12 @@ enum CacheId { Bloom(TraceGroupPosition), } -/// Trace database. +/// Database to store transaction execution trace. +/// +/// Whenever a transaction is executed by EVM it's execution trace is stored +/// in trace database. Each trace has information, which contracts have been +/// touched, which have been created during the execution of transaction, and +/// which calls failed. pub struct TraceDB where T: DatabaseExtras { // cache traces: RwLock>, @@ -215,8 +222,11 @@ impl TraceDB where T: DatabaseExtras { block_number: BlockNumber, tx_number: usize ) -> Vec { - let tx_hash = self.extras.transaction_hash(block_number, tx_number) - .expect("Expected to find transaction hash. Database is probably corrupted"); + let (trace_tx_number, trace_tx_hash) = match self.extras.transaction_hash(block_number, tx_number) { + Some(hash) => (Some(tx_number), Some(hash.clone())), + //None means trace without transaction (reward) + None => (None, None), + }; let flat_traces: Vec = traces.into(); flat_traces.into_iter() @@ -227,8 +237,8 @@ impl TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_number, - transaction_hash: tx_hash.clone(), + transaction_number: trace_tx_number, + transaction_hash: trace_tx_hash, block_number: block_number, block_hash: block_hash }), @@ -274,8 +284,6 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { } else { self.traces(block_hash).expect("Traces database is incomplete.").bloom() }) - .map(blooms::Bloom::from) - .map(Into::into) .collect(); let chain = BloomGroupChain::new(self.bloom_config, self); @@ -321,8 +329,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash, + transaction_number: Some(tx_position), + transaction_hash: Some(tx_hash), block_number: block_number, block_hash: block_hash, } @@ -345,8 +353,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash.clone(), + transaction_number: Some(tx_position), + transaction_hash: Some(tx_hash.clone()), block_number: block_number, block_hash: block_hash }) @@ -363,8 +371,11 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { .map(Into::>::into) .enumerate() .flat_map(|(tx_position, traces)| { - let tx_hash = self.extras.transaction_hash(block_number, tx_position) - .expect("Expected to find transaction hash. Database is probably corrupted"); + let (trace_tx_number, trace_tx_hash) = match self.extras.transaction_hash(block_number, tx_position) { + Some(hash) => (Some(tx_position), Some(hash.clone())), + //None means trace without transaction (reward) + None => (None, None), + }; traces.into_iter() .map(|trace| LocalizedTrace { @@ -372,8 +383,8 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { result: trace.result, subtraces: trace.subtraces, trace_address: trace.trace_address.into_iter().collect(), - transaction_number: tx_position, - transaction_hash: tx_hash.clone(), + transaction_number: trace_tx_number, + transaction_hash: trace_tx_hash, block_number: block_number, block_hash: block_hash, }) @@ -404,7 +415,9 @@ impl TraceDatabase for TraceDB where T: DatabaseExtras { mod tests { use std::collections::HashMap; use std::sync::Arc; - use util::{Address, U256, H256, DBTransaction}; + use ethereum_types::{H256, U256, Address}; + use kvdb::{DBTransaction, KeyValueDB}; + use kvdb_memorydb; use header::BlockNumber; use trace::{Config, TraceDB, Database as TraceDatabase, DatabaseExtras, ImportRequest}; use trace::{Filter, LocalizedTrace, AddressesFilter, TraceError}; @@ -454,8 +467,8 @@ mod tests { } } - fn new_db() -> Arc<::util::kvdb::KeyValueDB> { - Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))) + fn new_db() -> Arc { + Arc::new(kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))) } #[test] @@ -543,8 +556,8 @@ mod tests { result: Res::FailedCall(TraceError::OutOfGas), trace_address: vec![], subtraces: 0, - transaction_number: 0, - transaction_hash: tx_hash, + transaction_number: Some(0), + transaction_hash: Some(tx_hash), block_number: block_number, block_hash: block_hash, } diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index ba4d0eff997dc9205da34fcca8370ffe76e8460a..b1d116d69d59accbbbd31a07e8442472a3a0ef1e 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -16,9 +16,10 @@ //! Simple executive tracer. -use util::{Bytes, Address, U256}; +use ethereum_types::{U256, Address}; +use bytes::Bytes; use vm::ActionParams; -use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide}; +use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType}; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; /// Simple executive tracer. Traces all calls and creates. Ignores delegatecalls. @@ -81,6 +82,8 @@ fn should_prefix_address_properly() { } impl Tracer for ExecutiveTracer { + type Output = FlatTrace; + fn prepare_trace_call(&self, params: &ActionParams) -> Option { Some(Call::from(params.clone())) } @@ -151,15 +154,22 @@ impl Tracer for ExecutiveTracer { fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address) { let trace = FlatTrace { subtraces: 0, - action: Action::Suicide(Suicide { - address: address, - refund_address: refund_address, - balance: balance, - }), + action: Action::Suicide(Suicide { address, refund_address, balance } ), result: Res::None, trace_address: Default::default(), }; - debug!(target: "trace", "Traced failed suicide {:?}", trace); + debug!(target: "trace", "Traced suicide {:?}", trace); + self.traces.push(trace); + } + + fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType) { + let trace = FlatTrace { + subtraces: 0, + action: Action::Reward(Reward { author, value, reward_type } ), + result: Res::None, + trace_address: Default::default(), + }; + debug!(target: "trace", "Traced reward {:?}", trace); self.traces.push(trace); } @@ -192,7 +202,9 @@ impl ExecutiveVMTracer { } impl VMTracer for ExecutiveVMTracer { - fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { true } + type Output = VMTrace; + + fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { true } fn trace_prepare_execute(&mut self, pc: usize, instruction: u8, gas_cost: U256) { self.data.operations.push(VMOperation { diff --git a/ethcore/src/trace/import.rs b/ethcore/src/trace/import.rs index 4bcc376f9933848d0eeb8e797ffb7ef56b12a0e7..fb72e220e45fb91b9a9a8c7b646c9f50854a9a24 100644 --- a/ethcore/src/trace/import.rs +++ b/ethcore/src/trace/import.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . //! Traces import request. -use util::H256; +use ethereum_types::H256; use header::BlockNumber; use trace::FlatBlockTraces; diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index c749bfd8292cd68b98d60851ebb2a6f46111e9bc..381dcd9f0d186a51fff8baad461ec96d57baabb6 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -16,7 +16,6 @@ //! Tracing -mod bloom; mod config; mod db; mod executive_tracer; @@ -31,19 +30,24 @@ pub use self::executive_tracer::{ExecutiveTracer, ExecutiveVMTracer}; pub use self::import::ImportRequest; pub use self::localized::LocalizedTrace; -pub use self::types::{filter, flat, localized, trace}; +pub use self::types::{filter, flat, localized, trace, Tracing}; pub use self::types::error::Error as TraceError; -pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff}; +pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, RewardType}; pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces}; pub use self::types::filter::{Filter, AddressesFilter}; -use util::{Bytes, Address, U256, H256, DBTransaction}; +use ethereum_types::{H256, U256, Address}; +use kvdb::DBTransaction; +use bytes::Bytes; use self::trace::{Call, Create}; use vm::ActionParams; use header::BlockNumber; /// This trait is used by executive to build traces. pub trait Tracer: Send { + /// Data returned when draining the Tracer. + type Output; + /// Prepares call trace for given params. Noop tracer should return None. fn prepare_trace_call(&self, params: &ActionParams) -> Option; @@ -59,7 +63,7 @@ pub trait Tracer: Send { call: Option, gas_used: U256, output: Option, - subs: Vec, + subs: Vec, ); /// Stores trace create info. @@ -69,32 +73,38 @@ pub trait Tracer: Send { gas_used: U256, code: Option, address: Address, - subs: Vec + subs: Vec ); /// Stores failed call trace. - fn trace_failed_call(&mut self, call: Option, subs: Vec, error: TraceError); + fn trace_failed_call(&mut self, call: Option, subs: Vec, error: TraceError); /// Stores failed create trace. - fn trace_failed_create(&mut self, create: Option, subs: Vec, error: TraceError); + fn trace_failed_create(&mut self, create: Option, subs: Vec, error: TraceError); /// Stores suicide info. fn trace_suicide(&mut self, address: Address, balance: U256, refund_address: Address); + /// Stores reward info. + fn trace_reward(&mut self, author: Address, value: U256, reward_type: RewardType); + /// Spawn subtracer which will be used to trace deeper levels of execution. fn subtracer(&self) -> Self where Self: Sized; /// Consumes self and returns all traces. - fn drain(self) -> Vec; + fn drain(self) -> Vec; } /// Used by executive to build VM traces. pub trait VMTracer: Send { + /// Data returned when draining the VMTracer. + type Output; + /// Trace the progression of interpreter to next instruction. /// If tracer returns `false` it won't be called again. /// @returns true if `trace_prepare_execute` and `trace_executed` should be called. - fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { false } + fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } /// Trace the preparation to execute a single valid instruction. fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256) {} @@ -109,7 +119,7 @@ pub trait VMTracer: Send { fn done_subtrace(&mut self, sub: Self) where Self: Sized; /// Consumes self and returns the VM trace. - fn drain(self) -> Option; + fn drain(self) -> Option; } /// `DbExtras` provides an interface to query extra data which is not stored in tracesdb, diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index 03d6f57a002b5bdcc445e614ae179f31e16da1c6..ab0bf77ff1cad8e676953151aacc33ed00aca3ec 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -16,15 +16,18 @@ //! Nonoperative tracer. -use util::{Bytes, Address, U256}; +use ethereum_types::{U256, Address}; +use bytes::Bytes; use vm::ActionParams; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; -use trace::trace::{Call, Create, VMTrace}; +use trace::trace::{Call, Create, VMTrace, RewardType}; /// Nonoperative tracer. Does not trace anything. pub struct NoopTracer; impl Tracer for NoopTracer { + type Output = FlatTrace; + fn prepare_trace_call(&self, _: &ActionParams) -> Option { None } @@ -58,6 +61,9 @@ impl Tracer for NoopTracer { fn trace_suicide(&mut self, _address: Address, _balance: U256, _refund_address: Address) { } + fn trace_reward(&mut self, _: Address, _: U256, _: RewardType) { + } + fn subtracer(&self) -> Self { NoopTracer } @@ -71,7 +77,9 @@ impl Tracer for NoopTracer { pub struct NoopVMTracer; impl VMTracer for NoopVMTracer { - fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { false } + type Output = VMTrace; + + fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256) {} diff --git a/ethcore/src/trace/types/error.rs b/ethcore/src/trace/types/error.rs index 5cedefd09f407a4658f4d18319f486b7b63598a5..70a3c315ad60938ed314b009112f2b8aee4f55b6 100644 --- a/ethcore/src/trace/types/error.rs +++ b/ethcore/src/trace/types/error.rs @@ -43,6 +43,10 @@ pub enum Error { MutableCallInStaticContext, /// Wasm error Wasm, + /// Contract tried to access past the return data buffer. + OutOfBounds, + /// Execution has been reverted with REVERT instruction. + Reverted, } impl<'a> From<&'a VmError> for Error { @@ -57,6 +61,8 @@ impl<'a> From<&'a VmError> for Error { VmError::Wasm { .. } => Error::Wasm, VmError::Internal(_) => Error::Internal, VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext, + VmError::OutOfBounds => Error::OutOfBounds, + VmError::Reverted => Error::Reverted, } } } @@ -80,6 +86,8 @@ impl fmt::Display for Error { Wasm => "Wasm runtime error", Internal => "Internal error", MutableCallInStaticContext => "Mutable Call In Static Context", + OutOfBounds => "Out of bounds", + Reverted => "Reverted", }; message.fmt(f) } @@ -98,6 +106,8 @@ impl Encodable for Error { BuiltIn => 6, MutableCallInStaticContext => 7, Wasm => 8, + OutOfBounds => 9, + Reverted => 10, }; s.append_internal(&value); @@ -118,6 +128,8 @@ impl Decodable for Error { 6 => Ok(BuiltIn), 7 => Ok(MutableCallInStaticContext), 8 => Ok(Wasm), + 9 => Ok(OutOfBounds), + 10 => Ok(Reverted), _ => Err(DecoderError::Custom("Invalid error type")), } } diff --git a/ethcore/src/trace/types/filter.rs b/ethcore/src/trace/types/filter.rs index 1b2e2077acb830888480b0501af94b56a172631d..308eb72da7b42700510989219b9aad34432c8e09 100644 --- a/ethcore/src/trace/types/filter.rs +++ b/ethcore/src/trace/types/filter.rs @@ -17,11 +17,8 @@ //! Trace filters type definitions use std::ops::Range; -use bloomchain::{Filter as BloomFilter, Bloom, Number}; -use util::Address; -use util::sha3::Hashable; -use bloomable::Bloomable; -use basic_types::LogBloom; +use bloomchain::{Filter as BloomFilter, Number}; +use ethereum_types::{Address, Bloom, BloomInput}; use trace::flat::FlatTrace; use super::trace::{Action, Res}; @@ -51,23 +48,27 @@ impl AddressesFilter { } /// Returns blooms of this addresses filter. - pub fn blooms(&self) -> Vec { + pub fn blooms(&self) -> Vec { match self.list.is_empty() { - true => vec![LogBloom::default()], + true => vec![Bloom::default()], false => self.list.iter() - .map(|address| LogBloom::from_bloomed(&address.sha3())) + .map(|address| Bloom::from(BloomInput::Raw(address))) .collect(), } } /// Returns vector of blooms zipped with blooms of this addresses filter. - pub fn with_blooms(&self, blooms: Vec) -> Vec { + pub fn with_blooms(&self, blooms: Vec) -> Vec { match self.list.is_empty() { true => blooms, false => blooms .into_iter() .flat_map(|bloom| self.list.iter() - .map(|address| bloom.with_bloomed(&address.sha3())) + .map(|address| { + let mut bloom = bloom.clone(); + bloom.accrue(BloomInput::Raw(address)); + bloom + }) .collect::>()) .collect(), } @@ -90,9 +91,6 @@ pub struct Filter { impl BloomFilter for Filter { fn bloom_possibilities(&self) -> Vec { self.bloom_possibilities() - .into_iter() - .map(|b| Bloom::from(b.0)) - .collect() } fn range(&self) -> Range { @@ -102,7 +100,7 @@ impl BloomFilter for Filter { impl Filter { /// Returns combinations of each address. - fn bloom_possibilities(&self) -> Vec { + fn bloom_possibilities(&self) -> Vec { self.to_address.with_blooms(self.from_address.blooms()) } @@ -113,7 +111,7 @@ impl Filter { let from_matches = self.from_address.matches(&call.from); let to_matches = self.to_address.matches(&call.to); from_matches && to_matches - } + }, Action::Create(ref create) => { let from_matches = self.from_address.matches(&create.from); @@ -128,19 +126,20 @@ impl Filter { let from_matches = self.from_address.matches(&suicide.address); let to_matches = self.to_address.matches(&suicide.refund_address); from_matches && to_matches - } + }, + Action::Reward(ref reward) => { + self.from_address.matches_all() && self.to_address.matches(&reward.author) + }, } } } #[cfg(test)] mod tests { - use util::Address; - use util::sha3::Hashable; - use bloomable::Bloomable; - use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide}; + use ethereum_types::{Address, Bloom, BloomInput}; + use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide, Reward}; use trace::flat::FlatTrace; - use trace::{Filter, AddressesFilter, TraceError}; + use trace::{Filter, AddressesFilter, TraceError, RewardType}; use evm::CallType; #[test] @@ -152,7 +151,7 @@ mod tests { }; let blooms = filter.bloom_possibilities(); - assert_eq!(blooms, vec![Default::default()]); + assert_eq!(blooms, vec![Bloom::default()]); } #[test] @@ -166,9 +165,9 @@ mod tests { let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 1); - assert!(blooms[0].contains_bloomed(&Address::from(1).sha3())); - assert!(blooms[0].contains_bloomed(&Address::from(2).sha3())); - assert!(!blooms[0].contains_bloomed(&Address::from(3).sha3())); + assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(3)))); } #[test] @@ -182,8 +181,8 @@ mod tests { let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 1); - assert!(blooms[0].contains_bloomed(&Address::from(1).sha3())); - assert!(!blooms[0].contains_bloomed(&Address::from(2).sha3())); + assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); } #[test] @@ -197,8 +196,8 @@ mod tests { let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 1); - assert!(blooms[0].contains_bloomed(&Address::from(1).sha3())); - assert!(!blooms[0].contains_bloomed(&Address::from(2).sha3())); + assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); } #[test] @@ -212,25 +211,25 @@ mod tests { let blooms = filter.bloom_possibilities(); assert_eq!(blooms.len(), 4); - assert!(blooms[0].contains_bloomed(&Address::from(1).sha3())); - assert!(blooms[0].contains_bloomed(&Address::from(2).sha3())); - assert!(!blooms[0].contains_bloomed(&Address::from(3).sha3())); - assert!(!blooms[0].contains_bloomed(&Address::from(4).sha3())); - - assert!(blooms[1].contains_bloomed(&Address::from(1).sha3())); - assert!(blooms[1].contains_bloomed(&Address::from(4).sha3())); - assert!(!blooms[1].contains_bloomed(&Address::from(2).sha3())); - assert!(!blooms[1].contains_bloomed(&Address::from(3).sha3())); - - assert!(blooms[2].contains_bloomed(&Address::from(2).sha3())); - assert!(blooms[2].contains_bloomed(&Address::from(3).sha3())); - assert!(!blooms[2].contains_bloomed(&Address::from(1).sha3())); - assert!(!blooms[2].contains_bloomed(&Address::from(4).sha3())); - - assert!(blooms[3].contains_bloomed(&Address::from(3).sha3())); - assert!(blooms[3].contains_bloomed(&Address::from(4).sha3())); - assert!(!blooms[3].contains_bloomed(&Address::from(1).sha3())); - assert!(!blooms[3].contains_bloomed(&Address::from(2).sha3())); + assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(blooms[0].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(3)))); + assert!(!blooms[0].contains_input(BloomInput::Raw(&Address::from(4)))); + + assert!(blooms[1].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(blooms[1].contains_input(BloomInput::Raw(&Address::from(4)))); + assert!(!blooms[1].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(!blooms[1].contains_input(BloomInput::Raw(&Address::from(3)))); + + assert!(blooms[2].contains_input(BloomInput::Raw(&Address::from(2)))); + assert!(blooms[2].contains_input(BloomInput::Raw(&Address::from(3)))); + assert!(!blooms[2].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(!blooms[2].contains_input(BloomInput::Raw(&Address::from(4)))); + + assert!(blooms[3].contains_input(BloomInput::Raw(&Address::from(3)))); + assert!(blooms[3].contains_input(BloomInput::Raw(&Address::from(4)))); + assert!(!blooms[3].contains_input(BloomInput::Raw(&Address::from(1)))); + assert!(!blooms[3].contains_input(BloomInput::Raw(&Address::from(2)))); } #[test] @@ -341,5 +340,60 @@ mod tests { assert!(f4.matches(&trace)); assert!(f5.matches(&trace)); assert!(!f6.matches(&trace)); + + let trace = FlatTrace { + action: Action::Reward(Reward { + author: 2.into(), + value: 100.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![].into_iter().collect(), + subtraces: 0 + }; + + assert!(!f0.matches(&trace)); + assert!(!f1.matches(&trace)); + assert!(f2.matches(&trace)); + assert!(f3.matches(&trace)); + assert!(f4.matches(&trace)); + assert!(!f5.matches(&trace)); + assert!(!f6.matches(&trace)); + } + + #[test] + fn filter_match_block_reward_fix_8070() { + let f0 = Filter { + range: (0..0), + from_address: vec![1.into()].into(), + to_address: vec![].into(), + }; + + let f1 = Filter { + range: (0..0), + from_address: vec![].into(), + to_address: vec![].into(), + }; + + let f2 = Filter { + range: (0..0), + from_address: vec![].into(), + to_address: vec![2.into()].into(), + }; + + let trace = FlatTrace { + action: Action::Reward(Reward { + author: 2.into(), + value: 10.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + + assert!(!f0.matches(&trace)); + assert!(f1.matches(&trace)); + assert!(f2.matches(&trace)); } } diff --git a/ethcore/src/trace/types/flat.rs b/ethcore/src/trace/types/flat.rs index 8b65f1f4c3261f27d1123970baea3de22c378f53..e97f4d32359b89c0c807b1341f3d4d295e5e5f64 100644 --- a/ethcore/src/trace/types/flat.rs +++ b/ethcore/src/trace/types/flat.rs @@ -18,8 +18,8 @@ use std::collections::VecDeque; use rlp::*; -use util::HeapSizeOf; -use basic_types::LogBloom; +use heapsize::HeapSizeOf; +use ethereum_types::Bloom; use super::trace::{Action, Res}; /// Trace localized in vector of traces produced by a single transaction. @@ -41,7 +41,7 @@ pub struct FlatTrace { impl FlatTrace { /// Returns bloom of the trace. - pub fn bloom(&self) -> LogBloom { + pub fn bloom(&self) -> Bloom { self.action.bloom() | self.result.bloom() } } @@ -94,7 +94,7 @@ impl HeapSizeOf for FlatTransactionTraces { impl FlatTransactionTraces { /// Returns bloom of all traces in the collection. - pub fn bloom(&self) -> LogBloom { + pub fn bloom(&self) -> Bloom { self.0.iter().fold(Default::default(), | bloom, trace | bloom | trace.bloom()) } } @@ -123,7 +123,7 @@ impl From> for FlatBlockTraces { impl FlatBlockTraces { /// Returns bloom of all traces in the block. - pub fn bloom(&self) -> LogBloom { + pub fn bloom(&self) -> Bloom { self.0.iter().fold(Default::default(), | bloom, tx_traces | bloom | tx_traces.bloom()) } } @@ -138,8 +138,9 @@ impl Into> for FlatBlockTraces { mod tests { use rlp::*; use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; - use trace::trace::{Action, Res, CallResult, Call, Suicide}; + use trace::trace::{Action, Res, CallResult, Call, Suicide, Reward}; use evm::CallType; + use trace::RewardType; #[test] fn encode_flat_transaction_traces() { @@ -214,9 +215,32 @@ mod tests { subtraces: 0, }; + let flat_trace3 = FlatTrace { + action: Action::Reward(Reward { + author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + value: 10.into(), + reward_type: RewardType::Uncle, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + + let flat_trace4 = FlatTrace { + action: Action::Reward(Reward { + author: "412fda7643b37d436cb40628f6dbbb80a07267ed".parse().unwrap(), + value: 10.into(), + reward_type: RewardType::Block, + }), + result: Res::None, + trace_address: vec![0].into_iter().collect(), + subtraces: 0, + }; + let block_traces = FlatBlockTraces(vec![ FlatTransactionTraces(vec![flat_trace]), - FlatTransactionTraces(vec![flat_trace1, flat_trace2]) + FlatTransactionTraces(vec![flat_trace1, flat_trace2]), + FlatTransactionTraces(vec![flat_trace3, flat_trace4]) ]); let encoded = ::rlp::encode(&block_traces); diff --git a/ethcore/src/trace/types/localized.rs b/ethcore/src/trace/types/localized.rs index 39a4b08cc390cf1f1f153034fa228e936753ff91..f649e169971fe62964507dd5742a79848182c3c1 100644 --- a/ethcore/src/trace/types/localized.rs +++ b/ethcore/src/trace/types/localized.rs @@ -16,7 +16,7 @@ //! Localized traces type definitions -use util::H256; +use ethereum_types::H256; use super::trace::{Action, Res}; use header::BlockNumber; @@ -34,9 +34,9 @@ pub struct LocalizedTrace { /// [index in root, index in first CALL, index in second CALL, ...] pub trace_address: Vec, /// Transaction number within the block. - pub transaction_number: usize, + pub transaction_number: Option, /// Signed transaction hash. - pub transaction_hash: H256, + pub transaction_hash: Option, /// Block number. pub block_number: BlockNumber, /// Block hash. diff --git a/ethcore/src/trace/types/mod.rs b/ethcore/src/trace/types/mod.rs index 434bae4e1dd8a75d6196b322ab1d8d3ec5d1f7f8..a9be2865b0fbf335dfb5ac30a8f1e81e9b76cc59 100644 --- a/ethcore/src/trace/types/mod.rs +++ b/ethcore/src/trace/types/mod.rs @@ -21,3 +21,37 @@ pub mod filter; pub mod flat; pub mod trace; pub mod localized; + +use self::flat::FlatTransactionTraces; + +/// Container for block traces. +#[derive(Clone)] +pub enum Tracing { + /// This variant should be used when tracing is enabled. + Enabled(Vec), + /// Tracing is disabled. + Disabled, +} + +impl Tracing { + /// Creates new instance of enabled tracing object. + pub fn enabled() -> Self { + Tracing::Enabled(Default::default()) + } + + /// Returns true if tracing is enabled. + pub fn is_enabled(&self) -> bool { + match *self { + Tracing::Enabled(_) => true, + Tracing::Disabled => false, + } + } + + /// Drain all traces. + pub fn drain(self) -> Vec { + match self { + Tracing::Enabled(traces) => traces, + Tracing::Disabled => vec![], + } + } +} diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index 5fa0260c6752ee9f8d77221af1367ab73fc4eb56..18fe329c442c99e894894c2ec91d90ab861d9e2e 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -16,19 +16,16 @@ //! Tracing datatypes. -use util::{U256, Bytes, Address}; -use util::sha3::Hashable; -use bloomable::Bloomable; +use ethereum_types::{U256, Address, Bloom, BloomInput}; +use bytes::Bytes; use rlp::*; use vm::ActionParams; -use basic_types::LogBloom; use evm::CallType; use super::error::Error; /// `Call` result. #[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] pub struct CallResult { /// Gas used by call. pub gas_used: U256, @@ -38,7 +35,6 @@ pub struct CallResult { /// `Create` result. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] pub struct CreateResult { /// Gas used by create. pub gas_used: U256, @@ -50,14 +46,13 @@ pub struct CreateResult { impl CreateResult { /// Returns bloom. - pub fn bloom(&self) -> LogBloom { - LogBloom::from_bloomed(&self.address.sha3()) + pub fn bloom(&self) -> Bloom { + BloomInput::Raw(&self.address).into() } } /// Description of a _call_ action, either a `CALL` operation or a message transction. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] pub struct Call { /// The sending account. pub from: Address, @@ -75,13 +70,23 @@ pub struct Call { impl From for Call { fn from(p: ActionParams) -> Self { - Call { - from: p.sender, - to: p.address, - value: p.value.value(), - gas: p.gas, - input: p.data.unwrap_or_else(Vec::new), - call_type: p.call_type, + match p.call_type { + CallType::DelegateCall => Call { + from: p.address, + to: p.code_address, + value: p.value.value(), + gas: p.gas, + input: p.data.unwrap_or_else(Vec::new), + call_type: p.call_type, + }, + _ => Call { + from: p.sender, + to: p.address, + value: p.value.value(), + gas: p.gas, + input: p.data.unwrap_or_else(Vec::new), + call_type: p.call_type, + }, } } } @@ -89,15 +94,16 @@ impl From for Call { impl Call { /// Returns call action bloom. /// The bloom contains from and to addresses. - pub fn bloom(&self) -> LogBloom { - LogBloom::from_bloomed(&self.from.sha3()) - .with_bloomed(&self.to.sha3()) + pub fn bloom(&self) -> Bloom { + let mut bloom = Bloom::default(); + bloom.accrue(BloomInput::Raw(&self.from)); + bloom.accrue(BloomInput::Raw(&self.to)); + bloom } } /// Description of a _create_ action, either a `CREATE` operation or a create transction. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] pub struct Create { /// The address of the creator. pub from: Address, @@ -123,14 +129,82 @@ impl From for Create { impl Create { /// Returns bloom create action bloom. /// The bloom contains only from address. - pub fn bloom(&self) -> LogBloom { - LogBloom::from_bloomed(&self.from.sha3()) + pub fn bloom(&self) -> Bloom { + BloomInput::Raw(&self.from).into() + } +} + +/// Reward type. +#[derive(Debug, PartialEq, Clone)] +pub enum RewardType { + /// Block + Block, + /// Uncle + Uncle, +} + +impl Encodable for RewardType { + fn rlp_append(&self, s: &mut RlpStream) { + let v = match *self { + RewardType::Block => 0u32, + RewardType::Uncle => 1, + }; + Encodable::rlp_append(&v, s); } } +impl Decodable for RewardType { + fn decode(rlp: &UntrustedRlp) -> Result { + rlp.as_val().and_then(|v| Ok(match v { + 0u32 => RewardType::Block, + 1 => RewardType::Uncle, + _ => return Err(DecoderError::Custom("Invalid value of RewardType item")), + })) + } +} + +/// Reward action +#[derive(Debug, Clone, PartialEq)] +pub struct Reward { + /// Author's address. + pub author: Address, + /// Reward amount. + pub value: U256, + /// Reward type. + pub reward_type: RewardType, +} + +impl Reward { + /// Return reward action bloom. + pub fn bloom(&self) -> Bloom { + BloomInput::Raw(&self.author).into() + } +} + +impl Encodable for Reward { + fn rlp_append(&self, s: &mut RlpStream) { + s.begin_list(3); + s.append(&self.author); + s.append(&self.value); + s.append(&self.reward_type); + } +} + +impl Decodable for Reward { + fn decode(rlp: &UntrustedRlp) -> Result { + let res = Reward { + author: rlp.val_at(0)?, + value: rlp.val_at(1)?, + reward_type: rlp.val_at(2)?, + }; + + Ok(res) + } +} + + /// Suicide action. #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] pub struct Suicide { /// Suicided address. pub address: Address, @@ -142,15 +216,16 @@ pub struct Suicide { impl Suicide { /// Return suicide action bloom. - pub fn bloom(&self) -> LogBloom { - LogBloom::from_bloomed(&self.address.sha3()) - .with_bloomed(&self.refund_address.sha3()) + pub fn bloom(&self) -> Bloom { + let mut bloom = Bloom::default(); + bloom.accrue(BloomInput::Raw(&self.address)); + bloom.accrue(BloomInput::Raw(&self.refund_address)); + bloom } } /// Description of an action that we trace; will be either a call or a create. #[derive(Debug, Clone, PartialEq)] -#[cfg_attr(feature = "ipc", binary)] pub enum Action { /// It's a call action. Call(Call), @@ -158,6 +233,8 @@ pub enum Action { Create(Create), /// Suicide. Suicide(Suicide), + /// Reward + Reward(Reward), } impl Encodable for Action { @@ -175,7 +252,12 @@ impl Encodable for Action { Action::Suicide(ref suicide) => { s.append(&2u8); s.append(suicide); + }, + Action::Reward(ref reward) => { + s.append(&3u8); + s.append(reward); } + } } } @@ -187,6 +269,7 @@ impl Decodable for Action { 0 => rlp.val_at(1).map(Action::Call), 1 => rlp.val_at(1).map(Action::Create), 2 => rlp.val_at(1).map(Action::Suicide), + 3 => rlp.val_at(1).map(Action::Reward), _ => Err(DecoderError::Custom("Invalid action type.")), } } @@ -194,18 +277,18 @@ impl Decodable for Action { impl Action { /// Returns action bloom. - pub fn bloom(&self) -> LogBloom { + pub fn bloom(&self) -> Bloom { match *self { Action::Call(ref call) => call.bloom(), Action::Create(ref create) => create.bloom(), Action::Suicide(ref suicide) => suicide.bloom(), + Action::Reward(ref reward) => reward.bloom(), } } } /// The result of the performed action. #[derive(Debug, Clone, PartialEq)] -#[cfg_attr(feature = "ipc", binary)] pub enum Res { /// Successful call action result. Call(CallResult), @@ -266,7 +349,7 @@ impl Decodable for Res { impl Res { /// Returns result bloom. - pub fn bloom(&self) -> LogBloom { + pub fn bloom(&self) -> Bloom { match *self { Res::Create(ref create) => create.bloom(), Res::Call(_) | Res::FailedCall(_) | Res::FailedCreate(_) | Res::None => Default::default(), @@ -283,7 +366,6 @@ impl Res { } #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] /// A diff of some chunk of memory. pub struct MemoryDiff { /// Offset into memory the change begins. @@ -293,7 +375,6 @@ pub struct MemoryDiff { } #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] /// A diff of some storage value. pub struct StorageDiff { /// Which key in storage is changed. @@ -303,7 +384,6 @@ pub struct StorageDiff { } #[derive(Debug, Clone, PartialEq, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] /// A record of an executed VM operation. pub struct VMExecutedOperation { /// The total gas used. @@ -317,7 +397,6 @@ pub struct VMExecutedOperation { } #[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] /// A record of the execution of a single VM operation. pub struct VMOperation { /// The program counter. @@ -331,7 +410,6 @@ pub struct VMOperation { } #[derive(Debug, Clone, PartialEq, Default, RlpEncodable, RlpDecodable)] -#[cfg_attr(feature = "ipc", binary)] /// A record of a full VM trace for a CALL/CREATE. pub struct VMTrace { /// The step (i.e. index into operations) at which this trace corresponds. diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs new file mode 100644 index 0000000000000000000000000000000000000000..12e6fe3ebbbf6470bc4eded8564663361d3f8535 --- /dev/null +++ b/ethcore/src/tx_filter.rs @@ -0,0 +1,214 @@ +// 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 . + +//! Smart contract based transaction filter. + +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use ethereum_types::{H256, Address}; +use client::{BlockInfo, CallContract, BlockId, ChainNotify}; +use bytes::Bytes; +use parking_lot::Mutex; +use spec::CommonParams; +use transaction::{Action, SignedTransaction}; +use hash::KECCAK_EMPTY; + +use_contract!(transact_acl, "TransactAcl", "res/contracts/tx_acl.json"); + +const MAX_CACHE_SIZE: usize = 4096; + +mod tx_permissions { + pub const _ALL: u32 = 0xffffffff; + pub const NONE: u32 = 0x0; + pub const BASIC: u32 = 0b00000001; + pub const CALL: u32 = 0b00000010; + pub const CREATE: u32 = 0b00000100; + pub const _PRIVATE: u32 = 0b00001000; +} + +/// Connection filter that uses a contract to manage permissions. +pub struct TransactionFilter { + contract: transact_acl::TransactAcl, + contract_address: Address, + permission_cache: Mutex>, +} + +impl TransactionFilter { + /// Create a new instance if address is specified in params. + pub fn from_params(params: &CommonParams) -> Option { + params.transaction_permission_contract.map(|address| + TransactionFilter { + contract: transact_acl::TransactAcl::default(), + contract_address: address, + permission_cache: Mutex::new(HashMap::new()), + } + ) + } + + /// Clear cached permissions. + pub fn clear_cache(&self) { + self.permission_cache.lock().clear(); + } + + /// Check if transaction is allowed at given block. + pub fn transaction_allowed(&self, parent_hash: &H256, transaction: &SignedTransaction, client: &C) -> bool { + let mut cache = self.permission_cache.lock(); let len = cache.len(); + + let tx_type = match transaction.action { + Action::Create => tx_permissions::CREATE, + Action::Call(address) => if client.code_hash(&address, BlockId::Hash(*parent_hash)).map_or(false, |c| c != KECCAK_EMPTY) { + tx_permissions::CALL + } else { + tx_permissions::BASIC + } + }; + let sender = transaction.sender(); + match cache.entry((*parent_hash, sender)) { + Entry::Occupied(entry) => *entry.get() & tx_type != 0, + Entry::Vacant(entry) => { + let contract_address = self.contract_address; + let permissions = self.contract.functions() + .allowed_tx_types() + .call(sender, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)) + .map(|p| p.low_u32()) + .unwrap_or_else(|e| { + debug!("Error callling tx permissions contract: {:?}", e); + tx_permissions::NONE + }); + + if len < MAX_CACHE_SIZE { + entry.insert(permissions); + } + trace!("Permissions required: {}, got: {}", tx_type, permissions); + permissions & tx_type != 0 + } + } + } +} + +impl ChainNotify for TransactionFilter { + fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { + if !imported.is_empty() { + self.clear_cache(); + } + } +} + +#[cfg(test)] +mod test { + use std::sync::Arc; + use spec::Spec; + use client::{BlockChainClient, Client, ClientConfig, BlockId}; + use miner::Miner; + use ethereum_types::Address; + use io::IoChannel; + use ethkey::{Secret, KeyPair}; + use super::TransactionFilter; + use transaction::{Transaction, Action}; + use tempdir::TempDir; + + /// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a + #[test] + fn transaction_filter() { + let spec_data = r#" + { + "name": "TestNodeFilterContract", + "engine": { + "authorityRound": { + "params": { + "stepDuration": 1, + "startStep": 2, + "validators": { + "contract": "0x0000000000000000000000000000000000000000" + } + } + } + }, + "params": { + "accountStartNonce": "0x0", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x69", + "gasLimitBoundDivisor": "0x0400", + "transactionPermissionContract": "0x0000000000000000000000000000000000000005" + }, + "genesis": { + "seal": { + "generic": "0xc180" + }, + "difficulty": "0x20000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x", + "gasLimit": "0x222222" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { + "balance": "1", + "constructor": "6060604052341561000f57600080fd5b5b6101868061001f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063e17512211461003e575b600080fd5b341561004957600080fd5b610075600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610097565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b6000737e5f4552091a69125d5dfcb7b8c2659029395bdf8273ffffffffffffffffffffffffffffffffffffffff1614156100d75763ffffffff9050610155565b732b5ad5c4795c026514f8317c7a215e218dccd6cf8273ffffffffffffffffffffffffffffffffffffffff1614156101155760026001179050610155565b736813eb9362372eef6200f3b1dbc3f819671cba698273ffffffffffffffffffffffffffffffffffffffff1614156101505760019050610155565b600090505b9190505600a165627a7a72305820f1f21cb978925a8a92c6e30c8c81adf598adff6d1ef941cf5ed6c0ec7ad1ae3d0029" + } + } + } + "#; + + let tempdir = TempDir::new("").unwrap(); + let spec = Spec::load(&tempdir.path(), spec_data.as_bytes()).unwrap(); + let client_db = Arc::new(::kvdb_memorydb::create(::db::NUM_COLUMNS.unwrap_or(0))); + + let client = Client::new( + ClientConfig::default(), + &spec, + client_db, + Arc::new(Miner::with_spec(&spec)), + IoChannel::disconnected(), + ).unwrap(); + let key1 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000001")).unwrap(); + let key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000002")).unwrap(); + let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000003")).unwrap(); + let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000004")).unwrap(); + + let filter = TransactionFilter::from_params(spec.params()).unwrap(); + let mut basic_tx = Transaction::default(); + basic_tx.action = Action::Call(Address::from("000000000000000000000000000000000000032")); + let create_tx = Transaction::default(); + let mut call_tx = Transaction::default(); + call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005")); + + let genesis = client.block_hash(BlockId::Latest).unwrap(); + + assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client)); + assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client)); + assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client)); + + assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client)); + assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client)); + assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client)); + + assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client)); + assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client)); + assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client)); + + assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client)); + assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client)); + assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client)); + } +} + diff --git a/ethcore/src/verification/canon_verifier.rs b/ethcore/src/verification/canon_verifier.rs index a5d8fe73fdf75ee98031aa22d8567b2fbb179f3c..3d0fd77c6e5bc906a51be6a964365b76ef64293c 100644 --- a/ethcore/src/verification/canon_verifier.rs +++ b/ethcore/src/verification/canon_verifier.rs @@ -16,8 +16,8 @@ //! Canonical verifier. -use blockchain::BlockProvider; -use engines::Engine; +use client::{BlockInfo, CallContract}; +use engines::EthEngine; use error::Error; use header::Header; use super::Verifier; @@ -26,16 +26,22 @@ use super::verification; /// A canonial verifier -- this does full verification. pub struct CanonVerifier; -impl Verifier for CanonVerifier { - fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { - verification::verify_block_family(header, bytes, engine, bc) +impl Verifier for CanonVerifier { + fn verify_block_family( + &self, + header: &Header, + parent: &Header, + engine: &EthEngine, + do_full: Option>, + ) -> Result<(), Error> { + verification::verify_block_family(header, parent, engine, do_full) } fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error> { verification::verify_block_final(expected, got) } - fn verify_block_external(&self, header: &Header, bytes: &[u8], engine: &Engine) -> Result<(), Error> { - engine.verify_block_external(header, Some(bytes)) + fn verify_block_external(&self, header: &Header, engine: &EthEngine) -> Result<(), Error> { + engine.verify_block_external(header) } } diff --git a/ethcore/src/verification/mod.rs b/ethcore/src/verification/mod.rs index c83d9e20fdb00a53a27a869e15f6e251edcfc724..d5fd4e847610fbcda6f5e844283070955fbc6bb9 100644 --- a/ethcore/src/verification/mod.rs +++ b/ethcore/src/verification/mod.rs @@ -28,6 +28,8 @@ pub use self::canon_verifier::CanonVerifier; pub use self::noop_verifier::NoopVerifier; pub use self::queue::{BlockQueue, Config as QueueConfig, VerificationQueue, QueueInfo}; +use client::{BlockInfo, CallContract}; + /// Verifier type. #[derive(Debug, PartialEq, Clone)] pub enum VerifierType { @@ -47,7 +49,7 @@ impl Default for VerifierType { } /// Create a new verifier based on type. -pub fn new(v: VerifierType) -> Box { +pub fn new(v: VerifierType) -> Box> { match v { VerifierType::Canon | VerifierType::CanonNoSeal => Box::new(CanonVerifier), VerifierType::Noop => Box::new(NoopVerifier), diff --git a/ethcore/src/verification/noop_verifier.rs b/ethcore/src/verification/noop_verifier.rs index 8464ba1e2e778bd7e3849b3f6125db212d6f8642..24b117bbc16afbfe19801cce3912741525adc535 100644 --- a/ethcore/src/verification/noop_verifier.rs +++ b/ethcore/src/verification/noop_verifier.rs @@ -16,18 +16,24 @@ //! No-op verifier. -use blockchain::BlockProvider; -use engines::Engine; +use client::{BlockInfo, CallContract}; +use engines::EthEngine; use error::Error; use header::Header; -use super::Verifier; +use super::{verification, Verifier}; /// A no-op verifier -- this will verify everything it's given immediately. #[allow(dead_code)] pub struct NoopVerifier; -impl Verifier for NoopVerifier { - fn verify_block_family(&self, _header: &Header, _bytes: &[u8], _engine: &Engine, _bc: &BlockProvider) -> Result<(), Error> { +impl Verifier for NoopVerifier { + fn verify_block_family( + &self, + _: &Header, + _t: &Header, + _: &EthEngine, + _: Option> + ) -> Result<(), Error> { Ok(()) } @@ -35,7 +41,7 @@ impl Verifier for NoopVerifier { Ok(()) } - fn verify_block_external(&self, _header: &Header, _bytes: &[u8], _engine: &Engine) -> Result<(), Error> { + fn verify_block_external(&self, _header: &Header, _engine: &EthEngine) -> Result<(), Error> { Ok(()) } } diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 6ab6d692e302eaff6fc0ea9d04a4612b58026595..b437dba7a047b24b135b5b04397ea62ac6f67af8 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -16,10 +16,11 @@ //! Definition of valid items for the verification queue. -use engines::Engine; +use engines::EthEngine; use error::Error; -use util::{HeapSizeOf, H256, U256}; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, U256}; pub use self::blocks::Blocks; pub use self::headers::Headers; @@ -57,22 +58,24 @@ pub trait Kind: 'static + Sized + Send + Sync { type Verified: Sized + Send + BlockLike + HeapSizeOf; /// Attempt to create the `Unverified` item from the input. - fn create(input: Self::Input, engine: &Engine) -> Result; + fn create(input: Self::Input, engine: &EthEngine) -> Result; /// Attempt to verify the `Unverified` item using the given engine. - fn verify(unverified: Self::Unverified, engine: &Engine, check_seal: bool) -> Result; + fn verify(unverified: Self::Unverified, engine: &EthEngine, check_seal: bool) -> Result; } /// The blocks verification module. pub mod blocks { use super::{Kind, BlockLike}; - use engines::Engine; + use engines::EthEngine; use error::Error; use header::Header; use verification::{PreverifiedBlock, verify_block_basic, verify_block_unordered}; - use util::{Bytes, HeapSizeOf, H256, U256}; + use heapsize::HeapSizeOf; + use ethereum_types::{H256, U256}; + use bytes::Bytes; /// A mode for verifying blocks. pub struct Blocks; @@ -82,7 +85,7 @@ pub mod blocks { type Unverified = Unverified; type Verified = PreverifiedBlock; - fn create(input: Self::Input, engine: &Engine) -> Result { + fn create(input: Self::Input, engine: &EthEngine) -> Result { match verify_block_basic(&input.header, &input.bytes, engine) { Ok(()) => Ok(input), Err(e) => { @@ -92,7 +95,7 @@ pub mod blocks { } } - fn verify(un: Self::Unverified, engine: &Engine, check_seal: bool) -> Result { + fn verify(un: Self::Unverified, engine: &EthEngine, check_seal: bool) -> Result { let hash = un.hash(); match verify_block_unordered(un.header, un.bytes, engine, check_seal) { Ok(verified) => Ok(verified), @@ -162,13 +165,12 @@ pub mod blocks { pub mod headers { use super::{Kind, BlockLike}; - use engines::Engine; + use engines::EthEngine; use error::Error; use header::Header; use verification::verify_header_params; - use util::hash::H256; - use util::U256; + use ethereum_types::{H256, U256}; impl BlockLike for Header { fn hash(&self) -> H256 { self.hash() } @@ -184,13 +186,13 @@ pub mod headers { type Unverified = Header; type Verified = Header; - fn create(input: Self::Input, engine: &Engine) -> Result { + fn create(input: Self::Input, engine: &EthEngine) -> Result { verify_header_params(&input, engine, true).map(|_| input) } - fn verify(unverified: Self::Unverified, engine: &Engine, check_seal: bool) -> Result { + fn verify(unverified: Self::Unverified, engine: &EthEngine, check_seal: bool) -> Result { match check_seal { - true => engine.verify_block_unordered(&unverified, None).map(|_| unverified), + true => engine.verify_block_unordered(&unverified,).map(|_| unverified), false => Ok(unverified), } } diff --git a/ethcore/src/verification/queue/mod.rs b/ethcore/src/verification/queue/mod.rs index ce0cb41791be4f0e2376a9647ca6d76f9771c777..58b1bb7bb3cf1ae906dcbb015fbb061eb544d8eb 100644 --- a/ethcore/src/verification/queue/mod.rs +++ b/ethcore/src/verification/queue/mod.rs @@ -22,11 +22,13 @@ use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering}; use std::sync::{Condvar as SCondvar, Mutex as SMutex, Arc}; use std::cmp; use std::collections::{VecDeque, HashSet, HashMap}; -use util::*; +use heapsize::HeapSizeOf; +use ethereum_types::{H256, U256}; +use parking_lot::{Condvar, Mutex, RwLock}; use io::*; use error::*; -use engines::Engine; -use service::*; +use engines::EthEngine; +use client::ClientIoMessage; use self::kind::{BlockLike, Kind}; @@ -138,7 +140,7 @@ struct Sizes { /// A queue of items to be verified. Sits between network or other I/O and the `BlockChain`. /// Keeps them in the same order as inserted, minus invalid items. pub struct VerificationQueue { - engine: Arc, + engine: Arc, more_to_verify: Arc, verification: Arc>, deleting: Arc, @@ -161,7 +163,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) { @@ -176,7 +177,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) { @@ -210,7 +210,7 @@ struct Verification { impl VerificationQueue { /// Creates a new queue instance. - pub fn new(config: Config, engine: Arc, message_channel: IoChannel, check_seal: bool) -> Self { + pub fn new(config: Config, engine: Arc, message_channel: IoChannel, check_seal: bool) -> Self { let verification = Arc::new(Verification { unverified: Mutex::new(VecDeque::new()), verifying: Mutex::new(VecDeque::new()), @@ -291,7 +291,7 @@ impl VerificationQueue { fn verify( verification: Arc>, - engine: Arc, + engine: Arc, wait: Arc, ready: Arc, empty: Arc, @@ -502,7 +502,7 @@ impl VerificationQueue { Err(err) => { match err { // Don't mark future blocks as bad. - Error::Block(BlockError::InvalidTimestamp(ref e)) if e.max.is_some() => {}, + Error::Block(BlockError::TemporarilyInvalid(_)) => {}, _ => { self.verification.bad.lock().insert(h.clone()); } @@ -519,7 +519,7 @@ impl VerificationQueue { return; } let mut verified_lock = self.verification.verified.lock(); - let mut verified = &mut *verified_lock; + let verified = &mut *verified_lock; let mut bad = self.verification.bad.lock(); let mut processing = self.processing.write(); bad.reserve(hashes.len()); @@ -728,17 +728,17 @@ impl Drop for VerificationQueue { #[cfg(test)] mod tests { use io::*; - use spec::*; + use spec::Spec; use super::{BlockQueue, Config, State}; use super::kind::blocks::Unverified; - use tests::helpers::*; + use tests::helpers::{get_good_dummy_block_seq, get_good_dummy_block}; use error::*; use views::*; // create a test block queue. // auto_scaling enables verifier adjustment. fn get_test_queue(auto_scale: bool) -> BlockQueue { - let spec = get_test_spec(); + let spec = Spec::new_test(); let engine = spec.engine; let mut config = Config::default(); @@ -827,7 +827,7 @@ mod tests { #[test] fn test_mem_limit() { - let spec = get_test_spec(); + let spec = Spec::new_test(); let engine = spec.engine; let mut config = Config::default(); config.max_mem_use = super::MIN_MEM_LIMIT; // empty queue uses about 15000 diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 00976dca7cd83280ba3a0d7c2ccaac2f3a01b8ee..f78059ac8dbf25422f2011de9f6346b608ab63c4 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -22,15 +22,23 @@ //! 3. Final verification against the blockchain done before enactment. use std::collections::HashSet; -use util::*; -use engines::Engine; -use error::{BlockError, Error}; +use std::time::{SystemTime, UNIX_EPOCH}; + +use bytes::Bytes; +use ethereum_types::{H256, U256}; +use hash::keccak; +use heapsize::HeapSizeOf; +use rlp::UntrustedRlp; +use triehash::ordered_trie_root; +use unexpected::{Mismatch, OutOfBounds}; + use blockchain::*; +use client::{BlockInfo, CallContract}; +use engines::EthEngine; +use error::{BlockError, Error}; use header::{BlockNumber, Header}; -use rlp::UntrustedRlp; -use transaction::SignedTransaction; +use transaction::{SignedTransaction, UnverifiedTransaction}; use views::BlockView; -use time::get_time; /// Preprocessed block data gathered in `verify_block_unordered` call pub struct PreverifiedBlock { @@ -51,20 +59,18 @@ impl HeapSizeOf for PreverifiedBlock { } /// Phase 1 quick block verification. Only does checks that are cheap. Operates on a single block -pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Result<(), Error> { +pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &EthEngine) -> Result<(), Error> { verify_header_params(&header, engine, true)?; verify_block_integrity(bytes, &header.transactions_root(), &header.uncles_hash())?; - engine.verify_block_basic(&header, Some(bytes))?; + engine.verify_block_basic(&header)?; for u in UntrustedRlp::new(bytes).at(2)?.iter().map(|rlp| rlp.as_val::
()) { let u = u?; verify_header_params(&u, engine, false)?; - engine.verify_block_basic(&u, None)?; + engine.verify_block_basic(&u)?; } - // Verify transactions. - // TODO: either use transaction views or cache the decoded transactions. - let v = BlockView::new(bytes); - for t in v.transactions() { - engine.verify_transaction_basic(&t, &header)?; + + for t in UntrustedRlp::new(bytes).at(1)?.iter().map(|rlp| rlp.as_val::()) { + engine.verify_transaction_basic(&t?, &header)?; } Ok(()) } @@ -72,11 +78,11 @@ pub fn verify_block_basic(header: &Header, bytes: &[u8], engine: &Engine) -> Res /// Phase 2 verification. Perform costly checks such as transaction signatures and block nonce for ethash. /// Still operates on a individual block /// Returns a `PreverifiedBlock` structure populated with transactions -pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine, check_seal: bool) -> Result { +pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &EthEngine, check_seal: bool) -> Result { if check_seal { - engine.verify_block_unordered(&header, Some(&bytes))?; + engine.verify_block_unordered(&header)?; for u in UntrustedRlp::new(&bytes).at(2)?.iter().map(|rlp| rlp.as_val::
()) { - engine.verify_block_unordered(&u?, None)?; + engine.verify_block_unordered(&u?)?; } } // Verify transactions. @@ -87,7 +93,7 @@ pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine, che { let v = BlockView::new(&bytes); for t in v.transactions() { - let t = engine.verify_transaction(t, &header)?; + let t = engine.verify_transaction_unordered(t, &header)?; if let Some(max_nonce) = nonce_cap { if t.nonce >= max_nonce { return Err(BlockError::TooManyTransactions(t.sender()).into()); @@ -103,17 +109,51 @@ pub fn verify_block_unordered(header: Header, bytes: Bytes, engine: &Engine, che }) } +/// Parameters for full verification of block family +pub struct FullFamilyParams<'a, C: BlockInfo + CallContract + 'a> { + /// Serialized block bytes + pub block_bytes: &'a [u8], + + /// Signed transactions + pub transactions: &'a [SignedTransaction], + + /// Block provider to use during verification + pub block_provider: &'a BlockProvider, + + /// Engine client to use during verification + pub client: &'a C, +} + /// Phase 3 verification. Check block information against parent and uncles. -pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error> { +pub fn verify_block_family(header: &Header, parent: &Header, engine: &EthEngine, do_full: Option>) -> Result<(), Error> { // TODO: verify timestamp - let parent = bc.block_header(&header.parent_hash()).ok_or_else(|| Error::from(BlockError::UnknownParent(header.parent_hash().clone())))?; - verify_parent(&header, &parent)?; - engine.verify_block_family(&header, &parent, Some(bytes))?; + verify_parent(&header, &parent, engine.params().gas_limit_bound_divisor)?; + engine.verify_block_family(&header, &parent)?; + + let params = match do_full { + Some(x) => x, + None => return Ok(()), + }; + verify_uncles(header, params.block_bytes, params.block_provider, engine)?; + + for transaction in params.transactions { + engine.machine().verify_transaction(transaction, header, params.client)?; + } + + Ok(()) +} + +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(); @@ -184,11 +224,12 @@ pub fn verify_block_family(header: &Header, bytes: &[u8], engine: &Engine, bc: & return Err(From::from(BlockError::UncleParentNotInChain(uncle_parent.hash()))); } - verify_parent(&uncle, &uncle_parent)?; - engine.verify_block_family(&uncle, &uncle_parent, Some(bytes))?; + verify_parent(&uncle, &uncle_parent, engine.params().gas_limit_bound_divisor)?; + engine.verify_block_family(&uncle, &uncle_parent)?; verified.insert(uncle.hash()); } } + Ok(()) } @@ -210,7 +251,14 @@ pub fn verify_block_final(expected: &Header, got: &Header) -> Result<(), Error> } /// Check basic header parameters. -pub fn verify_header_params(header: &Header, engine: &Engine, is_full: bool) -> Result<(), Error> { +pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool) -> Result<(), Error> { + let expected_seal_fields = engine.seal_fields(header); + if header.seal().len() != expected_seal_fields { + return Err(From::from(BlockError::InvalidSealArity( + Mismatch { expected: expected_seal_fields, found: header.seal().len() } + ))); + } + if header.number() >= From::from(BlockNumber::max_value()) { return Err(From::from(BlockError::RidiculousNumber(OutOfBounds { max: Some(From::from(BlockNumber::max_value())), min: None, found: header.number() }))) } @@ -225,17 +273,36 @@ pub fn verify_header_params(header: &Header, engine: &Engine, is_full: bool) -> if header.number() != 0 && header.extra_data().len() > maximum_extra_data_size { return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: Some(maximum_extra_data_size), found: header.extra_data().len() }))); } + + if let Some(ref ext) = engine.machine().ethash_extensions() { + if header.number() >= ext.dao_hardfork_transition && + header.number() <= ext.dao_hardfork_transition + 9 && + header.extra_data()[..] != b"dao-hard-fork"[..] { + return Err(From::from(BlockError::ExtraDataOutOfBounds(OutOfBounds { min: None, max: None, found: 0 }))); + } + } + if is_full { - let max_time = get_time().sec as u64 + 30; - if header.timestamp() > max_time { - return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: header.timestamp() }))) + const ACCEPTABLE_DRIFT_SECS: u64 = 15; + let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default(); + let max_time = now.as_secs() + ACCEPTABLE_DRIFT_SECS; + let invalid_threshold = max_time + ACCEPTABLE_DRIFT_SECS * 9; + let timestamp = header.timestamp(); + + if timestamp > invalid_threshold { + return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: timestamp }))) + } + + if timestamp > max_time { + return Err(From::from(BlockError::TemporarilyInvalid(OutOfBounds { max: Some(max_time), min: None, found: timestamp }))) } } + Ok(()) } /// Check header parameters agains parent header. -fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> { +fn verify_parent(header: &Header, parent: &Header, gas_limit_divisor: U256) -> Result<(), Error> { if !header.parent_hash().is_zero() && &parent.hash() != header.parent_hash() { return Err(From::from(BlockError::InvalidParentHash(Mismatch { expected: parent.hash(), found: header.parent_hash().clone() }))) } @@ -245,6 +312,18 @@ fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> { if header.number() != parent.number() + 1 { return Err(From::from(BlockError::InvalidNumber(Mismatch { expected: parent.number() + 1, found: header.number() }))); } + + if header.number() == 0 { + return Err(BlockError::RidiculousNumber(OutOfBounds { min: Some(1), max: None, found: header.number() }).into()); + } + + let parent_gas_limit = *parent.gas_limit(); + let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor; + let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor; + if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas { + return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() }))); + } + Ok(()) } @@ -252,11 +331,11 @@ fn verify_parent(header: &Header, parent: &Header) -> Result<(), Error> { fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: &H256) -> Result<(), Error> { let block = UntrustedRlp::new(block); let tx = block.at(1)?; - let expected_root = &ordered_trie_root(tx.iter().map(|r| r.as_raw().to_vec())); //TODO: get rid of vectors here + let expected_root = &ordered_trie_root(tx.iter().map(|r| r.as_raw())); if expected_root != transactions_root { return Err(From::from(BlockError::InvalidTransactionsRoot(Mismatch { expected: expected_root.clone(), found: transactions_root.clone() }))) } - let expected_uncles = &block.at(2)?.as_raw().sha3(); + let expected_uncles = &keccak(block.at(2)?.as_raw()); if expected_uncles != uncles_hash { return Err(From::from(BlockError::InvalidUnclesHash(Mismatch { expected: expected_uncles.clone(), found: uncles_hash.clone() }))) } @@ -265,23 +344,23 @@ fn verify_block_integrity(block: &[u8], transactions_root: &H256, uncles_hash: & #[cfg(test)] mod tests { + use super::*; + use std::collections::{BTreeMap, HashMap}; - use util::*; - use ethkey::{Random, Generator}; - use header::*; - use verification::*; - use blockchain::extras::*; - use error::*; + use std::time::{SystemTime, UNIX_EPOCH}; + use ethereum_types::{H256, Bloom, U256}; + use blockchain::{BlockDetails, TransactionAddress, BlockReceipts}; + use encoded; + use hash::keccak; + use engines::EthEngine; use error::BlockError::*; - use views::*; - use blockchain::*; - use engines::Engine; - use spec::*; - use transaction::*; - use tests::helpers::*; + use ethkey::{Random, Generator}; + use spec::{CommonParams, Spec}; + use tests::helpers::{create_test_block_with_data, create_test_block}; + use transaction::{SignedTransaction, Transaction, UnverifiedTransaction, Action}; use types::log_entry::{LogEntry, LocalizedLogEntry}; - use time::get_time; - use encoded; + use rlp; + use triehash::ordered_trie_root; fn check_ok(result: Result<(), Error>) { result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e)); @@ -295,11 +374,13 @@ mod tests { } } - fn check_fail_timestamp(result: Result<(), Error>) { + fn check_fail_timestamp(result: Result<(), Error>, temp: bool) { + let name = if temp { "TemporarilyInvalid" } else { "InvalidTimestamp" }; match result { - Err(Error::Block(BlockError::InvalidTimestamp(_))) => (), - Err(other) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: {:?}", other), - Ok(_) => panic!("Block verification failed.\nExpected: InvalidTimestamp\nGot: Ok"), + Err(Error::Block(BlockError::InvalidTimestamp(_))) if !temp => (), + Err(Error::Block(BlockError::TemporarilyInvalid(_))) if temp => (), + Err(other) => panic!("Block verification failed.\nExpected: {}\nGot: {:?}", name, other), + Ok(_) => panic!("Block verification failed.\nExpected: {}\nGot: Ok", name), } } @@ -324,7 +405,7 @@ mod tests { pub fn insert(&mut self, bytes: Bytes) { let number = BlockView::new(&bytes).header_view().number(); - let hash = BlockView::new(&bytes).header_view().sha3(); + let hash = BlockView::new(&bytes).header_view().hash(); self.blocks.insert(hash.clone(), bytes); self.numbers.insert(number, hash.clone()); } @@ -382,39 +463,79 @@ mod tests { self.numbers.get(&index).cloned() } - fn blocks_with_bloom(&self, _bloom: &H2048, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec { + fn block_receipts(&self, _hash: &H256) -> Option { unimplemented!() } - fn block_receipts(&self, _hash: &H256) -> Option { + fn blocks_with_bloom(&self, _bloom: &Bloom, _from_block: BlockNumber, _to_block: BlockNumber) -> Vec { unimplemented!() } - fn logs(&self, _blocks: Vec, _matches: F, _limit: Option) -> Vec where F: Fn(&LogEntry) -> bool, Self: Sized { unimplemented!() } } - fn basic_test(bytes: &[u8], engine: &Engine) -> Result<(), Error> { + fn basic_test(bytes: &[u8], engine: &EthEngine) -> Result<(), Error> { let header = BlockView::new(bytes).header(); verify_block_basic(&header, bytes, engine) } - fn family_test(bytes: &[u8], engine: &Engine, bc: &BC) -> Result<(), Error> where BC: BlockProvider { - let header = BlockView::new(bytes).header(); - verify_block_family(&header, bytes, engine, bc) + fn family_test(bytes: &[u8], engine: &EthEngine, bc: &BC) -> Result<(), Error> where BC: BlockProvider { + let view = BlockView::new(bytes); + let header = view.header(); + let transactions: Vec<_> = view.transactions() + .into_iter() + .map(SignedTransaction::new) + .collect::>()?; + + // TODO: client is really meant to be used for state query here by machine + // additions that need access to state (tx filter in specific) + // no existing tests need access to test, so having this not function + // is fine. + let client = ::client::TestBlockChainClient::default(); + + let parent = bc.block_header(header.parent_hash()) + .ok_or(BlockError::UnknownParent(header.parent_hash().clone()))?; + + let full_params = FullFamilyParams { + block_bytes: bytes, + transactions: &transactions[..], + block_provider: bc as &BlockProvider, + client: &client, + }; + verify_block_family(&header, &parent, engine, Some(full_params)) } - fn unordered_test(bytes: &[u8], engine: &Engine) -> Result<(), Error> { + fn unordered_test(bytes: &[u8], engine: &EthEngine) -> Result<(), Error> { let header = BlockView::new(bytes).header(); verify_block_unordered(header, bytes.to_vec(), engine, false)?; Ok(()) } #[test] - #[cfg_attr(feature="dev", allow(similar_names))] + fn test_verify_block_basic_with_invalid_transactions() { + let spec = Spec::new_test(); + let engine = &*spec.engine; + + let block = { + let mut rlp = rlp::RlpStream::new_list(3); + let mut header = Header::default(); + // that's an invalid transaction list rlp + let invalid_transactions = vec![vec![0u8]]; + header.set_transactions_root(ordered_trie_root(&invalid_transactions)); + header.set_gas_limit(engine.params().min_gas_limit); + rlp.append(&header); + rlp.append_list::, _>(&invalid_transactions); + rlp.append_raw(&rlp::EMPTY_LIST_RLP, 1); + rlp.out() + }; + + assert!(basic_test(&block, engine).is_err()); + } + + #[test] fn test_verify_block() { use rlp::RlpStream; @@ -482,8 +603,8 @@ mod tests { let good_uncles = vec![ good_uncle1.clone(), good_uncle2.clone() ]; let mut uncles_rlp = RlpStream::new(); uncles_rlp.append_list(&good_uncles); - let good_uncles_hash = uncles_rlp.as_raw().sha3(); - let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| ::rlp::encode::(t).into_vec())); + let good_uncles_hash = keccak(uncles_rlp.as_raw()); + let good_transactions_root = ordered_trie_root(good_transactions.iter().map(|t| ::rlp::encode::(t))); let mut parent = good.clone(); parent.set_number(9); @@ -559,11 +680,17 @@ mod tests { header = good.clone(); header.set_timestamp(2450000000); - check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine)); + check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine), false); header = good.clone(); - header.set_timestamp(get_time().sec as u64 + 40); - check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine)); + header.set_timestamp(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 20); + check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine), true); + + header = good.clone(); + header.set_timestamp(SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() + 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); @@ -574,13 +701,22 @@ 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() ]; check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &bad_uncles), engine, &bc), DuplicateUncle(good_uncle1.hash())); + header = good.clone(); + header.set_gas_limit(0.into()); + header.set_difficulty("0000000000000000000000000000000000000000000000000000000000020000".parse::().unwrap()); + match family_test(&create_test_block(&header), engine, &bc) { + Err(Error::Block(InvalidGasLimit(_))) => {}, + Err(_) => { panic!("should be invalid difficulty fail"); }, + _ => { panic!("Should be error, got Ok"); }, + } + // TODO: some additional uncle checks } @@ -588,6 +724,7 @@ mod tests { fn dust_protection() { use ethkey::{Generator, Random}; use transaction::{Transaction, Action}; + use machine::EthereumMachine; use engines::NullEngine; let mut params = CommonParams::default(); @@ -609,7 +746,8 @@ mod tests { let good_transactions = [bad_transactions[0].clone(), bad_transactions[1].clone()]; - let engine = NullEngine::new(params, BTreeMap::new()); + let machine = EthereumMachine::regular(params, BTreeMap::new()); + let engine = NullEngine::new(Default::default(), machine); check_fail(unordered_test(&create_test_block_with_data(&header, &bad_transactions, &[]), &engine), TooManyTransactions(keypair.address())); unordered_test(&create_test_block_with_data(&header, &good_transactions, &[]), &engine).unwrap(); } diff --git a/ethcore/src/verification/verifier.rs b/ethcore/src/verification/verifier.rs index 55b711c1c4a469a2b3ada1b46f12f17d295c9be6..a9ca22a4c8aa8534cd7fcb07c112606408cb361e 100644 --- a/ethcore/src/verification/verifier.rs +++ b/ethcore/src/verification/verifier.rs @@ -16,17 +16,27 @@ //! A generic verifier trait. -use blockchain::BlockProvider; -use engines::Engine; +use client::{BlockInfo, CallContract}; +use engines::EthEngine; use error::Error; use header::Header; +use super::verification; /// Should be used to verify blocks. -pub trait Verifier: Send + Sync { +pub trait Verifier: Send + Sync + where C: BlockInfo + CallContract +{ /// Verify a block relative to its parent and uncles. - fn verify_block_family(&self, header: &Header, bytes: &[u8], engine: &Engine, bc: &BlockProvider) -> Result<(), Error>; + fn verify_block_family( + &self, + header: &Header, + parent: &Header, + engine: &EthEngine, + do_full: Option> + ) -> Result<(), Error>; + /// Do a final verification check for an enacted header vs its expected counterpart. fn verify_block_final(&self, expected: &Header, got: &Header) -> Result<(), Error>; /// Verify a block, inspecing external state. - fn verify_block_external(&self, header: &Header, bytes: &[u8], engine: &Engine) -> Result<(), Error>; + fn verify_block_external(&self, header: &Header, engine: &EthEngine) -> Result<(), Error>; } diff --git a/ethcore/src/views/block.rs b/ethcore/src/views/block.rs index f00ca548fd57d28ef9d34759c5c8c909da81de11..c60cc07c5425581304521f05d3f2d59d120d5399 100644 --- a/ethcore/src/views/block.rs +++ b/ethcore/src/views/block.rs @@ -16,11 +16,13 @@ //! View onto block rlp. -use util::*; -use header::*; -use transaction::*; -use super::{TransactionView, HeaderView}; +use bytes::Bytes; +use ethereum_types::H256; +use hash::keccak; +use header::Header; use rlp::Rlp; +use transaction::{UnverifiedTransaction, LocalizedTransaction}; +use views::{TransactionView, HeaderView}; /// View onto block rlp. pub struct BlockView<'a> { @@ -44,7 +46,7 @@ impl<'a> BlockView<'a> { /// Block header hash. pub fn hash(&self) -> H256 { - self.sha3() + self.header_view().hash() } /// Return reference to underlaying rlp. @@ -75,7 +77,7 @@ impl<'a> BlockView<'a> { /// Return List of transactions with additional localization info. pub fn localized_transactions(&self) -> Vec { let header = self.header_view(); - let block_hash = header.sha3(); + let block_hash = header.hash(); let block_number = header.number(); self.transactions() .into_iter() @@ -101,7 +103,7 @@ impl<'a> BlockView<'a> { /// Return transaction hashes. pub fn transaction_hashes(&self) -> Vec { - self.rlp.at(1).iter().map(|rlp| rlp.as_raw().sha3()).collect() + self.rlp.at(1).iter().map(|rlp| keccak(rlp.as_raw())).collect() } /// Returns transaction at given index without deserializing unnecessary data. @@ -112,7 +114,7 @@ impl<'a> BlockView<'a> { /// Returns localized transaction at given index. pub fn localized_transaction_at(&self, index: usize) -> Option { let header = self.header_view(); - let block_hash = header.sha3(); + let block_hash = header.hash(); let block_number = header.number(); self.transaction_at(index).map(|t| LocalizedTransaction { signed: t, @@ -140,7 +142,7 @@ impl<'a> BlockView<'a> { /// Return list of uncle hashes of given block. pub fn uncle_hashes(&self) -> Vec { - self.rlp.at(2).iter().map(|rlp| rlp.as_raw().sha3()).collect() + self.rlp.at(2).iter().map(|rlp| keccak(rlp.as_raw())).collect() } /// Return nth uncle. @@ -154,17 +156,9 @@ impl<'a> BlockView<'a> { } } -impl<'a> Hashable for BlockView<'a> { - fn sha3(&self) -> H256 { - self.header_view().sha3() - } -} - #[cfg(test)] mod tests { - use std::str::FromStr; use rustc_hex::FromHex; - use util::H256; use super::BlockView; #[test] @@ -173,7 +167,7 @@ mod tests { let rlp = "f90261f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23f862f86002018304cb2f94ec0e71ad0a90ffe1909d27dac207f7680abba42d01801ba03a347e72953c860f32b1eb2c78a680d8734b2ea08085d949d729479796f218d5a047ea6239d9e31ccac8af3366f5ca37184d26e7646e3191a3aeb81c4cf74de500c0".from_hex().unwrap(); let view = BlockView::new(&rlp); - assert_eq!(view.hash(), H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259").unwrap()); + assert_eq!(view.hash(), "2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259".into()); assert_eq!(view.transactions_count(), 1); assert_eq!(view.uncles_count(), 0); } diff --git a/ethcore/src/views/body.rs b/ethcore/src/views/body.rs index 038e152b04e74f94f8b2e3e201df1a7c55d1f271..433f7c2b68fd2a124f4134e601d529d59fdac030 100644 --- a/ethcore/src/views/body.rs +++ b/ethcore/src/views/body.rs @@ -16,11 +16,13 @@ //! View onto block body rlp. -use util::*; -use header::*; -use transaction::*; -use super::{TransactionView, HeaderView}; +use bytes::Bytes; +use ethereum_types::H256; +use hash::keccak; +use header::{Header, BlockNumber}; use rlp::Rlp; +use transaction::{LocalizedTransaction, UnverifiedTransaction}; +use views::{TransactionView, HeaderView}; /// View onto block rlp. pub struct BodyView<'a> { @@ -78,7 +80,7 @@ impl<'a> BodyView<'a> { /// Return transaction hashes. pub fn transaction_hashes(&self) -> Vec { - self.rlp.at(0).iter().map(|rlp| rlp.as_raw().sha3()).collect() + self.rlp.at(0).iter().map(|rlp| keccak(rlp.as_raw())).collect() } /// Returns transaction at given index without deserializing unnecessary data. @@ -114,7 +116,7 @@ impl<'a> BodyView<'a> { /// Return list of uncle hashes of given block. pub fn uncle_hashes(&self) -> Vec { - self.rlp.at(1).iter().map(|rlp| rlp.as_raw().sha3()).collect() + self.rlp.at(1).iter().map(|rlp| keccak(rlp.as_raw())).collect() } /// Return nth uncle. @@ -144,4 +146,3 @@ mod tests { assert_eq!(view.uncles_count(), 0); } } - diff --git a/ethcore/src/views/header.rs b/ethcore/src/views/header.rs index 4506d98ec2c664832d0d2ad827f484979abd5519..cce4eee82814620a931f8c986d2b047342cd599f 100644 --- a/ethcore/src/views/header.rs +++ b/ethcore/src/views/header.rs @@ -16,9 +16,11 @@ //! View onto block header rlp -use util::{U256, Bytes, Hashable, H256, Address, H2048}; -use rlp::Rlp; +use bytes::Bytes; +use ethereum_types::{H256, Bloom, U256, Address}; +use hash::keccak; use header::BlockNumber; +use rlp::{self, Rlp}; /// View onto block header rlp. pub struct HeaderView<'a> { @@ -41,7 +43,9 @@ impl<'a> HeaderView<'a> { } /// Returns header hash. - pub fn hash(&self) -> H256 { self.sha3() } + pub fn hash(&self) -> H256 { + keccak(self.rlp.as_raw()) + } /// Returns raw rlp. pub fn rlp(&self) -> &Rlp<'a> { &self.rlp } @@ -65,7 +69,7 @@ impl<'a> HeaderView<'a> { pub fn receipts_root(&self) -> H256 { self.rlp.val_at(5) } /// Returns block log bloom. - pub fn log_bloom(&self) -> H2048 { self.rlp.val_at(6) } + pub fn log_bloom(&self) -> Bloom { self.rlp.val_at(6) } /// Returns block difficulty. pub fn difficulty(&self) -> U256 { self.rlp.val_at(7) } @@ -93,19 +97,20 @@ impl<'a> HeaderView<'a> { } seal } -} -impl<'a> Hashable for HeaderView<'a> { - fn sha3(&self) -> H256 { - self.rlp.as_raw().sha3() + /// Returns a vector of seal fields (RLP-decoded). + pub fn decode_seal(&self) -> Result, rlp::DecoderError> { + let seal = self.seal(); + seal.into_iter() + .map(|s| rlp::UntrustedRlp::new(&s).data().map(|x| x.to_vec())) + .collect() } } #[cfg(test)] mod tests { - use std::str::FromStr; use rustc_hex::FromHex; - use util::{H256, Address, H2048, U256}; + use ethereum_types::Bloom; use super::HeaderView; #[test] @@ -116,18 +121,18 @@ mod tests { let nonce = "88ab4e252a7e8c2a23".from_hex().unwrap(); let view = HeaderView::new(&rlp); - assert_eq!(view.hash(), H256::from_str("2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259").unwrap()); - assert_eq!(view.parent_hash(), H256::from_str("d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7").unwrap()); - assert_eq!(view.uncles_hash(), H256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap()); - assert_eq!(view.author(), Address::from_str("8888f1f195afa192cfee860698584c030f4c9db1").unwrap()); - assert_eq!(view.state_root(), H256::from_str("5fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25").unwrap()); - assert_eq!(view.transactions_root(), H256::from_str("88d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158").unwrap()); - assert_eq!(view.receipts_root(), H256::from_str("07c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1").unwrap()); - assert_eq!(view.log_bloom(), H2048::default()); - assert_eq!(view.difficulty(), U256::from(0x02_00_80)); + assert_eq!(view.hash(), "2c9747e804293bd3f1a986484343f23bc88fd5be75dfe9d5c2860aff61e6f259".into()); + assert_eq!(view.parent_hash(), "d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7".into()); + assert_eq!(view.uncles_hash(), "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347".into()); + assert_eq!(view.author(), "8888f1f195afa192cfee860698584c030f4c9db1".into()); + assert_eq!(view.state_root(), "5fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25".into()); + assert_eq!(view.transactions_root(), "88d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158".into()); + assert_eq!(view.receipts_root(), "07c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1".into()); + assert_eq!(view.log_bloom(), Bloom::default()); + assert_eq!(view.difficulty(), 0x020080.into()); assert_eq!(view.number(), 3); - assert_eq!(view.gas_limit(), U256::from(0x2f_ef_ba)); - assert_eq!(view.gas_used(), U256::from(0x52_4d)); + assert_eq!(view.gas_limit(), 0x2fefba.into()); + assert_eq!(view.gas_used(), 0x524d.into()); assert_eq!(view.timestamp(), 0x56_8e_93_2a); assert_eq!(view.extra_data(), vec![] as Vec); assert_eq!(view.seal(), vec![mix_hash, nonce]); diff --git a/ethcore/src/views/mod.rs b/ethcore/src/views/mod.rs index 4e6ae34d213273a13420f5b708a842f0dc3dc557..5d3cc8cdccd78fa398272c768feb3197b8807d3a 100644 --- a/ethcore/src/views/mod.rs +++ b/ethcore/src/views/mod.rs @@ -17,11 +17,11 @@ //! Block oriented views onto rlp. mod block; +mod body; mod header; mod transaction; -mod body; pub use self::block::BlockView; -pub use self::header::HeaderView; pub use self::body::BodyView; +pub use self::header::HeaderView; pub use self::transaction::TransactionView; diff --git a/ethcore/src/views/transaction.rs b/ethcore/src/views/transaction.rs index 11c7fc2f17ecc9b61c818e2a98a50af2359bddaf..92bd49c276835d33776ea6db85a798997ba24238 100644 --- a/ethcore/src/views/transaction.rs +++ b/ethcore/src/views/transaction.rs @@ -15,7 +15,9 @@ // along with Parity. If not, see . //! View onto transaction rlp -use util::{U256, Bytes, Hashable, H256}; +use bytes::Bytes; +use ethereum_types::{H256, U256}; +use hash::keccak; use rlp::Rlp; /// View onto transaction rlp. @@ -43,6 +45,11 @@ impl<'a> TransactionView<'a> { &self.rlp } + /// Returns transaction hash. + pub fn hash(&self) -> H256 { + keccak(self.rlp.as_raw()) + } + /// Get the nonce field of the transaction. pub fn nonce(&self) -> U256 { self.rlp.val_at(0) } @@ -68,17 +75,9 @@ impl<'a> TransactionView<'a> { pub fn s(&self) -> U256 { self.rlp.val_at(8) } } -impl<'a> Hashable for TransactionView<'a> { - fn sha3(&self) -> H256 { - self.rlp.as_raw().sha3() - } -} - #[cfg(test)] mod tests { - use std::str::FromStr; use rustc_hex::FromHex; - use util::U256; use super::TransactionView; #[test] @@ -86,13 +85,13 @@ mod tests { let rlp = "f87c80018261a894095e7baea6a6c7c4c2dfeb977efac326af552d870a9d00000000000000000000000000000000000000000000000000000000001ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".from_hex().unwrap(); let view = TransactionView::new(&rlp); - assert_eq!(view.nonce(), U256::from(0)); - assert_eq!(view.gas_price(), U256::from(1)); - assert_eq!(view.gas(), U256::from(0x61a8)); - assert_eq!(view.value(), U256::from(0xa)); + assert_eq!(view.nonce(), 0.into()); + assert_eq!(view.gas_price(), 1.into()); + assert_eq!(view.gas(), 0x61a8.into()); + assert_eq!(view.value(), 0xa.into()); assert_eq!(view.data(), "0000000000000000000000000000000000000000000000000000000000".from_hex().unwrap()); - assert_eq!(view.r(), U256::from_str("48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353").unwrap()); - assert_eq!(view.s(), U256::from_str("efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); + assert_eq!(view.r(), "48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353".into()); + assert_eq!(view.s(), "efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804".into()); assert_eq!(view.v(), 0x1b); } } diff --git a/ethcore/transaction/Cargo.toml b/ethcore/transaction/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..7b45cae479b5b6dea4fb92fb2d00fef4b51a65b6 --- /dev/null +++ b/ethcore/transaction/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "ethcore-transaction" +description = "Transaction type" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +ethjson = { path = "../../json" } +ethkey = { path = "../../ethkey" } +evm = { path = "../evm" } +heapsize = "0.4" +keccak-hash = { path = "../../util/hash" } +rlp = { path = "../../util/rlp" } +unexpected = { path = "../../util/unexpected" } +ethereum-types = "0.2" + +[dev-dependencies] +rustc-hex= "1.0" + +[features] +json-tests = [] diff --git a/ethcore/transaction/src/error.rs b/ethcore/transaction/src/error.rs new file mode 100644 index 0000000000000000000000000000000000000000..4578b88acd040f8cc83055e89808ee286b91db70 --- /dev/null +++ b/ethcore/transaction/src/error.rs @@ -0,0 +1,114 @@ +// 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 . + +use std::fmt; + +use ethereum_types::U256; +use ethkey; +use unexpected::OutOfBounds; + +#[derive(Debug, PartialEq, Clone)] +/// Errors concerning transaction processing. +pub enum Error { + /// Transaction is already imported to the queue + AlreadyImported, + /// Transaction is not valid anymore (state already has higher nonce) + Old, + /// Transaction has too low fee + /// (there is already a transaction with the same sender-nonce but higher gas price) + TooCheapToReplace, + /// Transaction was not imported to the queue because limit has been reached. + LimitReached, + /// Transaction's gas price is below threshold. + InsufficientGasPrice { + /// Minimal expected gas price + minimal: U256, + /// Transaction gas price + got: U256, + }, + /// Transaction's gas is below currently set minimal gas requirement. + InsufficientGas { + /// Minimal expected gas + minimal: U256, + /// Transaction gas + got: U256, + }, + /// Sender doesn't have enough funds to pay for this transaction + InsufficientBalance { + /// Senders balance + balance: U256, + /// Transaction cost + cost: U256, + }, + /// Transactions gas is higher then current gas limit + GasLimitExceeded { + /// Current gas limit + limit: U256, + /// Declared transaction gas + got: U256, + }, + /// Transaction's gas limit (aka gas) is invalid. + InvalidGasLimit(OutOfBounds), + /// Transaction sender is banned. + SenderBanned, + /// Transaction receipient is banned. + RecipientBanned, + /// Contract creation code is banned. + CodeBanned, + /// Invalid chain ID given. + InvalidChainId, + /// Not enough permissions given by permission contract. + NotAllowed, + /// Signature error + InvalidSignature(String), +} + +impl From for Error { + fn from(err: ethkey::Error) -> Self { + Error::InvalidSignature(format!("{}", err)) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Error::*; + let msg = match *self { + AlreadyImported => "Already imported".into(), + Old => "No longer valid".into(), + TooCheapToReplace => "Gas price too low to replace".into(), + LimitReached => "Transaction limit reached".into(), + InsufficientGasPrice { minimal, got } => + format!("Insufficient gas price. Min={}, Given={}", minimal, got), + InsufficientGas { minimal, got } => + format!("Insufficient gas. Min={}, Given={}", minimal, got), + InsufficientBalance { balance, cost } => + format!("Insufficient balance for transaction. Balance={}, Cost={}", + balance, cost), + GasLimitExceeded { limit, got } => + format!("Gas limit exceeded. Limit={}, Given={}", limit, got), + InvalidGasLimit(ref err) => format!("Invalid gas limit. {}", err), + SenderBanned => "Sender is temporarily banned.".into(), + RecipientBanned => "Recipient is temporarily banned.".into(), + CodeBanned => "Contract code is temporarily banned.".into(), + InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), + InvalidSignature(ref err) => format!("Transaction has invalid signature: {}.", err), + NotAllowed => "Sender does not have permissions to execute this type of transction".into(), + }; + + f.write_fmt(format_args!("Transaction error ({})", msg)) + } +} + diff --git a/js/src/modals/DeployContract/index.js b/ethcore/transaction/src/lib.rs similarity index 56% rename from js/src/modals/DeployContract/index.js rename to ethcore/transaction/src/lib.rs index 81cd843a91b059d2947392ad6e7e3091a97f9b3a..6d6c269f30ca7797f44df606913dae255e41e2ac 100644 --- a/js/src/modals/DeployContract/index.js +++ b/ethcore/transaction/src/lib.rs @@ -14,4 +14,33 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export default from './deployContract'; +//! Ethereum Transactions + +extern crate ethereum_types; +extern crate ethjson; +extern crate ethkey; +extern crate evm; +extern crate heapsize; +extern crate keccak_hash as hash; +extern crate rlp; +extern crate unexpected; + +#[cfg(test)] +extern crate rustc_hex; + +mod error; +mod transaction; + +pub use error::Error; +pub use transaction::*; + +// TODO [ToDr] Move to miner! + +/// Represents the result of importing transaction. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ImportResult { + /// Transaction was imported to current queue. + Current, + /// Transaction was imported to future queue. + Future +} diff --git a/ethcore/src/transaction.rs b/ethcore/transaction/src/transaction.rs similarity index 89% rename from ethcore/src/transaction.rs rename to ethcore/transaction/src/transaction.rs index 0bd61dcebc3bf133cd02af181113ba644049359b..f206c549a7cd17433bc16a3e9b4452d2d7e9edf1 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/transaction/src/transaction.rs @@ -17,20 +17,24 @@ //! Transaction data structure. use std::ops::Deref; -use rlp::*; -use util::sha3::Hashable; -use util::{H256, Address, U256, Bytes, HeapSizeOf}; -use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError}; -use error::*; -use evm::Schedule; -use header::BlockNumber; +use ethereum_types::{H256, H160, Address, U256}; +use error; use ethjson; +use ethkey::{self, Signature, Secret, Public, recover, public_to_address}; +use evm::Schedule; +use hash::keccak; +use heapsize::HeapSizeOf; +use rlp::{self, RlpStream, UntrustedRlp, DecoderError, Encodable}; +// use rlp::*; + +type Bytes = Vec; +type BlockNumber = u64; /// Fake address for unsigned transactions as defined by EIP-86. -pub const UNSIGNED_SENDER: Address = ::util::H160([0xff; 20]); +pub const UNSIGNED_SENDER: Address = H160([0xff; 20]); /// System sender address for internal state updates. -pub const SYSTEM_ADDRESS: Address = ::util::H160([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xfe]); +pub const SYSTEM_ADDRESS: Address = H160([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xfe]); /// Transaction action type. #[derive(Debug, Clone, PartialEq, Eq)] @@ -46,7 +50,7 @@ impl Default for Action { fn default() -> Action { Action::Create } } -impl Decodable for Action { +impl rlp::Decodable for Action { fn decode(rlp: &UntrustedRlp) -> Result { if rlp.is_empty() { Ok(Action::Create) @@ -56,7 +60,7 @@ impl Decodable for Action { } } -impl Encodable for Action { +impl rlp::Encodable for Action { fn rlp_append(&self, s: &mut RlpStream) { match *self { Action::Create => s.append_internal(&""), @@ -166,7 +170,7 @@ impl Transaction { pub fn hash(&self, chain_id: Option) -> H256 { let mut stream = RlpStream::new(); self.rlp_append_unsigned_transaction(&mut stream, chain_id); - stream.as_raw().sha3() + keccak(stream.as_raw()) } /// Signs the transaction as coming from `sender`. @@ -268,12 +272,12 @@ impl Deref for UnverifiedTransaction { } } -impl Decodable for UnverifiedTransaction { +impl rlp::Decodable for UnverifiedTransaction { fn decode(d: &UntrustedRlp) -> Result { if d.item_count()? != 9 { return Err(DecoderError::RlpIncorrectListLen); } - let hash = d.as_raw().sha3(); + let hash = keccak(d.as_raw()); Ok(UnverifiedTransaction { unsigned: Transaction { nonce: d.val_at(0)?, @@ -291,14 +295,14 @@ impl Decodable for UnverifiedTransaction { } } -impl Encodable for UnverifiedTransaction { +impl rlp::Encodable for UnverifiedTransaction { fn rlp_append(&self, s: &mut RlpStream) { self.rlp_append_sealed_transaction(s) } } impl UnverifiedTransaction { /// Used to compute hash of created transactions fn compute_hash(mut self) -> UnverifiedTransaction { - let hash = (&*self.rlp_bytes()).sha3(); + let hash = keccak(&*self.rlp_bytes()); self.hash = hash; self } @@ -348,53 +352,54 @@ impl UnverifiedTransaction { } /// Checks whether the signature has a low 's' value. - pub fn check_low_s(&self) -> Result<(), Error> { + pub fn check_low_s(&self) -> Result<(), ethkey::Error> { if !self.signature().is_low_s() { - Err(EthkeyError::InvalidSignature.into()) + Err(ethkey::Error::InvalidSignature.into()) } else { Ok(()) } } - /// Get the hash of this header (sha3 of the RLP). + /// Get the hash of this header (keccak of the RLP). pub fn hash(&self) -> H256 { self.hash } /// Recovers the public key of the sender. - pub fn recover_public(&self) -> Result { + pub fn recover_public(&self) -> Result { Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?) } /// Do basic validation, checking for valid signature and minimum gas, // TODO: consider use in block validation. - #[cfg(test)] #[cfg(feature = "json-tests")] - pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) -> Result { + pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) + -> Result + { let chain_id = if allow_chain_id_of_one { Some(1) } else { None }; self.verify_basic(require_low, chain_id, allow_empty_signature)?; if !allow_empty_signature || !self.is_unsigned() { self.recover_public()?; } if self.gas < U256::from(self.gas_required(&schedule)) { - return Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) + return Err(error::Error::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) } Ok(self) } /// Verify basic signature params. Does not attempt sender recovery. - pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), Error> { + pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), error::Error> { if check_low_s && !(allow_empty_signature && self.is_unsigned()) { self.check_low_s()?; } // EIP-86: Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account 0. if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) { - return Err(EthkeyError::InvalidSignature.into()) + return Err(ethkey::Error::InvalidSignature.into()) } match (self.chain_id(), chain_id) { (None, _) => {}, (Some(n), Some(m)) if n == m => {}, - _ => return Err(TransactionError::InvalidChainId.into()), + _ => return Err(error::Error::InvalidChainId), }; Ok(()) } @@ -414,7 +419,7 @@ impl HeapSizeOf for SignedTransaction { } } -impl Encodable for SignedTransaction { +impl rlp::Encodable for SignedTransaction { fn rlp_append(&self, s: &mut RlpStream) { self.transaction.rlp_append_sealed_transaction(s) } } @@ -433,7 +438,7 @@ impl From for UnverifiedTransaction { impl SignedTransaction { /// Try to verify transaction and recover sender. - pub fn new(transaction: UnverifiedTransaction) -> Result { + pub fn new(transaction: UnverifiedTransaction) -> Result { if transaction.is_unsigned() { Ok(SignedTransaction { transaction: transaction, @@ -465,6 +470,11 @@ impl SignedTransaction { pub fn is_unsigned(&self) -> bool { self.transaction.is_unsigned() } + + /// Deconstructs this transaction back into `UnverifiedTransaction` + pub fn deconstruct(self) -> (UnverifiedTransaction, Address, Option) { + (self.transaction, self.sender, self.public) + } } /// Signed Transaction that is a part of canon blockchain. @@ -544,11 +554,12 @@ impl From for PendingTransaction { #[cfg(test)] mod tests { use super::*; - use util::{Hashable, U256}; + use ethereum_types::U256; + use hash::keccak; #[test] fn sender_test() { - let t: UnverifiedTransaction = decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); + let t: UnverifiedTransaction = rlp::decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); assert_eq!(t.data, b""); assert_eq!(t.gas, U256::from(0x5208u64)); assert_eq!(t.gas_price, U256::from(0x01u64)); @@ -574,7 +585,7 @@ mod tests { value: U256::from(1), data: b"Hello!".to_vec() }.sign(&key.secret(), None); - assert_eq!(Address::from(key.public().sha3()), t.sender()); + assert_eq!(Address::from(keccak(key.public())), t.sender()); assert_eq!(t.chain_id(), None); } @@ -608,7 +619,7 @@ mod tests { value: U256::from(1), data: b"Hello!".to_vec() }.sign(&key.secret(), Some(69)); - assert_eq!(Address::from(key.public().sha3()), t.sender()); + assert_eq!(Address::from(keccak(key.public())), t.sender()); assert_eq!(t.chain_id(), Some(69)); } @@ -617,10 +628,10 @@ mod tests { use rustc_hex::FromHex; let test_vector = |tx_data: &str, address: &'static str| { - let signed = decode(&FromHex::from_hex(tx_data).unwrap()); + let signed = rlp::decode(&FromHex::from_hex(tx_data).unwrap()); let signed = SignedTransaction::new(signed).unwrap(); assert_eq!(signed.sender(), address.into()); - flushln!("chainid: {:?}", signed.chain_id()); + println!("chainid: {:?}", signed.chain_id()); }; test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce"); diff --git a/ethcore/types/Cargo.toml b/ethcore/types/Cargo.toml index 82963f960973cab94f83a92499aab97b4881a222..a14929f47edbc3332c4edfbb4fe6fc3f3568fec3 100644 --- a/ethcore/types/Cargo.toml +++ b/ethcore/types/Cargo.toml @@ -7,9 +7,11 @@ authors = ["Parity Technologies "] [dependencies] rlp = { path = "../../util/rlp" } rlp_derive = { path = "../../util/rlp_derive" } -ethcore-util = { path = "../../util" } +ethcore-bytes = { path = "../../util/bytes" } +ethereum-types = "0.2" ethjson = { path = "../../json" } -bloomable = { path = "../../util/bloomable" } +keccak-hash = { path = "../../util/hash" } +heapsize = "0.4" [dev-dependencies] rustc-hex= "1.0" diff --git a/ethcore/types/src/account_diff.rs b/ethcore/types/src/account_diff.rs index 337c5df1bfcd730a0a34a10fe76d6b0672549102..c3edb1fb1e3d18186346306dcfeacf5b207b4e24 100644 --- a/ethcore/types/src/account_diff.rs +++ b/ethcore/types/src/account_diff.rs @@ -19,7 +19,8 @@ use std::cmp::*; use std::fmt; use std::collections::BTreeMap; -use util::{U256, H256, Bytes}; +use ethereum_types::{H256, U256}; +use bytes::Bytes; #[derive(Debug, PartialEq, Eq, Clone)] /// Diff type for specifying a change (or not). @@ -49,7 +50,6 @@ impl Diff where T: Eq { } #[derive(Debug, PartialEq, Eq, Clone)] -#[cfg_attr(feature = "ipc", binary)] /// Account diff. pub struct AccountDiff { /// Change in balance, allowed to be `Diff::Same`. @@ -63,7 +63,6 @@ pub struct AccountDiff { } #[derive(Debug, PartialEq, Eq, Clone)] -#[cfg_attr(feature = "ipc", binary)] /// Change in existance type. // TODO: include other types of change. pub enum Existance { @@ -112,7 +111,7 @@ fn interpreted_hash(u: &H256) -> String { impl fmt::Display for AccountDiff { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use util::bytes::ToPretty; + use bytes::ToPretty; match self.nonce { Diff::Born(ref x) => write!(f, " non {}", x)?, diff --git a/ethcore/types/src/basic_account.rs b/ethcore/types/src/basic_account.rs index f30872f6b3e5c686251379329bf9c2a4ddb4b84c..79e75dfc0144a72176fd1211df57111524598e90 100644 --- a/ethcore/types/src/basic_account.rs +++ b/ethcore/types/src/basic_account.rs @@ -16,7 +16,7 @@ //! Basic account type -- the decoded RLP from the state trie. -use util::{U256, H256}; +use ethereum_types::{U256, H256}; /// Basic account type. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] diff --git a/ethcore/types/src/blockchain_info.rs b/ethcore/types/src/blockchain_info.rs index 4ab1432b7be9913bcf185e0acfb17809ca40f16d..836ee7618bd7f0ac5b18ec13ee1da34c888190e9 100644 --- a/ethcore/types/src/blockchain_info.rs +++ b/ethcore/types/src/blockchain_info.rs @@ -18,7 +18,7 @@ use std::fmt; -use util::{U256, H256}; +use ethereum_types::{U256, H256}; use security_level::SecurityLevel; use {BlockNumber}; diff --git a/ethcore/types/src/filter.rs b/ethcore/types/src/filter.rs index 6e344b4efb4b63b1651c63c54e5e328ebca236f7..0a37482b94e66aaf23b8ed3e4375e30ffa5a7aab 100644 --- a/ethcore/types/src/filter.rs +++ b/ethcore/types/src/filter.rs @@ -16,8 +16,7 @@ //! Blockchain filter -use util::{Address, H256, Hashable, H2048}; -use bloomable::Bloomable; +use ethereum_types::{H256, Address, Bloom, BloomInput}; use ids::BlockId; use log_entry::LogEntry; @@ -73,15 +72,13 @@ impl Clone for Filter { impl Filter { /// Returns combinations of each address and topic. - pub fn bloom_possibilities(&self) -> Vec { + pub fn bloom_possibilities(&self) -> Vec { let blooms = match self.address { Some(ref addresses) if !addresses.is_empty() => - addresses.iter().map(|ref address| { - let mut bloom = H2048::default(); - bloom.shift_bloomed(&address.sha3()); - bloom - }).collect(), - _ => vec![H2048::default()] + addresses.iter() + .map(|ref address| Bloom::from(BloomInput::Raw(address))) + .collect(), + _ => vec![Bloom::default()] }; self.topics.iter().fold(blooms, |bs, topic| match *topic { @@ -89,9 +86,9 @@ impl Filter { Some(ref topics) => bs.into_iter().flat_map(|bloom| { topics.into_iter().map(|topic| { let mut b = bloom.clone(); - b.shift_bloomed(&topic.sha3()); + b.accrue(BloomInput::Raw(topic)); b - }).collect::>() + }).collect::>() }).collect() }) } @@ -112,6 +109,7 @@ impl Filter { #[cfg(test)] mod tests { + use ethereum_types::Bloom; use filter::Filter; use ids::BlockId; use log_entry::LogEntry; @@ -148,7 +146,7 @@ mod tests { }; let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities, vec!["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()]); + assert_eq!(possibilities, vec!["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()] as Vec); } #[test] @@ -167,7 +165,7 @@ mod tests { }; let possibilities = filter.bloom_possibilities(); - assert_eq!(possibilities, vec!["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()]); + assert_eq!(possibilities, vec!["00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()] as Vec); } #[test] @@ -197,7 +195,7 @@ mod tests { // number of possibilites should be equal 2 * 2 * 2 * 1 = 8 let possibilities = filter.bloom_possibilities(); assert_eq!(possibilities.len(), 8); - assert_eq!(possibilities[0], "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000".into()); + assert_eq!(possibilities[0], Bloom::from("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000004000000004000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000")); } #[test] diff --git a/ethcore/types/src/ids.rs b/ethcore/types/src/ids.rs index feda18307f32ee92cf68852bd8185c9260449554..e304698a4ca83c01506bc43b1ca1d390340a6f6d 100644 --- a/ethcore/types/src/ids.rs +++ b/ethcore/types/src/ids.rs @@ -16,7 +16,7 @@ //! Unique identifiers. -use util::hash::H256; +use ethereum_types::H256; use {BlockNumber}; /// Uniquely identifies block. @@ -31,8 +31,6 @@ pub enum BlockId { Earliest, /// Latest mined block. Latest, - /// Pending block. - Pending, } /// Uniquely identifies transaction. diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index 10a4ac71ef353055a99068d2d7d549bb4c54f5ba..83a1cc65579e4d8a46b11e42c2d4286011b31bf6 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -16,12 +16,14 @@ //! Types used in the public API -extern crate ethcore_util as util; +extern crate ethereum_types; +extern crate ethcore_bytes as bytes; extern crate ethjson; extern crate rlp; #[macro_use] extern crate rlp_derive; -extern crate bloomable; +extern crate keccak_hash as hash; +extern crate heapsize; #[cfg(test)] extern crate rustc_hex; diff --git a/ethcore/types/src/log_entry.rs b/ethcore/types/src/log_entry.rs index 152b48a0e4d21f63ff1daf74c4d0d55cc18384e1..951a7389f2901b28179c5e85f1ea934f3eb83ec4 100644 --- a/ethcore/types/src/log_entry.rs +++ b/ethcore/types/src/log_entry.rs @@ -17,14 +17,13 @@ //! Log entry type definition. use std::ops::Deref; -use util::{H256, Address, Bytes, HeapSizeOf, Hashable}; -use bloomable::Bloomable; +use heapsize::HeapSizeOf; +use bytes::Bytes; +use ethereum_types::{H256, Address, Bloom, BloomInput}; use {BlockNumber}; use ethjson; -pub type LogBloom = ::util::H2048; - /// A record of execution for a `LOG` operation. #[derive(Default, Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] pub struct LogEntry { @@ -44,8 +43,11 @@ impl HeapSizeOf for LogEntry { impl LogEntry { /// Calculates the bloom of this log entry. - pub fn bloom(&self) -> LogBloom { - self.topics.iter().fold(LogBloom::from_bloomed(&self.address.sha3()), |b, t| b.with_bloomed(&t.sha3())) + pub fn bloom(&self) -> Bloom { + self.topics.iter().fold(Bloom::from(BloomInput::Raw(&self.address)), |mut b, t| { + b.accrue(BloomInput::Raw(t)); + b + }) } } @@ -88,12 +90,12 @@ impl Deref for LocalizedLogEntry { #[cfg(test)] mod tests { - use util::*; + use ethereum_types::{Bloom, Address}; use super::LogEntry; #[test] fn test_empty_log_bloom() { - let bloom = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".parse::().unwrap(); + let bloom = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".parse::().unwrap(); let address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse::
().unwrap(); let log = LogEntry { address: address, diff --git a/ethcore/types/src/receipt.rs b/ethcore/types/src/receipt.rs index 81439ecdf640ac9493186519e5db73936d74348c..29b2e909b9a57ef548a0605c27e21765936d3aae 100644 --- a/ethcore/types/src/receipt.rs +++ b/ethcore/types/src/receipt.rs @@ -16,45 +16,63 @@ //! Receipt -use util::{H256, U256, Address}; -use util::HeapSizeOf; +use ethereum_types::{H256, U256, Address, Bloom}; +use heapsize::HeapSizeOf; use rlp::*; use {BlockNumber}; -use log_entry::{LogBloom, LogEntry, LocalizedLogEntry}; +use log_entry::{LogEntry, LocalizedLogEntry}; + +/// Transaction outcome store in the receipt. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum TransactionOutcome { + /// Status and state root are unknown under EIP-98 rules. + Unknown, + /// State root is known. Pre EIP-98 and EIP-658 rules. + StateRoot(H256), + /// Status code is known. EIP-658 rules. + StatusCode(u8), +} /// Information describing execution of a transaction. -#[derive(Default, Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Receipt { - /// The state root after executing the transaction. Optional since EIP98 - pub state_root: Option, /// The total gas used in the block following execution of the transaction. pub gas_used: U256, /// The OR-wide combination of all logs' blooms for this transaction. - pub log_bloom: LogBloom, + pub log_bloom: Bloom, /// The logs stemming from this transaction. pub logs: Vec, + /// Transaction outcome. + pub outcome: TransactionOutcome, } impl Receipt { /// Create a new receipt. - pub fn new(state_root: Option, gas_used: U256, logs: Vec) -> Receipt { + pub fn new(outcome: TransactionOutcome, gas_used: U256, logs: Vec) -> Receipt { Receipt { - state_root: state_root, gas_used: gas_used, - log_bloom: logs.iter().fold(LogBloom::default(), |mut b, l| { b = &b | &l.bloom(); b }), //TODO: use |= operator + log_bloom: logs.iter().fold(Bloom::default(), |mut b, l| { b = &b | &l.bloom(); b }), //TODO: use |= operator logs: logs, + outcome: outcome, } } } impl Encodable for Receipt { fn rlp_append(&self, s: &mut RlpStream) { - if let Some(ref root) = self.state_root { - s.begin_list(4); - s.append(root); - } else { - s.begin_list(3); + match self.outcome { + TransactionOutcome::Unknown => { + s.begin_list(3); + }, + TransactionOutcome::StateRoot(ref root) => { + s.begin_list(4); + s.append(root); + }, + TransactionOutcome::StatusCode(ref status_code) => { + s.begin_list(4); + s.append(status_code); + }, } s.append(&self.gas_used); s.append(&self.log_bloom); @@ -66,17 +84,24 @@ impl Decodable for Receipt { fn decode(rlp: &UntrustedRlp) -> Result { if rlp.item_count()? == 3 { Ok(Receipt { - state_root: None, + outcome: TransactionOutcome::Unknown, gas_used: rlp.val_at(0)?, log_bloom: rlp.val_at(1)?, logs: rlp.list_at(2)?, }) } else { Ok(Receipt { - state_root: Some(rlp.val_at(0)?), gas_used: rlp.val_at(1)?, log_bloom: rlp.val_at(2)?, logs: rlp.list_at(3)?, + outcome: { + let first = rlp.at(0)?; + if first.is_data() && first.data()?.len() <= 1 { + TransactionOutcome::StatusCode(first.as_val()?) + } else { + TransactionOutcome::StateRoot(first.as_val()?) + } + } }) } } @@ -104,9 +129,9 @@ pub struct RichReceipt { /// Logs pub logs: Vec, /// Logs bloom - pub log_bloom: LogBloom, - /// State root - pub state_root: Option, + pub log_bloom: Bloom, + /// Transaction outcome. + pub outcome: TransactionOutcome, } /// Receipt with additional info. @@ -129,21 +154,21 @@ pub struct LocalizedReceipt { /// Logs pub logs: Vec, /// Logs bloom - pub log_bloom: LogBloom, - /// State root - pub state_root: Option, + pub log_bloom: Bloom, + /// Transaction outcome. + pub outcome: TransactionOutcome, } #[cfg(test)] mod tests { - use super::Receipt; + use super::{Receipt, TransactionOutcome}; use log_entry::LogEntry; #[test] fn test_no_state_root() { let expected = ::rustc_hex::FromHex::from_hex("f9014183040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); let r = Receipt::new( - None, + TransactionOutcome::Unknown, 0x40cae.into(), vec![LogEntry { address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), @@ -158,7 +183,25 @@ mod tests { fn test_basic() { let expected = ::rustc_hex::FromHex::from_hex("f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); let r = Receipt::new( - Some("2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into()), + TransactionOutcome::StateRoot("2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into()), + 0x40cae.into(), + vec![LogEntry { + address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), + topics: vec![], + data: vec![0u8; 32] + }] + ); + let encoded = ::rlp::encode(&r); + assert_eq!(&encoded[..], &expected[..]); + let decoded: Receipt = ::rlp::decode(&encoded); + assert_eq!(decoded, r); + } + + #[test] + fn test_status_code() { + let expected = ::rustc_hex::FromHex::from_hex("f901428083040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); + let r = Receipt::new( + TransactionOutcome::StatusCode(0), 0x40cae.into(), vec![LogEntry { address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), diff --git a/ethcore/types/src/snapshot_manifest.rs b/ethcore/types/src/snapshot_manifest.rs index 2dcce2904fad8f148712e604402bdbde795ddf4e..72f83afeb2829e75d77e37e0ba809bbbcd5a76d7 100644 --- a/ethcore/types/src/snapshot_manifest.rs +++ b/ethcore/types/src/snapshot_manifest.rs @@ -16,9 +16,9 @@ //! Snapshot manifest type definition -use util::hash::H256; +use ethereum_types::H256; use rlp::*; -use util::Bytes; +use bytes::Bytes; /// Manifest data. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/ethcore/types/src/state_diff.rs b/ethcore/types/src/state_diff.rs index af28f550fe02a39a6c08b15537c06dc90834d168..dd976eb36c6938a326f1bc99f0e82f56cf07ee26 100644 --- a/ethcore/types/src/state_diff.rs +++ b/ethcore/types/src/state_diff.rs @@ -19,7 +19,7 @@ use std::fmt; use std::ops::*; use std::collections::BTreeMap; -use util::Address; +use ethereum_types::Address; use account_diff::*; /// Expression for the delta between two system states. Encoded the diff --git a/ethcore/types/src/trace_filter.rs b/ethcore/types/src/trace_filter.rs index 4eed19b4c57fed10ca6648f9ad5924b729eefb89..2afa752ccbb44d054541ea1b20aa1229d944872e 100644 --- a/ethcore/types/src/trace_filter.rs +++ b/ethcore/types/src/trace_filter.rs @@ -17,7 +17,7 @@ //! Trace filter related types use std::ops::Range; -use util::{Address}; +use ethereum_types::Address; use ids::BlockId; /// Easy to use trace filter. @@ -28,4 +28,8 @@ pub struct Filter { pub from_address: Vec
, /// To address. pub to_address: Vec
, + /// Output offset + pub after: Option, + /// Output amount + pub count: Option, } diff --git a/ethcore/types/src/tree_route.rs b/ethcore/types/src/tree_route.rs index a47e94ee5676488adc47e1016880a46166cccb76..b3fe431ab9973bc0279fb8aaf2deeda217ac7f18 100644 --- a/ethcore/types/src/tree_route.rs +++ b/ethcore/types/src/tree_route.rs @@ -16,7 +16,7 @@ //! Tree route info type definition -use util::H256; +use ethereum_types::H256; /// Represents a tree route between `from` block and `to` block: #[derive(Debug)] diff --git a/ethcore/vm/Cargo.toml b/ethcore/vm/Cargo.toml index 50efe936c11c0bb4f5411f6e81bb9d07a67dceca..41ff98d0a056dee2c214dc7f0937b20fe3a8ef94 100644 --- a/ethcore/vm/Cargo.toml +++ b/ethcore/vm/Cargo.toml @@ -5,10 +5,11 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" -ethcore-util = { path = "../../util" } +ethcore-bytes = { path = "../../util/bytes" } +ethereum-types = "0.2" +patricia-trie = { path = "../../util/patricia_trie" } log = "0.3" common-types = { path = "../types" } -evmjit = { path = "../../evmjit", optional = true } ethjson = { path = "../../json" } -lazy_static = "0.2" -rlp = { path = "../../util/rlp" } \ No newline at end of file +rlp = { path = "../../util/rlp" } +keccak-hash = { path = "../../util/hash" } diff --git a/ethcore/vm/src/action_params.rs b/ethcore/vm/src/action_params.rs index 401d7ee57289ecf981d74453709f1023d5fe5897..9e9a35528c89e3247ed07683a86c438bb3a3e45d 100644 --- a/ethcore/vm/src/action_params.rs +++ b/ethcore/vm/src/action_params.rs @@ -15,9 +15,9 @@ // along with Parity. If not, see . //! Evm input params. -use util::{Address, Bytes, U256}; -use util::hash::{H256}; -use util::sha3::{Hashable, SHA3_EMPTY}; +use ethereum_types::{U256, H256, Address}; +use bytes::Bytes; +use hash::{keccak, KECCAK_EMPTY}; use ethjson; use call_type::CallType; @@ -33,6 +33,15 @@ pub enum ActionValue { Apparent(U256) } +/// Type of the way parameters encoded +#[derive(Clone, Debug)] +pub enum ParamsType { + /// Parameters are included in code + Embedded, + /// Parameters are passed in data section + Separate, +} + impl ActionValue { /// Returns action value as U256. pub fn value(&self) -> U256 { @@ -79,7 +88,8 @@ pub struct ActionParams { pub data: Option, /// Type of call pub call_type: CallType, - + /// Param types encoding + pub params_type: ParamsType, } impl Default for ActionParams { @@ -87,7 +97,7 @@ impl Default for ActionParams { fn default() -> ActionParams { ActionParams { code_address: Address::new(), - code_hash: Some(SHA3_EMPTY), + code_hash: Some(KECCAK_EMPTY), address: Address::new(), sender: Address::new(), origin: Address::new(), @@ -97,6 +107,7 @@ impl Default for ActionParams { code: None, data: None, call_type: CallType::None, + params_type: ParamsType::Separate, } } } @@ -106,7 +117,7 @@ impl From for ActionParams { let address: Address = t.address.into(); ActionParams { code_address: Address::new(), - code_hash: Some((&*t.code).sha3()), + code_hash: Some(keccak(&*t.code)), address: address, sender: t.sender.into(), origin: t.origin.into(), @@ -116,6 +127,7 @@ impl From for ActionParams { gas_price: t.gas_price.into(), value: ActionValue::Transfer(t.value.into()), call_type: match address.is_zero() { true => CallType::None, false => CallType::Call }, // TODO @debris is this correct? + params_type: ParamsType::Separate, } } } diff --git a/ethcore/vm/src/env_info.rs b/ethcore/vm/src/env_info.rs index 8634d9c759ef8f5e123edf288d860f1e0ddd4b12..71bb48eeb721383f127866717f6affb093db59d2 100644 --- a/ethcore/vm/src/env_info.rs +++ b/ethcore/vm/src/env_info.rs @@ -18,7 +18,8 @@ use std::cmp; use std::sync::Arc; -use util::{U256, Address, H256, Hashable}; +use hash::keccak; +use ethereum_types::{U256, H256, Address}; use types::BlockNumber; use ethjson; @@ -68,7 +69,7 @@ impl From for EnvInfo { difficulty: e.difficulty.into(), gas_limit: e.gas_limit.into(), timestamp: e.timestamp.into(), - last_hashes: Arc::new((1..cmp::min(number + 1, 257)).map(|i| format!("{}", number - i).as_bytes().sha3()).collect()), + last_hashes: Arc::new((1..cmp::min(number + 1, 257)).map(|i| keccak(format!("{}", number - i).as_bytes())).collect()), gas_used: U256::default(), } } @@ -78,7 +79,7 @@ impl From for EnvInfo { mod tests { use std::str::FromStr; use super::*; - use util::{U256, Address}; + use ethereum_types::{U256, Address}; use ethjson; #[test] diff --git a/ethcore/vm/src/error.rs b/ethcore/vm/src/error.rs index e4b19943830f92fdb7e70bc9d7f1e91bf1882579..fe8d7054cfe1ff8d59490fee0216f1a18dbcc7cf 100644 --- a/ethcore/vm/src/error.rs +++ b/ethcore/vm/src/error.rs @@ -16,7 +16,7 @@ //! VM errors module -use util::trie; +use trie; use std::fmt; /// VM errors. @@ -65,6 +65,10 @@ pub enum Error { Internal(String), /// Wasm runtime error Wasm(String), + /// Out of bounds access in RETURNDATACOPY. + OutOfBounds, + /// Execution has been reverted with REVERT. + Reverted, } @@ -93,6 +97,8 @@ impl fmt::Display for Error { Internal(ref msg) => write!(f, "Internal error: {}", msg), MutableCallInStaticContext => write!(f, "Mutable call in static context"), Wasm(ref msg) => write!(f, "Internal error: {}", msg), + OutOfBounds => write!(f, "Out of bounds"), + Reverted => write!(f, "Reverted"), } } } diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 54871e5119df2140c1d4550e7a0d97682b7dc965..98661e47e2f8d9c6f82de8ad5f254b7b980e3e1c 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -17,7 +17,8 @@ //! Interface for Evm externalities. use std::sync::Arc; -use util::*; +use ethereum_types::{U256, H256, Address}; +use bytes::Bytes; use call_type::CallType; use env_info::EnvInfo; use schedule::Schedule; @@ -31,7 +32,9 @@ pub enum ContractCreateResult { Created(Address, U256), /// Returned when contract creation failed. /// VM doesn't have to know the reason. - Failed + Failed, + /// Reverted with REVERT. + Reverted(U256, ReturnData), } /// Result of externalities call function. @@ -41,7 +44,10 @@ pub enum MessageCallResult { Success(U256, ReturnData), /// Returned when message call failed. /// VM doesn't have to know the reason. - Failed + Failed, + /// Returned when message call was reverted. + /// Contains gas left and output data. + Reverted(U256, ReturnData), } /// Specifies how an address is calculated for a new contract. @@ -88,7 +94,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, @@ -111,7 +116,7 @@ pub trait Ext { /// Should be called when transaction calls `RETURN` opcode. /// Returns gas_left if cost of returning the data is not too high. - fn ret(self, gas: &U256, data: &ReturnData) -> Result; + fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> Result; /// Should be called when contract commits suicide. /// Address to which funds should be refunded. @@ -133,11 +138,14 @@ pub trait Ext { fn inc_sstore_clears(&mut self); /// Decide if any more operations should be traced. Passthrough for the VM trace. - fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { false } + fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } /// Prepare to trace an operation. Passthrough for the VM trace. fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256) {} /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} + + /// Check if running in static context. + fn is_static(&self) -> bool; } diff --git a/ethcore/vm/src/lib.rs b/ethcore/vm/src/lib.rs index 0c9e32dc6630a799a35b34deee605eef6a2fd828..67fc59bab5ec02338738ea39c0bdbd59af10f443 100644 --- a/ethcore/vm/src/lib.rs +++ b/ethcore/vm/src/lib.rs @@ -16,10 +16,13 @@ //! Virtual machines support library -extern crate ethcore_util as util; +extern crate ethereum_types; +extern crate ethcore_bytes as bytes; extern crate common_types as types; extern crate ethjson; extern crate rlp; +extern crate keccak_hash as hash; +extern crate patricia_trie as trie; mod action_params; mod call_type; @@ -31,10 +34,10 @@ mod error; pub mod tests; -pub use action_params::{ActionParams, ActionValue}; +pub use action_params::{ActionParams, ActionValue, ParamsType}; pub use call_type::CallType; pub use env_info::{EnvInfo, LastHashes}; -pub use schedule::{Schedule, CleanDustMode}; +pub use schedule::{Schedule, CleanDustMode, WasmCosts}; pub use ext::{Ext, MessageCallResult, ContractCreateResult, CreateContractAddress}; pub use return_data::{ReturnData, GasLeft}; pub use error::{Error, Result}; @@ -45,4 +48,4 @@ pub trait Vm { /// It returns either an error, a known amount of gas left, or parameters to be used /// to compute the final gas left. fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result; -} \ No newline at end of file +} diff --git a/ethcore/vm/src/return_data.rs b/ethcore/vm/src/return_data.rs index 3c8bd182ff53e9a2cd47849d74c6b73930719eb2..067a26e35e33a5eb3aa0e59a3f2eef3f1b498615 100644 --- a/ethcore/vm/src/return_data.rs +++ b/ethcore/vm/src/return_data.rs @@ -14,7 +14,7 @@ //! Return data structures -use util::U256; +use ethereum_types::U256; /// Return data buffer. Holds memory from a previous call and a slice into that memory. #[derive(Debug)] @@ -65,4 +65,4 @@ pub enum GasLeft { /// Apply or revert state changes on revert. apply_state: bool }, -} \ No newline at end of file +} diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 6966c26e6a576845c453d8be2b9b2c1900307681..6cfabed0df3c4f76acb500648f551f115aa1cbbd 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -111,6 +111,57 @@ pub struct Schedule { pub have_return_data: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, + /// Enable EIP-86 rules + pub eip86: bool, + /// Wasm extra schedule settings, if wasm activated + pub wasm: Option, +} + +/// Wasm cost table +pub struct WasmCosts { + /// Default opcode cost + pub regular: u32, + /// Div operations multiplier. + pub div: u32, + /// Div operations multiplier. + pub mul: u32, + /// Memory (load/store) operations multiplier. + pub mem: u32, + /// General static query of U256 value from env-info + pub static_u256: u32, + /// General static query of Address value from env-info + pub static_address: u32, + /// Memory stipend. Amount of free memory (in 64kb pages) each contract can use for stack. + pub initial_mem: u32, + /// Grow memory cost, per page (64kb) + pub grow_mem: u32, + /// Memory copy cost, per byte + pub memcpy: u32, + /// Max stack height (native WebAssembly stack limiter) + pub max_stack_height: u32, + /// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div` + pub opcodes_mul: u32, + /// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div` + pub opcodes_div: u32, +} + +impl Default for WasmCosts { + fn default() -> Self { + WasmCosts { + regular: 1, + div: 16, + mul: 4, + mem: 2, + static_u256: 64, + static_address: 40, + initial_mem: 4096, + grow_mem: 8192, + memcpy: 1, + max_stack_height: 64*1024, + opcodes_mul: 3, + opcodes_div: 8, + } + } } /// Dust accounts cleanup mode. @@ -184,17 +235,18 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, + eip86: false, + wasm: None, } } - /// Schedule for the Metropolis of the Ethereum main net. - pub fn new_metropolis() -> Schedule { + /// Schedule for the Byzantium fork of the Ethereum main net. + pub fn new_byzantium() -> Schedule { let mut schedule = Self::new_post_eip150(24576, true, true, true); schedule.have_create2 = true; schedule.have_revert = true; schedule.have_static_call = true; schedule.have_return_data = true; - schedule.blockhash_gas = 350; schedule } @@ -246,8 +298,18 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, + eip86: false, + wasm: None, } } + + /// Returns wasm schedule + /// + /// May panic if there is no wasm schedule + pub fn wasm(&self) -> &WasmCosts { + // *** Prefer PANIC here instead of silently breaking consensus! *** + self.wasm.as_ref().expect("Wasm schedule expected to exist while checking wasm contract. Misconfigured client?") + } } impl Default for Schedule { diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index c3a290d4176e18aaf2c6a2b0628f2dfc30a00b29..ce47121458f998a5efb58096c20d1b2b74655a6a 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -17,7 +17,8 @@ use std::sync::Arc; use std::collections::{HashMap, HashSet}; -use util::{H256, U256, Address, Bytes}; +use ethereum_types::{U256, H256, Address}; +use bytes::Bytes; use { CallType, Schedule, EnvInfo, ReturnData, Ext, ContractCreateResult, MessageCallResult, @@ -62,6 +63,7 @@ pub struct FakeExt { pub schedule: Schedule, pub balances: HashMap, pub tracing: bool, + pub is_static: bool, } // similar to the normal `finalize` function, but ignoring NeedsReturn. @@ -74,9 +76,23 @@ pub fn test_finalize(res: Result) -> Result { } impl FakeExt { + /// New fake externalities pub fn new() -> Self { FakeExt::default() } + + /// New fake externalities with byzantium schedule rules + pub fn new_byzantium() -> Self { + let mut ext = FakeExt::default(); + ext.schedule = Schedule::new_byzantium(); + ext + } + + /// Alter fake externalities to allow wasm + pub fn with_wasm(mut self) -> Self { + self.schedule.wasm = Some(Default::default()); + self + } } impl Ext for FakeExt { @@ -161,7 +177,7 @@ impl Ext for FakeExt { Ok(()) } - fn ret(self, _gas: &U256, _data: &ReturnData) -> Result { + fn ret(self, _gas: &U256, _data: &ReturnData, _apply_state: bool) -> Result { unimplemented!(); } @@ -182,11 +198,15 @@ impl Ext for FakeExt { self.depth } + fn is_static(&self) -> bool { + self.is_static + } + fn inc_sstore_clears(&mut self) { self.sstore_clears += 1; } - fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8) -> bool { + fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _gas: U256) -> bool { self.tracing } } diff --git a/ethcore/wasm/Cargo.toml b/ethcore/wasm/Cargo.toml index bbeeeffc57e385838146ea9ee4219b3b6e8c87bb..fc820a67d4c8c623b6ad2c56b2da1119784b0836 100644 --- a/ethcore/wasm/Cargo.toml +++ b/ethcore/wasm/Cargo.toml @@ -5,9 +5,11 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" -ethcore-util = { path = "../../util" } +ethereum-types = "0.2" log = "0.3" -parity-wasm = "0.12" -wasm-utils = { git = "https://github.com/paritytech/wasm-utils" } +parity-wasm = "0.27" +libc = "0.2" +pwasm-utils = "0.1" vm = { path = "../vm" } -ethcore-logger = { path = "../../logger" } \ No newline at end of file +ethcore-logger = { path = "../../logger" } +wasmi = { version = "0.1", features = ["opt-in-32bit"] } diff --git a/ethcore/wasm/run/Cargo.toml b/ethcore/wasm/run/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..91cbfb996c391727878265cef79179c6d27d2c01 --- /dev/null +++ b/ethcore/wasm/run/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "pwasm-run-test" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +serde = "1" +serde_json = "1" +serde_derive = "1" +ethereum-types = "0.2" +ethjson = { path = "../../../json" } +vm = { path = "../../vm" } +wasm = { path = "../" } +clap = "2.24" +ethcore-logger = { path = "../../../logger" } +rustc-hex = "1" + +[features] +default = ["ethereum-types/std"] diff --git a/ethcore/wasm/run/res/sample-fixture.json b/ethcore/wasm/run/res/sample-fixture.json new file mode 100644 index 0000000000000000000000000000000000000000..7be3e04be0337415f3e945d047787e4084d2f65a --- /dev/null +++ b/ethcore/wasm/run/res/sample-fixture.json @@ -0,0 +1,45 @@ +[ + { + "caption": "Sample test", + "source": "./res/sample1.wasm", + "address": "0x1000000000000000000000000000000000000001", + "sender": "0x1000000000000000000000000000000000000002", + "value": "0x0000000000000000000000000000000000000000000000000000000000000000", + "gasLimit": 100000, + "payload": "0x", + "asserts": [ + { "Return": "0x01" }, + { "UsedGas": 17 }, + { "HasCall": { "codeAddress": "0x1000000000000000000000000000000000000002" }}, + { "HasStorage": + { + "key": "0x0000000000000000000000000000000000000000000000000000000000000001", + "value": "0x0000000000000000000000000000000000000000000000000000000000000002" + } + } + ] + }, + { + "caption": "Keccak test", + "source": "./res/sample2.wasm", + "payload": "0x736f6d657468696e67", + "gasLimit": 100000, + "asserts": [ + { "Return": "0x68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87" } + ] + }, + { + "caption": "Token total supply", + "source": { + "constructor": "./res/sample3.wasm", + "sender": "0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f", + "at": "0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", + "arguments": "0x0000000000000000000000000000000000000000000000000000000010000000" + }, + "payload": "0x18160ddd", + "gasLimit": 100000, + "asserts": [ + { "Return": "0x0000000000000000000000000000000000000000000000000000000010000000" } + ] + } +] \ No newline at end of file diff --git a/ethcore/wasm/run/res/sample1.wasm b/ethcore/wasm/run/res/sample1.wasm new file mode 100644 index 0000000000000000000000000000000000000000..6ea0c58cc77bec3f6ccec1a8d3616e28d48df29c Binary files /dev/null and b/ethcore/wasm/run/res/sample1.wasm differ diff --git a/ethcore/wasm/run/res/sample2.wasm b/ethcore/wasm/run/res/sample2.wasm new file mode 100644 index 0000000000000000000000000000000000000000..baf9d17aa98fd185167448c58cc0388993dfab0a Binary files /dev/null and b/ethcore/wasm/run/res/sample2.wasm differ diff --git a/ethcore/wasm/run/res/sample3.wasm b/ethcore/wasm/run/res/sample3.wasm new file mode 100644 index 0000000000000000000000000000000000000000..1811215b40f3e84c572712a6fbcec5a2830cdf4e Binary files /dev/null and b/ethcore/wasm/run/res/sample3.wasm differ diff --git a/ethcore/wasm/run/src/fixture.rs b/ethcore/wasm/run/src/fixture.rs new file mode 100644 index 0000000000000000000000000000000000000000..ba2da0670677a1d80473688ad57d0752684c1811 --- /dev/null +++ b/ethcore/wasm/run/src/fixture.rs @@ -0,0 +1,70 @@ +use std::borrow::Cow; +use ethjson::uint::Uint; +use ethjson::hash::{Address, H256}; +use ethjson::bytes::Bytes; + +#[derive(Deserialize)] +#[serde(untagged)] +pub enum Source { + Raw(Cow<'static, String>), + Constructor { + #[serde(rename="constructor")] + source: Cow<'static, String>, + arguments: Bytes, + sender: Address, + at: Address, + }, +} + +impl Source { + pub fn as_ref(&self) -> &str { + match *self { + Source::Raw(ref r) => r.as_ref(), + Source::Constructor { ref source, .. } => source.as_ref(), + } + } +} + +#[derive(Deserialize)] +pub struct Fixture { + pub caption: Cow<'static, String>, + pub source: Source, + pub address: Option
, + pub sender: Option
, + pub value: Option, + #[serde(rename="gasLimit")] + pub gas_limit: Option, + pub payload: Option, + pub storage: Option>, + pub asserts: Vec, +} + +#[derive(Deserialize, Debug)] +pub struct StorageEntry { + pub key: Uint, + pub value: Uint, +} + +#[derive(Deserialize, Debug, Clone)] +pub struct CallLocator { + pub sender: Option
, + pub receiver: Option
, + pub value: Option, + pub data: Option, + #[serde(rename="codeAddress")] + pub code_address: Option
, +} + +#[derive(Deserialize, Debug)] +pub struct StorageAssert { + pub key: H256, + pub value: H256, +} + +#[derive(Deserialize, Debug)] +pub enum Assert { + HasCall(CallLocator), + HasStorage(StorageAssert), + UsedGas(u64), + Return(Bytes), +} \ No newline at end of file diff --git a/ethcore/wasm/run/src/main.rs b/ethcore/wasm/run/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..ab8ac631df9136e8263fce5d5e3e8d9dba7a788d --- /dev/null +++ b/ethcore/wasm/run/src/main.rs @@ -0,0 +1,46 @@ +extern crate serde; +extern crate serde_json; +#[macro_use] extern crate serde_derive; +extern crate ethereum_types; +extern crate ethjson; +extern crate wasm; +extern crate vm; +extern crate clap; +extern crate ethcore_logger; +extern crate rustc_hex; + +mod fixture; +mod runner; + +use fixture::Fixture; +use clap::{App, Arg}; +use std::fs; + +fn main() { + ::ethcore_logger::init_log(); + + let matches = App::new("pwasm-run-test") + .arg(Arg::with_name("target") + .index(1) + .required(true) + .multiple(true) + .help("JSON fixture")) + .get_matches(); + + let mut exit_code = 0; + + for target in matches.values_of("target").expect("No target parameter") { + let mut f = fs::File::open(target).expect("Failed to open file"); + let fixtures: Vec = serde_json::from_reader(&mut f).expect("Failed to deserialize json"); + + for fixture in fixtures.into_iter() { + let fails = runner::run_fixture(&fixture); + for fail in fails.iter() { + exit_code = 1; + println!("Failed assert in test \"{}\" ('{}'): {}", fixture.caption.as_ref(), target, fail); + } + } + } + + std::process::exit(exit_code); +} diff --git a/ethcore/wasm/run/src/runner.rs b/ethcore/wasm/run/src/runner.rs new file mode 100644 index 0000000000000000000000000000000000000000..a30efc6f086c8d8c33a057b769bf466acdb1def8 --- /dev/null +++ b/ethcore/wasm/run/src/runner.rs @@ -0,0 +1,261 @@ +use fixture::{Fixture, Assert, CallLocator, Source}; +use wasm::WasmInterpreter; +use vm::{self, Vm, GasLeft, ActionParams, ActionValue, ParamsType}; +use vm::tests::FakeExt; +use std::io::{self, Read}; +use std::{fs, path, fmt}; +use std::sync::Arc; +use ethereum_types::{U256, H256, H160}; +use rustc_hex::ToHex; + +fn load_code>(p: P) -> io::Result> { + let mut result = Vec::new(); + let mut f = fs::File::open(p)?; + f.read_to_end(&mut result)?; + Ok(result) +} + +fn wasm_interpreter() -> WasmInterpreter { + WasmInterpreter +} + +#[derive(Debug)] +pub enum SpecNonconformity { + Address, +} + +#[derive(Debug)] +pub enum Fail { + Return { expected: Vec, actual: Vec }, + UsedGas { expected: u64, actual: u64 }, + Runtime(String), + Load(io::Error), + NoCall(CallLocator), + StorageMismatch { key: H256, expected: H256, actual: Option }, + Nonconformity(SpecNonconformity) +} + +impl Fail { + fn runtime(err: vm::Error) -> Vec { + vec![Fail::Runtime(format!("{}", err))] + } + + fn load(err: io::Error) -> Vec { + vec![Fail::Load(err)] + } + + fn nononformity(kind: SpecNonconformity) -> Vec { + vec![Fail::Nonconformity(kind)] + } +} + +impl fmt::Display for Fail { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Fail::*; + match *self { + Return { ref expected, ref actual } => + write!( + f, + "Expected to return result: 0x{} ({} bytes), but got 0x{} ({} bytes)", + expected.to_hex(), + expected.len(), + actual.to_hex(), + actual.len() + ), + + UsedGas { expected, actual } => + write!(f, "Expected to use gas: {}, but got actual gas used: {}", expected, actual), + + Runtime(ref s) => + write!(f, "WASM Runtime error: {}", s), + + Load(ref e) => + write!(f, "Load i/o error: {}", e), + + NoCall(ref call) => + write!(f, "Call not found: {:?}", call), + + StorageMismatch { ref key, ref expected, actual: Some(ref actual)} => + write!( + f, + "Storage key {} value mismatch, expected {}, got: {}", + key.as_ref().to_vec().to_hex(), + expected.as_ref().to_vec().to_hex(), + actual.as_ref().to_vec().to_hex(), + ), + + StorageMismatch { ref key, ref expected, actual: None} => + write!( + f, + "No expected storage value for key {} found, expected {}", + key.as_ref().to_vec().to_hex(), + expected.as_ref().to_vec().to_hex(), + ), + + Nonconformity(SpecNonconformity::Address) => + write!(f, "Cannot use address when constructor is specified!"), + } + } +} + +pub fn construct( + ext: &mut vm::Ext, + source: Vec, + arguments: Vec, + sender: H160, + at: H160, +) -> Result, vm::Error> { + + let mut params = ActionParams::default(); + params.sender = sender; + params.address = at; + params.gas = U256::from(100_000_000); + params.data = Some(arguments); + params.code = Some(Arc::new(source)); + params.params_type = ParamsType::Separate; + + Ok( + match wasm_interpreter().exec(params, ext)? { + GasLeft::Known(_) => Vec::new(), + GasLeft::NeedsReturn { data, .. } => data.to_vec(), + } + ) +} + +pub fn run_fixture(fixture: &Fixture) -> Vec { + let mut params = ActionParams::default(); + + let source = match load_code(fixture.source.as_ref()) { + Ok(code) => code, + Err(e) => { return Fail::load(e); }, + }; + + let mut ext = FakeExt::new().with_wasm(); + params.code = Some(Arc::new( + if let Source::Constructor { ref arguments, ref sender, ref at, .. } = fixture.source { + match construct(&mut ext, source, arguments.clone().into(), sender.clone().into(), at.clone().into()) { + Ok(code) => code, + Err(e) => { return Fail::runtime(e); } + } + } else { + source + } + )); + + if let Some(ref sender) = fixture.sender { + params.sender = sender.clone().into(); + } + + if let Some(ref address) = fixture.address { + if let Source::Constructor { .. } = fixture.source { + return Fail::nononformity(SpecNonconformity::Address); + } + + params.address = address.clone().into(); + } else if let Source::Constructor { ref at, .. } = fixture.source { + params.address = at.clone().into(); + } + + if let Some(gas_limit) = fixture.gas_limit { + params.gas = U256::from(gas_limit); + } + + if let Some(ref data) = fixture.payload { + params.data = Some(data.clone().into()) + } + + if let Some(value) = fixture.value { + params.value = ActionValue::Transfer(value.clone().into()) + } + + if let Some(ref storage) = fixture.storage { + for storage_entry in storage.iter() { + let key: U256 = storage_entry.key.into(); + let val: U256 = storage_entry.value.into(); + ext.store.insert(key.into(), val.into()); + } + } + + let mut interpreter = wasm_interpreter(); + + let interpreter_return = match interpreter.exec(params, &mut ext) { + Ok(ret) => ret, + Err(e) => { return Fail::runtime(e); } + }; + let (gas_left, result) = match interpreter_return { + GasLeft::Known(gas) => { (gas, Vec::new()) }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + }; + + let mut fails = Vec::new(); + + for assert in fixture.asserts.iter() { + match *assert { + Assert::Return(ref data) => { + if &data[..] != &result[..] { + fails.push(Fail::Return { expected: (&data[..]).to_vec(), actual: (&result[..]).to_vec() }) + } + }, + Assert::UsedGas(gas) => { + let used_gas = fixture.gas_limit.unwrap_or(0) - gas_left.low_u64(); + if gas != used_gas { + fails.push(Fail::UsedGas { expected: gas, actual: used_gas }); + } + }, + Assert::HasCall(ref locator) => { + let mut found = false; + + for fake_call in ext.calls.iter() { + let mut match_ = true; + if let Some(ref data) = locator.data { + if data.as_ref() != &fake_call.data[..] { match_ = false; } + } + + if let Some(ref code_addr) = locator.code_address { + if fake_call.code_address.unwrap_or(H160::zero()) != code_addr.clone().into() { match_ = false } + } + + if let Some(ref sender) = locator.sender { + if fake_call.sender_address.unwrap_or(H160::zero()) != sender.clone().into() { match_ = false } + } + + if let Some(ref receiver) = locator.receiver { + if fake_call.receive_address.unwrap_or(H160::zero()) != receiver.clone().into() { match_ = false } + } + + if match_ { + found = true; + break; + } + } + + if !found { + fails.push(Fail::NoCall(locator.clone())) + } + }, + Assert::HasStorage(ref storage_entry) => { + let expected_storage_key: H256 = storage_entry.key.clone().into(); + let expected_storage_value: H256 = storage_entry.value.clone().into(); + let val = ext.store.get(&expected_storage_key); + + if let Some(val) = val { + if val != &expected_storage_value { + fails.push(Fail::StorageMismatch { + key: expected_storage_key, + expected: expected_storage_value, + actual: Some(val.clone()) + }) + } + } else { + fails.push(Fail::StorageMismatch { + key: expected_storage_key, + expected: expected_storage_value, + actual: None, + }) + } + + }, + } + } + fails +} diff --git a/ethcore/wasm/src/call_args.rs b/ethcore/wasm/src/call_args.rs deleted file mode 100644 index b4cce4982e2465e8313cae5f6540e1c502f7c4cd..0000000000000000000000000000000000000000 --- a/ethcore/wasm/src/call_args.rs +++ /dev/null @@ -1,62 +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 . - -//! Wasm evm call arguments helper - -use util::{U256, H160}; - -/// Input part of the wasm call descriptor -pub struct CallArgs { - /// Receiver of the transaction - pub address: [u8; 20], - - /// Sender of the transaction - pub sender: [u8; 20], - - /// Original transaction initiator - pub origin: [u8; 20], - - /// Transfer value - pub value: [u8; 32], - - /// call/create params - pub data: Vec, -} - -impl CallArgs { - /// New contract call payload with known parameters - pub fn new(address: H160, sender: H160, origin: H160, value: U256, data: Vec) -> Self { - let mut descriptor = CallArgs { - address: [0u8; 20], - sender: [0u8; 20], - origin: [0u8; 20], - value: [0u8; 32], - data: data, - }; - - descriptor.address.copy_from_slice(&*address); - descriptor.sender.copy_from_slice(&*sender); - descriptor.origin.copy_from_slice(&*origin); - value.to_big_endian(&mut descriptor.value); - - descriptor - } - - /// Total call payload length in linear memory - pub fn len(&self) -> u32 { - self.data.len() as u32 + 92 - } -} \ No newline at end of file diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index 777016a1bd58edef01cc0604ee4579f16c2a6884..7ffaaf98abd2f04797e9fcd0c30abdc51d5085cb 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -14,97 +14,285 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Wasm env module bindings +//! Env module glue for wasmi interpreter -use parity_wasm::elements::ValueType::*; -use parity_wasm::interpreter::{self, UserFunctionDescriptor}; -use parity_wasm::interpreter::UserFunctionDescriptor::*; -use super::runtime::Runtime; +use std::cell::RefCell; +use wasmi::{ + self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor, + MemoryRef, MemoryInstance, memory_units, +}; -pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[ - Static( - "_storage_read", - &[I32; 2], +/// Internal ids all functions runtime supports. This is just a glue for wasmi interpreter +/// that lacks high-level api and later will be factored out +pub mod ids { + pub const STORAGE_WRITE_FUNC: usize = 0; + pub const STORAGE_READ_FUNC: usize = 10; + pub const RET_FUNC: usize = 20; + pub const GAS_FUNC: usize = 30; + pub const FETCH_INPUT_FUNC: usize = 40; + pub const INPUT_LENGTH_FUNC: usize = 50; + pub const CCALL_FUNC: usize = 60; + pub const SCALL_FUNC: usize = 70; + pub const DCALL_FUNC: usize = 80; + pub const VALUE_FUNC: usize = 90; + pub const CREATE_FUNC: usize = 100; + pub const SUICIDE_FUNC: usize = 110; + pub const BLOCKHASH_FUNC: usize = 120; + pub const BLOCKNUMBER_FUNC: usize = 130; + pub const COINBASE_FUNC: usize = 140; + pub const DIFFICULTY_FUNC: usize = 150; + pub const GASLIMIT_FUNC: usize = 160; + pub const TIMESTAMP_FUNC: usize = 170; + pub const ADDRESS_FUNC: usize = 180; + pub const SENDER_FUNC: usize = 190; + pub const ORIGIN_FUNC: usize = 200; + pub const ELOG_FUNC: usize = 210; + + pub const PANIC_FUNC: usize = 1000; + pub const DEBUG_FUNC: usize = 1010; +} + +/// Signatures of all functions runtime supports. The actual dispatch happens at +/// impl runtime::Runtime methods. +pub mod signatures { + use wasmi::{self, ValueType}; + use wasmi::ValueType::*; + + pub struct StaticSignature(pub &'static [ValueType], pub Option); + + pub const STORAGE_READ: StaticSignature = StaticSignature( + &[I32, I32], + None, + ); + + pub const STORAGE_WRITE: StaticSignature = StaticSignature( + &[I32, I32], + None, + ); + + pub const RET: StaticSignature = StaticSignature( + &[I32, I32], + None, + ); + + pub const GAS: StaticSignature = StaticSignature( + &[I32], + None, + ); + + pub const FETCH_INPUT: StaticSignature = StaticSignature( + &[I32], + None, + ); + + pub const INPUT_LENGTH: StaticSignature = StaticSignature( + &[], Some(I32), - ), - Static( - "_storage_write", - &[I32; 2], + ); + + pub const CCALL: StaticSignature = StaticSignature( + &[I64, I32, I32, I32, I32, I32, I32], Some(I32), - ), - Static( - "_malloc", + ); + + pub const DCALL: StaticSignature = StaticSignature( + &[I64, I32, I32, I32, I32, I32], + Some(I32), + ); + + pub const SCALL: StaticSignature = StaticSignature( + &[I64, I32, I32, I32, I32, I32], + Some(I32), + ); + + pub const PANIC: StaticSignature = StaticSignature( + &[I32, I32], + None, + ); + + pub const DEBUG: StaticSignature = StaticSignature( + &[I32, I32], + None, + ); + + pub const VALUE: StaticSignature = StaticSignature( &[I32], + None, + ); + + pub const CREATE: StaticSignature = StaticSignature( + &[I32, I32, I32, I32], Some(I32), - ), - Static( - "_free", + ); + + pub const SUICIDE: StaticSignature = StaticSignature( + &[I32], + None, + ); + + pub const BLOCKHASH: StaticSignature = StaticSignature( + &[I64, I32], + None, + ); + + pub const BLOCKNUMBER: StaticSignature = StaticSignature( + &[], + Some(I64), + ); + + pub const COINBASE: StaticSignature = StaticSignature( &[I32], None, - ), - Static( - "gas", + ); + + pub const DIFFICULTY: StaticSignature = StaticSignature( &[I32], None, - ), - Static( - "_debug", - &[I32; 2], + ); + + pub const GASLIMIT: StaticSignature = StaticSignature( + &[I32], None, - ), - Static( - "_suicide", + ); + + pub const TIMESTAMP: StaticSignature = StaticSignature( + &[], + Some(I64), + ); + + pub const ADDRESS: StaticSignature = StaticSignature( &[I32], None, - ), - Static( - "_create", - &[I32; 4], - Some(I32), - ), - Static( - "_ccall", - &[I32; 6], - Some(I32), - ), - Static( - "_dcall", - &[I32; 5], - Some(I32), - ), - Static( - "_scall", - &[I32; 5], - Some(I32), - ), - Static( - "abort", + ); + + pub const SENDER: StaticSignature = StaticSignature( &[I32], None, - ), - Static( - "_emscripten_memcpy_big", - &[I32; 3], - Some(I32), - ), - - // TODO: Get rid of it also somehow? - Static( - "_llvm_trap", - &[I32; 0], - None - ), - - Static( - "_llvm_bswap_i64", - &[I32; 2], - Some(I32) - ), -]; - -pub fn native_bindings<'a>(runtime: &'a mut Runtime) -> interpreter::UserFunctions<'a> { - interpreter::UserFunctions { - executor: runtime, - functions: ::std::borrow::Cow::from(SIGNATURES), + ); + + pub const ORIGIN: StaticSignature = StaticSignature( + &[I32], + None, + ); + + pub const ELOG: StaticSignature = StaticSignature( + &[I32, I32, I32, I32], + None, + ); + + impl Into for StaticSignature { + fn into(self) -> wasmi::Signature { + wasmi::Signature::new(self.0, self.1) + } + } +} + +fn host(signature: signatures::StaticSignature, idx: usize) -> FuncRef { + FuncInstance::alloc_host(signature.into(), idx) +} + +/// Import resolver for wasmi +/// Maps all functions that runtime support to the corresponding contract import +/// entries. +/// Also manages initial memory request from the runtime. +#[derive(Default)] +pub struct ImportResolver { + max_memory: u32, + memory: RefCell>, +} + +impl ImportResolver { + /// New import resolver with specifed maximum amount of inital memory (in wasm pages = 64kb) + pub fn with_limit(max_memory: u32) -> ImportResolver { + ImportResolver { + max_memory: max_memory, + memory: RefCell::new(None), + } + } + + /// Returns memory that was instantiated during the contract module + /// start. If contract does not use memory at all, the dummy memory of length (0, 0) + /// will be created instead. So this method always returns memory instance + /// unless errored. + pub fn memory_ref(&self) -> MemoryRef { + { + let mut mem_ref = self.memory.borrow_mut(); + if mem_ref.is_none() { + *mem_ref = Some( + MemoryInstance::alloc( + memory_units::Pages(0), + Some(memory_units::Pages(0)), + ).expect("Memory allocation (0, 0) should not fail; qed") + ); + } + } + + self.memory.borrow().clone().expect("it is either existed or was created as (0, 0) above; qed") + } + + /// Returns memory size module initially requested + pub fn memory_size(&self) -> Result { + Ok(self.memory_ref().current_size().0 as u32) + } +} + +impl wasmi::ModuleImportResolver for ImportResolver { + fn resolve_func(&self, field_name: &str, _signature: &Signature) -> Result { + let func_ref = match field_name { + "storage_read" => host(signatures::STORAGE_READ, ids::STORAGE_READ_FUNC), + "storage_write" => host(signatures::STORAGE_WRITE, ids::STORAGE_WRITE_FUNC), + "ret" => host(signatures::RET, ids::RET_FUNC), + "gas" => host(signatures::GAS, ids::GAS_FUNC), + "input_length" => host(signatures::INPUT_LENGTH, ids::INPUT_LENGTH_FUNC), + "fetch_input" => host(signatures::FETCH_INPUT, ids::FETCH_INPUT_FUNC), + "panic" => host(signatures::PANIC, ids::PANIC_FUNC), + "debug" => host(signatures::DEBUG, ids::DEBUG_FUNC), + "ccall" => host(signatures::CCALL, ids::CCALL_FUNC), + "dcall" => host(signatures::DCALL, ids::DCALL_FUNC), + "scall" => host(signatures::SCALL, ids::SCALL_FUNC), + "value" => host(signatures::VALUE, ids::VALUE_FUNC), + "create" => host(signatures::CREATE, ids::CREATE_FUNC), + "suicide" => host(signatures::SUICIDE, ids::SUICIDE_FUNC), + "blockhash" => host(signatures::BLOCKHASH, ids::BLOCKHASH_FUNC), + "blocknumber" => host(signatures::BLOCKNUMBER, ids::BLOCKNUMBER_FUNC), + "coinbase" => host(signatures::COINBASE, ids::COINBASE_FUNC), + "difficulty" => host(signatures::DIFFICULTY, ids::DIFFICULTY_FUNC), + "gaslimit" => host(signatures::GASLIMIT, ids::GASLIMIT_FUNC), + "timestamp" => host(signatures::TIMESTAMP, ids::TIMESTAMP_FUNC), + "address" => host(signatures::ADDRESS, ids::ADDRESS_FUNC), + "sender" => host(signatures::SENDER, ids::SENDER_FUNC), + "origin" => host(signatures::ORIGIN, ids::ORIGIN_FUNC), + "elog" => host(signatures::ELOG, ids::ELOG_FUNC), + _ => { + return Err(wasmi::Error::Instantiation( + format!("Export {} not found", field_name), + )) + } + }; + + Ok(func_ref) + } + + fn resolve_memory( + &self, + field_name: &str, + descriptor: &MemoryDescriptor, + ) -> Result { + if field_name == "memory" { + let effective_max = descriptor.maximum().unwrap_or(self.max_memory + 1); + if descriptor.initial() > self.max_memory || effective_max > self.max_memory + { + Err(Error::Instantiation("Module requested too much memory".to_owned())) + } else { + let mem = MemoryInstance::alloc( + memory_units::Pages(descriptor.initial() as usize), + descriptor.maximum().map(|x| memory_units::Pages(x as usize)), + )?; + *self.memory.borrow_mut() = Some(mem.clone()); + Ok(mem) + } + } else { + Err(Error::Instantiation("Memory imported under unknown name".to_owned())) + } } } \ No newline at end of file diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index 3fec0f7814adf752e2223f71530c5238772dc0e2..5605a7ea185683c44d0d1e542b7624748e98d20d 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -16,130 +16,164 @@ //! Wasm Interpreter -extern crate vm; -extern crate ethcore_util as util; -#[macro_use] extern crate log; -extern crate ethcore_logger; extern crate byteorder; +extern crate ethcore_logger; +extern crate ethereum_types; +#[macro_use] extern crate log; +extern crate libc; extern crate parity_wasm; -extern crate wasm_utils; +extern crate vm; +extern crate pwasm_utils as wasm_utils; +extern crate wasmi; mod runtime; -mod ptr; -mod call_args; -mod result; #[cfg(test)] mod tests; mod env; +mod panic_payload; +mod parser; -const DEFAULT_STACK_SPACE: u32 = 5 * 1024 * 1024; +use vm::{GasLeft, ReturnData, ActionParams}; +use wasmi::{Error as InterpreterError, Trap}; -use parity_wasm::{interpreter, elements}; -use parity_wasm::interpreter::ModuleInstanceInterface; +use runtime::{Runtime, RuntimeContext}; -use vm::{GasLeft, ReturnData, ActionParams}; -use self::runtime::{Runtime, RuntimeContext}; +use ethereum_types::U256; -pub use self::runtime::Error as RuntimeError; +/// Wrapped interpreter error +#[derive(Debug)] +pub enum Error { + Interpreter(InterpreterError), + Trap(Trap), +} -const DEFAULT_RESULT_BUFFER: usize = 1024; +impl From for Error { + fn from(e: InterpreterError) -> Self { + Error::Interpreter(e) + } +} -/// Wasm interpreter instance -pub struct WasmInterpreter { - program: interpreter::ProgramInstance, - result: Vec, +impl From for Error { + fn from(e: Trap) -> Self { + Error::Trap(e) + } +} + +impl From for vm::Error { + fn from(e: Error) -> Self { + match e { + Error::Interpreter(e) => vm::Error::Wasm(format!("Wasm runtime error: {:?}", e)), + Error::Trap(e) => vm::Error::Wasm(format!("Wasm contract trap: {:?}", e)), + } + } } -impl WasmInterpreter { - /// New wasm interpreter instance - pub fn new() -> Result { - Ok(WasmInterpreter { - program: interpreter::ProgramInstance::new()?, - result: Vec::with_capacity(DEFAULT_RESULT_BUFFER), - }) +/// Wasm interpreter instance +pub struct WasmInterpreter; + +impl From for vm::Error { + fn from(e: runtime::Error) -> Self { + vm::Error::Wasm(format!("Wasm runtime error: {:?}", e)) } } +enum ExecutionOutcome { + Suicide, + Return, + NotSpecial, +} + impl vm::Vm for WasmInterpreter { fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result { - use parity_wasm::elements::Deserialize; + let (module, data) = parser::payload(¶ms, ext.schedule().wasm())?; - let code = params.code.expect("exec is only called on contract with code; qed"); + let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?; - trace!(target: "wasm", "Started wasm interpreter with code.len={:?}", code.len()); + let instantiation_resolver = env::ImportResolver::with_limit(16); - let env_instance = self.program.module("env") - // prefer explicit panic here - .expect("Wasm program to contain env module"); + let module_instance = wasmi::ModuleInstance::new( + &loaded_module, + &wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolver) + ).map_err(Error::Interpreter)?; - let env_memory = env_instance.memory(interpreter::ItemIndex::Internal(0)) - // prefer explicit panic here - .expect("Linear memory to exist in wasm runtime"); + let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) / + U256::from(ext.schedule().wasm().opcodes_mul); - if params.gas > ::std::u64::MAX.into() { - return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned())); + if adjusted_gas > ::std::u64::MAX.into() + { + return Err(vm::Error::Wasm("Wasm interpreter cannot run contracts with gas (wasm adjusted) >= 2^64".to_owned())); } - let mut runtime = Runtime::with_params( - ext, - env_memory, - DEFAULT_STACK_SPACE, - params.gas.low_u64(), - RuntimeContext::new(params.address, params.sender), - &self.program, - ); - - let mut cursor = ::std::io::Cursor::new(&*code); - - let contract_module = wasm_utils::inject_gas_counter( - elements::Module::deserialize( - &mut cursor - ).map_err(|err| { - vm::Error::Wasm(format!("Error deserializing contract code ({:?})", err)) - })? - ); - - let d_ptr = runtime.write_descriptor( - call_args::CallArgs::new( - params.address, - params.sender, - params.origin, - params.value.value(), - params.data.unwrap_or(Vec::with_capacity(0)), + let initial_memory = instantiation_resolver.memory_size().map_err(Error::Interpreter)?; + trace!(target: "wasm", "Contract requested {:?} pages of initial memory", initial_memory); + + let (gas_left, result) = { + let mut runtime = Runtime::with_params( + ext, + instantiation_resolver.memory_ref(), + // cannot overflow, checked above + adjusted_gas.low_u64(), + data.to_vec(), + RuntimeContext { + address: params.address, + sender: params.sender, + origin: params.origin, + code_address: params.code_address, + value: params.value.value(), + }, + ); + + // cannot overflow if static_region < 2^16, + // initial_memory ∈ [0..2^32) + // total_charge <- static_region * 2^32 * 2^16 + // total_charge ∈ [0..2^64) if static_region ∈ [0..2^16) + // qed + assert!(runtime.schedule().wasm().initial_mem < 1 << 16); + runtime.charge(|s| initial_memory as u64 * s.wasm().initial_mem as u64)?; + + let module_instance = module_instance.run_start(&mut runtime).map_err(Error::Trap)?; + + let invoke_result = module_instance.invoke_export("call", &[], &mut runtime); + + let mut execution_outcome = ExecutionOutcome::NotSpecial; + if let Err(InterpreterError::Trap(ref trap)) = invoke_result { + if let wasmi::TrapKind::Host(ref boxed) = *trap.kind() { + let ref runtime_err = boxed.downcast_ref::() + .expect("Host errors other than runtime::Error never produced; qed"); + + match **runtime_err { + runtime::Error::Suicide => { execution_outcome = ExecutionOutcome::Suicide; }, + runtime::Error::Return => { execution_outcome = ExecutionOutcome::Return; }, + _ => {} + } + } + } + + if let (ExecutionOutcome::NotSpecial, Err(e)) = (execution_outcome, invoke_result) { + trace!(target: "wasm", "Error executing contract: {:?}", e); + return Err(vm::Error::from(Error::from(e))); + } + + ( + runtime.gas_left().expect("Cannot fail since it was not updated since last charge"), + runtime.into_result(), ) - )?; + }; - { - let execution_params = runtime.execution_params() - .add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32)); - - let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals)) - .map_err(|err| { - trace!(target: "wasm", "Error adding contract module: {:?}", err); - vm::Error::from(RuntimeError::Interpreter(err)) - })?; - - module_instance.execute_export("_call", execution_params) - .map_err(|err| { - trace!(target: "wasm", "Error executing contract: {:?}", err); - vm::Error::from(RuntimeError::Interpreter(err)) - })?; - } + let gas_left = + U256::from(gas_left) * U256::from(ext.schedule().wasm().opcodes_mul) + / U256::from(ext.schedule().wasm().opcodes_div); - let result = result::WasmResult::new(d_ptr); - if result.peek_empty(&*runtime.memory())? { + if result.is_empty() { trace!(target: "wasm", "Contract execution result is empty."); - Ok(GasLeft::Known(runtime.gas_left()?.into())) + Ok(GasLeft::Known(gas_left)) } else { - self.result.clear(); - // todo: use memory views to avoid copy - self.result.extend(result.pop(&*runtime.memory())?); - let len = self.result.len(); + let len = result.len(); Ok(GasLeft::NeedsReturn { - gas_left: runtime.gas_left()?.into(), + gas_left: gas_left, data: ReturnData::new( - ::std::mem::replace(&mut self.result, Vec::with_capacity(DEFAULT_RESULT_BUFFER)), + result, 0, len, ), @@ -148,9 +182,3 @@ impl vm::Vm for WasmInterpreter { } } } - -impl From for vm::Error { - fn from(err: runtime::Error) -> vm::Error { - vm::Error::Wasm(format!("WASM runtime-error: {:?}", err)) - } -} \ No newline at end of file diff --git a/ethcore/wasm/src/panic_payload.rs b/ethcore/wasm/src/panic_payload.rs new file mode 100644 index 0000000000000000000000000000000000000000..dc95f53fbfc9bca70fbb3b65c5885c120e795489 --- /dev/null +++ b/ethcore/wasm/src/panic_payload.rs @@ -0,0 +1,168 @@ +// 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 . + +use byteorder::{LittleEndian, ReadBytesExt}; +use std::io::{self, Read}; + +#[derive(Debug, PartialEq, Eq)] +pub struct PanicPayload { + pub msg: Option, + pub file: Option, + pub line: Option, + pub col: Option, +} + +fn read_string(rdr: &mut io::Cursor<&[u8]>) -> io::Result> { + let string_len = rdr.read_u32::()?; + let string = if string_len == 0 { + None + } else { + let mut content = vec![0; string_len as usize]; + rdr.read_exact(&mut content)?; + Some(String::from_utf8_lossy(&content).into_owned()) + }; + Ok(string) +} + +pub fn decode(raw: &[u8]) -> PanicPayload { + let mut rdr = io::Cursor::new(raw); + let msg = read_string(&mut rdr).ok().and_then(|x| x); + let file = read_string(&mut rdr).ok().and_then(|x| x); + let line = rdr.read_u32::().ok(); + let col = rdr.read_u32::().ok(); + PanicPayload { + msg: msg, + file: file, + line: line, + col: col, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use byteorder::WriteBytesExt; + + fn write_u32(payload: &mut Vec, val: u32) { + payload.write_u32::(val).unwrap(); + } + + fn write_bytes(payload: &mut Vec, bytes: &[u8]) { + write_u32(payload, bytes.len() as u32); + payload.extend(bytes); + } + + #[test] + fn it_works() { + let mut raw = Vec::new(); + write_bytes(&mut raw, b"msg"); + write_bytes(&mut raw, b"file"); + write_u32(&mut raw, 1); + write_u32(&mut raw, 2); + + let payload = decode(&raw); + + assert_eq!( + payload, + PanicPayload { + msg: Some("msg".to_string()), + file: Some("file".to_string()), + line: Some(1), + col: Some(2), + } + ); + } + + #[test] + fn only_msg() { + let mut raw = Vec::new(); + write_bytes(&mut raw, b"msg"); + + let payload = decode(&raw); + + assert_eq!( + payload, + PanicPayload { + msg: Some("msg".to_string()), + file: None, + line: None, + col: None, + } + ); + } + + #[test] + fn invalid_utf8() { + let mut raw = Vec::new(); + write_bytes(&mut raw, b"\xF0\x90\x80msg"); + write_bytes(&mut raw, b"file"); + write_u32(&mut raw, 1); + write_u32(&mut raw, 2); + + let payload = decode(&raw); + + assert_eq!( + payload, + PanicPayload { + msg: Some("�msg".to_string()), + file: Some("file".to_string()), + line: Some(1), + col: Some(2), + } + ); + } + + #[test] + fn trailing_data() { + let mut raw = Vec::new(); + write_bytes(&mut raw, b"msg"); + write_bytes(&mut raw, b"file"); + write_u32(&mut raw, 1); + write_u32(&mut raw, 2); + write_u32(&mut raw, 0xdeadbeef); + + let payload = decode(&raw); + + assert_eq!( + payload, + PanicPayload { + msg: Some("msg".to_string()), + file: Some("file".to_string()), + line: Some(1), + col: Some(2), + } + ); + } + + #[test] + fn empty_str_is_none() { + let mut raw = Vec::new(); + write_bytes(&mut raw, b"msg"); + write_bytes(&mut raw, b""); + + let payload = decode(&raw); + + assert_eq!( + payload, + PanicPayload { + msg: Some("msg".to_string()), + file: None, + line: None, + col: None, + } + ); + } +} diff --git a/ethcore/wasm/src/parser.rs b/ethcore/wasm/src/parser.rs new file mode 100644 index 0000000000000000000000000000000000000000..62cd66cb98c8e50fa13f665dbc24496d11d13eb7 --- /dev/null +++ b/ethcore/wasm/src/parser.rs @@ -0,0 +1,98 @@ +// 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 . + +//! ActionParams parser for wasm + +use vm; +use wasm_utils::{self, rules}; +use parity_wasm::elements::{self, Deserialize}; +use parity_wasm::peek_size; + +fn gas_rules(wasm_costs: &vm::WasmCosts) -> rules::Set { + rules::Set::new( + wasm_costs.regular, + { + let mut vals = ::std::collections::HashMap::with_capacity(8); + vals.insert(rules::InstructionType::Load, rules::Metering::Fixed(wasm_costs.mem as u32)); + vals.insert(rules::InstructionType::Store, rules::Metering::Fixed(wasm_costs.mem as u32)); + vals.insert(rules::InstructionType::Div, rules::Metering::Fixed(wasm_costs.div as u32)); + vals.insert(rules::InstructionType::Mul, rules::Metering::Fixed(wasm_costs.mul as u32)); + vals + }) + .with_grow_cost(wasm_costs.grow_mem) + .with_forbidden_floats() +} + +/// Splits payload to code and data according to params.params_type, also +/// loads the module instance from payload and injects gas counter according +/// to schedule. +pub fn payload<'a>(params: &'a vm::ActionParams, wasm_costs: &vm::WasmCosts) + -> Result<(elements::Module, &'a [u8]), vm::Error> +{ + let code = match params.code { + Some(ref code) => &code[..], + None => { return Err(vm::Error::Wasm("Invalid wasm call".to_owned())); } + }; + + let (mut cursor, data_position) = match params.params_type { + vm::ParamsType::Embedded => { + let module_size = peek_size(&*code); + ( + ::std::io::Cursor::new(&code[..module_size]), + module_size + ) + }, + vm::ParamsType::Separate => { + (::std::io::Cursor::new(&code[..]), 0) + }, + }; + + let deserialized_module = elements::Module::deserialize( + &mut cursor + ).map_err(|err| { + vm::Error::Wasm(format!("Error deserializing contract code ({:?})", err)) + })?; + + if deserialized_module.memory_section().map_or(false, |ms| ms.entries().len() > 0) { + // According to WebAssembly spec, internal memory is hidden from embedder and should not + // be interacted with. So we disable this kind of modules at decoding level. + return Err(vm::Error::Wasm(format!("Malformed wasm module: internal memory"))); + } + + let contract_module = wasm_utils::inject_gas_counter( + deserialized_module, + &gas_rules(wasm_costs), + ).map_err(|_| vm::Error::Wasm(format!("Wasm contract error: bytecode invalid")))?; + + let contract_module = wasm_utils::stack_height::inject_limiter( + contract_module, + wasm_costs.max_stack_height, + ).map_err(|_| vm::Error::Wasm(format!("Wasm contract error: stack limiter failure")))?; + + let data = match params.params_type { + vm::ParamsType::Embedded => { + if data_position < code.len() { &code[data_position..] } else { &[] } + }, + vm::ParamsType::Separate => { + match params.data { + Some(ref s) => &s[..], + None => &[] + } + } + }; + + Ok((contract_module, data)) +} \ No newline at end of file diff --git a/ethcore/wasm/src/ptr.rs b/ethcore/wasm/src/ptr.rs deleted file mode 100644 index 11edbad70086121949ac19c50e50d58f8e2aa013..0000000000000000000000000000000000000000 --- a/ethcore/wasm/src/ptr.rs +++ /dev/null @@ -1,52 +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 . - -//! Wasm bound-checked ptr - -use parity_wasm::interpreter; - -/// Bound-checked wrapper for webassembly memory -pub struct WasmPtr(u32); - -/// Error in bound check -#[derive(Debug)] -pub enum Error { - AccessViolation, -} - -impl From for WasmPtr { - fn from(raw: u32) -> Self { - WasmPtr(raw) - } -} - -impl WasmPtr { - // todo: use memory view when they are on - /// Check memory range and return data with given length starting from the current pointer value - pub fn slice(&self, len: u32, mem: &interpreter::MemoryInstance) -> Result, Error> { - mem.get(self.0, len as usize).map_err(|_| Error::AccessViolation) - } - - // todo: maybe 2gb limit can be enhanced - /// Convert i32 from wasm stack to the wrapped pointer - pub fn from_i32(raw_ptr: i32) -> Result { - if raw_ptr < 0 { return Err(Error::AccessViolation); } - Ok(WasmPtr(raw_ptr as u32)) - } - - /// Return pointer raw value - pub fn as_raw(&self) -> u32 { self.0 } -} \ No newline at end of file diff --git a/ethcore/wasm/src/result.rs b/ethcore/wasm/src/result.rs deleted file mode 100644 index 3d1e51f64e835b833901ee9175d46a3872a1e5bf..0000000000000000000000000000000000000000 --- a/ethcore/wasm/src/result.rs +++ /dev/null @@ -1,51 +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 . - -//! Wasm evm results helper - -use byteorder::{LittleEndian, ByteOrder}; - -use parity_wasm::interpreter; - -use super::ptr::WasmPtr; -use super::runtime::Error as RuntimeError; - -/// Wrapper for wasm contract call result -pub struct WasmResult { - ptr: WasmPtr, -} - -impl WasmResult { - /// New call result from given ptr - pub fn new(descriptor_ptr: WasmPtr) -> WasmResult { - WasmResult { ptr: descriptor_ptr } - } - - /// Check if the result contains any data - pub fn peek_empty(&self, mem: &interpreter::MemoryInstance) -> Result { - let result_len = LittleEndian::read_u32(&self.ptr.slice(16, mem)?[12..16]); - Ok(result_len == 0) - } - - /// Consume the result ptr and return the actual data from wasm linear memory - pub fn pop(self, mem: &interpreter::MemoryInstance) -> Result, RuntimeError> { - let result_ptr = LittleEndian::read_u32(&self.ptr.slice(16, mem)?[8..12]); - let result_len = LittleEndian::read_u32(&self.ptr.slice(16, mem)?[12..16]); - trace!(target: "wasm", "contract result: {} bytes at @{}", result_len, result_ptr); - - Ok(mem.get(result_ptr, result_len as usize)?) - } -} \ No newline at end of file diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index e1def857e138f7b5b05a30cafdaa83e9908e46f3..71fafd671e368d05e7e7706be72299609f93b2cb 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -1,278 +1,433 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. +use ethereum_types::{U256, H256, Address}; +use vm::{self, CallType}; +use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind}; +use super::panic_payload; -// 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 . - -//! Wasm evm program runtime intstance - -use std::sync::Arc; - -use byteorder::{LittleEndian, ByteOrder}; - -use vm; -use parity_wasm::interpreter; -use util::{Address, H256, U256}; +pub struct RuntimeContext { + pub address: Address, + pub sender: Address, + pub origin: Address, + pub code_address: Address, + pub value: U256, +} -use vm::CallType; -use super::ptr::{WasmPtr, Error as PtrError}; -use super::call_args::CallArgs; +pub struct Runtime<'a> { + gas_counter: u64, + gas_limit: u64, + ext: &'a mut vm::Ext, + context: RuntimeContext, + memory: MemoryRef, + args: Vec, + result: Vec, +} -/// Wasm runtime error -#[derive(Debug)] +/// User trap in native code +#[derive(Debug, Clone, PartialEq)] pub enum Error { - /// Storage error - Storage, - /// Allocator error - Allocator, - /// Invalid gas state during the call - InvalidGasState, + /// Storage read error + StorageReadError, + /// Storage update error + StorageUpdateError, /// Memory access violation - AccessViolation, - /// Interpreter runtime error - Interpreter(interpreter::Error), + MemoryAccessViolation, + /// Native code resulted in suicide + Suicide, + /// Native code requested execution to finish + Return, + /// Suicide was requested but coudn't complete + SuicideAbort, + /// Invalid gas state inside interpreter + InvalidGasState, + /// Query of the balance resulted in an error + BalanceQueryError, + /// Failed allocation + AllocationFailed, + /// Gas limit reached + GasLimit, + /// Unknown runtime function + Unknown, + /// Passed string had invalid utf-8 encoding + BadUtf8, + /// Log event error + Log, + /// Other error in native code + Other, + /// Syscall signature mismatch + InvalidSyscall, + /// Unreachable instruction encountered + Unreachable, + /// Invalid virtual call + InvalidVirtualCall, + /// Division by zero + DivisionByZero, + /// Invalid conversion to integer + InvalidConversionToInt, + /// Stack overflow + StackOverflow, + /// Panic with message + Panic(String), } -impl From for Error { - fn from(err: interpreter::Error) -> Self { - Error::Interpreter(err) +impl wasmi::HostError for Error { } + +impl From for Error { + fn from(trap: Trap) -> Self { + match *trap.kind() { + TrapKind::Unreachable => Error::Unreachable, + TrapKind::MemoryAccessOutOfBounds => Error::MemoryAccessViolation, + TrapKind::TableAccessOutOfBounds | TrapKind::ElemUninitialized => Error::InvalidVirtualCall, + TrapKind::DivisionByZero => Error::DivisionByZero, + TrapKind::InvalidConversionToInt => Error::InvalidConversionToInt, + TrapKind::UnexpectedSignature => Error::InvalidVirtualCall, + TrapKind::StackOverflow => Error::StackOverflow, + TrapKind::Host(_) => Error::Other, + } } } -impl From for Error { - fn from(err: PtrError) -> Self { +impl From for Error { + fn from(err: InterpreterError) -> Self { match err { - PtrError::AccessViolation => Error::AccessViolation, + InterpreterError::Value(_) => Error::InvalidSyscall, + InterpreterError::Memory(_) => Error::MemoryAccessViolation, + _ => Error::Other, } } } -pub struct RuntimeContext { - address: Address, - sender: Address, -} - -impl RuntimeContext { - pub fn new(address: Address, sender: Address) -> Self { - RuntimeContext { - address: address, - sender: sender, +impl ::std::fmt::Display for Error { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> { + match *self { + Error::StorageReadError => write!(f, "Storage read error"), + Error::StorageUpdateError => write!(f, "Storage update error"), + Error::MemoryAccessViolation => write!(f, "Memory access violation"), + Error::SuicideAbort => write!(f, "Attempt to suicide resulted in an error"), + Error::InvalidGasState => write!(f, "Invalid gas state"), + Error::BalanceQueryError => write!(f, "Balance query resulted in an error"), + Error::Suicide => write!(f, "Suicide result"), + Error::Return => write!(f, "Return result"), + Error::Unknown => write!(f, "Unknown runtime function invoked"), + Error::AllocationFailed => write!(f, "Memory allocation failed (OOM)"), + Error::BadUtf8 => write!(f, "String encoding is bad utf-8 sequence"), + Error::GasLimit => write!(f, "Invocation resulted in gas limit violated"), + Error::Log => write!(f, "Error occured while logging an event"), + Error::InvalidSyscall => write!(f, "Invalid syscall signature encountered at runtime"), + Error::Other => write!(f, "Other unspecified error"), + Error::Unreachable => write!(f, "Unreachable instruction encountered"), + Error::InvalidVirtualCall => write!(f, "Invalid virtual call"), + Error::DivisionByZero => write!(f, "Division by zero"), + Error::StackOverflow => write!(f, "Stack overflow"), + Error::InvalidConversionToInt => write!(f, "Invalid conversion to integer"), + Error::Panic(ref msg) => write!(f, "Panic: {}", msg), } } } -/// Runtime enviroment data for wasm contract execution -pub struct Runtime<'a, 'b> { - gas_counter: u64, - gas_limit: u64, - dynamic_top: u32, - ext: &'a mut vm::Ext, - memory: Arc, - context: RuntimeContext, - instance: &'b interpreter::ProgramInstance, -} +type Result = ::std::result::Result; + +impl<'a> Runtime<'a> { -impl<'a, 'b> Runtime<'a, 'b> { /// New runtime for wasm contract with specified params - pub fn with_params<'c, 'd>( - ext: &'c mut vm::Ext, - memory: Arc, - stack_space: u32, + pub fn with_params( + ext: &mut vm::Ext, + memory: MemoryRef, gas_limit: u64, + args: Vec, context: RuntimeContext, - program_instance: &'d interpreter::ProgramInstance, - ) -> Runtime<'c, 'd> { + ) -> Runtime { Runtime { gas_counter: 0, gas_limit: gas_limit, - dynamic_top: stack_space, memory: memory, ext: ext, context: context, - instance: program_instance, + args: args, + result: Vec::new(), + } + } + + /// Loads 256-bit hash from the specifed sandboxed memory pointer + fn h256_at(&self, ptr: u32) -> Result { + let mut buf = [0u8; 32]; + self.memory.get_into(ptr, &mut buf[..])?; + + Ok(H256::from(&buf[..])) + } + + /// Loads 160-bit hash (Ethereum address) from the specified sandboxed memory pointer + fn address_at(&self, ptr: u32) -> Result
{ + let mut buf = [0u8; 20]; + self.memory.get_into(ptr, &mut buf[..])?; + + Ok(Address::from(&buf[..])) + } + + /// Loads 256-bit integer represented with bigendian from the specified sandboxed memory pointer + fn u256_at(&self, ptr: u32) -> Result { + let mut buf = [0u8; 32]; + self.memory.get_into(ptr, &mut buf[..])?; + + Ok(U256::from_big_endian(&buf[..])) + } + + /// Charge specified amount of gas + /// + /// Returns false if gas limit exceeded and true if not. + /// Intuition about the return value sense is to aswer the question 'are we allowed to continue?' + fn charge_gas(&mut self, amount: u64) -> bool { + let prev = self.gas_counter; + match prev.checked_add(amount) { + // gas charge overflow protection + None => false, + Some(val) if val > self.gas_limit => false, + Some(_) => { + self.gas_counter = prev + amount; + true + } + } + } + + /// Charge gas according to closure + pub fn charge(&mut self, f: F) -> Result<()> + where F: FnOnce(&vm::Schedule) -> u64 + { + let amount = f(self.ext.schedule()); + if !self.charge_gas(amount as u64) { + Err(Error::GasLimit) + } else { + Ok(()) } } - /// Write to the storage from wasm memory - pub fn storage_write(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> + /// Adjusted charge of gas which scales actual charge according to the wasm opcode counting coefficient + pub fn adjusted_charge(&mut self, f: F) -> Result<()> + where F: FnOnce(&vm::Schedule) -> u64 { - let mut context = context; - let val = self.pop_h256(&mut context)?; - let key = self.pop_h256(&mut context)?; - trace!(target: "wasm", "storage_write: value {} at @{}", &val, &key); + self.charge(|schedule| f(schedule) * schedule.wasm().opcodes_div as u64 / schedule.wasm().opcodes_mul as u64) + } - self.ext.set_storage(key, val) - .map_err(|_| interpreter::Error::Trap("Storage update error".to_owned()))?; + /// Charge gas provided by the closure + /// + /// Closure also can return overflowing flag as None in gas cost. + pub fn overflow_charge(&mut self, f: F) -> Result<()> + where F: FnOnce(&vm::Schedule) -> Option + { + let amount = match f(self.ext.schedule()) { + Some(amount) => amount, + None => { return Err(Error::GasLimit.into()); } + }; - Ok(Some(0i32.into())) + if !self.charge_gas(amount as u64) { + Err(Error::GasLimit.into()) + } else { + Ok(()) + } + } + + /// Same as overflow_charge, but with amount adjusted by wasm opcodes coeff + pub fn adjusted_overflow_charge(&mut self, f: F) -> Result<()> + where F: FnOnce(&vm::Schedule) -> Option + { + self.overflow_charge(|schedule| + f(schedule) + .and_then(|x| x.checked_mul(schedule.wasm().opcodes_div as u64)) + .map(|x| x / schedule.wasm().opcodes_mul as u64) + ) } /// Read from the storage to wasm memory - pub fn storage_read(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> + pub fn storage_read(&mut self, args: RuntimeArgs) -> Result<()> { - let mut context = context; - let val_ptr = context.value_stack.pop_as::()?; - let key = self.pop_h256(&mut context)?; + let key = self.h256_at(args.nth_checked(0)?)?; + let val_ptr: u32 = args.nth_checked(1)?; + + let val = self.ext.storage_at(&key).map_err(|_| Error::StorageReadError)?; - let val = self.ext.storage_at(&key) - .map_err(|_| interpreter::Error::Trap("Storage read error".to_owned()))?; + self.adjusted_charge(|schedule| schedule.sload_gas as u64)?; self.memory.set(val_ptr as u32, &*val)?; - Ok(Some(0.into())) + Ok(()) } - /// Pass suicide to state runtime - pub fn suicide(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> + /// Write to storage from wasm memory + pub fn storage_write(&mut self, args: RuntimeArgs) -> Result<()> { - let mut context = context; - let refund_address = self.pop_address(&mut context)?; + let key = self.h256_at(args.nth_checked(0)?)?; + let val_ptr: u32 = args.nth_checked(1)?; + + let val = self.h256_at(val_ptr)?; + let former_val = self.ext.storage_at(&key).map_err(|_| Error::StorageUpdateError)?; + + if former_val == H256::zero() && val != H256::zero() { + self.adjusted_charge(|schedule| schedule.sstore_set_gas as u64)?; + } else { + self.adjusted_charge(|schedule| schedule.sstore_reset_gas as u64)?; + } + + self.ext.set_storage(key, val).map_err(|_| Error::StorageUpdateError)?; - self.ext.suicide(&refund_address) - .map_err(|_| interpreter::Error::Trap("Suicide error".to_owned()))?; + if former_val != H256::zero() && val == H256::zero() { + self.ext.inc_sstore_clears(); + } - Ok(None) + Ok(()) } - /// Invoke create in the state runtime - pub fn create(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - // - // method signature: - // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; - // + /// Return currently used schedule + pub fn schedule(&self) -> &vm::Schedule { + self.ext.schedule() + } - trace!(target: "wasm", "runtime: create contract"); - let mut context = context; - let result_ptr = context.value_stack.pop_as::()? as u32; - trace!(target: "wasm", "result_ptr: {:?}", result_ptr); - let code_len = context.value_stack.pop_as::()? as u32; - trace!(target: "wasm", " code_len: {:?}", code_len); - let code_ptr = context.value_stack.pop_as::()? as u32; - trace!(target: "wasm", " code_ptr: {:?}", code_ptr); - let endowment = self.pop_u256(&mut context)?; - trace!(target: "wasm", " val: {:?}", endowment); + /// Sets a return value for the call + /// + /// Syscall takes 2 arguments: + /// * pointer in sandboxed memory where result is + /// * the length of the result + pub fn ret(&mut self, args: RuntimeArgs) -> Result<()> { + let ptr: u32 = args.nth_checked(0)?; + let len: u32 = args.nth_checked(1)?; - let code = self.memory.get(code_ptr, code_len as usize)?; + trace!(target: "wasm", "Contract ret: {} bytes @ {}", len, ptr); - let gas_left = self.gas_left() - .map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))? - .into(); + self.result = self.memory.get(ptr, len as usize)?; - match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) { - vm::ContractCreateResult::Created(address, gas_left) => { - self.memory.set(result_ptr, &*address)?; - self.gas_counter = self.gas_limit - gas_left.low_u64(); - trace!(target: "wasm", "runtime: create contract success (@{:?})", address); - Ok(Some(0i32.into())) - }, - vm::ContractCreateResult::Failed => { - trace!(target: "wasm", "runtime: create contract fail"); - Ok(Some((-1i32).into())) - } - } + Err(Error::Return) } - pub fn call(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - // - // method signature: - // fn ( - // address: *const u8, - // val_ptr: *const u8, - // input_ptr: *const u8, - // input_len: u32, - // result_ptr: *mut u8, - // result_len: u32, - // ) -> i32 + /// Destroy the runtime, returning currently recorded result of the execution + pub fn into_result(self) -> Vec { + self.result + } - self.do_call(true, CallType::Call, context) + /// Query current gas left for execution + pub fn gas_left(&self) -> Result { + if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); } + Ok(self.gas_limit - self.gas_counter) } + + /// General gas charging extern. + fn gas(&mut self, args: RuntimeArgs) -> Result<()> { + let amount: u32 = args.nth_checked(0)?; + if self.charge_gas(amount as u64) { + Ok(()) + } else { + Err(Error::GasLimit.into()) + } + } + + /// Query the length of the input bytes + fn input_legnth(&mut self) -> RuntimeValue { + RuntimeValue::I32(self.args.len() as i32) + } + + /// Write input bytes to the memory location using the passed pointer + fn fetch_input(&mut self, args: RuntimeArgs) -> Result<()> { + let ptr: u32 = args.nth_checked(0)?; + + let args_len = self.args.len() as u64; + self.charge(|s| args_len * s.wasm().memcpy as u64)?; + self.memory.set(ptr, &self.args[..])?; + Ok(()) + } - fn call_code(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> + /// User panic + /// + /// Contract can invoke this when he encounters unrecoverable error. + fn panic(&mut self, args: RuntimeArgs) -> Result<()> { - // - // signature (same as static call): - // fn ( - // address: *const u8, - // input_ptr: *const u8, - // input_len: u32, - // result_ptr: *mut u8, - // result_len: u32, - // ) -> i32 + let payload_ptr: u32 = args.nth_checked(0)?; + let payload_len: u32 = args.nth_checked(1)?; + + let raw_payload = self.memory.get(payload_ptr, payload_len as usize)?; + let payload = panic_payload::decode(&raw_payload); + let msg = format!( + "{msg}, {file}:{line}:{col}", + msg = payload + .msg + .as_ref() + .map(String::as_ref) + .unwrap_or(""), + file = payload + .file + .as_ref() + .map(String::as_ref) + .unwrap_or(""), + line = payload.line.unwrap_or(0), + col = payload.col.unwrap_or(0) + ); + trace!(target: "wasm", "Contract custom panic message: {}", msg); - self.do_call(false, CallType::CallCode, context) + Err(Error::Panic(msg).into()) } fn do_call( &mut self, use_val: bool, call_type: CallType, - context: interpreter::CallerContext, + args: RuntimeArgs, ) - -> Result, interpreter::Error> + -> Result { + trace!(target: "wasm", "runtime: CALL({:?})", call_type); - trace!(target: "wasm", "runtime: call code"); - let mut context = context; - let result_alloc_len = context.value_stack.pop_as::()? as u32; - trace!(target: "wasm", " result_len: {:?}", result_alloc_len); + let gas: u64 = args.nth_checked(0)?; + trace!(target: "wasm", " gas: {:?}", gas); - let result_ptr = context.value_stack.pop_as::()? as u32; - trace!(target: "wasm", " result_ptr: {:?}", result_ptr); + let address = self.address_at(args.nth_checked(1)?)?; + trace!(target: "wasm", " address: {:?}", address); - let input_len = context.value_stack.pop_as::()? as u32; - trace!(target: "wasm", " input_len: {:?}", input_len); + let vofs = if use_val { 1 } else { 0 }; + let val = if use_val { Some(self.u256_at(args.nth_checked(2)?)?) } else { None }; + trace!(target: "wasm", " val: {:?}", val); - let input_ptr = context.value_stack.pop_as::()? as u32; + let input_ptr: u32 = args.nth_checked(2 + vofs)?; trace!(target: "wasm", " input_ptr: {:?}", input_ptr); - let val = if use_val { Some(self.pop_u256(&mut context)?) } - else { None }; - trace!(target: "wasm", " val: {:?}", val); + let input_len: u32 = args.nth_checked(3 + vofs)?; + trace!(target: "wasm", " input_len: {:?}", input_len); - let address = self.pop_address(&mut context)?; - trace!(target: "wasm", " address: {:?}", address); + let result_ptr: u32 = args.nth_checked(4 + vofs)?; + trace!(target: "wasm", " result_ptr: {:?}", result_ptr); + + let result_alloc_len: u32 = args.nth_checked(5 + vofs)?; + trace!(target: "wasm", " result_len: {:?}", result_alloc_len); if let Some(ref val) = val { let address_balance = self.ext.balance(&self.context.address) - .map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))?; + .map_err(|_| Error::BalanceQueryError)?; if &address_balance < val { trace!(target: "wasm", "runtime: call failed due to balance check"); - return Ok(Some((-1i32).into())); + return Ok((-1i32).into()); } } + self.adjusted_charge(|schedule| schedule.call_gas as u64)?; + 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(|_| interpreter::Error::Trap("Gas state error".to_owned()))? - .into(); + // todo: optimize to use memory views once it's in let payload = self.memory.get(input_ptr, input_len as usize)?; + let adjusted_gas = match gas.checked_mul(self.ext.schedule().wasm().opcodes_div as u64) + .map(|x| x / self.ext.schedule().wasm().opcodes_mul as u64) + { + Some(x) => x, + None => { + trace!("CALL overflowed gas, call aborted with error returned"); + return Ok(RuntimeValue::I32(-1)) + }, + }; + + self.charge(|_| adjusted_gas)?; + 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, @@ -282,276 +437,298 @@ 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.ext.schedule().wasm().opcodes_div as u64 + / self.ext.schedule().wasm().opcodes_mul as u64; + + self.memory.set(result_ptr, &result)?; + Ok(0i32.into()) + }, + vm::MessageCallResult::Reverted(gas_left, _) => { + // 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.ext.schedule().wasm().opcodes_div as u64 + / self.ext.schedule().wasm().opcodes_mul as u64; + self.memory.set(result_ptr, &result)?; - Ok(Some(0i32.into())) + Ok((-1i32).into()) }, vm::MessageCallResult::Failed => { - Ok(Some((-1i32).into())) + Ok((-1i32).into()) } } } - pub fn static_call(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - // signature (same as code call): - // fn ( - // address: *const u8, - // input_ptr: *const u8, - // input_len: u32, - // result_ptr: *mut u8, - // result_len: u32, - // ) -> i32 - - self.do_call(false, CallType::StaticCall, context) + /// Message call + fn ccall(&mut self, args: RuntimeArgs) -> Result { + self.do_call(true, CallType::Call, args) } - - /// Allocate memory using the wasm stack params - pub fn malloc(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - let amount = context.value_stack.pop_as::()? as u32; - let previous_top = self.dynamic_top; - self.dynamic_top = previous_top + amount; - Ok(Some((previous_top as i32).into())) + /// Delegate call + fn dcall(&mut self, args: RuntimeArgs) -> Result { + self.do_call(false, CallType::DelegateCall, args) } - /// Allocate memory in wasm memory instance - pub fn alloc(&mut self, amount: u32) -> Result { - let previous_top = self.dynamic_top; - self.dynamic_top = previous_top + amount; - Ok(previous_top.into()) + /// Static call + fn scall(&mut self, args: RuntimeArgs) -> Result { + self.do_call(false, CallType::StaticCall, args) } - /// Report gas cost with the params passed in wasm stack - fn gas(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> + fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<()> { - let amount = context.value_stack.pop_as::()? as u64; - if self.charge_gas(amount) { - Ok(None) - } else { - Err(interpreter::Error::Trap(format!("Gas exceeds limits of {}", self.gas_limit))) - } + self.charge(|schedule| schedule.wasm().static_address as u64)?; + self.memory.set(ptr, &*val)?; + Ok(()) } - fn charge_gas(&mut self, amount: u64) -> bool { - let prev = self.gas_counter; - if prev + amount > self.gas_limit { - // exceeds gas - false - } else { - self.gas_counter = prev + amount; - true - } + fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<()> { + let value: H256 = val.into(); + self.charge(|schedule| schedule.wasm().static_u256 as u64)?; + self.memory.set(ptr, &*value)?; + Ok(()) } - fn h256_at(&self, ptr: WasmPtr) -> Result { - Ok(H256::from_slice(&ptr.slice(32, &*self.memory) - .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))? - )) + /// Returns value (in Wei) passed to contract + pub fn value(&mut self, args: RuntimeArgs) -> Result<()> { + let val = self.context.value; + self.return_u256_ptr(args.nth_checked(0)?, val) } - fn pop_h256(&self, context: &mut interpreter::CallerContext) -> Result { - let ptr = WasmPtr::from_i32(context.value_stack.pop_as::()?) - .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?; - self.h256_at(ptr) - } + /// Creates a new contract + /// + /// Arguments: + /// * endowment - how much value (in Wei) transfer to the newly created contract + /// * code_ptr - pointer to the code data + /// * code_len - lenght of the code data + /// * result_ptr - pointer to write an address of the newly created contract + pub fn create(&mut self, args: RuntimeArgs) -> Result + { + // + // method signature: + // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; + // + trace!(target: "wasm", "runtime: CREATE"); + let endowment = self.u256_at(args.nth_checked(0)?)?; + trace!(target: "wasm", " val: {:?}", endowment); + let code_ptr: u32 = args.nth_checked(1)?; + trace!(target: "wasm", " code_ptr: {:?}", code_ptr); + let code_len: u32 = args.nth_checked(2)?; + trace!(target: "wasm", " code_len: {:?}", code_len); + let result_ptr: u32 = args.nth_checked(3)?; + trace!(target: "wasm", "result_ptr: {:?}", result_ptr); - fn pop_u256(&self, context: &mut interpreter::CallerContext) -> Result { - let ptr = WasmPtr::from_i32(context.value_stack.pop_as::()?) - .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?; - self.h256_at(ptr).map(Into::into) - } + let code = self.memory.get(code_ptr, code_len as usize)?; - fn address_at(&self, ptr: WasmPtr) -> Result { - Ok(Address::from_slice(&ptr.slice(20, &*self.memory) - .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))? - )) - } + self.adjusted_charge(|schedule| schedule.create_gas as u64)?; + self.adjusted_charge(|schedule| schedule.create_data_gas as u64 * code.len() as u64)?; + + let gas_left: U256 = U256::from(self.gas_left()?) + * U256::from(self.ext.schedule().wasm().opcodes_mul) + / U256::from(self.ext.schedule().wasm().opcodes_div); - fn pop_address(&self, context: &mut interpreter::CallerContext) -> Result { - let ptr = WasmPtr::from_i32(context.value_stack.pop_as::()?) - .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?; - self.address_at(ptr) + match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) { + vm::ContractCreateResult::Created(address, gas_left) => { + self.memory.set(result_ptr, &*address)?; + self.gas_counter = self.gas_limit - + // this cannot overflow, since initial gas is in [0..u64::max) range, + // and gas_left cannot be bigger + gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64 + / self.ext.schedule().wasm().opcodes_mul as u64; + trace!(target: "wasm", "runtime: create contract success (@{:?})", address); + Ok(0i32.into()) + }, + vm::ContractCreateResult::Failed => { + trace!(target: "wasm", "runtime: create contract fail"); + Ok((-1i32).into()) + }, + vm::ContractCreateResult::Reverted(gas_left, _) => { + trace!(target: "wasm", "runtime: create contract reverted"); + self.gas_counter = self.gas_limit - + // this cannot overflow, since initial gas is in [0..u64::max) range, + // and gas_left cannot be bigger + gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64 + / self.ext.schedule().wasm().opcodes_mul as u64; + + Ok((-1i32).into()) + }, + } } - fn user_trap(&mut self, _context: interpreter::CallerContext) - -> Result, interpreter::Error> + fn debug(&mut self, args: RuntimeArgs) -> Result<()> { - Err(interpreter::Error::Trap("unknown trap".to_owned())) - } + trace!(target: "wasm", "Contract debug message: {}", { + let msg_ptr: u32 = args.nth_checked(0)?; + let msg_len: u32 = args.nth_checked(1)?; - fn user_noop(&mut self, - _context: interpreter::CallerContext - ) -> Result, interpreter::Error> { - Ok(None) - } + String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?) + .map_err(|_| Error::BadUtf8)? + }); - /// Write call descriptor to wasm memory - pub fn write_descriptor(&mut self, call_args: CallArgs) -> Result { - let d_ptr = self.alloc(16)?; + Ok(()) + } - let args_len = call_args.len(); - let args_ptr = self.alloc(args_len)?; + /// Pass suicide to state runtime + pub fn suicide(&mut self, args: RuntimeArgs) -> Result<()> + { + let refund_address = self.address_at(args.nth_checked(0)?)?; - // write call descriptor - // call descriptor is [args_ptr, args_len, return_ptr, return_len] - // all are 4 byte length, last 2 are zeroed - let mut d_buf = [0u8; 16]; - LittleEndian::write_u32(&mut d_buf[0..4], args_ptr); - LittleEndian::write_u32(&mut d_buf[4..8], args_len); - self.memory.set(d_ptr, &d_buf)?; + if self.ext.exists(&refund_address).map_err(|_| Error::SuicideAbort)? { + trace!(target: "wasm", "Suicide: refund to existing address {}", refund_address); + self.adjusted_charge(|schedule| schedule.suicide_gas as u64)?; + } else { + trace!(target: "wasm", "Suicide: refund to new address {}", refund_address); + self.adjusted_charge(|schedule| schedule.suicide_to_new_account_cost as u64)?; + } - // write call args to memory - self.memory.set(args_ptr, &call_args.address)?; - self.memory.set(args_ptr+20, &call_args.sender)?; - self.memory.set(args_ptr+40, &call_args.origin)?; - self.memory.set(args_ptr+60, &call_args.value)?; - self.memory.set(args_ptr+92, &call_args.data)?; + self.ext.suicide(&refund_address).map_err(|_| Error::SuicideAbort)?; - Ok(d_ptr.into()) + // We send trap to interpreter so it should abort further execution + Err(Error::Suicide.into()) } - fn debug_log(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - let msg_len = context.value_stack.pop_as::()? as u32; - let msg_ptr = context.value_stack.pop_as::()? as u32; + /// Signature: `fn blockhash(number: i64, dest: *mut u8)` + pub fn blockhash(&mut self, args: RuntimeArgs) -> Result<()> { + self.adjusted_charge(|schedule| schedule.blockhash_gas as u64)?; + let hash = self.ext.blockhash(&U256::from(args.nth_checked::(0)?)); + self.memory.set(args.nth_checked(1)?, &*hash)?; - let msg = String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?) - .map_err(|_| interpreter::Error::Trap("Debug log utf-8 decoding error".to_owned()))?; + Ok(()) + } - trace!(target: "wasm", "Contract debug message: {}", msg); + /// Signature: `fn blocknumber() -> i64` + pub fn blocknumber(&mut self) -> Result { + Ok(RuntimeValue::from(self.ext.env_info().number)) + } - Ok(None) + /// Signature: `fn coinbase(dest: *mut u8)` + pub fn coinbase(&mut self, args: RuntimeArgs) -> Result<()> { + let coinbase = self.ext.env_info().author; + self.return_address_ptr(args.nth_checked(0)?, coinbase) } - /// Query current gas left for execution - pub fn gas_left(&self) -> Result { - if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); } - Ok(self.gas_limit - self.gas_counter) + /// Signature: `fn difficulty(dest: *mut u8)` + pub fn difficulty(&mut self, args: RuntimeArgs) -> Result<()> { + let difficulty = self.ext.env_info().difficulty; + self.return_u256_ptr(args.nth_checked(0)?, difficulty) } - /// Shared memory reference - pub fn memory(&self) -> &interpreter::MemoryInstance { - &*self.memory + /// Signature: `fn gaslimit(dest: *mut u8)` + pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> { + let gas_limit = self.ext.env_info().gas_limit; + self.return_u256_ptr(args.nth_checked(0)?, gas_limit) } - fn mem_copy(&self, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - let len = context.value_stack.pop_as::()? as u32; - let dst = context.value_stack.pop_as::()? as u32; - let src = context.value_stack.pop_as::()? as u32; + /// Signature: `fn address(dest: *mut u8)` + pub fn address(&mut self, args: RuntimeArgs) -> Result<()> { + let address = self.context.address; + self.return_address_ptr(args.nth_checked(0)?, address) + } - let mem = self.memory().get(src, len as usize)?; - self.memory().set(dst, &mem)?; + /// Signature: `sender(dest: *mut u8)` + pub fn sender(&mut self, args: RuntimeArgs) -> Result<()> { + let sender = self.context.sender; + self.return_address_ptr(args.nth_checked(0)?, sender) + } - Ok(Some(0i32.into())) + /// Signature: `origin(dest: *mut u8)` + pub fn origin(&mut self, args: RuntimeArgs) -> Result<()> { + let origin = self.context.origin; + self.return_address_ptr(args.nth_checked(0)?, origin) } - fn bswap_32(x: u32) -> u32 { - x >> 24 | x >> 8 & 0xff00 | x << 8 & 0xff0000 | x << 24 + /// Signature: `timestamp() -> i64` + pub fn timestamp(&mut self) -> Result { + let timestamp = self.ext.env_info().timestamp; + Ok(RuntimeValue::from(timestamp)) } - fn bitswap_i64(&mut self, context: interpreter::CallerContext) - -> Result, interpreter::Error> + /// Signature: `fn elog(topic_ptr: *const u8, topic_count: u32, data_ptr: *const u8, data_len: u32)` + pub fn elog(&mut self, args: RuntimeArgs) -> Result<()> { - let x1 = context.value_stack.pop_as::()?; - let x2 = context.value_stack.pop_as::()?; - - let result = ((Runtime::bswap_32(x2 as u32) as u64) << 32 - | Runtime::bswap_32(x1 as u32) as u64) as i64; - - self.return_i64(result) - } + let topic_ptr: u32 = args.nth_checked(0)?; + let topic_count: u32 = args.nth_checked(1)?; + let data_ptr: u32 = args.nth_checked(2)?; + let data_len: u32 = args.nth_checked(3)?; - fn return_i64(&mut self, val: i64) -> Result, interpreter::Error> { - let uval = val as u64; - let hi = (uval >> 32) as i32; - let lo = (uval << 32 >> 32) as i32; + if topic_count > 4 { + return Err(Error::Log.into()); + } - let target = self.instance.module("contract") - .ok_or(interpreter::Error::Trap("Error locating main execution entry".to_owned()))?; - target.execute_export( - "setTempRet0", - self.execution_params().add_argument( - interpreter::RuntimeValue::I32(hi).into() - ), + self.adjusted_overflow_charge(|schedule| + { + let topics_gas = schedule.log_gas as u64 + schedule.log_topic_gas as u64 * topic_count as u64; + (schedule.log_data_gas as u64) + .checked_mul(schedule.log_data_gas as u64) + .and_then(|data_gas| data_gas.checked_add(topics_gas)) + } )?; - Ok(Some( - (lo).into() - )) - } - pub fn execution_params(&mut self) -> interpreter::ExecutionParams { - use super::env; + let mut topics: Vec = Vec::with_capacity(topic_count as usize); + topics.resize(topic_count as usize, H256::zero()); + for i in 0..topic_count { + let offset = i.checked_mul(32).ok_or(Error::MemoryAccessViolation)? + .checked_add(topic_ptr).ok_or(Error::MemoryAccessViolation)?; - let env_instance = self.instance.module("env") - .expect("Env module always exists; qed"); + *topics.get_mut(i as usize) + .expect("topics is resized to `topic_count`, i is in 0..topic count iterator, get_mut uses i as an indexer, get_mut cannot fail; qed") + = H256::from(&self.memory.get(offset, 32)?[..]); + } + self.ext.log(topics, &self.memory.get(data_ptr, data_len as usize)?).map_err(|_| Error::Log)?; - interpreter::ExecutionParams::with_external( - "env".into(), - Arc::new( - interpreter::env_native_module(env_instance, env::native_bindings(self)) - .expect("Env module always exists; qed") - ) - ) + Ok(()) } } -impl<'a, 'b> interpreter::UserFunctionExecutor for Runtime<'a, 'b> { - fn execute(&mut self, name: &str, context: interpreter::CallerContext) - -> Result, interpreter::Error> - { - match name { - "_malloc" => { - self.malloc(context) - }, - "_free" => { - // Since it is arena allocator, free does nothing - // todo: update if changed - self.user_noop(context) - }, - "_storage_read" => { - self.storage_read(context) - }, - "_storage_write" => { - self.storage_write(context) - }, - "_suicide" => { - self.suicide(context) - }, - "_create" => { - self.create(context) - }, - "_ccall" => { - self.call(context) - }, - "_dcall" => { - self.call_code(context) - }, - "_scall" => { - self.static_call(context) - }, - "_debug" => { - self.debug_log(context) - }, - "gas" => { - self.gas(context) - }, - "_emscripten_memcpy_big" => { - self.mem_copy(context) - }, - "_llvm_bswap_i64" => { - self.bitswap_i64(context) - }, - _ => { - trace!(target: "wasm", "Trapped due to unhandled function: '{}'", name); - self.user_trap(context) +mod ext_impl { + + use wasmi::{Externals, RuntimeArgs, RuntimeValue, Trap}; + use env::ids::*; + + macro_rules! void { + { $e: expr } => { { $e?; Ok(None) } } + } + + macro_rules! some { + { $e: expr } => { { Ok(Some($e?)) } } + } + + macro_rules! cast { + { $e: expr } => { { Ok(Some($e)) } } + } + + impl<'a> Externals for super::Runtime<'a> { + fn invoke_index( + &mut self, + index: usize, + args: RuntimeArgs, + ) -> Result, Trap> { + match index { + STORAGE_WRITE_FUNC => void!(self.storage_write(args)), + STORAGE_READ_FUNC => void!(self.storage_read(args)), + RET_FUNC => void!(self.ret(args)), + GAS_FUNC => void!(self.gas(args)), + INPUT_LENGTH_FUNC => cast!(self.input_legnth()), + FETCH_INPUT_FUNC => void!(self.fetch_input(args)), + PANIC_FUNC => void!(self.panic(args)), + DEBUG_FUNC => void!(self.debug(args)), + CCALL_FUNC => some!(self.ccall(args)), + DCALL_FUNC => some!(self.dcall(args)), + SCALL_FUNC => some!(self.scall(args)), + VALUE_FUNC => void!(self.value(args)), + CREATE_FUNC => some!(self.create(args)), + SUICIDE_FUNC => void!(self.suicide(args)), + BLOCKHASH_FUNC => void!(self.blockhash(args)), + BLOCKNUMBER_FUNC => some!(self.blocknumber()), + COINBASE_FUNC => void!(self.coinbase(args)), + DIFFICULTY_FUNC => void!(self.difficulty(args)), + GASLIMIT_FUNC => void!(self.gaslimit(args)), + TIMESTAMP_FUNC => some!(self.timestamp()), + ADDRESS_FUNC => void!(self.address(args)), + SENDER_FUNC => void!(self.sender(args)), + ORIGIN_FUNC => void!(self.origin(args)), + ELOG_FUNC => void!(self.elog(args)), + _ => panic!("env module doesn't provide function at index {}", index), } } } diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index de0b528a1574cf9acc8bd57c9550298a00c04ef2..2b71a1768eb395befbb6c2d1da3b55684a1c19de 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -15,8 +15,9 @@ // along with Parity. If not, see . use std::sync::Arc; +use std::collections::HashMap; use byteorder::{LittleEndian, ByteOrder}; -use util::{U256, H256, Address}; +use ethereum_types::{H256, U256, Address}; use super::WasmInterpreter; use vm::{self, Vm, GasLeft, ActionParams, ActionValue}; @@ -28,6 +29,34 @@ macro_rules! load_sample { } } +macro_rules! reqrep_test { + ($name: expr, $input: expr) => { + reqrep_test!($name, $input, vm::EnvInfo::default(), HashMap::new()) + }; + ($name: expr, $input: expr, $info: expr, $block_hashes: expr) => { + { + ::ethcore_logger::init_log(); + let code = load_sample!($name); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.data = Some($input); + + let mut fake_ext = FakeExt::new().with_wasm(); + fake_ext.info = $info; + fake_ext.blockhashes = $block_hashes; + + let mut interpreter = wasm_interpreter(); + interpreter.exec(params, &mut fake_ext) + .map(|result| match result { + GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + }) + } + }; +} + fn test_finalize(res: Result) -> Result { match res { Ok(GasLeft::Known(gas)) => Ok(gas), @@ -37,7 +66,7 @@ fn test_finalize(res: Result) -> Result { } fn wasm_interpreter() -> WasmInterpreter { - WasmInterpreter::new().expect("wasm interpreter to create without errors") + WasmInterpreter } /// Empty contract does almost nothing except producing 1 (one) local node debug log message @@ -50,14 +79,14 @@ fn empty() { params.address = address.clone(); params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let gas_left = { let mut interpreter = wasm_interpreter(); test_finalize(interpreter.exec(params, &mut ext)).unwrap() }; - assert_eq!(gas_left, U256::from(99_992)); + assert_eq!(gas_left, U256::from(98462)); } // This test checks if the contract deserializes payload header properly. @@ -65,6 +94,8 @@ fn empty() { // logger.wasm writes all these provided fixed header fields to some arbitrary storage keys. #[test] fn logger() { + ::ethcore_logger::init_log(); + let code = load_sample!("logger.wasm"); let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); let sender: Address = "0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d".parse().unwrap(); @@ -77,15 +108,13 @@ fn logger() { params.gas = U256::from(100_000); params.value = ActionValue::transfer(1_000_000_000); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let gas_left = { let mut interpreter = wasm_interpreter(); test_finalize(interpreter.exec(params, &mut ext)).unwrap() }; - println!("ext.store: {:?}", ext.store); - assert_eq!(gas_left, U256::from(99327)); let address_val: H256 = address.into(); assert_eq!( ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"), @@ -109,6 +138,7 @@ fn logger() { U256::from(1_000_000_000), "Logger sets 0x04 key to the trasferred value" ); + assert_eq!(gas_left, U256::from(17_578)); } // This test checks if the contract can allocate memory and pass pointer to the result stream properly. @@ -118,6 +148,8 @@ fn logger() { // if it has any result. #[test] fn identity() { + ::ethcore_logger::init_log(); + let code = load_sample!("identity.wasm"); let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); @@ -125,7 +157,7 @@ fn identity() { params.sender = sender.clone(); params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let (gas_left, result) = { let mut interpreter = wasm_interpreter(); @@ -136,13 +168,12 @@ fn identity() { } }; - assert_eq!(gas_left, U256::from(99_672)); - assert_eq!( Address::from_slice(&result), sender, "Idenity test contract does not return the sender passed" ); + assert_eq!(gas_left, U256::from(98_408)); } // Dispersion test sends byte array and expect the contract to 'disperse' the original elements with @@ -151,6 +182,8 @@ fn identity() { // This also tests byte-perfect memory allocation and in/out ptr lifecycle. #[test] fn dispersion() { + ::ethcore_logger::init_log(); + let code = load_sample!("dispersion.wasm"); let mut params = ActionParams::default(); @@ -159,7 +192,7 @@ fn dispersion() { params.data = Some(vec![ 0u8, 125, 197, 255, 19 ]); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let (gas_left, result) = { let mut interpreter = wasm_interpreter(); @@ -170,12 +203,11 @@ fn dispersion() { } }; - assert_eq!(gas_left, U256::from(99_270)); - assert_eq!( result, vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0] ); + assert_eq!(gas_left, U256::from(94_013)); } #[test] @@ -188,7 +220,7 @@ fn suicide_not() { params.data = Some(vec![ 0u8 ]); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let (gas_left, result) = { let mut interpreter = wasm_interpreter(); @@ -199,16 +231,17 @@ fn suicide_not() { } }; - assert_eq!(gas_left, U256::from(99_578)); - assert_eq!( result, vec![0u8] ); + assert_eq!(gas_left, U256::from(94_984)); } #[test] fn suicide() { + ::ethcore_logger::init_log(); + let code = load_sample!("suicidal.wasm"); let refund: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); @@ -220,7 +253,7 @@ fn suicide() { args.extend(refund.to_vec()); params.data = Some(args); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let gas_left = { let mut interpreter = wasm_interpreter(); @@ -233,8 +266,8 @@ fn suicide() { } }; - assert_eq!(gas_left, U256::from(99_621)); assert!(ext.suicides.contains(&refund)); + assert_eq!(gas_left, U256::from(94_925)); } #[test] @@ -247,7 +280,7 @@ fn create() { params.data = Some(vec![0u8, 2, 4, 8, 16, 32, 64, 128]); params.value = ActionValue::transfer(1_000_000_000); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let gas_left = { let mut interpreter = wasm_interpreter(); @@ -264,7 +297,7 @@ fn create() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Create, - gas: U256::from(99_674), + gas: U256::from(60_914), sender_address: None, receive_address: None, value: Some(1_000_000_000.into()), @@ -272,9 +305,52 @@ fn create() { code_address: None, } )); - assert_eq!(gas_left, U256::from(99_596)); + assert_eq!(gas_left, U256::from(60_900)); } +#[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().with_wasm(); + 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(93_511)); +} #[test] fn call_code() { @@ -291,7 +367,7 @@ fn call_code() { params.data = Some(Vec::new()); params.value = ActionValue::transfer(1_000_000_000); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let (gas_left, result) = { let mut interpreter = wasm_interpreter(); @@ -306,7 +382,7 @@ fn call_code() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, - gas: U256::from(99_069), + gas: U256::from(20_000), sender_address: Some(sender), receive_address: Some(receiver), value: None, @@ -314,11 +390,11 @@ fn call_code() { code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()), } )); - assert_eq!(gas_left, U256::from(94144)); // siphash result let res = LittleEndian::read_u32(&result[..]); assert_eq!(res, 4198595614); + assert_eq!(gas_left, U256::from(92_381)); } #[test] @@ -327,6 +403,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(); @@ -335,8 +412,9 @@ 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(); + let mut ext = FakeExt::new().with_wasm(); let (gas_left, result) = { let mut interpreter = wasm_interpreter(); @@ -351,19 +429,20 @@ fn call_static() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, - gas: U256::from(99_069), - 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()), } )); - assert_eq!(gas_left, U256::from(94144)); // siphash result let res = LittleEndian::read_u32(&result[..]); assert_eq!(res, 317632590); + + assert_eq!(gas_left, U256::from(92_381)); } // Realloc test @@ -375,7 +454,7 @@ fn realloc() { params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.data = Some(vec![0u8]); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); let (gas_left, result) = { let mut interpreter = wasm_interpreter(); @@ -385,21 +464,45 @@ fn realloc() { GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), } }; - assert_eq!(gas_left, U256::from(99432)); assert_eq!(result, vec![0u8; 2]); + assert_eq!(gas_left, U256::from(94_372)); +} + +#[test] +fn alloc() { + let code = load_sample!("alloc.wasm"); + + let mut params = ActionParams::default(); + params.gas = U256::from(10_000_000); + params.code = Some(Arc::new(code)); + params.data = Some(vec![0u8]); + let mut ext = FakeExt::new().with_wasm(); + + let (gas_left, result) = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => { panic!("alloc test should return payload"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + } + }; + assert_eq!(result, vec![5u8; 1024*450]); + assert_eq!(gas_left, U256::from(6_506_844)); } // Tests that contract's ability to read from a storage // Test prepopulates address into storage, than executes a contract which read that address from storage and write this address into result #[test] fn storage_read() { + ::ethcore_logger::init_log(); + let code = load_sample!("storage_read.wasm"); let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); let mut params = ActionParams::default(); params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); - let mut ext = FakeExt::new(); + let mut ext = FakeExt::new().with_wasm(); ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into()); let (gas_left, result) = { @@ -411,33 +514,34 @@ fn storage_read() { } }; - assert_eq!(gas_left, U256::from(99682)); assert_eq!(Address::from(&result[12..32]), address); + assert_eq!(gas_left, U256::from(98_298)); } -macro_rules! reqrep_test { - ($name: expr, $input: expr) => { - { - ::ethcore_logger::init_log(); - let code = load_sample!($name); - - let mut params = ActionParams::default(); - params.gas = U256::from(100_000); - params.code = Some(Arc::new(code)); - params.data = Some($input); +// Tests keccak calculation +// keccak.wasm runs wasm-std::keccak function on data param and returns hash +#[test] +fn keccak() { + ::ethcore_logger::init_log(); + let code = load_sample!("keccak.wasm"); - let (gas_left, result) = { - let mut interpreter = wasm_interpreter(); - let result = interpreter.exec(params, &mut FakeExt::new()).expect("Interpreter to execute without any errors"); - match result { - GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); }, - GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), - } - }; + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.data = Some(b"something".to_vec()); + let mut ext = FakeExt::new().with_wasm(); - (gas_left, result) + let (gas_left, result) = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => { panic!("keccak should return payload"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), } - } + }; + + assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); + assert_eq!(gas_left, U256::from(84_240)); } // math_* tests check the ability of wasm contract to perform big integer operations @@ -460,13 +564,13 @@ fn math_add() { arg_b.to_big_endian(&mut args[33..65]); args.to_vec() } - ); + ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(98087)); assert_eq!( U256::from_dec_str("1888888888888888888888888888887").unwrap(), (&result[..]).into() ); + assert_eq!(gas_left, U256::from(93_814)); } // multiplication @@ -482,16 +586,16 @@ fn math_mul() { arg_b.to_big_endian(&mut args[33..65]); args.to_vec() } - ); + ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(97236)); assert_eq!( U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), (&result[..]).into() ); + assert_eq!(gas_left, U256::from(93_300)); } -// substraction +// subtraction #[test] fn math_sub() { let (gas_left, result) = reqrep_test!( @@ -504,13 +608,34 @@ fn math_sub() { arg_b.to_big_endian(&mut args[33..65]); args.to_vec() } - ); + ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(98131)); assert_eq!( U256::from_dec_str("111111111111111111111111111111").unwrap(), (&result[..]).into() ); + assert_eq!(gas_left, U256::from(93_826)); +} + +// subtraction with overflow +#[test] +fn math_sub_with_overflow() { + let result = reqrep_test!( + "math.wasm", + { + let mut args = [2u8; 65]; + let arg_a = U256::from_dec_str("888888888888888888888888888888").unwrap(); + let arg_b = U256::from_dec_str("999999999999999999999999999999").unwrap(); + arg_a.to_big_endian(&mut args[1..33]); + arg_b.to_big_endian(&mut args[33..65]); + args.to_vec() + } + ); + + match result { + Err(vm::Error::Wasm(_)) => {}, + _ => panic!("Unexpected result {:?}", result), + } } #[test] @@ -525,11 +650,207 @@ fn math_div() { arg_b.to_big_endian(&mut args[33..65]); args.to_vec() } - ); + ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(91420)); assert_eq!( U256::from_dec_str("1125000").unwrap(), (&result[..]).into() ); + assert_eq!(gas_left, U256::from(90_603)); +} + +#[test] +fn storage_metering() { + ::ethcore_logger::init_log(); + + // #1 + let mut ext = FakeExt::new().with_wasm(); + + let code = Arc::new(load_sample!("setter.wasm")); + let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = Some(code.clone()); + params.data = Some(vec![ + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, + ]); + + let gas_left = { + let mut interpreter = wasm_interpreter(); + test_finalize(interpreter.exec(params, &mut ext)).unwrap() + }; + + // 0 -> not 0 + assert_eq!(gas_left, U256::from(74_338)); + + // #2 + + let mut params = ActionParams::default(); + params.address = address.clone(); + params.gas = U256::from(100_000); + params.code = Some(code.clone()); + params.data = Some(vec![ + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x6b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, + ]); + + let gas_left = { + let mut interpreter = wasm_interpreter(); + test_finalize(interpreter.exec(params, &mut ext)).unwrap() + }; + + // not 0 -> not 0 + assert_eq!(gas_left, U256::from(89_338)); +} + +// This test checks the ability of wasm contract to invoke +// varios blockchain runtime methods +#[test] +fn externs() { + let (gas_left, result) = reqrep_test!( + "externs.wasm", + Vec::new(), + vm::EnvInfo { + number: 0x9999999999u64.into(), + author: "efefefefefefefefefefefefefefefefefefefef".parse().unwrap(), + timestamp: 0x8888888888u64.into(), + difficulty: H256::from("0f1f2f3f4f5f6f7f8f9fafbfcfdfefff0d1d2d3d4d5d6d7d8d9dadbdcdddedfd").into(), + gas_limit: 0x777777777777u64.into(), + last_hashes: Default::default(), + gas_used: 0.into(), + }, + { + let mut hashes = HashMap::new(); + hashes.insert( + U256::from(0), + H256::from("9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d") + ); + hashes.insert( + U256::from(1), + H256::from("7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b") + ); + hashes + } + ).expect("Interpreter to execute without any errors"); + + assert_eq!( + &result[0..64].to_vec(), + &vec![ + 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, + 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, + ], + "Block hashes requested and returned do not match" + ); + + assert_eq!( + &result[64..84].to_vec(), + &vec![ + 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, + ], + "Coinbase requested and returned does not match" + ); + + assert_eq!( + &result[84..92].to_vec(), + &vec![ + 0x88, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00 + ], + "Timestamp requested and returned does not match" + ); + + assert_eq!( + &result[92..100].to_vec(), + &vec![ + 0x99, 0x99, 0x99, 0x99, 0x99, 0x00, 0x00, 0x00 + ], + "Block number requested and returned does not match" + ); + + assert_eq!( + &result[100..132].to_vec(), + &vec![ + 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, + 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff, + 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, + 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd, + ], + "Difficulty requested and returned does not match" + ); + + assert_eq!( + &result[132..164].to_vec(), + &vec![ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, + ], + "Gas limit requested and returned does not match" + ); + + assert_eq!(gas_left, U256::from(92_110)); +} + +#[test] +fn embedded_keccak() { + ::ethcore_logger::init_log(); + let mut code = load_sample!("keccak.wasm"); + code.extend_from_slice(b"something"); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.params_type = vm::ParamsType::Embedded; + + let mut ext = FakeExt::new().with_wasm(); + + let (gas_left, result) = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => { panic!("keccak should return payload"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + } + }; + + assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); + assert_eq!(gas_left, U256::from(84_240)); +} + +/// This test checks the correctness of log extern +/// Target test puts one event with two topic [keccak(input), reverse(keccak(input))] +/// and reversed input as a data +#[test] +fn events() { + ::ethcore_logger::init_log(); + let code = load_sample!("events.wasm"); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.data = Some(b"something".to_vec()); + + let mut ext = FakeExt::new().with_wasm(); + + let (gas_left, result) = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => { panic!("events should return payload"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + } + }; + + assert_eq!(ext.logs.len(), 1); + let log_entry = &ext.logs[0]; + assert_eq!(log_entry.topics.len(), 2); + assert_eq!(&log_entry.topics[0], &H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); + assert_eq!(&log_entry.topics[1], &H256::from("871d5ea37430753faab7dff7a7187783517d83bd822c02e28a164c887e1d3768")); + assert_eq!(&log_entry.data, b"gnihtemos"); + + assert_eq!(&result, b"gnihtemos"); + assert_eq!(gas_left, U256::from(81_292)); } diff --git a/ethcrypto/Cargo.toml b/ethcrypto/Cargo.toml index a84032f2624705b72b98dcb6d56eebb3ac62dab2..dfa351023cd1dce00acb8d57937c20028247d438 100644 --- a/ethcrypto/Cargo.toml +++ b/ethcrypto/Cargo.toml @@ -6,7 +6,11 @@ authors = ["Parity Technologies "] [dependencies] rust-crypto = "0.2.36" tiny-keccak = "1.3" -eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } -ethkey = { path = "../ethkey" } -ethcore-bigint = { path = "../util/bigint" } -subtle = "0.1" +eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", optional = true } +ethkey = { path = "../ethkey", optional = true } +ethereum-types = "0.2" +subtle = "0.5" + +[features] +default = ["secp256k1"] +secp256k1 = ["eth-secp256k1", "ethkey"] diff --git a/ethcrypto/README.md b/ethcrypto/README.md new file mode 100644 index 0000000000000000000000000000000000000000..130d27f3ccb65cc6fd4c2bd569acc9575f34dcd9 --- /dev/null +++ b/ethcrypto/README.md @@ -0,0 +1,5 @@ +# Ethcrypto + +General cryptographic utilities for Ethereum. + +By default, this library is compiled with the `secp256k1` feature, which provides ECDH and ECIES capability on that curve. It can be compiled without to avoid a dependency on the `libsecp256k1` library. diff --git a/ethcrypto/src/lib.rs b/ethcrypto/src/lib.rs index 3d34a7975bb2edf6827b19e6d1ce23ac97405d6c..caa4cf77c4d80bfde6824fe5e1c8c4de00ce9b11 100644 --- a/ethcrypto/src/lib.rs +++ b/ethcrypto/src/lib.rs @@ -17,18 +17,23 @@ //! Crypto utils used ethstore and network. extern crate crypto as rcrypto; -extern crate ethcore_bigint as bigint; -extern crate ethkey; -extern crate secp256k1; +extern crate ethereum_types; extern crate subtle; extern crate tiny_keccak; +#[cfg(feature = "secp256k1")] +extern crate secp256k1; +#[cfg(feature = "secp256k1")] +extern crate ethkey; + use std::fmt; use tiny_keccak::Keccak; use rcrypto::pbkdf2::pbkdf2; use rcrypto::scrypt::{scrypt, ScryptParams}; use rcrypto::sha2::Sha256; use rcrypto::hmac::Hmac; + +#[cfg(feature = "secp256k1")] use secp256k1::Error as SecpError; pub const KEY_LENGTH: usize = 32; @@ -59,6 +64,7 @@ impl fmt::Display for ScryptError { #[derive(PartialEq, Debug)] pub enum Error { + #[cfg(feature = "secp256k1")] Secp(SecpError), Scrypt(ScryptError), InvalidMessage, @@ -73,6 +79,7 @@ impl From for Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let s = match *self { + #[cfg(feature = "secp256k1")] Error::Secp(ref err) => err.to_string(), Error::Scrypt(ref err) => err.to_string(), Error::InvalidMessage => "Invalid message".into(), @@ -88,6 +95,7 @@ impl Into for Error { } } +#[cfg(feature = "secp256k1")] impl From for Error { fn from(e: SecpError) -> Self { Error::Secp(e) @@ -174,7 +182,7 @@ pub mod aes { } /// ECDH functions -#[cfg_attr(feature="dev", allow(similar_names))] +#[cfg(feature = "secp256k1")] pub mod ecdh { use secp256k1::{ecdh, key, Error as SecpError}; use ethkey::{Secret, Public, SECP256K1}; @@ -199,15 +207,15 @@ pub mod ecdh { } /// ECIES function -#[cfg_attr(feature="dev", allow(similar_names))] +#[cfg(feature = "secp256k1")] pub mod ecies { use rcrypto::digest::Digest; use rcrypto::sha2::Sha256; use rcrypto::hmac::Hmac; use rcrypto::mac::Mac; - use bigint::hash::H128; + use ethereum_types::H128; use ethkey::{Random, Generator, Public, Secret}; - use {Error, ecdh, aes, Keccak256}; + use {Error, ecdh, aes}; /// Encrypt a message with a public key, writing an HMAC covering both /// the plaintext and authenticated data. @@ -227,7 +235,7 @@ pub mod ecies { hasher.result(&mut mkey); let ekey = &key[0..16]; - let mut msg = vec![0u8; (1 + 64 + 16 + plain.len() + 32)]; + let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32]; msg[0] = 0x04u8; { let msgd = &mut msg[1..]; @@ -249,33 +257,6 @@ pub mod ecies { Ok(msg) } - /// Encrypt a message with a public key and no HMAC - pub fn encrypt_single_message(public: &Public, plain: &[u8]) -> Result, Error> { - let r = Random.generate() - .expect("context known to have key-generation capabilities"); - - let z = ecdh::agree(r.secret(), public)?; - let mut key = [0u8; 32]; - let mut mkey = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - let mut hasher = Sha256::new(); - let mkey_material = &key[16..32]; - hasher.input(mkey_material); - hasher.result(&mut mkey); - let ekey = &key[0..16]; - - let mut msgd = vec![0u8; (64 + plain.len())]; - { - r.public().copy_to(&mut msgd[0..64]); - let iv = H128::from_slice(&z.keccak256()[0..16]); - { - let cipher = &mut msgd[64..(64 + plain.len())]; - aes::encrypt(ekey, &iv, plain, cipher); - } - } - Ok(msgd) - } - /// Decrypt a message with a secret key, checking HMAC for ciphertext /// and authenticated data validity. pub fn decrypt(secret: &Secret, auth_data: &[u8], encrypted: &[u8]) -> Result, Error> { @@ -310,7 +291,7 @@ pub mod ecies { hmac.raw_result(&mut mac); // constant time compare to avoid timing attack. - if ::subtle::arrays_equal(&mac[..], msg_mac) != 1 { + if ::subtle::slices_equal(&mac[..], msg_mac) != 1 { return Err(Error::InvalidMessage); } @@ -319,33 +300,6 @@ pub mod ecies { Ok(msg) } - /// Decrypt single message with a secret key and no HMAC. - pub fn decrypt_single_message(secret: &Secret, encrypted: &[u8]) -> Result, Error> { - let meta_len = 64; - if encrypted.len() < meta_len { - return Err(Error::InvalidMessage); //invalid message: publickey - } - - let e = encrypted; - let p = Public::from_slice(&e[0..64]); - let z = ecdh::agree(secret, &p)?; - let mut key = [0u8; 32]; - kdf(&z, &[0u8; 0], &mut key); - let ekey = &key[0..16]; - let mkey_material = &key[16..32]; - let mut hasher = Sha256::new(); - let mut mkey = [0u8; 32]; - hasher.input(mkey_material); - hasher.result(&mut mkey); - - let clen = encrypted.len() - meta_len; - let cipher = &e[64..(64+clen)]; - let mut msg = vec![0u8; clen]; - let iv = H128::from_slice(&z.keccak256()[0..16]); - aes::decrypt(ekey, &iv, cipher, &mut msg[..]); - Ok(msg) - } - fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) { let mut hasher = Sha256::new(); // SEC/ISO/Shoup specify counter size SHOULD be equivalent @@ -386,15 +340,5 @@ mod tests { let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap(); assert_eq!(decrypted[..message.len()], message[..]); } - - #[test] - fn ecies_shared_single() { - let kp = Random.generate().unwrap(); - let message = b"So many books, so little time"; - let encrypted = ecies::encrypt_single_message(kp.public(), message).unwrap(); - assert!(encrypted[..] != message[..]); - let decrypted = ecies::decrypt_single_message(kp.secret(), &encrypted).unwrap(); - assert_eq!(decrypted[..message.len()], message[..]); - } } diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml index 519accadfe1eb86c462646e0c1b4bee6900920d3..a3e903271beab2208671c744479261ac170424af 100644 --- a/ethkey/Cargo.toml +++ b/ethkey/Cargo.toml @@ -1,14 +1,17 @@ [package] name = "ethkey" -version = "0.2.0" +version = "0.3.0" authors = ["Parity Technologies "] [dependencies] -rand = "0.3.14" -lazy_static = "0.2" -tiny-keccak = "1.3" +byteorder = "1.0" +edit-distance = "2.0" eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" } -rustc-hex = "1.0" -ethcore-bigint = { path = "../util/bigint" } +ethereum-types = "0.2" +lazy_static = "1.0" +log = "0.3" +parity-wordlist = "1.2" +rand = "0.4" rust-crypto = "0.2" -byteorder = "1.0" +rustc-hex = "1.0" +tiny-keccak = "1.3" diff --git a/ethkey/README.md b/ethkey/README.md index 3886338ea83118baae61ae9693c2c9d0366b7658..12161b3770db43acdf2ccfc4e4c1409da9ba9485 100644 --- a/ethkey/README.md +++ b/ethkey/README.md @@ -16,13 +16,13 @@ Ethereum keys generator. Copyright 2016, 2017 Parity Technologies (UK) Ltd Usage: - ethkey info [options] + ethkey info [options] ethkey generate random [options] - ethkey generate prefix [options] - ethkey generate brain [options] + ethkey generate prefix [options] ethkey sign ethkey verify public ethkey verify address
+ ethkey recover
ethkey [-h | --help] Options: @@ -30,15 +30,15 @@ Options: -s, --secret Display only the secret. -p, --public Display only the public. -a, --address Display only the address. + -b, --brain Use parity brain wallet algorithm. Commands: info Display public and address of the secret. - generate Generates new ethereum key. - random Random generation. - prefix Random generation, but address must start with a prefix - brain Generate new key from string seed. + generate random Generates new random ethereum key. + generate prefix Random generation, but address must start with a prefix. sign Sign message using secret. verify Verify signer of the signature. + recover Try to find brain phrase matching given address from partial phrase. ``` ### Examples @@ -60,20 +60,22 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5 -- -#### `generate brain ` -*Generate new brain-wallet keypair using 16384 iterations.* -- `` - brain-wallet seed, any string +#### `info --brain ` +*Display info about private key generate from brain wallet recovery phrase.* +- `` - Parity recovery phrase, 12 words ``` -ethkey generate brain "this is sparta" +ethkey info --brain "this is sparta" ``` ``` -secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55 -public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124 -address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5 +The recover phrase was not generated by Parity: The word 'this' does not come from the dictionary. + +secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2 +public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4 +address: 006e27b6a72e1f34c626762f3c4761547aff1421 ``` -- @@ -93,14 +95,30 @@ address: a8fa5dd30a87bb9e3288d604eb74949c515ab66e -- -#### `generate prefix ` +#### `generate random --brain` +*Generate new keypair with recovery phrase randomly.* + +``` +ethkey generate random --brain +``` + +``` +recovery phrase: thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octagon +secret: 001ce488d50d2f7579dc190c4655f32918d505cee3de63bddc7101bc91c0c2f0 +public: 4e19a5fdae82596e1485c69b687c9cc52b5078e5b0668ef3ce8543cd90e712cb00df822489bc1f1dcb3623538a54476c7b3def44e1a51dc174e86448b63f42d0 +address: 00cf3711cbd3a1512570639280758118ba0b2bcb +``` + + +-- + +#### `generate prefix ` *Generate new keypair randomly with address starting with prefix.* - `` - desired address prefix, 0 - 32 bytes long. -- `` - maximum number of tries before generation is assumed to be a failure. ``` -ethkey generate prefix ff 1000 +ethkey generate prefix ff ``` ``` @@ -111,6 +129,24 @@ address: fff7e25dff2aa60f61f9d98130c8646a01f31649 -- +#### `generate prefix --brain ` +*Generate new keypair with recovery phrase randomly with address starting with prefix.* + +- `` - desired address prefix, 0 - 32 bytes long. + +``` +ethkey generate prefix --brain 00cf +``` + +``` +recovery phrase: thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octagon +secret: 001ce488d50d2f7579dc190c4655f32918d505cee3de63bddc7101bc91c0c2f0 +public: 4e19a5fdae82596e1485c69b687c9cc52b5078e5b0668ef3ce8543cd90e712cb00df822489bc1f1dcb3623538a54476c7b3def44e1a51dc174e86448b63f42d0 +address: 00cf3711cbd3a1512570639280758118ba0b2bcb +``` + +-- + #### `sign ` *Sign a message with a secret.* @@ -159,9 +195,32 @@ ethkey verify address 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6 true ``` +-- + +#### `recover
` +*Try to recover an account given expected address and partial (too short or with invalid words) recovery phrase.* + +- `
` - ethereum address, 20 bytes long +- `` - known phrase, can be in a form of `thwarting * creamer` + +``` +RUST_LOG="info" ethkey recover "00cf3711cbd3a1512570639280758118ba0b2bcb" "thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octag" +``` + +``` +INFO:ethkey::brain_recover: Invalid word 'octag', looking for potential substitutions. +INFO:ethkey::brain_recover: Closest words: ["ocean", "octagon", "octane", "outage", "tag", "acting", "acts", "aorta", "cage", "chug"] +INFO:ethkey::brain_recover: Starting to test 7776 possible combinations. + +thwarting scandal creamer nuzzle asparagus blast crouch trusting anytime elixir frenzied octagon +secret: 001ce488d50d2f7579dc190c4655f32918d505cee3de63bddc7101bc91c0c2f0 +public: 4e19a5fdae82596e1485c69b687c9cc52b5078e5b0668ef3ce8543cd90e712cb00df822489bc1f1dcb3623538a54476c7b3def44e1a51dc174e86448b63f42d0 +address: 00cf3711cbd3a1512570639280758118ba0b2bcb +``` + -# Ethcore toolchain -*this project is a part of the ethcore toolchain* +# Parity toolchain +*this project is a part of the parity toolchain* - [**ethkey**](https://github.com/paritytech/ethkey) - Ethereum keys generator and signer. - [**ethstore**](https://github.com/paritytech/ethstore) - Ethereum key management. diff --git a/ethkey/cli/Cargo.toml b/ethkey/cli/Cargo.toml index 6921af745f4fccdbd556b3fef04bec0ff954f1cf..779ca2872b95d71c95beddd175f98258b43813d5 100644 --- a/ethkey/cli/Cargo.toml +++ b/ethkey/cli/Cargo.toml @@ -4,12 +4,15 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +docopt = "0.8" +env_logger = "0.4" ethkey = { path = "../" } +panic_hook = { path = "../../util/panic_hook" } +parity-wordlist="1.2" +rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" -rustc-hex = "1.0" -docopt = "0.8" -panic_hook = { path = "../../panic_hook" } +threadpool = "1.7" [[bin]] name = "ethkey" diff --git a/ethkey/cli/src/main.rs b/ethkey/cli/src/main.rs index e60b4583aebbf54538fc86705078cbb89df5b957..9298788f069f6647a193089af055618decb9984d 100644 --- a/ethkey/cli/src/main.rs +++ b/ethkey/cli/src/main.rs @@ -15,32 +15,36 @@ // along with Parity. If not, see . extern crate docopt; +extern crate env_logger; +extern crate ethkey; +extern crate panic_hook; +extern crate parity_wordlist; extern crate rustc_hex; extern crate serde; +extern crate threadpool; + #[macro_use] extern crate serde_derive; -extern crate ethkey; -extern crate panic_hook; -use std::{env, fmt, process}; use std::num::ParseIntError; +use std::{env, fmt, process, io, sync}; + use docopt::Docopt; -use rustc_hex::{ToHex, FromHex, FromHexError}; -use ethkey::{KeyPair, Random, Brain, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address}; -use std::io; +use ethkey::{KeyPair, Random, Brain, BrainPrefix, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address, brain_recover}; +use rustc_hex::{FromHex, FromHexError}; -pub const USAGE: &'static str = r#" +const USAGE: &'static str = r#" Ethereum keys generator. Copyright 2016, 2017 Parity Technologies (UK) Ltd Usage: - ethkey info [options] + ethkey info [options] ethkey generate random [options] - ethkey generate prefix [options] - ethkey generate brain [options] + ethkey generate prefix [options] ethkey sign ethkey verify public ethkey verify address
+ ethkey recover
ethkey [-h | --help] Options: @@ -48,15 +52,15 @@ Options: -s, --secret Display only the secret. -p, --public Display only the public. -a, --address Display only the address. + -b, --brain Use parity brain wallet algorithm. Commands: info Display public and address of the secret. - generate Generates new ethereum key. - random Random generation. - prefix Random generation, but address must start with a prefix - brain Generate new key from string seed. + generate random Generates new random ethereum key. + generate prefix Random generation, but address must start with a prefix. sign Sign message using secret. verify Verify signer of the signature. + recover Try to find brain phrase matching given address from partial phrase. "#; #[derive(Debug, Deserialize)] @@ -65,15 +69,15 @@ struct Args { cmd_generate: bool, cmd_random: bool, cmd_prefix: bool, - cmd_brain: bool, cmd_sign: bool, cmd_verify: bool, cmd_public: bool, cmd_address: bool, + cmd_recover: bool, arg_prefix: String, - arg_iterations: String, - arg_seed: String, arg_secret: String, + arg_secret_or_phrase: String, + arg_known_phrase: String, arg_message: String, arg_public: String, arg_address: String, @@ -81,6 +85,7 @@ struct Args { flag_secret: bool, flag_public: bool, flag_address: bool, + flag_brain: bool, } #[derive(Debug)] @@ -157,6 +162,7 @@ impl DisplayMode { fn main() { panic_hook::set(); + env_logger::init().expect("Logger initialized only once."); match execute(env::args()) { Ok(ok) => println!("{}", ok), @@ -167,10 +173,14 @@ fn main() { } } -fn display(keypair: KeyPair, mode: DisplayMode) -> String { +fn display(result: (KeyPair, Option), mode: DisplayMode) -> String { + let keypair = result.0; match mode { - DisplayMode::KeyPair => format!("{}", keypair), - DisplayMode::Secret => format!("{}", keypair.secret().to_hex()), + DisplayMode::KeyPair => match result.1 { + Some(extra_data) => format!("{}\n{}", extra_data, keypair), + None => format!("{}", keypair) + }, + DisplayMode::Secret => format!("{:?}", keypair.secret()), DisplayMode::Public => format!("{:?}", keypair.public()), DisplayMode::Address => format!("{:?}", keypair.address()), } @@ -182,23 +192,53 @@ fn execute(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator= 1024 { + return Ok(None) + } + } + + Err(EthkeyError::Custom("Couldn't find any results.".into())) + } + })?; + Ok(display((keypair, Some(phrase)), display_mode)) } else { - unreachable!(); + Ok(format!("{}", USAGE)) } } +const BRAIN_WORDS: usize = 12; + +fn validate_phrase(phrase: &str) -> String { + match Brain::validate_phrase(phrase, BRAIN_WORDS) { + Ok(()) => format!("The recovery phrase looks correct.\n"), + Err(err) => format!("The recover phrase was not generated by Parity: {}", err) + } +} + +fn in_threads(prepare: F) -> Result where + O: Send + 'static, + X: Send + 'static, + F: Fn() -> X, + X: FnMut() -> Result, EthkeyError>, +{ + let pool = threadpool::Builder::new().build(); + + let (tx, rx) = sync::mpsc::sync_channel(1); + let is_done = sync::Arc::new(sync::atomic::AtomicBool::default()); + + for _ in 0..pool.max_count() { + let is_done = is_done.clone(); + let tx = tx.clone(); + let mut task = prepare(); + pool.execute(move || { + loop { + if is_done.load(sync::atomic::Ordering::SeqCst) { + return; + } + + let res = match task() { + Ok(None) => continue, + Ok(Some(v)) => Ok(v), + Err(err) => Err(err), + }; + + // We are interested only in the first response. + let _ = tx.send(res); + } + }); + } + + if let Ok(solution) = rx.recv() { + is_done.store(true, sync::atomic::Ordering::SeqCst); + return solution; + } + + Err(EthkeyError::Custom("No results found.".into())) +} + #[cfg(test)] mod tests { use super::execute; @@ -242,13 +357,15 @@ address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned(); #[test] fn brain() { - let command = vec!["ethkey", "generate", "brain", "this is sparta"] + let command = vec!["ethkey", "info", "--brain", "this is sparta"] .into_iter() .map(Into::into) .collect::>(); let expected = -"secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2 +"The recover phrase was not generated by Parity: The word 'this' does not come from the dictionary. + +secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2 public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4 address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned(); assert_eq!(execute(command).unwrap(), expected); @@ -256,7 +373,7 @@ address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned(); #[test] fn secret() { - let command = vec!["ethkey", "generate", "brain", "this is sparta", "--secret"] + let command = vec!["ethkey", "info", "--brain", "this is sparta", "--secret"] .into_iter() .map(Into::into) .collect::>(); @@ -267,7 +384,7 @@ address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned(); #[test] fn public() { - let command = vec!["ethkey", "generate", "brain", "this is sparta", "--public"] + let command = vec!["ethkey", "info", "--brain", "this is sparta", "--public"] .into_iter() .map(Into::into) .collect::>(); @@ -278,7 +395,7 @@ address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned(); #[test] fn address() { - let command = vec!["ethkey", "generate", "brain", "this is sparta", "--address"] + let command = vec!["ethkey", "info", "-b", "this is sparta", "--address"] .into_iter() .map(Into::into) .collect::>(); diff --git a/ethkey/src/brain.rs b/ethkey/src/brain.rs index 8bc9d2cd77c6140d6bc7e23cb44bdf9d6fe52abe..fffae0bed8e08ba9955e502969ec37062cd281ed 100644 --- a/ethkey/src/brain.rs +++ b/ethkey/src/brain.rs @@ -16,6 +16,7 @@ use keccak::Keccak256; use super::{KeyPair, Generator, Secret}; +use parity_wordlist; /// Simple brainwallet. pub struct Brain(String); @@ -24,13 +25,17 @@ impl Brain { pub fn new(s: String) -> Self { Brain(s) } + + pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> { + parity_wordlist::validate_phrase(phrase, expected_words) + } } impl Generator for Brain { type Error = ::Void; - fn generate(self) -> Result { - let seed = self.0; + fn generate(&mut self) -> Result { + let seed = self.0.clone(); let mut secret = seed.into_bytes().keccak256(); let mut i = 0; @@ -43,7 +48,10 @@ impl Generator for Brain { if let Ok(pair) = Secret::from_unsafe_slice(&secret) .and_then(KeyPair::from_secret) { - if pair.address()[0] == 0 { return Ok(pair) } + if pair.address()[0] == 0 { + trace!("Testing: {}, got: {:?}", self.0, pair.address()); + return Ok(pair) + } } }, } diff --git a/ethkey/src/brain_prefix.rs b/ethkey/src/brain_prefix.rs new file mode 100644 index 0000000000000000000000000000000000000000..a4e31e989c969d063dfb36ad600700479deca63a --- /dev/null +++ b/ethkey/src/brain_prefix.rs @@ -0,0 +1,70 @@ +// 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 . + +use super::{Generator, KeyPair, Error, Brain}; +use parity_wordlist as wordlist; + +/// Tries to find brain-seed keypair with address starting with given prefix. +pub struct BrainPrefix { + prefix: Vec, + iterations: usize, + no_of_words: usize, + last_phrase: String, +} + +impl BrainPrefix { + pub fn new(prefix: Vec, iterations: usize, no_of_words: usize) -> Self { + BrainPrefix { + prefix, + iterations, + no_of_words, + last_phrase: String::new(), + } + } + + pub fn phrase(&self) -> &str { + &self.last_phrase + } +} + +impl Generator for BrainPrefix { + type Error = Error; + + fn generate(&mut self) -> Result { + for _ in 0..self.iterations { + let phrase = wordlist::random_phrase(self.no_of_words); + let keypair = Brain::new(phrase.clone()).generate().unwrap(); + if keypair.address().starts_with(&self.prefix) { + self.last_phrase = phrase; + return Ok(keypair) + } + } + + Err(Error::Custom("Could not find keypair".into())) + } +} + +#[cfg(test)] +mod tests { + use {Generator, BrainPrefix}; + + #[test] + fn prefix_generator() { + let prefix = vec![0x00u8]; + let keypair = BrainPrefix::new(prefix.clone(), usize::max_value(), 12).generate().unwrap(); + assert!(keypair.address().starts_with(&prefix)); + } +} diff --git a/ethkey/src/brain_recover.rs b/ethkey/src/brain_recover.rs new file mode 100644 index 0000000000000000000000000000000000000000..f064c6fd0e1bc6bf9dcc1f4134faf69ef09c66c2 --- /dev/null +++ b/ethkey/src/brain_recover.rs @@ -0,0 +1,175 @@ +// 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 . + +use std::collections::HashSet; + +use edit_distance::edit_distance; +use parity_wordlist; + +use super::{Address, Brain, Generator}; + + +/// Tries to find a phrase for address, given the number +/// of expected words and a partial phrase. +/// +/// Returns `None` if phrase couldn't be found. +pub fn brain_recover( + address: &Address, + known_phrase: &str, + expected_words: usize, +) -> Option { + let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words); + for phrase in it { + let keypair = Brain::new(phrase.clone()).generate().expect("Brain wallets are infallible; qed"); + trace!("Testing: {}, got: {:?}", phrase, keypair.address()); + if &keypair.address() == address { + return Some(phrase); + } + } + + None +} + +fn generate_substitutions(word: &str) -> Vec<&'static str> { + let mut words = parity_wordlist::WORDS.iter().cloned() + .map(|w| (edit_distance(w, word), w)) + .collect::>(); + words.sort_by(|a, b| a.0.cmp(&b.0)); + + words.into_iter() + .map(|pair| pair.1) + .collect() +} + +/// Iterator over possible +pub struct PhrasesIterator { + words: Vec>, + combinations: u64, + indexes: Vec, + has_next: bool, +} + +impl PhrasesIterator { + pub fn from_known_phrase(known_phrase: &str, expected_words: usize) -> Self { + let known_words = parity_wordlist::WORDS.iter().cloned().collect::>(); + let mut words = known_phrase.split(' ') + .map(|word| match known_words.get(word) { + None => { + info!("Invalid word '{}', looking for potential substitutions.", word); + let substitutions = generate_substitutions(word); + info!("Closest words: {:?}", &substitutions[..10]); + substitutions + }, + Some(word) => vec![*word], + }) + .collect::>(); + + // add missing words + if words.len() < expected_words { + let to_add = expected_words - words.len(); + info!("Number of words is insuficcient adding {} more.", to_add); + for _ in 0..to_add { + words.push(parity_wordlist::WORDS.iter().cloned().collect()); + } + } + + // start searching + PhrasesIterator::new(words) + } + + pub fn new(words: Vec>) -> Self { + let combinations = words.iter().fold(1u64, |acc, x| acc * x.len() as u64); + let indexes = words.iter().map(|_| 0).collect(); + info!("Starting to test {} possible combinations.", combinations); + + PhrasesIterator { + words, + combinations, + indexes, + has_next: combinations > 0, + } + } + + pub fn combinations(&self) -> u64 { + self.combinations + } + + fn current(&self) -> String { + let mut s = self.words[0][self.indexes[0]].to_owned(); + for i in 1..self.indexes.len() { + s.push(' '); + s.push_str(self.words[i][self.indexes[i]]); + } + s + } + + fn next_index(&mut self) -> bool { + let mut pos = self.indexes.len(); + while pos > 0 { + pos -= 1; + self.indexes[pos] += 1; + if self.indexes[pos] >= self.words[pos].len() { + self.indexes[pos] = 0; + } else { + return true; + } + } + + false + } +} + +impl Iterator for PhrasesIterator { + type Item = String; + + fn next(&mut self) -> Option { + if !self.has_next { + return None; + } + + let phrase = self.current(); + self.has_next = self.next_index(); + Some(phrase) + } +} + +#[cfg(test)] +mod tests { + use super::PhrasesIterator; + + + #[test] + fn should_generate_possible_combinations() { + let mut it = PhrasesIterator::new(vec![ + vec!["1", "2", "3"], + vec!["test"], + vec!["a", "b", "c"], + ]); + + assert_eq!(it.combinations(), 9); + assert_eq!(it.next(), Some("1 test a".to_owned())); + assert_eq!(it.next(), Some("1 test b".to_owned())); + assert_eq!(it.next(), Some("1 test c".to_owned())); + assert_eq!(it.next(), Some("2 test a".to_owned())); + assert_eq!(it.next(), Some("2 test b".to_owned())); + assert_eq!(it.next(), Some("2 test c".to_owned())); + assert_eq!(it.next(), Some("3 test a".to_owned())); + assert_eq!(it.next(), Some("3 test b".to_owned())); + assert_eq!(it.next(), Some("3 test c".to_owned())); + assert_eq!(it.next(), None); + } + +} diff --git a/ethkey/src/extended.rs b/ethkey/src/extended.rs index 45ed0547f07c05eeaeac8a4c58a06f46ab66d6a5..23aff0bee8ea3b549e8013baf414466ffe911385 100644 --- a/ethkey/src/extended.rs +++ b/ethkey/src/extended.rs @@ -18,7 +18,7 @@ use secret::Secret; use Public; -use bigint::hash::H256; +use ethereum_types::H256; pub use self::derivation::Error as DerivationError; /// Represents label that can be stored as a part of key derivation @@ -207,12 +207,10 @@ impl ExtendedKeyPair { // Work is based on BIP0032 // https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki mod derivation { - use rcrypto::hmac::Hmac; use rcrypto::mac::Mac; use rcrypto::sha2::Sha512; - use bigint::hash::{H512, H256}; - use bigint::prelude::{U256, U512}; + use ethereum_types::{U256, U512, H512, H256}; use secp256k1::key::{SecretKey, PublicKey}; use SECP256K1; use keccak; @@ -388,7 +386,7 @@ mod tests { use super::{ExtendedSecret, ExtendedPublic, ExtendedKeyPair}; use secret::Secret; use std::str::FromStr; - use bigint::hash::{H128, H256}; + use ethereum_types::{H128, H256}; use super::{derivation, Derivation}; fn master_chain_basic() -> (H256, H256) { @@ -477,8 +475,8 @@ mod tests { .expect("Seed should be valid H128") .to_vec(); - /// private key from bitcoin test vector - /// xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs + // private key from bitcoin test vector + // xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs let test_private = H256::from_str("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35") .expect("Private should be decoded ok"); @@ -489,8 +487,8 @@ mod tests { #[test] fn test_vector_1() { - /// xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 - /// H(0) + // xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7 + // H(0) test_extended( |secret| secret.derive(2147483648.into()), H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea") @@ -500,8 +498,8 @@ mod tests { #[test] fn test_vector_2() { - /// xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs - /// H(0)/1 + // xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs + // H(0)/1 test_extended( |secret| secret.derive(2147483648.into()).derive(1.into()), H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368") diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs index 271a5f166c37d2520faf3e4758b7bd429d091e7c..09a100b74cd93851267abd5009808d97054064b4 100644 --- a/ethkey/src/lib.rs +++ b/ethkey/src/lib.rs @@ -14,18 +14,25 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +// #![warn(missing_docs)] + +extern crate byteorder; +extern crate crypto as rcrypto; +extern crate edit_distance; +extern crate ethereum_types; +extern crate parity_wordlist; extern crate rand; -extern crate tiny_keccak; -extern crate secp256k1; extern crate rustc_hex; -extern crate ethcore_bigint as bigint; -extern crate crypto as rcrypto; -extern crate byteorder; +extern crate secp256k1; +extern crate tiny_keccak; #[macro_use] extern crate lazy_static; +#[macro_use] +extern crate log; mod brain; +mod brain_prefix; mod error; mod keypair; mod keccak; @@ -35,9 +42,12 @@ mod signature; mod secret; mod extended; +pub mod brain_recover; pub mod math; +pub use self::parity_wordlist::Error as WordlistError; pub use self::brain::Brain; +pub use self::brain_prefix::BrainPrefix; pub use self::error::Error; pub use self::keypair::{KeyPair, public_to_address}; pub use self::math::public_is_valid; @@ -47,7 +57,10 @@ pub use self::signature::{sign, verify_public, verify_address, recover, Signatur pub use self::secret::Secret; pub use self::extended::{ExtendedPublic, ExtendedSecret, ExtendedKeyPair, DerivationError, Derivation}; -use bigint::hash::{H160, H256, H512}; +use ethereum_types::H256; + +pub use ethereum_types::{Address, Public}; +pub type Message = H256; lazy_static! { pub static ref SECP256K1: secp256k1::Secp256k1 = secp256k1::Secp256k1::new(); @@ -62,9 +75,5 @@ pub trait Generator { type Error; /// Should be called to generate new keypair. - fn generate(self) -> Result; + fn generate(&mut self) -> Result; } - -pub type Address = H160; -pub type Message = H256; -pub type Public = H512; diff --git a/ethkey/src/math.rs b/ethkey/src/math.rs index 4c875bd8fa19ae1165606308fb2cbd16a067606e..e2426b4fbdff3b37a3166276c8a18cca62b2f41d 100644 --- a/ethkey/src/math.rs +++ b/ethkey/src/math.rs @@ -17,8 +17,7 @@ use super::{SECP256K1, Public, Secret, Error}; use secp256k1::key; use secp256k1::constants::{GENERATOR_X, GENERATOR_Y, CURVE_ORDER}; -use bigint::prelude::U256; -use bigint::hash::H256; +use ethereum_types::{U256, H256}; /// Whether the public key is valid. pub fn public_is_valid(public: &Public) -> bool { diff --git a/ethkey/src/prefix.rs b/ethkey/src/prefix.rs index 25b1ab3f767bbbc0a537873b70076654fd15ccf8..f2ef0f0ffb4610d05cd37e2d9ca3f59e25cdfe58 100644 --- a/ethkey/src/prefix.rs +++ b/ethkey/src/prefix.rs @@ -34,7 +34,7 @@ impl Prefix { impl Generator for Prefix { type Error = Error; - fn generate(self) -> Result { + fn generate(&mut self) -> Result { for _ in 0..self.iterations { let keypair = Random.generate()?; if keypair.address().starts_with(&self.prefix) { diff --git a/ethkey/src/random.rs b/ethkey/src/random.rs index 715dd3cb5832e2e29f30b95fa5bcc4bcd186bee2..b44a4b2ca8015acef2b72882e1f8cafc03fc9fa9 100644 --- a/ethkey/src/random.rs +++ b/ethkey/src/random.rs @@ -23,7 +23,7 @@ pub struct Random; impl Generator for Random { type Error = ::std::io::Error; - fn generate(self) -> Result { + fn generate(&mut self) -> Result { let mut rng = OsRng::new()?; match rng.generate() { Ok(pair) => Ok(pair), @@ -32,10 +32,10 @@ impl Generator for Random { } } -impl<'a> Generator for &'a mut OsRng { +impl Generator for OsRng { type Error = ::Void; - fn generate(self) -> Result { + fn generate(&mut self) -> Result { let (sec, publ) = SECP256K1.generate_keypair(self) .expect("context always created with full capabilities; qed"); diff --git a/ethkey/src/secret.rs b/ethkey/src/secret.rs index 433d8c68e0e1efe2858b98e730afe30fcabce29a..6e0548264f934fc43ce9ba97842799ef3c2b0234 100644 --- a/ethkey/src/secret.rs +++ b/ethkey/src/secret.rs @@ -19,7 +19,7 @@ use std::ops::Deref; use std::str::FromStr; use rustc_hex::ToHex; use secp256k1::key; -use bigint::hash::H256; +use ethereum_types::H256; use {Error, SECP256K1}; #[derive(Clone, PartialEq, Eq)] @@ -34,6 +34,12 @@ impl ToHex for Secret { } impl fmt::Debug for Secret { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "{:?}", self.inner) + } +} + +impl fmt::Display for Secret { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "Secret: 0x{:x}{:x}..{:x}{:x}", self.inner[0], self.inner[1], self.inner[30], self.inner[31]) } @@ -48,6 +54,11 @@ impl Secret { Secret { inner: h } } + /// Creates zero key, which is invalid for crypto operations, but valid for math operation. + pub fn zero() -> Self { + Secret { inner: Default::default() } + } + /// Imports and validates the key. pub fn from_unsafe_slice(key: &[u8]) -> Result { let secret = key::SecretKey::from_slice(&super::SECP256K1, key)?; @@ -61,51 +72,91 @@ impl Secret { /// Inplace add one secret key to another (scalar + scalar) pub fn add(&mut self, other: &Secret) -> Result<(), Error> { - let mut key_secret = self.to_secp256k1_secret()?; - let other_secret = other.to_secp256k1_secret()?; - key_secret.add_assign(&SECP256K1, &other_secret)?; + match (self.is_zero(), other.is_zero()) { + (true, true) | (false, true) => Ok(()), + (true, false) => { + *self = other.clone(); + Ok(()) + }, + (false, false) => { + let mut key_secret = self.to_secp256k1_secret()?; + let other_secret = other.to_secp256k1_secret()?; + key_secret.add_assign(&SECP256K1, &other_secret)?; - *self = key_secret.into(); - Ok(()) + *self = key_secret.into(); + Ok(()) + }, + } } /// Inplace subtract one secret key from another (scalar - scalar) pub fn sub(&mut self, other: &Secret) -> Result<(), Error> { - let mut key_secret = self.to_secp256k1_secret()?; - let mut other_secret = other.to_secp256k1_secret()?; - other_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - key_secret.add_assign(&SECP256K1, &other_secret)?; - - *self = key_secret.into(); - Ok(()) + match (self.is_zero(), other.is_zero()) { + (true, true) | (false, true) => Ok(()), + (true, false) => { + *self = other.clone(); + self.neg() + }, + (false, false) => { + let mut key_secret = self.to_secp256k1_secret()?; + let mut other_secret = other.to_secp256k1_secret()?; + other_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + key_secret.add_assign(&SECP256K1, &other_secret)?; + + *self = key_secret.into(); + Ok(()) + }, + } } /// Inplace decrease secret key (scalar - 1) pub fn dec(&mut self) -> Result<(), Error> { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.add_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + match self.is_zero() { + true => { + *self = key::MINUS_ONE_KEY.into(); + Ok(()) + }, + false => { + let mut key_secret = self.to_secp256k1_secret()?; + key_secret.add_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - *self = key_secret.into(); - Ok(()) + *self = key_secret.into(); + Ok(()) + }, + } } /// Inplace multiply one secret key to another (scalar * scalar) pub fn mul(&mut self, other: &Secret) -> Result<(), Error> { - let mut key_secret = self.to_secp256k1_secret()?; - let other_secret = other.to_secp256k1_secret()?; - key_secret.mul_assign(&SECP256K1, &other_secret)?; + match (self.is_zero(), other.is_zero()) { + (true, true) | (true, false) => Ok(()), + (false, true) => { + *self = Self::zero(); + Ok(()) + }, + (false, false) => { + let mut key_secret = self.to_secp256k1_secret()?; + let other_secret = other.to_secp256k1_secret()?; + key_secret.mul_assign(&SECP256K1, &other_secret)?; - *self = key_secret.into(); - Ok(()) + *self = key_secret.into(); + Ok(()) + }, + } } /// Inplace negate secret key (-scalar) pub fn neg(&mut self) -> Result<(), Error> { - let mut key_secret = self.to_secp256k1_secret()?; - key_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; - - *self = key_secret.into(); - Ok(()) + match self.is_zero() { + true => Ok(()), + false => { + let mut key_secret = self.to_secp256k1_secret()?; + key_secret.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?; + + *self = key_secret.into(); + Ok(()) + }, + } } /// Inplace inverse secret key (1 / scalar) @@ -120,6 +171,10 @@ impl Secret { /// Compute power of secret key inplace (secret ^ pow). /// This function is not intended to be used with large powers. pub fn pow(&mut self, pow: usize) -> Result<(), Error> { + if self.is_zero() { + return Ok(()); + } + match pow { 0 => *self = key::ONE_KEY.into(), 1 => (), diff --git a/ethkey/src/signature.rs b/ethkey/src/signature.rs index 67115c98b48e3adfa55360a9206571b15499f25f..ec225ec011b3d78ed743d7573894401169ef868e 100644 --- a/ethkey/src/signature.rs +++ b/ethkey/src/signature.rs @@ -22,7 +22,7 @@ use std::hash::{Hash, Hasher}; use secp256k1::{Message as SecpMessage, RecoverableSignature, RecoveryId, Error as SecpError}; use secp256k1::key::{SecretKey, PublicKey}; use rustc_hex::{ToHex, FromHex}; -use bigint::hash::{H520, H256}; +use ethereum_types::{H520, H256}; use {Secret, Public, SECP256K1, Error, Message, public_to_address, Address}; /// Signature encoded as RSV components diff --git a/ethstore/Cargo.toml b/ethstore/Cargo.toml index 200dec3668795b2b7cbb6b3dd10b4d93ad5ca739..a504c7f2a55fc9a3449a0c6c431223e6e4956705 100755 --- a/ethstore/Cargo.toml +++ b/ethstore/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "ethstore" -version = "0.1.0" +version = "0.2.0" authors = ["Parity Technologies "] [dependencies] log = "0.3" libc = "0.2" -rand = "0.3" +rand = "0.4" ethkey = { path = "../ethkey" } serde = "1.0" serde_json = "1.0" @@ -16,11 +16,16 @@ rust-crypto = "0.2.36" tiny-keccak = "1.3" time = "0.1.34" itertools = "0.5" -parking_lot = "0.4" +parking_lot = "0.5" ethcrypto = { path = "../ethcrypto" } -ethcore-bigint = { path = "../util/bigint" } +ethereum-types = "0.2" +dir = { path = "../util/dir" } smallvec = "0.4" parity-wordlist = "1.0" +subtle = "0.5" tempdir = "0.3" +[dev-dependencies] +matches = "0.1" + [lib] diff --git a/ethstore/README.md b/ethstore/README.md index 4f7daf4e26d7e6a2edc7865ad3cf434cf42abfaf..c56a24a9314309500b0f94ea55451c864867a5bc 100644 --- a/ethstore/README.md +++ b/ethstore/README.md @@ -21,6 +21,7 @@ Usage: ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore import [--src DIR] [--dir DIR] ethstore import-wallet [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] + ethstore find-wallet-pass ethstore remove
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore sign
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore public
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] @@ -50,6 +51,7 @@ Commands: list List accounts. import Import accounts from src. import-wallet Import presale wallet. + find-wallet-pass Tries to open a wallet with list of passwords given. remove Remove account. sign Sign message. public Displays public key for an address. @@ -164,6 +166,25 @@ ethstore import-wallet ethwallet.json password.txt e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb ``` + +-- + +#### `find-wallet-pass ` +Try to open presale wallet given a list of passwords from a file. +The list of passwords can be generated using e.g. [Phildo/brutedist](https://github.com/Phildo/brutedist). + +- `` - presale wallet path +- `` - possible passwords, file path + +``` +ethstore find-wallet-pass ethwallet.json passwords.txt +``` + +``` +Found password: test +``` + + -- #### `remove
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]` @@ -318,8 +339,8 @@ OK -- -# Ethcore toolchain -*this project is a part of the ethcore toolchain* +# Parity toolchain +*this project is a part of the parity toolchain* - [**ethkey**](https://github.com/paritytech/ethkey) - Ethereum keys generator and signer. - [**ethstore**](https://github.com/paritytech/ethstore) - Ethereum key management. diff --git a/ethstore/cli/Cargo.toml b/ethstore/cli/Cargo.toml index 71215fefefcabcafbf9fff9e47275b75ab7a18c2..f164f0a6722ce217bd779fce4c93f4e67af3f3c7 100644 --- a/ethstore/cli/Cargo.toml +++ b/ethstore/cli/Cargo.toml @@ -4,12 +4,15 @@ version = "0.1.0" authors = ["Parity Technologies "] [dependencies] +docopt = "0.8" +num_cpus = "1.6" rustc-hex = "1.0" serde = "1.0" serde_derive = "1.0" -docopt = "0.8" +parking_lot = "0.5" ethstore = { path = "../" } -panic_hook = { path = "../../panic_hook" } +dir = { path = '../../util/dir' } +panic_hook = { path = "../../util/panic_hook" } [[bin]] name = "ethstore" diff --git a/ethstore/cli/src/crack.rs b/ethstore/cli/src/crack.rs new file mode 100644 index 0000000000000000000000000000000000000000..64eda66e56ed378ed10fb9d9a92377aee03af1bd --- /dev/null +++ b/ethstore/cli/src/crack.rs @@ -0,0 +1,50 @@ +use std::{cmp, thread}; +use std::sync::Arc; +use std::collections::VecDeque; +use parking_lot::Mutex; + +use ethstore::{PresaleWallet, Error}; +use num_cpus; + +pub fn run(passwords: VecDeque, wallet_path: &str) -> Result<(), Error> { + let passwords = Arc::new(Mutex::new(passwords)); + + let mut handles = Vec::new(); + + for _ in 0..num_cpus::get() { + let passwords = passwords.clone(); + let wallet = PresaleWallet::open(&wallet_path)?; + handles.push(thread::spawn(move || { + look_for_password(passwords, wallet); + })); + } + + for handle in handles { + handle.join().map_err(|err| Error::Custom(format!("Error finishing thread: {:?}", err)))?; + } + + Ok(()) +} + +fn look_for_password(passwords: Arc>>, wallet: PresaleWallet) { + let mut counter = 0; + while !passwords.lock().is_empty() { + let package = { + let mut passwords = passwords.lock(); + let len = passwords.len(); + passwords.split_off(cmp::min(len, 32)) + }; + for pass in package { + counter += 1; + match wallet.decrypt(&pass) { + Ok(_) => { + println!("Found password: {}", &pass); + passwords.lock().clear(); + return; + }, + _ if counter % 100 == 0 => print!("."), + _ => {}, + } + } + } +} diff --git a/ethstore/cli/src/main.rs b/ethstore/cli/src/main.rs index 09ccc8cd4df0478bebbd5284d7a2284cbc495654..45f9f6920ee548599c11c28e2dfdc89f3882a98d 100644 --- a/ethstore/cli/src/main.rs +++ b/ethstore/cli/src/main.rs @@ -14,21 +14,28 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -extern crate rustc_hex; +extern crate dir; extern crate docopt; +extern crate ethstore; +extern crate num_cpus; +extern crate panic_hook; +extern crate parking_lot; +extern crate rustc_hex; extern crate serde; + #[macro_use] extern crate serde_derive; -extern crate ethstore; -extern crate panic_hook; -use std::{env, process, fs, fmt}; +use std::collections::VecDeque; use std::io::Read; +use std::{env, process, fs, fmt}; + use docopt::Docopt; +use ethstore::accounts_dir::{KeyDirectory, RootDiskDirectory}; use ethstore::ethkey::Address; -use ethstore::dir::{paths, KeyDirectory, RootDiskDirectory}; -use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, PresaleWallet, - SecretVaultRef, StoreAccountRef}; +use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, PresaleWallet, SecretVaultRef, StoreAccountRef}; + +mod crack; pub const USAGE: &'static str = r#" Ethereum key management. @@ -40,6 +47,7 @@ Usage: ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore import [--src DIR] [--dir DIR] ethstore import-wallet [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] + ethstore find-wallet-pass ethstore remove
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore sign
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] ethstore public
[--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD] @@ -69,6 +77,7 @@ Commands: list List accounts. import Import accounts from src. import-wallet Import presale wallet. + find-wallet-pass Tries to open a wallet with list of passwords given. remove Remove account. sign Sign message. public Displays public key for an address. @@ -86,6 +95,7 @@ struct Args { cmd_list: bool, cmd_import: bool, cmd_import_wallet: bool, + cmd_find_wallet_pass: bool, cmd_remove: bool, cmd_sign: bool, cmd_public: bool, @@ -148,11 +158,11 @@ fn main() { fn key_dir(location: &str) -> Result, Error> { let dir: Box = match location { - "geth" => Box::new(RootDiskDirectory::create(paths::geth(false))?), - "geth-test" => Box::new(RootDiskDirectory::create(paths::geth(true))?), + "geth" => Box::new(RootDiskDirectory::create(dir::geth(false))?), + "geth-test" => Box::new(RootDiskDirectory::create(dir::geth(true))?), path if path.starts_with("parity") => { let chain = path.split('-').nth(1).unwrap_or("ethereum"); - let path = paths::parity(chain); + let path = dir::parity(chain); Box::new(RootDiskDirectory::create(path)?) }, path => Box::new(RootDiskDirectory::create(path)?), @@ -209,8 +219,8 @@ fn execute(command: I) -> Result where I: IntoIterator(command: I) -> Result where I: IntoIterator>(); + crack::run(passwords, &args.arg_path)?; + Ok(format!("Password not found.")) } else if args.cmd_remove { let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?; let password = load_password(&args.arg_password)?; @@ -251,7 +266,7 @@ fn execute(command: I) -> Result where I: IntoIterator. -use std::iter::repeat; use std::str; use ethkey::Secret; use {json, Error, crypto}; @@ -22,6 +21,7 @@ use crypto::Keccak256; use random::Random; use smallvec::SmallVec; use account::{Cipher, Kdf, Aes128Ctr, Pbkdf2, Prf}; +use subtle; /// Encrypted data #[derive(Debug, PartialEq, Clone)] @@ -90,9 +90,7 @@ impl Crypto { // preallocated (on-stack in case of `Secret`) buffer to hold cipher // length = length(plain) as we are using CTR-approach let plain_len = plain.len(); - let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::new(); - ciphertext.grow(plain_len); - ciphertext.extend(repeat(0).take(plain_len)); + let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; plain_len]); // aes-128-ctr with initial vector of iv crypto::aes::encrypt(&derived_left_bits, &iv, plain, &mut *ciphertext); @@ -139,13 +137,11 @@ impl Crypto { let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256(); - if mac != self.mac { + if subtle::slices_equal(&mac, &self.mac) == 0 { return Err(Error::InvalidPassword); } - let mut plain: SmallVec<[u8; 32]> = SmallVec::new(); - plain.grow(expected_len); - plain.extend(repeat(0).take(expected_len)); + let mut plain: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; expected_len]); match self.cipher { Cipher::Aes128Ctr(ref params) => { @@ -163,7 +159,7 @@ impl Crypto { #[cfg(test)] mod tests { use ethkey::{Generator, Random}; - use super::Crypto; + use super::{Crypto, Error}; #[test] fn crypto_with_secret_create() { @@ -174,11 +170,10 @@ mod tests { } #[test] - #[should_panic] fn crypto_with_secret_invalid_password() { let keypair = Random.generate().unwrap(); let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240); - let _ = crypto.secret("this is sparta!").unwrap(); + assert_matches!(crypto.secret("this is sparta!"), Err(Error::InvalidPassword)) } #[test] diff --git a/ethstore/src/dir/disk.rs b/ethstore/src/accounts_dir/disk.rs similarity index 78% rename from ethstore/src/dir/disk.rs rename to ethstore/src/accounts_dir/disk.rs index 3f56ebe4062762e80130e14aef0c83a1d7dd3647..1446118440667bcce4afec375e4e45a4009f6d39 100755 --- a/ethstore/src/dir/disk.rs +++ b/ethstore/src/accounts_dir/disk.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . use std::{fs, io}; +use std::io::Write; use std::path::{PathBuf, Path}; use std::collections::HashMap; use time; @@ -122,6 +123,13 @@ impl DiskDirectory where T: KeyFileManager { Ok(hasher.finish()) } + fn last_modification_date(&self) -> Result { + use std::time::{Duration, UNIX_EPOCH}; + let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or(Duration::default()); + let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64); + Ok(timestamp) + } + /// all accounts found in keys directory fn files_content(&self) -> Result, Error> { // it's not done using one iterator cause @@ -145,31 +153,39 @@ impl DiskDirectory where T: KeyFileManager { ) } - /// insert account with given file name - pub fn insert_with_filename(&self, account: SafeAccount, filename: String) -> Result { + + /// insert account with given filename. if the filename is a duplicate of any stored account and dedup is set to + /// true, a random suffix is appended to the filename. + pub fn insert_with_filename(&self, account: SafeAccount, mut filename: String, dedup: bool) -> Result { + // path to keyfile + let mut keyfile_path = self.path.join(filename.as_str()); + + // check for duplicate filename and append random suffix + if dedup && keyfile_path.exists() { + let suffix = ::random::random_string(4); + filename.push_str(&format!("-{}", suffix)); + keyfile_path.set_file_name(&filename); + } + // update account filename let original_account = account.clone(); let mut account = account; - account.filename = Some(filename.clone()); + account.filename = Some(filename); { - // Path to keyfile - let mut keyfile_path = self.path.clone(); - keyfile_path.push(filename.as_str()); - // save the file let mut file = fs::File::create(&keyfile_path)?; - if let Err(err) = self.key_manager.write(original_account, &mut file).map_err(|e| Error::Custom(format!("{:?}", e))) { - drop(file); - fs::remove_file(keyfile_path).expect("Expected to remove recently created file"); - return Err(err); - } + + // write key content + self.key_manager.write(original_account, &mut file).map_err(|e| Error::Custom(format!("{:?}", e)))?; + + file.flush()?; if let Err(_) = restrict_permissions_to_owner(keyfile_path.as_path()) { - drop(file); - fs::remove_file(keyfile_path).expect("Expected to remove recently created file"); return Err(Error::Io(io::Error::last_os_error())); } + + file.sync_all()?; } Ok(account) @@ -192,17 +208,13 @@ impl KeyDirectory for DiskDirectory where T: KeyFileManager { fn update(&self, account: SafeAccount) -> Result { // Disk store handles updates correctly iff filename is the same - self.insert(account) + let filename = account_filename(&account); + self.insert_with_filename(account, filename, false) } fn insert(&self, account: SafeAccount) -> Result { - // build file path - let filename = account.filename.as_ref().cloned().unwrap_or_else(|| { - let timestamp = time::strftime("%Y-%m-%dT%H-%M-%S", &time::now_utc()).expect("Time-format string is valid."); - format!("UTC--{}Z--{}", timestamp, Uuid::from(account.id)) - }); - - self.insert_with_filename(account, filename) + let filename = account_filename(&account); + self.insert_with_filename(account, filename, true) } fn remove(&self, account: &SafeAccount) -> Result<(), Error> { @@ -226,7 +238,7 @@ impl KeyDirectory for DiskDirectory where T: KeyFileManager { } fn unique_repr(&self) -> Result { - self.files_hash() + self.last_modification_date() } } @@ -278,13 +290,20 @@ impl KeyFileManager for DiskKeyFileManager { } } +fn account_filename(account: &SafeAccount) -> String { + // build file path + account.filename.clone().unwrap_or_else(|| { + let timestamp = time::strftime("%Y-%m-%dT%H-%M-%S", &time::now_utc()).expect("Time-format string is valid."); + format!("UTC--{}Z--{}", timestamp, Uuid::from(account.id)) + }) +} + #[cfg(test)] mod test { extern crate tempdir; use std::{env, fs}; - use super::RootDiskDirectory; - use dir::{KeyDirectory, VaultKey}; + use super::{KeyDirectory, RootDiskDirectory, VaultKey}; use account::SafeAccount; use ethkey::{Random, Generator}; use self::tempdir::TempDir; @@ -310,6 +329,38 @@ mod test { let _ = fs::remove_dir_all(dir); } + #[test] + fn should_handle_duplicate_filenames() { + // given + let mut dir = env::temp_dir(); + dir.push("ethstore_should_handle_duplicate_filenames"); + let keypair = Random.generate().unwrap(); + let password = "hello world"; + let directory = RootDiskDirectory::create(dir.clone()).unwrap(); + + // when + let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); + let filename = "test".to_string(); + let dedup = true; + + directory.insert_with_filename(account.clone(), "foo".to_string(), dedup).unwrap(); + let file1 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap(); + let file2 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap(); + let file3 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap(); + + // then + // the first file should have the original names + assert_eq!(file1, filename); + + // the following duplicate files should have a suffix appended + assert!(file2 != file3); + assert_eq!(file2.len(), filename.len() + 5); + assert_eq!(file3.len(), filename.len() + 5); + + // cleanup + let _ = fs::remove_dir_all(dir); + } + #[test] fn should_manage_vaults() { // given diff --git a/ethstore/src/dir/memory.rs b/ethstore/src/accounts_dir/memory.rs similarity index 89% rename from ethstore/src/dir/memory.rs rename to ethstore/src/accounts_dir/memory.rs index b8c2ad9ff5b549f154b279b4dcdc1dd53b526a0e..bd162b5ef0ce7ca7b4360c323878b32b3cd8634d 100644 --- a/ethstore/src/dir/memory.rs +++ b/ethstore/src/accounts_dir/memory.rs @@ -35,7 +35,7 @@ impl KeyDirectory for MemoryDirectory { fn update(&self, account: SafeAccount) -> Result { let mut lock = self.accounts.write(); - let mut accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new); + let accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new); // If the filename is the same we just need to replace the entry accounts.retain(|acc| acc.filename != account.filename); accounts.push(account.clone()); @@ -44,14 +44,14 @@ impl KeyDirectory for MemoryDirectory { fn insert(&self, account: SafeAccount) -> Result { let mut lock = self.accounts.write(); - let mut accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new); + let accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new); accounts.push(account.clone()); Ok(account) } fn remove(&self, account: &SafeAccount) -> Result<(), Error> { let mut accounts = self.accounts.write(); - let is_empty = if let Some(mut accounts) = accounts.get_mut(&account.address) { + let is_empty = if let Some(accounts) = accounts.get_mut(&account.address) { if let Some(position) = accounts.iter().position(|acc| acc == account) { accounts.remove(position); } diff --git a/ethstore/src/dir/mod.rs b/ethstore/src/accounts_dir/mod.rs similarity index 99% rename from ethstore/src/dir/mod.rs rename to ethstore/src/accounts_dir/mod.rs index b6e168f6e47788f290f719ef3ef25125657864fc..ec72d05da32895864a92536df06150549153015e 100755 --- a/ethstore/src/dir/mod.rs +++ b/ethstore/src/accounts_dir/mod.rs @@ -22,7 +22,6 @@ use {SafeAccount, Error}; mod disk; mod memory; mod vault; -pub mod paths; /// `VaultKeyDirectory::set_key` error #[derive(Debug)] diff --git a/ethstore/src/dir/vault.rs b/ethstore/src/accounts_dir/vault.rs similarity index 99% rename from ethstore/src/dir/vault.rs rename to ethstore/src/accounts_dir/vault.rs index a7b3516436e287e104ea0dfec4e9e817ef6f7dbd..1ef85402a7ac91b0ecd4e9a73d4ad435cafdd040 100755 --- a/ethstore/src/dir/vault.rs +++ b/ethstore/src/accounts_dir/vault.rs @@ -106,7 +106,7 @@ impl VaultDiskDirectory { fn copy_to_vault(&self, vault: &VaultDiskDirectory) -> Result<(), Error> { for account in self.load()? { let filename = account.filename.clone().expect("self is instance of DiskDirectory; DiskDirectory fills filename in load; qed"); - vault.insert_with_filename(account, filename)?; + vault.insert_with_filename(account, filename, true)?; } Ok(()) @@ -284,7 +284,7 @@ mod test { use std::fs; use std::io::Write; use std::path::PathBuf; - use dir::VaultKey; + use super::VaultKey; use super::{VAULT_FILE_NAME, check_vault_name, make_vault_dir_path, create_vault_file, read_vault_file, VaultDiskDirectory}; use self::tempdir::TempDir; diff --git a/ethstore/src/dir/paths.rs b/ethstore/src/dir/paths.rs deleted file mode 100644 index db3178cff8d54037277f7338895aff401f590970..0000000000000000000000000000000000000000 --- a/ethstore/src/dir/paths.rs +++ /dev/null @@ -1,96 +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 . - -//! Common tools paths. - -use std::env; -use std::path::PathBuf; - -fn home() -> PathBuf { - env::home_dir().expect("Failed to get home dir") -} - -/// Geth path -pub fn geth(testnet: bool) -> PathBuf { - let mut base = geth_base(); - if testnet { - base.push("testnet"); - } - base.push("keystore"); - base -} - -/// Parity path for specific chain -pub fn parity(chain: &str) -> PathBuf { - let mut base = parity_base(); - base.push(chain); - base -} - -#[cfg(target_os = "macos")] -fn parity_base() -> PathBuf { - let mut home = home(); - home.push("Library"); - home.push("Application Support"); - home.push("io.parity.ethereum"); - home.push("keys"); - home -} - -#[cfg(windows)] -fn parity_base() -> PathBuf { - let mut home = home(); - home.push("AppData"); - home.push("Roaming"); - home.push("Parity"); - home.push("Ethereum"); - home.push("keys"); - home -} - -#[cfg(not(any(target_os = "macos", windows)))] -fn parity_base() -> PathBuf { - let mut home = home(); - home.push(".local"); - home.push("share"); - home.push("io.parity.ethereum"); - home.push("keys"); - home -} - -#[cfg(target_os = "macos")] -fn geth_base() -> PathBuf { - let mut home = home(); - home.push("Library"); - home.push("Ethereum"); - home -} - -#[cfg(windows)] -fn geth_base() -> PathBuf { - let mut home = home(); - home.push("AppData"); - home.push("Roaming"); - home.push("Ethereum"); - home -} - -#[cfg(not(any(target_os = "macos", windows)))] -fn geth_base() -> PathBuf { - let mut home = home(); - home.push(".ethereum"); - home -} diff --git a/ethstore/src/ethstore.rs b/ethstore/src/ethstore.rs index f3bb2407134f4c2912fc99492bccd4c5254fd900..40a687fc9880354c8ca8bdc8208ca43662b4b7bd 100755 --- a/ethstore/src/ethstore.rs +++ b/ethstore/src/ethstore.rs @@ -18,11 +18,12 @@ use std::collections::{BTreeMap, HashMap}; use std::mem; use std::path::PathBuf; use parking_lot::{Mutex, RwLock}; +use std::time::{Instant, Duration}; use crypto::KEY_ITERATIONS; use random::Random; use ethkey::{self, Signature, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair}; -use dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError}; +use accounts_dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError}; use account::SafeAccount; use presale::PresaleWallet; use json::{self, Uuid, OpaqueKeyFile}; @@ -46,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 { let mut accounts = self.store.get_accounts(account)?.into_iter(); accounts.next().ok_or(Error::InvalidAccount) @@ -155,9 +166,14 @@ impl SecretStore for EthStore { self.insert_account(vault, keypair.secret().clone(), password) } - fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result { + fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str, gen_id: bool) -> Result { let json_keyfile = json::KeyFile::load(json).map_err(|_| Error::InvalidKeyFile("Invalid JSON format".to_owned()))?; let mut safe_account = SafeAccount::from_file(json_keyfile, None); + + if gen_id { + safe_account.id = Random::random(); + } + let secret = safe_account.crypto.secret(password).map_err(|_| Error::InvalidPassword)?; safe_account.address = KeyPair::from_secret(secret)?.address(); self.store.import(vault, safe_account) @@ -245,7 +261,13 @@ pub struct EthMultiStore { // order lock: cache, then vaults cache: RwLock>>, vaults: Mutex>>, - dir_hash: Mutex>, + timestamp: Mutex, +} + +struct Timestamp { + dir_hash: Option, + last_checked: Instant, + refresh_time: Duration, } impl EthMultiStore { @@ -261,20 +283,39 @@ impl EthMultiStore { vaults: Mutex::new(HashMap::new()), iterations: iterations, cache: Default::default(), - dir_hash: Default::default(), + 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_dir_hash = self.dir_hash.lock(); - let dir_hash = Some(self.dir.unique_repr()?); - if *last_dir_hash == dir_hash { - return Ok(()) + let mut last_timestamp = self.timestamp.lock(); + let now = Instant::now(); + 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 { + return Ok(()) + } + self.reload_accounts()?; + last_timestamp.dir_hash = dir_hash; } - self.reload_accounts()?; - *last_dir_hash = dir_hash; Ok(()) } @@ -304,22 +345,23 @@ impl EthMultiStore { } fn get_accounts(&self, account: &StoreAccountRef) -> Result, 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) + } } } @@ -358,7 +400,7 @@ impl EthMultiStore { // update cache let mut cache = self.cache.write(); - let mut accounts = cache.entry(account_ref.clone()).or_insert_with(Vec::new); + let accounts = cache.entry(account_ref.clone()).or_insert_with(Vec::new); // Remove old account accounts.retain(|acc| acc != &old); // And push updated to the end @@ -455,11 +497,20 @@ impl SimpleSecretStore for EthMultiStore { } fn account_ref(&self, address: &Address) -> Result { - self.reload_if_changed()?; - self.cache.read().keys() - .find(|r| &r.address == address) - .cloned() - .ok_or(Error::InvalidAccount) + 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, Error> { @@ -638,12 +689,12 @@ impl SimpleSecretStore for EthMultiStore { mod tests { extern crate tempdir; - use dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory}; + use accounts_dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory}; use ethkey::{Random, Generator, KeyPair}; use secret_store::{SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation}; use super::{EthStore, EthMultiStore}; use self::tempdir::TempDir; - use bigint::hash::H256; + use ethereum_types::H256; fn keypair() -> KeyPair { Random.generate().unwrap() diff --git a/ethstore/src/import.rs b/ethstore/src/import.rs index 2b2c34eb19f101a1bf37cad5295485caefdfc964..2aaef51f504153d9808790f48e0b281137bc6b12 100644 --- a/ethstore/src/import.rs +++ b/ethstore/src/import.rs @@ -19,7 +19,8 @@ use std::path::Path; use std::fs; use ethkey::Address; -use dir::{paths, KeyDirectory, RootDiskDirectory, DiskKeyFileManager, KeyFileManager}; +use accounts_dir::{KeyDirectory, RootDiskDirectory, DiskKeyFileManager, KeyFileManager}; +use dir; use Error; /// Import an account from a file. @@ -54,7 +55,7 @@ pub fn import_accounts(src: &KeyDirectory, dst: &KeyDirectory) -> Result Vec
{ - RootDiskDirectory::at(paths::geth(testnet)) + RootDiskDirectory::at(dir::geth(testnet)) .load() .map(|d| d.into_iter().map(|a| a.address).collect()) .unwrap_or_else(|_| Vec::new()) @@ -62,7 +63,7 @@ pub fn read_geth_accounts(testnet: bool) -> Vec
{ /// Import specific `desired` accounts from the Geth keystore into `dst`. pub fn import_geth_accounts(dst: &KeyDirectory, desired: HashSet
, testnet: bool) -> Result, Error> { - let src = RootDiskDirectory::at(paths::geth(testnet)); + let src = RootDiskDirectory::at(dir::geth(testnet)); let accounts = src.load()?; let existing_accounts = dst.load()?.into_iter().map(|a| a.address).collect::>(); diff --git a/ethstore/src/lib.rs b/ethstore/src/lib.rs index 65935f89ca06b72de82d180a6709c56ec0e1e013..3422a5ff72f7885a7f607854c3fca37a28abca0b 100755 --- a/ethstore/src/lib.rs +++ b/ethstore/src/lib.rs @@ -19,6 +19,7 @@ #![warn(missing_docs)] extern crate crypto as rcrypto; +extern crate dir; extern crate itertools; extern crate libc; extern crate parking_lot; @@ -27,12 +28,13 @@ extern crate rustc_hex; extern crate serde; extern crate serde_json; extern crate smallvec; +extern crate subtle; extern crate time; extern crate tiny_keccak; extern crate tempdir; -extern crate ethcore_bigint as bigint; extern crate ethcrypto as crypto; +extern crate ethereum_types; extern crate ethkey as _ethkey; extern crate parity_wordlist; @@ -41,7 +43,11 @@ extern crate log; #[macro_use] extern crate serde_derive; -pub mod dir; +#[cfg(test)] +#[macro_use] +extern crate matches; + +pub mod accounts_dir; pub mod ethkey; mod account; diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs index e364245b79943fa396bc7946285273f6e0610e4e..ebac2f992292cb0e79dfe6b1932aded84f752578 100755 --- a/ethstore/src/secret_store.rs +++ b/ethstore/src/secret_store.rs @@ -16,10 +16,11 @@ use std::hash::{Hash, Hasher}; use std::path::PathBuf; +use std::cmp::Ordering; use ethkey::{Address, Message, Signature, Secret, Public}; use Error; use json::{Uuid, OpaqueKeyFile}; -use bigint::hash::H256; +use ethereum_types::H256; use OpaqueSecret; /// Key directory reference @@ -32,12 +33,24 @@ pub enum SecretVaultRef { } /// Stored account reference -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Clone, PartialEq, Eq, Ord)] pub struct StoreAccountRef { - /// Vault reference - pub vault: SecretVaultRef, /// Account address pub address: Address, + /// Vault reference + pub vault: SecretVaultRef, +} + +impl PartialOrd for StoreAccountRef { + fn partial_cmp(&self, other: &StoreAccountRef) -> Option { + Some(self.address.cmp(&other.address).then_with(|| self.vault.cmp(&other.vault))) + } +} + +impl ::std::borrow::Borrow
for StoreAccountRef { + fn borrow(&self) -> &Address { + &self.address + } } /// Simple Secret Store API @@ -103,7 +116,7 @@ pub trait SecretStore: SimpleSecretStore { /// Imports presale wallet fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result; /// Imports existing JSON wallet - fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result; + fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str, gen_id: bool) -> Result; /// Copies account between stores and vaults. fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &str, new_password: &str) -> Result<(), Error>; /// Checks if password matches given account. diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs index a70163895a45a6c593ba4cdefd1585431baeddf3..fb24ff3367d73661ffad6718f15c7784dd2b060e 100755 --- a/ethstore/tests/api.rs +++ b/ethstore/tests/api.rs @@ -21,7 +21,7 @@ mod util; use ethstore::{EthStore, SimpleSecretStore, SecretVaultRef, StoreAccountRef}; use ethstore::ethkey::{Random, Generator, Secret, KeyPair, verify_address}; -use ethstore::dir::RootDiskDirectory; +use ethstore::accounts_dir::RootDiskDirectory; use util::TransientDir; #[test] diff --git a/ethstore/tests/util/transient_dir.rs b/ethstore/tests/util/transient_dir.rs index 45e2aab09d5771542bc8f3824eebbf71af60f553..dcc65ec6985365f918fc4aa4d2c5ecb8261cb4f9 100755 --- a/ethstore/tests/util/transient_dir.rs +++ b/ethstore/tests/util/transient_dir.rs @@ -17,7 +17,7 @@ use std::path::PathBuf; use std::{env, fs}; use rand::{Rng, OsRng}; -use ethstore::dir::{KeyDirectory, RootDiskDirectory}; +use ethstore::accounts_dir::{KeyDirectory, RootDiskDirectory}; use ethstore::{Error, SafeAccount}; pub fn random_dir() -> PathBuf { diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 5538e10cc02eb447b730a9b6b69d0506f611496b..000019214a7c789efc8c8fb165e7939e3c57730e 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -9,16 +9,22 @@ name = "parity-evm" path = "./src/main.rs" [dependencies] -rustc-hex = "1.0" docopt = "0.8" -serde = "1.0" -serde_derive = "1.0" ethcore = { path = "../ethcore" } ethjson = { path = "../json" } -ethcore-util = { path = "../util" } +ethcore-bytes = { path = "../util/bytes" } +ethcore-transaction = { path = "../ethcore/transaction" } +ethereum-types = "0.2" evm = { path = "../ethcore/evm" } +panic_hook = { path = "../util/panic_hook" } +rustc-hex = "1.0" +serde = "1.0" +serde_derive = "1.0" vm = { path = "../ethcore/vm" } -panic_hook = { path = "../panic_hook" } + +[dev-dependencies] +pretty_assertions = "0.1" +tempdir = "0.3" [features] evm-debug = ["ethcore/evm-debug-tests"] diff --git a/evmbin/benches/mod.rs b/evmbin/benches/mod.rs index f4deda88e6f49a1283abaa45fc31f62a75d31923..6b6746e747b25354c3cbcf2cd6b35b3b4a697c2a 100644 --- a/evmbin/benches/mod.rs +++ b/evmbin/benches/mod.rs @@ -26,13 +26,14 @@ extern crate test; extern crate ethcore; extern crate evm; extern crate ethcore_util; +extern crate ethcore_bigint; extern crate rustc_hex; use self::test::{Bencher, black_box}; use evm::run_vm; use ethcore::vm::ActionParams; -use ethcore_util::U256; +use ethcore_bigint::prelude::U256; use rustc_hex::FromHex; #[bench] diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index 39147ffa34df99b8964afa1c337b2d99bbd937b4..00ca91b94fef22d9bf7de73257877f4386921969 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -16,9 +16,12 @@ //! JSON VM output. -use ethcore::trace; use std::collections::HashMap; -use util::{U256, H256, ToPretty}; +use std::mem; + +use ethereum_types::{U256, H256}; +use bytes::ToPretty; +use ethcore::trace; use display; use info as vm; @@ -35,6 +38,9 @@ pub struct Informant { stack: Vec, memory: Vec, storage: HashMap, + traces: Vec, + subtraces: Vec, + unmatched: bool, } impl Informant { @@ -43,7 +49,7 @@ impl Informant { } fn stack(&self) -> String { - let items = self.stack.iter().map(display::u256_as_str).collect::>(); + let items = self.stack.iter().map(|i| format!("\"0x{:x}\"", i)).collect::>(); format!("[{}]", items.join(",")) } @@ -56,7 +62,7 @@ impl Informant { } impl vm::Informant for Informant { - fn before_test(&self, name: &str, action: &str) { + fn before_test(&mut self, name: &str, action: &str) { println!( "{{\"test\":\"{name}\",\"action\":\"{action}\"}}", name = name, @@ -68,28 +74,43 @@ impl vm::Informant for Informant { self.gas_used = gas; } - fn finish(result: Result) { + fn finish(result: vm::RunResult) { match result { - Ok(success) => println!( - "{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", - output = success.output.to_hex(), - gas = success.gas_used, - time = display::as_micros(&success.time), - ), - Err(failure) => println!( - "{{\"error\":\"{error}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", - error = failure.error, - gas = failure.gas_used, - time = display::as_micros(&failure.time), - ), + Ok(success) => { + for trace in success.traces.unwrap_or_else(Vec::new) { + println!("{}", trace); + } + + println!( + "{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", + output = success.output.to_hex(), + gas = success.gas_used, + time = display::as_micros(&success.time), + ) + }, + Err(failure) => { + for trace in failure.traces.unwrap_or_else(Vec::new) { + println!("{}", trace); + } + + println!( + "{{\"error\":\"{error}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", + error = failure.error, + gas = failure.gas_used, + time = display::as_micros(&failure.time), + ) + }, } } } impl trace::VMTracer for Informant { - fn trace_next_instruction(&mut self, pc: usize, instruction: u8) -> bool { + type Output = Vec; + + fn trace_next_instruction(&mut self, pc: usize, instruction: u8, _current_gas: U256) -> bool { self.pc = pc; self.instruction = instruction; + self.unmatched = true; true } @@ -102,25 +123,28 @@ impl trace::VMTracer for Informant { fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { let info = ::evm::INSTRUCTIONS[self.instruction as usize]; - println!( - "{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":{gas},\"gasCost\":{gas_cost},\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", + let trace = format!( + "{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"gasCost\":\"0x{gas_cost:x}\",\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", pc = self.pc, op = self.instruction, name = info.name, - gas = display::u256_as_str(&(gas_used + self.gas_cost)), - gas_cost = display::u256_as_str(&self.gas_cost), + gas = gas_used.saturating_add(self.gas_cost), + gas_cost = self.gas_cost, memory = self.memory(), stack = self.stack(), storage = self.storage(), depth = self.depth, ); + self.traces.push(trace); + self.unmatched = false; self.gas_used = gas_used; let len = self.stack.len(); self.stack.truncate(if len > info.args { len - info.args } else { 0 }); self.stack.extend_from_slice(stack_push); + // TODO [ToDr] Align memory? if let Some((pos, data)) = mem_diff { if self.memory.len() < (pos + data.len()) { self.memory.resize(pos + data.len(), 0); @@ -131,6 +155,11 @@ impl trace::VMTracer for Informant { if let Some((pos, val)) = store_diff { self.storage.insert(pos.into(), val.into()); } + + + if !self.subtraces.is_empty() { + self.traces.extend(mem::replace(&mut self.subtraces, vec![])); + } } fn prepare_subtrace(&self, code: &[u8]) -> Self where Self: Sized { @@ -141,14 +170,117 @@ impl trace::VMTracer for Informant { vm } - fn done_subtrace(&mut self, mut sub: Self) { - if sub.depth == 1 { + fn done_subtrace(&mut self, sub: Self) { + if let Some(subtraces) = sub.drain() { + self.subtraces.extend(subtraces); + } + } + + fn drain(mut self) -> Option { + if self.unmatched { // print last line with final state: - sub.gas_cost = 0.into(); - let gas_used = sub.gas_used; - trace::VMTracer::trace_executed(&mut sub, gas_used, &[], None, None); + self.gas_cost = 0.into(); + let gas_used = self.gas_used; + self.trace_executed(gas_used, &[], None, None); + } else if !self.subtraces.is_empty() { + self.traces.extend(mem::replace(&mut self.subtraces, vec![])); } + Some(self.traces) } +} + +#[cfg(test)] +mod tests { + use super::*; + use info::tests::run_test; - fn drain(self) -> Option { None } + fn assert_traces_eq( + a: &[String], + b: &[String], + ) { + let mut ita = a.iter(); + let mut itb = b.iter(); + + loop { + match (ita.next(), itb.next()) { + (Some(a), Some(b)) => { + assert_eq!(a, b); + println!("{}", a); + }, + (None, None) => return, + e => { + panic!("Traces mismatch: {:?}", e); + } + } + } + } + + fn compare_json(traces: Option>, expected: &str) { + let expected = expected.split("\n") + .map(|x| x.trim()) + .map(|x| x.to_owned()) + .filter(|x| !x.is_empty()) + .collect::>(); + assert_traces_eq(&traces.unwrap(), &expected); + } + + #[test] + fn should_trace_failure() { + run_test( + Informant::default(), + &compare_json, + "60F8d6", + 0xffff, + r#" +{"pc":0,"op":96,"opName":"PUSH1","gas":"0xffff","gasCost":"0x3","memory":"0x","stack":[],"storage":{},"depth":1} +{"pc":2,"op":214,"opName":"","gas":"0xfffc","gasCost":"0x0","memory":"0x","stack":["0xf8"],"storage":{},"depth":1} + "#, + ); + + run_test( + Informant::default(), + &compare_json, + "F8d6", + 0xffff, + r#" +{"pc":0,"op":248,"opName":"","gas":"0xffff","gasCost":"0x0","memory":"0x","stack":[],"storage":{},"depth":1} + "#, + ); + } + + #[test] + fn should_trace_create_correctly() { + run_test( + Informant::default(), + &compare_json, + "32343434345830f138343438323439f0", + 0xffff, + r#" +{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":1} +{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0xfffd","gasCost":"0x2","memory":"0x","stack":["0x0"],"storage":{},"depth":1} +{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0xfffb","gasCost":"0x2","memory":"0x","stack":["0x0","0x0"],"storage":{},"depth":1} +{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0xfff9","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0"],"storage":{},"depth":1} +{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0xfff7","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":1} +{"pc":5,"op":88,"opName":"PC","gas":"0xfff5","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":1} +{"pc":6,"op":48,"opName":"ADDRESS","gas":"0xfff3","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":1} +{"pc":7,"op":241,"opName":"CALL","gas":"0xfff1","gasCost":"0x61d0","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{},"depth":1} +{"pc":8,"op":56,"opName":"CODESIZE","gas":"0x9e21","gasCost":"0x2","memory":"0x","stack":["0x1"],"storage":{},"depth":1} +{"pc":9,"op":52,"opName":"CALLVALUE","gas":"0x9e1f","gasCost":"0x2","memory":"0x","stack":["0x1","0x10"],"storage":{},"depth":1} +{"pc":10,"op":52,"opName":"CALLVALUE","gas":"0x9e1d","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0"],"storage":{},"depth":1} +{"pc":11,"op":56,"opName":"CODESIZE","gas":"0x9e1b","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1} +{"pc":12,"op":50,"opName":"ORIGIN","gas":"0x9e19","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{},"depth":1} +{"pc":13,"op":52,"opName":"CALLVALUE","gas":"0x9e17","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{},"depth":1} +{"pc":14,"op":57,"opName":"CODECOPY","gas":"0x9e15","gasCost":"0x9","memory":"0x","stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{},"depth":1} +{"pc":15,"op":240,"opName":"CREATE","gas":"0x9e0c","gasCost":"0x9e0c","memory":"0x32343434345830f138343438323439f0","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1} +{"pc":0,"op":50,"opName":"ORIGIN","gas":"0x210c","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":2} +{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0x210a","gasCost":"0x2","memory":"0x","stack":["0x0"],"storage":{},"depth":2} +{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0x2108","gasCost":"0x2","memory":"0x","stack":["0x0","0x0"],"storage":{},"depth":2} +{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0x2106","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0"],"storage":{},"depth":2} +{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0x2104","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":2} +{"pc":5,"op":88,"opName":"PC","gas":"0x2102","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2} +{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2} +{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","gasCost":"0x0","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2} + "#, + ) + } } diff --git a/evmbin/src/display/mod.rs b/evmbin/src/display/mod.rs index 2c25fe7219fec1e0dc8ab485389a99c1c1524d7f..b9390058b6022230c745786f9cdcb32caa0dac50 100644 --- a/evmbin/src/display/mod.rs +++ b/evmbin/src/display/mod.rs @@ -17,9 +17,9 @@ //! VM Output display utils. use std::time::Duration; -use util::U256; pub mod json; +pub mod std_json; pub mod simple; /// Formats duration into human readable format. @@ -31,13 +31,3 @@ pub fn format_time(time: &Duration) -> String { pub fn as_micros(time: &Duration) -> u64 { time.as_secs() * 1_000_000 + time.subsec_nanos() as u64 / 1_000 } - -/// Converts U256 into string. -/// TODO Overcomes: https://github.com/paritytech/bigint/issues/13 -pub fn u256_as_str(v: &U256) -> String { - if v.is_zero() { - "\"0x0\"".into() - } else { - format!("\"{:x}\"", v) - } -} diff --git a/evmbin/src/display/simple.rs b/evmbin/src/display/simple.rs index bb4ecc12744e63cd5b83a0a9eb9e655fcd8679a0..30bb8ffcf7a286c8a6f557f3fd04efbb95764b26 100644 --- a/evmbin/src/display/simple.rs +++ b/evmbin/src/display/simple.rs @@ -17,7 +17,7 @@ //! Simple VM output. use ethcore::trace; -use util::ToPretty; +use bytes::ToPretty; use display; use info as vm; @@ -27,11 +27,11 @@ use info as vm; pub struct Informant; impl vm::Informant for Informant { - fn before_test(&self, name: &str, action: &str) { + fn before_test(&mut self, name: &str, action: &str) { println!("Test: {} ({})", name, action); } - fn finish(result: Result) { + fn finish(result: vm::RunResult) { match result { Ok(success) => { println!("Output: 0x{}", success.output.to_hex()); @@ -47,7 +47,9 @@ impl vm::Informant for Informant { } impl trace::VMTracer for Informant { + type Output = (); + fn prepare_subtrace(&self, _code: &[u8]) -> Self where Self: Sized { Default::default() } fn done_subtrace(&mut self, _sub: Self) {} - fn drain(self) -> Option { None } + fn drain(self) -> Option<()> { None } } diff --git a/evmbin/src/display/std_json.rs b/evmbin/src/display/std_json.rs new file mode 100644 index 0000000000000000000000000000000000000000..3d8f52dbd1f744068788aaca69d76b6e4313b0e7 --- /dev/null +++ b/evmbin/src/display/std_json.rs @@ -0,0 +1,265 @@ +// 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 . + +//! Standardized JSON VM output. + +use std::collections::HashMap; +use std::io; + +use ethereum_types::{H256, U256}; +use bytes::ToPretty; +use ethcore::trace; + +use display; +use info as vm; + +pub trait Writer: io::Write + Send + Sized { + fn clone(&self) -> Self; +} + +impl Writer for io::Stdout { + fn clone(&self) -> Self { + io::stdout() + } +} + +/// JSON formatting informant. +pub struct Informant { + code: Vec, + instruction: u8, + depth: usize, + stack: Vec, + storage: HashMap, + sink: T, +} + +impl Default for Informant { + fn default() -> Self { + Self::new(io::stdout()) + } +} + +impl Informant { + pub fn new(sink: T) -> Self { + Informant { + code: Default::default(), + instruction: Default::default(), + depth: Default::default(), + stack: Default::default(), + storage: Default::default(), + sink, + } + } +} + +impl Informant { + fn stack(&self) -> String { + let items = self.stack.iter().map(|i| format!("\"0x{:x}\"", i)).collect::>(); + format!("[{}]", items.join(",")) + } + + fn storage(&self) -> String { + let vals = self.storage.iter() + .map(|(k, v)| format!("\"0x{:?}\": \"0x{:?}\"", k, v)) + .collect::>(); + format!("{{{}}}", vals.join(",")) + } +} + +impl vm::Informant for Informant { + fn before_test(&mut self, name: &str, action: &str) { + writeln!( + &mut self.sink, + "{{\"test\":\"{name}\",\"action\":\"{action}\"}}", + name = name, + action = action, + ).expect("The sink must be writeable."); + } + + fn set_gas(&mut self, _gas: U256) {} + + fn finish(result: vm::RunResult) { + match result { + Ok(success) => { + println!("{{\"stateRoot\":\"{:?}\"}}", success.state_root); + println!( + "{{\"output\":\"0x{output}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", + output = success.output.to_hex(), + gas = success.gas_used, + time = display::as_micros(&success.time), + ); + }, + Err(failure) => { + println!( + "{{\"error\":\"{error}\",\"gasUsed\":\"{gas:x}\",\"time\":{time}}}", + error = failure.error, + gas = failure.gas_used, + time = display::as_micros(&failure.time), + ) + }, + } + } +} + +impl trace::VMTracer for Informant { + type Output = (); + + fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { + let info = ::evm::INSTRUCTIONS[instruction as usize]; + self.instruction = instruction; + let storage = self.storage(); + let stack = self.stack(); + + writeln!( + &mut self.sink, + "{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", + pc = pc, + op = instruction, + name = info.name, + gas = current_gas, + stack = stack, + storage = storage, + depth = self.depth, + ).expect("The sink must be writeable."); + + true + } + + fn trace_prepare_execute(&mut self, _pc: usize, _instruction: u8, _gas_cost: U256) { + } + + fn trace_executed(&mut self, _gas_used: U256, stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { + let info = ::evm::INSTRUCTIONS[self.instruction as usize]; + + let len = self.stack.len(); + self.stack.truncate(if len > info.args { len - info.args } else { 0 }); + self.stack.extend_from_slice(stack_push); + + if let Some((pos, val)) = store_diff { + self.storage.insert(pos.into(), val.into()); + } + } + + fn prepare_subtrace(&self, code: &[u8]) -> Self where Self: Sized { + let mut vm = Informant::new(self.sink.clone()); + vm.depth = self.depth + 1; + vm.code = code.to_vec(); + vm + } + + fn done_subtrace(&mut self, _sub: Self) {} + + fn drain(self) -> Option { None } +} + +#[cfg(test)] +mod tests { + use std::sync::{Arc, Mutex}; + use super::*; + use info::tests::run_test; + + #[derive(Debug, Clone, Default)] + struct TestWriter(pub Arc>>); + + impl Writer for TestWriter { + fn clone(&self) -> Self { Clone::clone(self) } + } + + impl io::Write for TestWriter { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.0.lock().unwrap().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.0.lock().unwrap().flush() + } + } + + fn informant() -> (Informant, Arc>>) { + let writer = TestWriter::default(); + let res = writer.0.clone(); + (Informant::new(writer), res) + } + + #[test] + fn should_trace_failure() { + let (inf, res) = informant(); + run_test( + inf, + move |_, expected| { + let bytes = res.lock().unwrap(); + assert_eq!(expected, &String::from_utf8_lossy(&**bytes)) + }, + "60F8d6", + 0xffff, + r#"{"pc":0,"op":96,"opName":"PUSH1","gas":"0xffff","stack":[],"storage":{},"depth":1} +{"pc":2,"op":214,"opName":"","gas":"0xfffc","stack":["0xf8"],"storage":{},"depth":1} +"#, + ); + + let (inf, res) = informant(); + run_test( + inf, + move |_, expected| { + let bytes = res.lock().unwrap(); + assert_eq!(expected, &String::from_utf8_lossy(&**bytes)) + }, + "F8d6", + 0xffff, + r#"{"pc":0,"op":248,"opName":"","gas":"0xffff","stack":[],"storage":{},"depth":1} +"#, + ); + } + + #[test] + fn should_trace_create_correctly() { + let (informant, res) = informant(); + run_test( + informant, + move |_, expected| { + let bytes = res.lock().unwrap(); + assert_eq!(expected, &String::from_utf8_lossy(&**bytes)) + }, + "32343434345830f138343438323439f0", + 0xffff, + r#"{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","stack":[],"storage":{},"depth":1} +{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0xfffd","stack":["0x0"],"storage":{},"depth":1} +{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0xfffb","stack":["0x0","0x0"],"storage":{},"depth":1} +{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0xfff9","stack":["0x0","0x0","0x0"],"storage":{},"depth":1} +{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0xfff7","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":1} +{"pc":5,"op":88,"opName":"PC","gas":"0xfff5","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":1} +{"pc":6,"op":48,"opName":"ADDRESS","gas":"0xfff3","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":1} +{"pc":7,"op":241,"opName":"CALL","gas":"0xfff1","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{},"depth":1} +{"pc":8,"op":56,"opName":"CODESIZE","gas":"0x9e21","stack":["0x1"],"storage":{},"depth":1} +{"pc":9,"op":52,"opName":"CALLVALUE","gas":"0x9e1f","stack":["0x1","0x10"],"storage":{},"depth":1} +{"pc":10,"op":52,"opName":"CALLVALUE","gas":"0x9e1d","stack":["0x1","0x10","0x0"],"storage":{},"depth":1} +{"pc":11,"op":56,"opName":"CODESIZE","gas":"0x9e1b","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1} +{"pc":12,"op":50,"opName":"ORIGIN","gas":"0x9e19","stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{},"depth":1} +{"pc":13,"op":52,"opName":"CALLVALUE","gas":"0x9e17","stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{},"depth":1} +{"pc":14,"op":57,"opName":"CODECOPY","gas":"0x9e15","stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{},"depth":1} +{"pc":15,"op":240,"opName":"CREATE","gas":"0x9e0c","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1} +{"pc":0,"op":50,"opName":"ORIGIN","gas":"0x210c","stack":[],"storage":{},"depth":2} +{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0x210a","stack":["0x0"],"storage":{},"depth":2} +{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0x2108","stack":["0x0","0x0"],"storage":{},"depth":2} +{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0x2106","stack":["0x0","0x0","0x0"],"storage":{},"depth":2} +{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0x2104","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":2} +{"pc":5,"op":88,"opName":"PC","gas":"0x2102","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2} +{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2} +{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2} +"#, + ) + } +} diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index 3392cb441ea158071ff1cb00c2a9b5bac5c25387..1be81d9132f9d1d80af1f42cdf46dfe77aea7cc2 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -17,39 +17,67 @@ //! VM runner. use std::time::{Instant, Duration}; -use util::{U256, H256}; -use ethcore::{trace, spec, transaction, pod_state}; +use ethereum_types::{H256, U256}; use ethcore::client::{self, EvmTestClient, EvmTestError, TransactResult}; +use ethcore::{trace, spec, pod_state}; use ethjson; +use transaction; +use vm::ActionParams; /// VM execution informant pub trait Informant: trace::VMTracer { /// Display a single run init message - fn before_test(&self, test: &str, action: &str); + fn before_test(&mut self, test: &str, action: &str); /// Set initial gas. fn set_gas(&mut self, _gas: U256) {} /// Display final result. - fn finish(result: Result); + fn finish(result: RunResult); } /// Execution finished correctly -pub struct Success { +#[derive(Debug)] +pub struct Success { + /// State root + pub state_root: H256, /// Used gas pub gas_used: U256, /// Output as bytes pub output: Vec, /// Time Taken pub time: Duration, + /// Traces + pub traces: Option, } /// Execution failed -pub struct Failure { +#[derive(Debug)] +pub struct Failure { /// Used gas pub gas_used: U256, /// Internal error pub error: EvmTestError, /// Duration pub time: Duration, + /// Traces + pub traces: Option, +} + +/// EVM Execution result +pub type RunResult = Result, Failure>; + +/// Execute given `ActionParams` and return the result. +pub fn run_action( + spec: &spec::Spec, + params: ActionParams, + mut informant: T, +) -> RunResult { + informant.set_gas(params.gas); + run(spec, params.gas, None, |mut client| { + let result = client + .call(params, &mut trace::NoopTracer, &mut informant) + .map(|r| (0.into(), r.gas_left, r.return_data.to_vec())); + (result, informant.drain()) + }) } /// Execute given Transaction and verify resulting state root. @@ -78,22 +106,22 @@ pub fn run_transaction( informant.set_gas(env_info.gas_limit); let result = run(spec, env_info.gas_limit, pre_state, |mut client| { - let result = client.transact(env_info, transaction, informant); + let result = client.transact(env_info, transaction, trace::NoopTracer, informant); match result { TransactResult::Ok { state_root, .. } if state_root != post_root => { - Err(EvmTestError::PostCondition(format!( + (Err(EvmTestError::PostCondition(format!( "State root mismatch (got: {}, expected: {})", state_root, post_root, - ))) + ))), None) }, - TransactResult::Ok { gas_left, output, .. } => { - Ok((gas_left, output)) + TransactResult::Ok { state_root, gas_left, output, vm_trace, .. } => { + (Ok((state_root, gas_left, output)), vm_trace) }, TransactResult::Err { error, .. } => { - Err(EvmTestError::PostCondition(format!( + (Err(EvmTestError::PostCondition(format!( "Unexpected execution error: {:?}", error - ))) + ))), None) }, } }); @@ -102,8 +130,13 @@ pub fn run_transaction( } /// Execute VM with given `ActionParams` -pub fn run<'a, F, T>(spec: &'a spec::Spec, initial_gas: U256, pre_state: T, run: F) -> Result where - F: FnOnce(EvmTestClient) -> Result<(U256, Vec), EvmTestError>, +pub fn run<'a, F, T, X>( + spec: &'a spec::Spec, + initial_gas: U256, + pre_state: T, + run: F, +) -> RunResult where + F: FnOnce(EvmTestClient) -> (Result<(H256, U256, Vec), EvmTestError>, Option), T: Into>, { let test_client = match pre_state.into() { @@ -112,23 +145,63 @@ pub fn run<'a, F, T>(spec: &'a spec::Spec, initial_gas: U256, pre_state: T, run: }.map_err(|error| Failure { gas_used: 0.into(), error, - time: Duration::from_secs(0) + time: Duration::from_secs(0), + traces: None, })?; let start = Instant::now(); let result = run(test_client); - let duration = start.elapsed(); + let time = start.elapsed(); match result { - Ok((gas_left, output)) => Ok(Success { + (Ok((state_root, gas_left, output)), traces) => Ok(Success { + state_root, gas_used: initial_gas - gas_left, - output: output, - time: duration, + output, + time, + traces, }), - Err(e) => Err(Failure { + (Err(error), traces) => Err(Failure { gas_used: initial_gas, - error: e, - time: duration, + error, + time, + traces, }), } } + +#[cfg(test)] +pub mod tests { + use std::sync::Arc; + use rustc_hex::FromHex; + use super::*; + use tempdir::TempDir; + + pub fn run_test( + informant: I, + compare: F, + code: &str, + gas: T, + expected: &str, + ) where + T: Into, + I: Informant, + F: FnOnce(Option, &str), + { + let mut params = ActionParams::default(); + params.code = Some(Arc::new(code.from_hex().unwrap())); + params.gas = gas.into(); + + let tempdir = TempDir::new("").unwrap(); + let spec = ::ethcore::ethereum::new_foundation(&tempdir.path()); + let result = run_action(&spec, params, informant); + match result { + Ok(Success { traces, .. }) => { + compare(traces, expected) + }, + Err(Failure { traces, .. }) => { + compare(traces, expected) + }, + } + } +} diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 5eb43ed61a4ac3c849bba7fb7f3a3d6620ccc115..bddb40ecd235c38cabe0572385381d8e69a5a964 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -25,17 +25,27 @@ extern crate serde; #[macro_use] extern crate serde_derive; extern crate docopt; -extern crate ethcore_util as util; +extern crate ethcore_transaction as transaction; +extern crate ethcore_bytes as bytes; +extern crate ethereum_types; extern crate vm; extern crate evm; extern crate panic_hook; +#[cfg(test)] +#[macro_use] +extern crate pretty_assertions; + +#[cfg(test)] +extern crate tempdir; + use std::sync::Arc; use std::{fmt, fs}; use std::path::PathBuf; use docopt::Docopt; use rustc_hex::FromHex; -use util::{U256, Bytes, Address}; +use ethereum_types::{U256, Address}; +use bytes::Bytes; use ethcore::spec; use vm::{ActionParams, CallType}; @@ -49,7 +59,7 @@ EVM implementation for Parity. Copyright 2016, 2017 Parity Technologies (UK) Ltd Usage: - parity-evm state-test [--json --only NAME --chain CHAIN] + parity-evm state-test [--json --std-json --only NAME --chain CHAIN] parity-evm stats [options] parity-evm [options] parity-evm [-h | --help] @@ -68,6 +78,7 @@ State test options: General options: --json Display verbose results in JSON. + --std-json Display results in standardized JSON format. --chain CHAIN Chain spec file path. -h, --help Display this message and exit. "#; @@ -82,6 +93,8 @@ fn main() { run_state_test(args) } else if args.flag_json { run_call(args, display::json::Informant::default()) + } else if args.flag_std_json { + run_call(args, display::std_json::Informant::default()) } else { run_call(args, display::simple::Informant::default()) } @@ -123,6 +136,9 @@ fn run_state_test(args: Args) { if args.flag_json { let i = display::json::Informant::default(); info::run_transaction(&name, idx, &spec, &pre, post_root, &env_info, transaction, i) + } else if args.flag_std_json { + let i = display::std_json::Informant::default(); + info::run_transaction(&name, idx, &spec, &pre, post_root, &env_info, transaction, i) } else { let i = display::simple::Informant::default(); info::run_transaction(&name, idx, &spec, &pre, post_root, &env_info, transaction, i) @@ -132,7 +148,7 @@ fn run_state_test(args: Args) { } } -fn run_call(args: Args, mut informant: T) { +fn run_call(args: Args, informant: T) { let from = arg(args.from(), "--from"); let to = arg(args.to(), "--to"); let code = arg(args.code(), "--code"); @@ -156,10 +172,7 @@ fn run_call(args: Args, mut informant: T) { params.code = code.map(Arc::new); params.data = data; - informant.set_gas(gas); - let result = info::run(&spec, gas, None, |mut client| { - client.call(params, &mut informant) - }); + let result = info::run_action(&spec, params, informant); T::finish(result); } @@ -177,13 +190,14 @@ struct Args { flag_input: Option, flag_chain: Option, flag_json: bool, + flag_std_json: bool, } impl Args { pub fn gas(&self) -> Result { match self.flag_gas { Some(ref gas) => gas.parse().map_err(to_string), - None => Ok(!U256::zero()), + None => Ok(U256::from(u64::max_value())), } } @@ -226,7 +240,7 @@ impl Args { Ok(match self.flag_chain { Some(ref filename) => { let file = fs::File::open(filename).map_err(|e| format!("{}", e))?; - spec::Spec::load(::std::env::temp_dir(), file)? + spec::Spec::load(&::std::env::temp_dir(), file)? }, None => { ethcore::ethereum::new_foundation(&::std::env::temp_dir()) @@ -262,6 +276,7 @@ mod tests { let args = run(&[ "parity-evm", "--json", + "--std-json", "--gas", "1", "--gas-price", "2", "--from", "0000000000000000000000000000000000000003", @@ -272,6 +287,7 @@ mod tests { ]); assert_eq!(args.flag_json, true); + assert_eq!(args.flag_std_json, true); assert_eq!(args.gas(), Ok(1.into())); assert_eq!(args.gas_price(), Ok(2.into())); assert_eq!(args.from(), Ok(3.into())); @@ -290,11 +306,13 @@ mod tests { "--chain", "homestead", "--only=add11", "--json", + "--std-json" ]); assert_eq!(args.cmd_state_test, true); assert!(args.arg_file.is_some()); assert_eq!(args.flag_json, true); + assert_eq!(args.flag_std_json, true); assert_eq!(args.flag_chain, Some("homestead".to_owned())); assert_eq!(args.flag_only, Some("add11".to_owned())); } diff --git a/evmjit/Cargo.toml b/evmjit/Cargo.toml index dbc0cd51acd87ab902ef96b7ceabb172c026e5f6..c7bf1f8ba9408e56cb753dddce3f8ae9334a8194 100644 --- a/evmjit/Cargo.toml +++ b/evmjit/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "evmjit" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] [lib] diff --git a/hash-fetch/Cargo.toml b/hash-fetch/Cargo.toml index 502723bbb8c8f1dba6d8adf4d7ade5f8f9a98f52..d5630993670ab6e15260c9173d10d5317c6f58e9 100644 --- a/hash-fetch/Cargo.toml +++ b/hash-fetch/Cargo.toml @@ -3,18 +3,28 @@ description = "Fetching hash-addressed content." homepage = "http://parity.io" license = "GPL-3.0" name = "parity-hash-fetch" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] [dependencies] -ethabi = "2.0" futures = "0.1" +futures-cpupool = "0.1" log = "0.3" -mime = "0.2" -mime_guess = "1.6.1" -rand = "0.3" +mime = "0.3" +mime_guess = "2.0.0-alpha.2" +rand = "0.4" rustc-hex = "1.0" fetch = { path = "../util/fetch" } -ethcore-util = { path = "../util" } +ethcore-bytes = { path = "../util/bytes" } +ethereum-types = "0.2" parity-reactor = { path = "../util/reactor" } -native-contracts = { path = "../ethcore/native_contracts" } +keccak-hash = { path = "../util/hash" } +registrar = { path = "../registrar" } + +ethabi = "5.1" +ethabi-derive = "5.0" +ethabi-contract = "5.0" + +[dev-dependencies] +hyper = "0.11" +parking_lot = "0.5" diff --git a/hash-fetch/src/client.rs b/hash-fetch/src/client.rs index bd773e9b3fc3efba4f3a47171fee5ce33b761e4c..b3a9356ea2c5b57ee85c728fbaa6d908d1efdddf 100644 --- a/hash-fetch/src/client.rs +++ b/hash-fetch/src/client.rs @@ -21,11 +21,14 @@ use std::io::Write; use std::sync::Arc; use std::path::PathBuf; -use fetch::{Fetch, Response, Error as FetchError, Client as FetchClient}; -use futures::Future; +use hash::keccak_buffer; +use fetch::{self, Fetch}; +use futures_cpupool::CpuPool; +use futures::{Future, IntoFuture}; use parity_reactor::Remote; -use urlhint::{ContractClient, URLHintContract, URLHint, URLHintResult}; -use util::{H256, sha3}; +use urlhint::{URLHintContract, URLHint, URLHintResult}; +use registrar::{RegistrarClient, Asynchronous}; +use ethereum_types::H256; /// API for fetching by hash. pub trait HashFetch: Send + Sync + 'static { @@ -35,7 +38,7 @@ pub trait HashFetch: Send + Sync + 'static { /// 2. `on_done` - callback function invoked when the content is ready (or there was error during fetch) /// /// This function may fail immediately when fetch cannot be initialized or content cannot be resolved. - fn fetch(&self, hash: H256, on_done: Box) + Send>); + fn fetch(&self, hash: H256, abort: fetch::Abort, on_done: Box) + Send>); } /// Hash-fetching error. @@ -55,7 +58,7 @@ pub enum Error { /// IO Error while validating hash. IO(io::Error), /// Error during fetch. - Fetch(FetchError), + Fetch(fetch::Error), } #[cfg(test)] @@ -75,8 +78,8 @@ impl PartialEq for Error { } } -impl From for Error { - fn from(error: FetchError) -> Self { +impl From for Error { + fn from(error: fetch::Error) -> Self { Error::Fetch(error) } } @@ -87,21 +90,16 @@ impl From for Error { } } -fn validate_hash(path: PathBuf, hash: H256, result: Result) -> Result { - let response = result?; - if !response.is_success() { - return Err(Error::InvalidStatus); - } - +fn validate_hash(path: PathBuf, hash: H256, body: fetch::BodyReader) -> Result { // Read the response - let mut reader = io::BufReader::new(response); + let mut reader = io::BufReader::new(body); let mut writer = io::BufWriter::new(fs::File::create(&path)?); io::copy(&mut reader, &mut writer)?; writer.flush()?; // And validate the hash let mut file_reader = io::BufReader::new(fs::File::open(&path)?); - let content_hash = sha3(&mut file_reader)?; + let content_hash = keccak_buffer(&mut file_reader)?; if content_hash != hash { Err(Error::HashMismatch{ got: content_hash, expected: hash }) } else { @@ -110,24 +108,19 @@ fn validate_hash(path: PathBuf, hash: H256, result: Result } /// Default Hash-fetching client using on-chain contract to resolve hashes to URLs. -pub struct Client { +pub struct Client { + pool: CpuPool, contract: URLHintContract, fetch: F, remote: Remote, random_path: Arc PathBuf + Sync + Send>, } -impl Client { - /// Creates new instance of the `Client` given on-chain contract client and task runner. - pub fn new(contract: Arc, remote: Remote) -> Self { - Client::with_fetch(contract, FetchClient::new().unwrap(), remote) - } -} - impl Client { /// Creates new instance of the `Client` given on-chain contract client, fetch service and task runner. - pub fn with_fetch(contract: Arc, fetch: F, remote: Remote) -> Self { + pub fn with_fetch(contract: Arc>, pool: CpuPool, fetch: F, remote: Remote) -> Self { Client { + pool, contract: URLHintContract::new(contract), fetch: fetch, remote: remote, @@ -137,37 +130,49 @@ impl Client { } impl HashFetch for Client { - fn fetch(&self, hash: H256, on_done: Box) + Send>) { + fn fetch(&self, hash: H256, abort: fetch::Abort, on_done: Box) + Send>) { debug!(target: "fetch", "Fetching: {:?}", hash); let random_path = self.random_path.clone(); let remote_fetch = self.fetch.clone(); - let future = self.contract.resolve(hash.to_vec()) + let pool = self.pool.clone(); + let future = self.contract.resolve(hash) .map_err(|e| { warn!("Error resolving URL: {}", e); Error::NoResolution }) .and_then(|maybe_url| maybe_url.ok_or(Error::NoResolution)) .map(|content| match content { URLHintResult::Dapp(dapp) => { dapp.url() }, + URLHintResult::GithubDapp(content) => { + content.url + }, URLHintResult::Content(content) => { content.url }, }) + .into_future() .and_then(move |url| { debug!(target: "fetch", "Resolved {:?} to {:?}. Fetching...", hash, url); - let future = remote_fetch.fetch(&url).then(move |result| { - debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash); - let path = random_path(); - let res = validate_hash(path.clone(), hash, result); - if let Err(ref err) = res { - trace!(target: "fetch", "Error: {:?}", err); - // Remove temporary file in case of error - let _ = fs::remove_file(&path); - } - res - }); - remote_fetch.process(future) + remote_fetch.fetch(&url, abort).from_err() }) + .and_then(move |response| { + if !response.is_success() { + Err(Error::InvalidStatus) + } else { + Ok(response) + } + }) + .and_then(move |response| pool.spawn_fn(move || { + debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash); + let path = random_path(); + let res = validate_hash(path.clone(), hash, fetch::BodyReader::new(response)); + if let Err(ref err) = res { + trace!(target: "fetch", "Error: {:?}", err); + // Remove temporary file in case of error + let _ = fs::remove_file(&path); + } + res + })) .then(move |res| { on_done(res); Ok(()) as Result<(), ()> }); self.remote.spawn(future); @@ -188,14 +193,17 @@ fn random_temp_path() -> PathBuf { #[cfg(test)] mod tests { + extern crate hyper; use rustc_hex::FromHex; use std::sync::{Arc, mpsc}; - use util::Mutex; + use parking_lot::Mutex; use futures::future; - use fetch::{self, Fetch}; + use futures_cpupool::CpuPool; + use fetch::{self, Fetch, Url}; use parity_reactor::Remote; use urlhint::tests::{FakeRegistrar, URLHINT}; use super::{Error, Client, HashFetch, random_temp_path}; + use self::hyper::StatusCode; #[derive(Clone)] @@ -206,17 +214,13 @@ mod tests { impl Fetch for FakeFetch { type Result = future::Ok; - fn new() -> Result where Self: Sized { - Ok(FakeFetch { return_success: true }) - } - - fn fetch_with_abort(&self, url: &str, _abort: fetch::Abort) -> Self::Result { + fn fetch(&self, url: &str, abort: fetch::Abort) -> Self::Result { assert_eq!(url, "https://parity.io/assets/images/ethcore-black-horizontal.png"); + let u = Url::parse(url).unwrap(); future::ok(if self.return_success { - let cursor = ::std::io::Cursor::new(b"result"); - fetch::Response::from_reader(cursor) + fetch::client::Response::new(u, hyper::Response::new().with_body(&b"result"[..]), abort) } else { - fetch::Response::not_found() + fetch::client::Response::new(u, hyper::Response::new().with_status(StatusCode::NotFound), abort) }) } } @@ -235,11 +239,11 @@ mod tests { // given let contract = Arc::new(FakeRegistrar::new()); let fetch = FakeFetch { return_success: false }; - let client = Client::with_fetch(contract.clone(), fetch, Remote::new_sync()); + let client = Client::with_fetch(contract.clone(), CpuPool::new(1), fetch, Remote::new_sync()); // when let (tx, rx) = mpsc::channel(); - client.fetch(2.into(), Box::new(move |result| { + client.fetch(2.into(), Default::default(), Box::new(move |result| { tx.send(result).unwrap(); })); @@ -253,11 +257,11 @@ mod tests { // given let registrar = Arc::new(registrar()); let fetch = FakeFetch { return_success: false }; - let client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let client = Client::with_fetch(registrar.clone(), CpuPool::new(1), fetch, Remote::new_sync()); // when let (tx, rx) = mpsc::channel(); - client.fetch(2.into(), Box::new(move |result| { + client.fetch(2.into(), Default::default(), Box::new(move |result| { tx.send(result).unwrap(); })); @@ -271,14 +275,14 @@ mod tests { // given let registrar = Arc::new(registrar()); let fetch = FakeFetch { return_success: true }; - let mut client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let mut client = Client::with_fetch(registrar.clone(), CpuPool::new(1), fetch, Remote::new_sync()); let path = random_temp_path(); let path2 = path.clone(); client.random_path = Arc::new(move || path2.clone()); // when let (tx, rx) = mpsc::channel(); - client.fetch(2.into(), Box::new(move |result| { + client.fetch(2.into(), Default::default(), Box::new(move |result| { tx.send(result).unwrap(); })); @@ -294,16 +298,17 @@ mod tests { // given let registrar = Arc::new(registrar()); let fetch = FakeFetch { return_success: true }; - let client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let client = Client::with_fetch(registrar.clone(), CpuPool::new(1), fetch, Remote::new_sync()); // when let (tx, rx) = mpsc::channel(); - client.fetch("0x06b0a4f426f6713234b2d4b2468640bc4e0bb72657a920ad24c5087153c593c8".into(), Box::new(move |result| { - tx.send(result).unwrap(); - })); + client.fetch("0x06b0a4f426f6713234b2d4b2468640bc4e0bb72657a920ad24c5087153c593c8".into(), + Default::default(), + Box::new(move |result| { tx.send(result).unwrap(); })); // then let result = rx.recv().unwrap(); assert!(result.is_ok(), "Should return path, got: {:?}", result); } } + diff --git a/hash-fetch/src/lib.rs b/hash-fetch/src/lib.rs index 4952ecea27e52001248594e1ec495170d9c91aa6..6e74982bb844ca32282f5e5be2adf40d3499a76e 100644 --- a/hash-fetch/src/lib.rs +++ b/hash-fetch/src/lib.rs @@ -20,22 +20,32 @@ #[macro_use] extern crate log; -#[macro_use] -extern crate mime; extern crate ethabi; -extern crate ethcore_util as util; +extern crate ethcore_bytes as bytes; +extern crate ethereum_types; extern crate futures; +extern crate futures_cpupool; +extern crate keccak_hash as hash; +extern crate mime; extern crate mime_guess; -extern crate native_contracts; extern crate parity_reactor; extern crate rand; extern crate rustc_hex; +extern crate registrar; pub extern crate fetch; +#[macro_use] +extern crate ethabi_derive; +#[macro_use] +extern crate ethabi_contract; +#[cfg(test)] +extern crate parking_lot; + mod client; pub mod urlhint; pub use client::{HashFetch, Client, Error}; +pub use fetch::Abort; diff --git a/hash-fetch/src/urlhint.rs b/hash-fetch/src/urlhint.rs index bc4b63cf2fb906b7d75753c7dce1fdcaa32b517f..d05dd40a22f225633ed574ea12c1c2886e06d806 100644 --- a/hash-fetch/src/urlhint.rs +++ b/hash-fetch/src/urlhint.rs @@ -18,23 +18,22 @@ use std::sync::Arc; use rustc_hex::ToHex; -use mime::Mime; +use mime::{self, Mime}; use mime_guess; -use futures::{future, BoxFuture, Future}; -use native_contracts::{Registry, Urlhint}; -use util::{Address, Bytes, Hashable}; +use futures::{future, Future}; +use futures::future::Either; +use ethereum_types::{H256, Address}; +use registrar::{Registrar, RegistrarClient, Asynchronous}; -const COMMIT_LEN: usize = 20; +use_contract!(urlhint, "Urlhint", "res/urlhint.json"); -/// RAW Contract interface. -/// Should execute transaction using current blockchain state. -pub trait ContractClient: Send + Sync { - /// Get registrar address - fn registrar(&self) -> Result; - /// Call Contract - fn call(&self, address: Address, data: Bytes) -> BoxFuture; -} +const COMMIT_LEN: usize = 20; +const GITHUB_HINT: &'static str = "githubhint"; +/// 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]; /// Github-hosted dapp. #[derive(Debug, PartialEq)] @@ -87,6 +86,8 @@ pub struct Content { pub enum URLHintResult { /// Dapp Dapp(GithubApp), + /// GithubDapp + GithubDapp(Content), /// Content Content(Content), } @@ -94,29 +95,37 @@ pub enum URLHintResult { /// URLHint Contract interface pub trait URLHint: Send + Sync { /// Resolves given id to registrar entry. - fn resolve(&self, id: Bytes) -> BoxFuture, String>; + fn resolve(&self, id: H256) -> Box, Error = String> + Send>; } /// `URLHintContract` API -#[derive(Clone)] pub struct URLHintContract { - urlhint: Arc, - registrar: Registry, - client: Arc, + urlhint: urlhint::Urlhint, + registrar: Registrar, + client: Arc>, } impl URLHintContract { /// Creates new `URLHintContract` - pub fn new(client: Arc) -> Self { + pub fn new(client: Arc>) -> Self { URLHintContract { - urlhint: Arc::new(Urlhint::new(Default::default())), - registrar: Registry::new(Default::default()), + urlhint: urlhint::Urlhint::default(), + registrar: Registrar::new(client.clone()), client: client, } } } -fn decode_urlhint_output(output: (String, ::util::H160, Address)) -> Option { +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, [u8; 20], Address)) -> Option { let (account_slash_repo, commit, owner) = output; if owner == Address::default() { @@ -124,13 +133,15 @@ fn decode_urlhint_output(output: (String, ::util::H160, Address)) -> Option Option BoxFuture, String> { - use futures::future::Either; - - let do_call = |_, data| { - let addr = match self.client.registrar() { - Ok(addr) => addr, - Err(e) => return future::err(e).boxed(), - }; - - self.client.call(addr, data) - }; - - let urlhint = self.urlhint.clone(); + fn resolve(&self, id: H256) -> Box, Error = String> + Send> { + let entries = self.urlhint.functions().entries(); let client = self.client.clone(); - self.registrar.get_address(do_call, "githubhint".sha3(), "A".into()) - .map(|addr| if addr == Address::default() { None } else { Some(addr) }) - .and_then(move |address| { - let mut fixed_id = [0; 32]; - let len = ::std::cmp::min(32, id.len()); - fixed_id[..len].copy_from_slice(&id[..len]); - - match address { - None => Either::A(future::ok(None)), - Some(address) => { - let do_call = move |_, data| client.call(address, data); - Either::B(urlhint.entries(do_call, ::util::H256(fixed_id)).map(decode_urlhint_output)) - } - } - }).boxed() + + let future = self.registrar.get_address(GITHUB_HINT) + .and_then(move |addr| if !addr.is_zero() { + let data = entries.input(id); + let result = client.call_contract(addr, data) + .and_then(move |output| entries.output(&output).map_err(|e| e.to_string())) + .map(decode_urlhint_output); + Either::B(result) + } else { + Either::A(future::ok(None)) + }); + Box::new(future) } } @@ -211,11 +208,13 @@ pub mod tests { use std::str::FromStr; use rustc_hex::FromHex; - use futures::{BoxFuture, Future, IntoFuture}; + use futures::{Future, IntoFuture}; use super::*; use super::guess_mime_type; - use util::{Bytes, Address, Mutex, ToPretty}; + use parking_lot::Mutex; + use ethereum_types::Address; + use bytes::{Bytes, ToPretty}; pub struct FakeRegistrar { pub calls: Arc>>, @@ -239,15 +238,17 @@ pub mod tests { } } - impl ContractClient for FakeRegistrar { - fn registrar(&self) -> Result { + impl RegistrarClient for FakeRegistrar { + type Call = Asynchronous; + + fn registrar_address(&self) -> Result { Ok(REGISTRAR.parse().unwrap()) } - fn call(&self, address: Address, data: Bytes) -> BoxFuture { + fn call_contract(&self, address: Address, data: Bytes) -> Self::Call { self.calls.lock().push((address.to_hex(), data.to_hex())); let res = self.responses.lock().remove(0); - res.into_future().boxed() + Box::new(res.into_future()) } } @@ -256,8 +257,8 @@ pub mod tests { // given let registrar = FakeRegistrar::new(); let resolve_result = { - use ethabi::{Encoder, Token}; - Encoder::encode(vec![Token::String(String::new()), Token::FixedBytes(vec![0; 20]), Token::Address([0; 20])]) + use ethabi::{encode, Token}; + encode(&[Token::String(String::new()), Token::FixedBytes(vec![0; 20]), Token::Address([0; 20].into())]) }; registrar.responses.lock()[1] = Ok(resolve_result); @@ -267,7 +268,7 @@ pub mod tests { // when - let res = urlhint.resolve("test".bytes().collect()).wait().unwrap(); + let res = urlhint.resolve("test".as_bytes().into()).wait().unwrap(); let calls = calls.lock(); let call0 = calls.get(0).expect("Registrar resolve called"); let call1 = calls.get(1).expect("URLHint Resolve called"); @@ -295,7 +296,7 @@ pub mod tests { let urlhint = URLHintContract::new(Arc::new(registrar)); // when - let res = urlhint.resolve("test".bytes().collect()).wait().unwrap(); + let res = urlhint.resolve("test".as_bytes().into()).wait().unwrap(); // then assert_eq!(res, Some(URLHintResult::Dapp(GithubApp { @@ -317,12 +318,12 @@ pub mod tests { let urlhint = URLHintContract::new(Arc::new(registrar)); // when - let res = urlhint.resolve("test".bytes().collect()).wait().unwrap(); + let res = urlhint.resolve("test".as_bytes().into()).wait().unwrap(); // then assert_eq!(res, Some(URLHintResult::Content(Content { url: "https://parity.io/assets/images/ethcore-black-horizontal.png".into(), - mime: mime!(Image/Png), + mime: mime::IMAGE_PNG, owner: Address::from_str("deadcafebeefbeefcafedeaddeedfeedffffffff").unwrap(), }))) } @@ -354,9 +355,9 @@ pub mod tests { assert_eq!(guess_mime_type(url1), None); - assert_eq!(guess_mime_type(url2), Some(mime!(Image/Png))); - assert_eq!(guess_mime_type(url3), Some(mime!(Image/Png))); - assert_eq!(guess_mime_type(url4), Some(mime!(Image/Jpeg))); - assert_eq!(guess_mime_type(url5), Some(mime!(Image/Png))); + assert_eq!(guess_mime_type(url2), Some(mime::IMAGE_PNG)); + assert_eq!(guess_mime_type(url3), Some(mime::IMAGE_PNG)); + assert_eq!(guess_mime_type(url4), Some(mime::IMAGE_JPEG)); + assert_eq!(guess_mime_type(url5), Some(mime::IMAGE_PNG)); } } diff --git a/hw/Cargo.toml b/hw/Cargo.toml index 345b1c3bbb94a4f795cb37c93a8dac7ca09e0152..c799c79c3820edeb06485ce4205438a41eacb40e 100644 --- a/hw/Cargo.toml +++ b/hw/Cargo.toml @@ -3,16 +3,18 @@ description = "Hardware wallet support." homepage = "http://parity.io" license = "GPL-3.0" name = "hardware-wallet" -version = "1.8.0" +version = "1.11.0" authors = ["Parity Technologies "] [dependencies] log = "0.3" -parking_lot = "0.4" +parking_lot = "0.5" +protobuf = "1.4" hidapi = { git = "https://github.com/paritytech/hidapi-rs" } libusb = { git = "https://github.com/paritytech/libusb-rs" } +trezor-sys = { git = "https://github.com/paritytech/trezor-sys" } ethkey = { path = "../ethkey" } -ethcore-bigint = { path = "../util/bigint" } +ethereum-types = "0.2" [dev-dependencies] rustc-hex = "1.0" diff --git a/hw/src/ledger.rs b/hw/src/ledger.rs index 0d787588d90e2eaecb030d7e517a0b5ca28fac23..e7d616d4f9fcc473087e621458f0b94611360fac 100644 --- a/hw/src/ledger.rs +++ b/hw/src/ledger.rs @@ -17,19 +17,27 @@ //! Ledger hardware wallet module. Supports Ledger Blue and Nano S. /// See https://github.com/LedgerHQ/blue-app-eth/blob/master/doc/ethapp.asc for protocol details. -use hidapi; -use std::fmt; use std::cmp::min; +use std::fmt; use std::str::FromStr; -use std::time::Duration; -use super::WalletInfo; -use ethkey::{Address, Signature}; -use bigint::hash::H256; +use std::sync::{Arc, Weak}; +use std::time::{Duration, Instant}; + +use ethereum_types::{H256, Address}; +use ethkey::Signature; +use hidapi; +use libusb; +use parking_lot::{Mutex, RwLock}; + +use super::{WalletInfo, KeyPath}; + +/// Ledger vendor ID +pub const LEDGER_VID: u16 = 0x2c97; +/// Legder product IDs: [Nano S and Blue] +pub const LEDGER_PIDS: [u16; 2] = [0x0000, 0x0001]; -const LEDGER_VID: u16 = 0x2c97; -const LEDGER_PIDS: [u16; 2] = [0x0000, 0x0001]; // Nano S and Blue -const ETH_DERIVATION_PATH_BE: [u8; 17] = [ 4, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0, 0, 0, 0, 0, 0, 0 ]; // 44'/60'/0'/0 -const ETC_DERIVATION_PATH_BE: [u8; 21] = [ 5, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0x02, 0x73, 0xd0, 0x80, 0, 0, 0, 0, 0, 0, 0 ]; // 44'/60'/160720'/0'/0 +const ETH_DERIVATION_PATH_BE: [u8; 17] = [4, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0, 0, 0, 0, 0, 0, 0]; // 44'/60'/0'/0 +const ETC_DERIVATION_PATH_BE: [u8; 21] = [5, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0x02, 0x73, 0xd0, 0x80, 0, 0, 0, 0, 0, 0, 0]; // 44'/60'/160720'/0'/0 const APDU_TAG: u8 = 0x05; const APDU_CLA: u8 = 0xe0; @@ -43,26 +51,21 @@ mod commands { pub const SIGN_ETH_TRANSACTION: u8 = 0x04; } -/// Key derivation paths used on ledger wallets. -#[derive(Debug, Clone, Copy)] -pub enum KeyPath { - /// Ethereum. - Ethereum, - /// Ethereum classic. - EthereumClassic, -} - -/// Hardware waller error. +/// Hardware wallet error. #[derive(Debug)] pub enum Error { /// Ethereum wallet protocol error. Protocol(&'static str), /// Hidapi error. Usb(hidapi::HidError), + /// Libusb error + LibUsb(libusb::Error), /// Device with request key is not available. KeyNotFound, /// Signing has been cancelled by user. UserCancel, + /// Invalid Device + InvalidDevice, } impl fmt::Display for Error { @@ -70,8 +73,10 @@ impl fmt::Display for Error { match *self { Error::Protocol(ref s) => write!(f, "Ledger protocol error: {}", s), Error::Usb(ref e) => write!(f, "USB communication error: {}", e), + Error::LibUsb(ref e) => write!(f, "LibUSB communication error: {}", e), Error::KeyNotFound => write!(f, "Key not found"), Error::UserCancel => write!(f, "Operation has been cancelled"), + Error::InvalidDevice => write!(f, "Unsupported product was entered"), } } } @@ -82,11 +87,17 @@ impl From for Error { } } +impl From for Error { + fn from(err: libusb::Error) -> Error { + Error::LibUsb(err) + } +} + /// Ledger device manager. pub struct Manager { - usb: hidapi::HidApi, - devices: Vec, - key_path: KeyPath, + usb: Arc>, + devices: RwLock>, + key_path: RwLock, } #[derive(Debug)] @@ -97,19 +108,19 @@ struct Device { impl Manager { /// Create a new instance. - pub fn new() -> Result { - let manager = Manager { - usb: hidapi::HidApi::new()?, - devices: Vec::new(), - key_path: KeyPath::Ethereum, - }; - Ok(manager) + pub fn new(hidapi: Arc>) -> Manager { + Manager { + usb: hidapi, + devices: RwLock::new(Vec::new()), + key_path: RwLock::new(KeyPath::Ethereum), + } } /// Re-populate device list. Only those devices that have Ethereum app open will be added. - pub fn update_devices(&mut self) -> Result { - self.usb.refresh_devices(); - let devices = self.usb.devices(); + pub fn update_devices(&self) -> Result { + let mut usb = self.usb.lock(); + usb.refresh_devices(); + let devices = usb.devices(); let mut new_devices = Vec::new(); let mut num_new_devices = 0; for device in devices { @@ -117,30 +128,30 @@ impl Manager { if device.vendor_id != LEDGER_VID || !LEDGER_PIDS.contains(&device.product_id) { continue; } - match self.read_device_info(&device) { + match self.read_device_info(&usb, &device) { Ok(info) => { debug!("Found device: {:?}", info); - if !self.devices.iter().any(|d| d.path == info.path) { + if !self.devices.read().iter().any(|d| d.path == info.path) { num_new_devices += 1; } new_devices.push(info); - }, + } Err(e) => debug!("Error reading device info: {}", e), }; } - self.devices = new_devices; + *self.devices.write() = new_devices; Ok(num_new_devices) } /// Select key derivation path for a known chain. - pub fn set_key_path(&mut self, key_path: KeyPath) { - self.key_path = key_path; + pub fn set_key_path(&self, key_path: KeyPath) { + *self.key_path.write() = key_path; } - fn read_device_info(&self, dev_info: &hidapi::HidDeviceInfo) -> Result { - let mut handle = self.open_path(&dev_info.path)?; - let address = Self::read_wallet_address(&mut handle, self.key_path)?; + fn read_device_info(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { + let mut handle = self.open_path(|| usb.open_path(&dev_info.path))?; + let address = Self::read_wallet_address(&mut handle, *self.key_path.read())?; let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); @@ -187,24 +198,24 @@ impl Manager { /// List connected wallets. This only returns wallets that are ready to be used. pub fn list_devices(&self) -> Vec { - self.devices.iter().map(|d| d.info.clone()).collect() + self.devices.read().iter().map(|d| d.info.clone()).collect() } /// Get wallet info. pub fn device_info(&self, address: &Address) -> Option { - self.devices.iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) + self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) } /// Sign transaction data with wallet managing `address`. pub fn sign_transaction(&self, address: &Address, data: &[u8]) -> Result { - let device = self.devices.iter().find(|d| &d.info.address == address) - .ok_or(Error::KeyNotFound)?; - - let handle = self.open_path(&device.path)?; + let usb = self.usb.lock(); + let devices = self.devices.read(); + let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; + let handle = self.open_path(|| usb.open_path(&device.path))?; let eth_path = Ð_DERIVATION_PATH_BE[..]; let etc_path = &ETC_DERIVATION_PATH_BE[..]; - let derivation_path = match self.key_path { + let derivation_path = match *self.key_path.read() { KeyPath::Ethereum => eth_path, KeyPath::EthereumClassic => etc_path, }; @@ -218,7 +229,7 @@ impl Manager { let p1 = if data_pos == 0 { 0x00 } else { 0x80 }; let dest_left = MAX_CHUNK_SIZE - dest_offset; let chunk_data_size = min(dest_left, data.len() - data_pos); - &mut chunk [dest_offset..][0..chunk_data_size].copy_from_slice(&data[data_pos..][0..chunk_data_size]); + &mut chunk[dest_offset..][0..chunk_data_size].copy_from_slice(&data[data_pos..][0..chunk_data_size]); result = Self::send_apdu(&handle, commands::SIGN_ETH_TRANSACTION, p1, 0, &chunk[0..(dest_offset + chunk_data_size)])?; dest_offset = 0; data_pos += chunk_data_size; @@ -236,50 +247,43 @@ impl Manager { Ok(Signature::from_rsv(&r, &s, v)) } - fn open_path(&self, path: &str) -> Result { - let mut err = Error::KeyNotFound; - /// Try to open device a few times. - for _ in 0..10 { - match self.usb.open_path(&path) { - Ok(handle) => return Ok(handle), - Err(e) => err = From::from(e), - } - ::std::thread::sleep(Duration::from_millis(200)); - } - Err(err) + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result + { + f().map_err(Into::into) } fn send_apdu(handle: &hidapi::HidDevice, command: u8, p1: u8, p2: u8, data: &[u8]) -> Result, Error> { const HID_PACKET_SIZE: usize = 64 + HID_PREFIX_ZERO; let mut offset = 0; let mut chunk_index = 0; - loop { - let mut hid_chunk: [u8; HID_PACKET_SIZE] = [0; HID_PACKET_SIZE]; - let mut chunk_size = if chunk_index == 0 { 12 } else { 5 }; - let size = min(64 - chunk_size, data.len() - offset); - { - let mut chunk = &mut hid_chunk[HID_PREFIX_ZERO..]; - &mut chunk[0..5].copy_from_slice(&[0x01, 0x01, APDU_TAG, (chunk_index >> 8) as u8, (chunk_index & 0xff) as u8 ]); - - if chunk_index == 0 { - let data_len = data.len() + 5; - &mut chunk[5..12].copy_from_slice(&[ (data_len >> 8) as u8, (data_len & 0xff) as u8, APDU_CLA, command, p1, p2, data.len() as u8 ]); - } - - &mut chunk[chunk_size..chunk_size + size].copy_from_slice(&data[offset..offset + size]); - offset += size; - chunk_size += size; - } - trace!("writing {:?}", &hid_chunk[..]); - let n = handle.write(&hid_chunk[..])?; - if n < chunk_size { - return Err(Error::Protocol("Write data size mismatch")); - } - if offset == data.len() { - break; + loop { + let mut hid_chunk: [u8; HID_PACKET_SIZE] = [0; HID_PACKET_SIZE]; + let mut chunk_size = if chunk_index == 0 { 12 } else { 5 }; + let size = min(64 - chunk_size, data.len() - offset); + { + let chunk = &mut hid_chunk[HID_PREFIX_ZERO..]; + &mut chunk[0..5].copy_from_slice(&[0x01, 0x01, APDU_TAG, (chunk_index >> 8) as u8, (chunk_index & 0xff) as u8 ]); + + if chunk_index == 0 { + let data_len = data.len() + 5; + &mut chunk[5..12].copy_from_slice(&[ (data_len >> 8) as u8, (data_len & 0xff) as u8, APDU_CLA, command, p1, p2, data.len() as u8 ]); } - chunk_index += 1; + + &mut chunk[chunk_size..chunk_size + size].copy_from_slice(&data[offset..offset + size]); + offset += size; + chunk_size += size; + } + trace!("writing {:?}", &hid_chunk[..]); + let n = handle.write(&hid_chunk[..])?; + if n < chunk_size { + return Err(Error::Protocol("Write data size mismatch")); } + if offset == data.len() { + break; + } + chunk_index += 1; + } // read response chunk_index = 0; @@ -303,7 +307,7 @@ impl Manager { if chunk_size < 7 { return Err(Error::Protocol("Unexpected chunk header")); } - message_size = (chunk[5] as usize) << 8 | (chunk[6] as usize); + message_size = (chunk[5] as usize) << 8 | (chunk[6] as usize); offset += 2; } message.extend_from_slice(&chunk[offset..chunk_size]); @@ -311,12 +315,12 @@ impl Manager { if message.len() == message_size { break; } - chunk_index +=1; + chunk_index += 1; } if message.len() < 2 { return Err(Error::Protocol("No status word")); } - let status = (message[message.len() - 2] as usize) << 8 | (message[message.len() - 1] as usize); + let status = (message[message.len() - 2] as usize) << 8 | (message[message.len() - 1] as usize); debug!("Read status {:x}", status); match status { 0x6700 => Err(Error::Protocol("Incorrect length")), @@ -336,14 +340,74 @@ impl Manager { message.truncate(new_len); Ok(message) } + + fn is_valid_ledger(device: &libusb::Device) -> Result<(), Error> { + let desc = device.device_descriptor()?; + let vendor_id = desc.vendor_id(); + let product_id = desc.product_id(); + + if vendor_id == LEDGER_VID && LEDGER_PIDS.contains(&product_id) { + Ok(()) + } else { + Err(Error::InvalidDevice) + } + } +} + +// Try to connect to the device using polling in at most the time specified by the `timeout` +fn try_connect_polling(ledger: Arc, timeout: Duration) -> bool { + let start_time = Instant::now(); + while start_time.elapsed() <= timeout { + if let Ok(_) = ledger.update_devices() { + return true + } + } + false +} + +/// Ledger event handler +/// A seperate thread is hanedling incoming events +/// +/// Note, that this run to completion and race-conditions can't occur but this can +/// therefore starve other events for being process with a spinlock or similar +pub struct EventHandler { + ledger: Weak, +} + +impl EventHandler { + /// Ledger event handler constructor + pub fn new(ledger: Weak) -> Self { + Self { ledger: ledger } + } +} + +impl libusb::Hotplug for EventHandler { + fn device_arrived(&mut self, device: libusb::Device) { + debug!(target: "hw", "Ledger arrived"); + if let (Some(ledger), Ok(_)) = (self.ledger.upgrade(), Manager::is_valid_ledger(&device)) { + if try_connect_polling(ledger, Duration::from_millis(500)) != true { + debug!(target: "hw", "Ledger connect timeout"); + } + } + } + + fn device_left(&mut self, device: libusb::Device) { + debug!(target: "hw", "Ledger left"); + if let (Some(ledger), Ok(_)) = (self.ledger.upgrade(), Manager::is_valid_ledger(&device)) { + if try_connect_polling(ledger, Duration::from_millis(500)) != true { + debug!(target: "hw", "Ledger disconnect timeout"); + } + } + } } #[test] fn smoke() { use rustc_hex::FromHex; - let mut manager = Manager::new().unwrap(); + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().unwrap())); + let manager = Manager::new(hidapi.clone()); manager.update_devices().unwrap(); - for d in &manager.devices { + for d in &*manager.devices.read() { println!("Device: {:?}", d); } diff --git a/hw/src/lib.rs b/hw/src/lib.rs index cda6c22412d469d570242a569b2a88469833ef4b..9bfec83410b55300551f6acb448bde7a85e45471 100644 --- a/hw/src/lib.rs +++ b/hw/src/lib.rs @@ -16,39 +16,70 @@ //! Hardware wallet management. -extern crate parking_lot; +#![warn(missing_docs)] + +extern crate ethereum_types; +extern crate ethkey; extern crate hidapi; extern crate libusb; -extern crate ethkey; -extern crate ethcore_bigint as bigint; +extern crate parking_lot; +extern crate protobuf; +extern crate trezor_sys; #[macro_use] extern crate log; #[cfg(test)] extern crate rustc_hex; mod ledger; +mod trezor; + +use ethkey::{Address, Signature}; +use parking_lot::Mutex; use std::fmt; -use std::thread; +use std::sync::Arc; use std::sync::atomic; -use std::sync::{Arc, Weak}; use std::sync::atomic::AtomicBool; +use std::thread; use std::time::Duration; -use parking_lot::Mutex; -use ethkey::{Address, Signature}; +use ethereum_types::U256; -pub use ledger::KeyPath; +const USB_DEVICE_CLASS_DEVICE: u8 = 0; -/// Hardware waller error. +/// Hardware wallet error. #[derive(Debug)] pub enum Error { /// Ledger device error. LedgerDevice(ledger::Error), + /// Trezor device error + TrezorDevice(trezor::Error), /// USB error. Usb(libusb::Error), + /// HID error + Hid(String), /// Hardware wallet not found for specified key. KeyNotFound, } -/// Hardware waller information. +/// This is the transaction info we need to supply to Trezor message. It's more +/// or less a duplicate of ethcore::transaction::Transaction, but we can't +/// import ethcore here as that would be a circular dependency. +pub struct TransactionInfo { + /// Nonce + pub nonce: U256, + /// Gas price + pub gas_price: U256, + /// Gas limit + pub gas_limit: U256, + /// Receiver + pub to: Option
, + /// Value + pub value: U256, + /// Data + pub data: Vec, + /// Chain ID + pub chain_id: Option, +} + +/// Hardware wallet information. #[derive(Debug, Clone)] pub struct WalletInfo { /// Wallet device name. @@ -61,12 +92,23 @@ pub struct WalletInfo { pub address: Address, } +/// Key derivation paths used on hardware wallets. +#[derive(Debug, Clone, Copy)] +pub enum KeyPath { + /// Ethereum. + Ethereum, + /// Ethereum classic. + EthereumClassic, +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { Error::KeyNotFound => write!(f, "Key not found for given address."), Error::LedgerDevice(ref e) => write!(f, "{}", e), + Error::TrezorDevice(ref e) => write!(f, "{}", e), Error::Usb(ref e) => write!(f, "{}", e), + Error::Hid(ref e) => write!(f, "{}", e), } } } @@ -80,6 +122,15 @@ impl From for Error { } } +impl From for Error { + fn from(err: trezor::Error) -> Error { + match err { + trezor::Error::KeyNotFound => Error::KeyNotFound, + _ => Error::TrezorDevice(err), + } + } +} + impl From for Error { fn from(err: libusb::Error) -> Error { Error::Usb(err) @@ -88,96 +139,134 @@ impl From for Error { /// Hardware wallet management interface. pub struct HardwareWalletManager { - update_thread: Option>, exiting: Arc, - ledger: Arc>, + ledger: Arc, + trezor: Arc, } -struct EventHandler { - ledger: Weak>, -} - -impl libusb::Hotplug for EventHandler { - fn device_arrived(&mut self, _device: libusb::Device) { - debug!("USB Device arrived"); - if let Some(l) = self.ledger.upgrade() { - for _ in 0..10 { - // The device might not be visible right away. Try a few times. - if l.lock().update_devices().unwrap_or_else(|e| { - debug!("Error enumerating Ledger devices: {}", e); - 0 - }) > 0 { - break; - } - thread::sleep(Duration::from_millis(200)); - } - } - } - - fn device_left(&mut self, _device: libusb::Device) { - debug!("USB Device lost"); - if let Some(l) = self.ledger.upgrade() { - if let Err(e) = l.lock().update_devices() { - debug!("Error enumerating Ledger devices: {}", e); - } - } - } -} impl HardwareWalletManager { + /// Hardware wallet constructor pub fn new() -> Result { - let usb_context = Arc::new(libusb::Context::new()?); - let ledger = Arc::new(Mutex::new(ledger::Manager::new()?)); - usb_context.register_callback(None, None, None, Box::new(EventHandler { ledger: Arc::downgrade(&ledger) }))?; + let usb_context_trezor = Arc::new(libusb::Context::new()?); + let usb_context_ledger = Arc::new(libusb::Context::new()?); + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().map_err(|e| Error::Hid(e.to_string().clone()))?)); + let ledger = Arc::new(ledger::Manager::new(hidapi.clone())); + let trezor = Arc::new(trezor::Manager::new(hidapi.clone())); + + // Subscribe to TREZOR V1 + // Note, this support only TREZOR V1 becasue TREZOR V2 has another vendorID for some reason + // Also, we now only support one product as the second argument specifies + usb_context_trezor.register_callback( + Some(trezor::TREZOR_VID), Some(trezor::TREZOR_PIDS[0]), Some(USB_DEVICE_CLASS_DEVICE), + Box::new(trezor::EventHandler::new(Arc::downgrade(&trezor))))?; + + // Subscribe to all Ledger Devices + // This means that we need to check that the given productID is supported + // None => LIBUSB_HOTPLUG_MATCH_ANY, in other words that all are subscribed to + // More info can be found: http://libusb.sourceforge.net/api-1.0/group__hotplug.html#gae6c5f1add6cc754005549c7259dc35ea + usb_context_ledger.register_callback( + Some(ledger::LEDGER_VID), None, Some(USB_DEVICE_CLASS_DEVICE), + Box::new(ledger::EventHandler::new(Arc::downgrade(&ledger))))?; + let exiting = Arc::new(AtomicBool::new(false)); - let thread_exiting = exiting.clone(); + let thread_exiting_ledger = exiting.clone(); + let thread_exiting_trezor = exiting.clone(); let l = ledger.clone(); - let thread = thread::Builder::new().name("hw_wallet".to_string()).spawn(move || { - if let Err(e) = l.lock().update_devices() { - debug!("Error updating ledger devices: {}", e); - } - loop { - usb_context.handle_events(Some(Duration::from_millis(500))).unwrap_or_else(|e| debug!("Error processing USB events: {}", e)); - if thread_exiting.load(atomic::Ordering::Acquire) { - break; + let t = trezor.clone(); + + // Ledger event thread + thread::Builder::new() + .name("hw_wallet_ledger".to_string()) + .spawn(move || { + if let Err(e) = l.update_devices() { + debug!(target: "hw", "Ledger couldn't connect at startup, error: {}", e); + } + loop { + usb_context_ledger.handle_events(Some(Duration::from_millis(500))) + .unwrap_or_else(|e| debug!(target: "hw", "Ledger event handler error: {}", e)); + if thread_exiting_ledger.load(atomic::Ordering::Acquire) { + break; + } } - } - }).ok(); + }) + .ok(); + + // Trezor event thread + thread::Builder::new() + .name("hw_wallet_trezor".to_string()) + .spawn(move || { + if let Err(e) = t.update_devices() { + debug!(target: "hw", "Trezor couldn't connect at startup, error: {}", e); + } + loop { + usb_context_trezor.handle_events(Some(Duration::from_millis(500))) + .unwrap_or_else(|e| debug!(target: "hw", "Trezor event handler error: {}", e)); + if thread_exiting_trezor.load(atomic::Ordering::Acquire) { + break; + } + } + }) + .ok(); + Ok(HardwareWalletManager { - update_thread: thread, exiting: exiting, ledger: ledger, + trezor: trezor, }) } /// Select key derivation path for a chain. pub fn set_key_path(&self, key_path: KeyPath) { - self.ledger.lock().set_key_path(key_path); + self.ledger.set_key_path(key_path); + self.trezor.set_key_path(key_path); } - /// List connected wallets. This only returns wallets that are ready to be used. pub fn list_wallets(&self) -> Vec { - self.ledger.lock().list_devices() + let mut wallets = Vec::new(); + wallets.extend(self.ledger.list_devices()); + wallets.extend(self.trezor.list_devices()); + wallets + } + + /// Return a list of paths to locked hardware wallets + pub fn list_locked_wallets(&self) -> Result, Error> { + Ok(self.trezor.list_locked_devices()) } /// Get connected wallet info. pub fn wallet_info(&self, address: &Address) -> Option { - self.ledger.lock().device_info(address) + if let Some(info) = self.ledger.device_info(address) { + Some(info) + } else { + self.trezor.device_info(address) + } } /// Sign transaction data with wallet managing `address`. - pub fn sign_transaction(&self, address: &Address, data: &[u8]) -> Result { - Ok(self.ledger.lock().sign_transaction(address, data)?) + pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo, encoded_transaction: &[u8]) -> Result { + if self.ledger.device_info(address).is_some() { + Ok(self.ledger.sign_transaction(address, encoded_transaction)?) + } else if self.trezor.device_info(address).is_some() { + Ok(self.trezor.sign_transaction(address, t_info)?) + } else { + Err(Error::KeyNotFound) + } + } + + /// Send a pin to a device at a certain path to unlock it + pub fn pin_matrix_ack(&self, path: &str, pin: &str) -> Result { + self.trezor.pin_matrix_ack(path, pin).map_err(Error::TrezorDevice) } } impl Drop for HardwareWalletManager { fn drop(&mut self) { + // Indicate to the USB Hotplug handlers that they + // shall terminate but don't wait for them to terminate. + // If they don't terminate for some reason USB Hotplug events will be handled + // even if the HardwareWalletManger has been dropped self.exiting.store(true, atomic::Ordering::Release); - if let Some(thread) = self.update_thread.take() { - thread.thread().unpark(); - thread.join().ok(); - } } } diff --git a/hw/src/trezor.rs b/hw/src/trezor.rs new file mode 100644 index 0000000000000000000000000000000000000000..7db226718bc6681981cfea05a22ae5e93390be70 --- /dev/null +++ b/hw/src/trezor.rs @@ -0,0 +1,480 @@ +// 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 . + +//! Trezor hardware wallet module. Supports Trezor v1. +//! See http://doc.satoshilabs.com/trezor-tech/api-protobuf.html +//! and https://github.com/trezor/trezor-common/blob/master/protob/protocol.md +//! for protocol details. + +use super::{WalletInfo, TransactionInfo, KeyPath}; + +use std::cmp::{min, max}; +use std::fmt; +use std::sync::{Arc, Weak}; +use std::time::{Duration, Instant}; + +use ethereum_types::{U256, H256, Address}; +use ethkey::Signature; +use hidapi; +use libusb; +use parking_lot::{Mutex, RwLock}; +use protobuf; +use protobuf::{Message, ProtobufEnum}; + +use trezor_sys::messages::{EthereumAddress, PinMatrixAck, MessageType, EthereumTxRequest, EthereumSignTx, EthereumGetAddress, EthereumTxAck, ButtonAck}; + +/// Trezor v1 vendor ID +pub const TREZOR_VID: u16 = 0x534c; +/// Trezor product IDs +pub const TREZOR_PIDS: [u16; 1] = [0x0001]; + +const ETH_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003C, 0x80000000, 0, 0]; // m/44'/60'/0'/0/0 +const ETC_DERIVATION_PATH: [u32; 5] = [0x8000002C, 0x8000003D, 0x80000000, 0, 0]; // m/44'/61'/0'/0/0 + +/// Hardware wallet error. +#[derive(Debug)] +pub enum Error { + /// Ethereum wallet protocol error. + Protocol(&'static str), + /// Hidapi error. + Usb(hidapi::HidError), + /// Device with request key is not available. + KeyNotFound, + /// Signing has been cancelled by user. + UserCancel, + /// The Message Type given in the trezor RPC call is not something we recognize + BadMessageType, + /// Trying to read from a closed device at the given path + LockedDevice(String), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::Protocol(ref s) => write!(f, "Trezor protocol error: {}", s), + Error::Usb(ref e) => write!(f, "USB communication error: {}", e), + Error::KeyNotFound => write!(f, "Key not found"), + Error::UserCancel => write!(f, "Operation has been cancelled"), + Error::BadMessageType => write!(f, "Bad Message Type in RPC call"), + Error::LockedDevice(ref s) => write!(f, "Device is locked, needs PIN to perform operations: {}", s), + } + } +} + +impl From for Error { + fn from(err: hidapi::HidError) -> Error { + Error::Usb(err) + } +} + +impl From for Error { + fn from(_: protobuf::ProtobufError) -> Error { + Error::Protocol(&"Could not read response from Trezor Device") + } +} + +/// Ledger device manager +pub struct Manager { + usb: Arc>, + devices: RwLock>, + locked_devices: RwLock>, + key_path: RwLock, +} + +#[derive(Debug)] +struct Device { + path: String, + info: WalletInfo, +} + +/// HID Version used for the Trezor device +enum HidVersion { + V1, + V2, +} + +impl Manager { + /// Create a new instance. + pub fn new(hidapi: Arc>) -> Manager { + Manager { + usb: hidapi, + devices: RwLock::new(Vec::new()), + locked_devices: RwLock::new(Vec::new()), + key_path: RwLock::new(KeyPath::Ethereum), + } + } + + /// Re-populate device list + pub fn update_devices(&self) -> Result { + let mut usb = self.usb.lock(); + usb.refresh_devices(); + let devices = usb.devices(); + let mut new_devices = Vec::new(); + let mut locked_devices = Vec::new(); + let mut error = None; + for usb_device in devices { + let is_trezor = usb_device.vendor_id == TREZOR_VID; + let is_supported_product = TREZOR_PIDS.contains(&usb_device.product_id); + let is_valid = usb_device.usage_page == 0xFF00 || usb_device.interface_number == 0; + + trace!( + "Checking device: {:?}, trezor: {:?}, prod: {:?}, valid: {:?}", + usb_device, + is_trezor, + is_supported_product, + is_valid, + ); + if !is_trezor || !is_supported_product || !is_valid { + continue; + } + match self.read_device_info(&usb, &usb_device) { + Ok(device) => new_devices.push(device), + Err(Error::LockedDevice(path)) => locked_devices.push(path.to_string()), + Err(e) => { + warn!("Error reading device: {:?}", e); + error = Some(e); + } + } + } + let count = new_devices.len(); + trace!("Got devices: {:?}, closed: {:?}", new_devices, locked_devices); + *self.devices.write() = new_devices; + *self.locked_devices.write() = locked_devices; + match error { + Some(e) => Err(e), + None => Ok(count), + } + } + + fn read_device_info(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { + let handle = self.open_path(|| usb.open_path(&dev_info.path))?; + let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); + let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); + let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); + match self.get_address(&handle) { + Ok(Some(addr)) => { + Ok(Device { + path: dev_info.path.clone(), + info: WalletInfo { + name: name, + manufacturer: manufacturer, + serial: serial, + address: addr, + }, + }) + } + Ok(None) => Err(Error::LockedDevice(dev_info.path.clone())), + Err(e) => Err(e), + } + } + + /// Select key derivation path for a known chain. + pub fn set_key_path(&self, key_path: KeyPath) { + *self.key_path.write() = key_path; + } + + /// List connected wallets. This only returns wallets that are ready to be used. + pub fn list_devices(&self) -> Vec { + self.devices.read().iter().map(|d| d.info.clone()).collect() + } + + pub fn list_locked_devices(&self) -> Vec { + (*self.locked_devices.read()).clone() + } + + /// Get wallet info. + pub fn device_info(&self, address: &Address) -> Option { + self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) + } + + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result + { + f().map_err(Into::into) + } + + pub fn pin_matrix_ack(&self, device_path: &str, pin: &str) -> Result { + let unlocked = { + let usb = self.usb.lock(); + let device = self.open_path(|| usb.open_path(&device_path))?; + let t = MessageType::MessageType_PinMatrixAck; + let mut m = PinMatrixAck::new(); + m.set_pin(pin.to_string()); + self.send_device_message(&device, &t, &m)?; + let (resp_type, _) = self.read_device_response(&device)?; + match resp_type { + // Getting an Address back means it's unlocked, this is undocumented behavior + MessageType::MessageType_EthereumAddress => Ok(true), + // Getting anything else means we didn't unlock it + _ => Ok(false), + + } + }; + self.update_devices()?; + unlocked + } + + fn get_address(&self, device: &hidapi::HidDevice) -> Result, Error> { + let typ = MessageType::MessageType_EthereumGetAddress; + let mut message = EthereumGetAddress::new(); + match *self.key_path.read() { + KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), + KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), + } + message.set_show_display(false); + self.send_device_message(&device, &typ, &message)?; + + let (resp_type, bytes) = self.read_device_response(&device)?; + match resp_type { + MessageType::MessageType_EthereumAddress => { + let response: EthereumAddress = protobuf::core::parse_from_bytes(&bytes)?; + Ok(Some(From::from(response.get_address()))) + } + _ => Ok(None), + } + } + + /// Sign transaction data with wallet managing `address`. + pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo) -> Result { + let usb = self.usb.lock(); + let devices = self.devices.read(); + let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; + let handle = self.open_path(|| usb.open_path(&device.path))?; + let msg_type = MessageType::MessageType_EthereumSignTx; + let mut message = EthereumSignTx::new(); + match *self.key_path.read() { + KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), + KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), + } + message.set_nonce(self.u256_to_be_vec(&t_info.nonce)); + message.set_gas_limit(self.u256_to_be_vec(&t_info.gas_limit)); + message.set_gas_price(self.u256_to_be_vec(&t_info.gas_price)); + message.set_value(self.u256_to_be_vec(&t_info.value)); + + match t_info.to { + Some(addr) => { + message.set_to(addr.to_vec()) + } + None => (), + } + let first_chunk_length = min(t_info.data.len(), 1024); + let chunk = &t_info.data[0..first_chunk_length]; + message.set_data_initial_chunk(chunk.to_vec()); + message.set_data_length(t_info.data.len() as u32); + if let Some(c_id) = t_info.chain_id { + message.set_chain_id(c_id as u32); + } + + self.send_device_message(&handle, &msg_type, &message)?; + + self.signing_loop(&handle, &t_info.chain_id, &t_info.data[first_chunk_length..]) + } + + fn u256_to_be_vec(&self, val: &U256) -> Vec { + let mut buf = [0u8; 32]; + val.to_big_endian(&mut buf); + buf.iter().skip_while(|x| **x == 0).cloned().collect() + } + + fn signing_loop(&self, handle: &hidapi::HidDevice, chain_id: &Option, data: &[u8]) -> Result { + let (resp_type, bytes) = self.read_device_response(&handle)?; + match resp_type { + MessageType::MessageType_Cancel => Err(Error::UserCancel), + MessageType::MessageType_ButtonRequest => { + self.send_device_message(handle, &MessageType::MessageType_ButtonAck, &ButtonAck::new())?; + // Signing loop goes back to the top and reading blocks + // for up to 5 minutes waiting for response from the device + // if the user doesn't click any button within 5 minutes you + // get a signing error and the device sort of locks up on the signing screen + self.signing_loop(handle, chain_id, data) + } + MessageType::MessageType_EthereumTxRequest => { + let resp: EthereumTxRequest = protobuf::core::parse_from_bytes(&bytes)?; + if resp.has_data_length() { + let mut msg = EthereumTxAck::new(); + let len = resp.get_data_length() as usize; + msg.set_data_chunk(data[..len].to_vec()); + self.send_device_message(handle, &MessageType::MessageType_EthereumTxAck, &msg)?; + self.signing_loop(handle, chain_id, &data[len..]) + } else { + let v = resp.get_signature_v(); + let r = H256::from_slice(resp.get_signature_r()); + let s = H256::from_slice(resp.get_signature_s()); + if let Some(c_id) = *chain_id { + // If there is a chain_id supplied, Trezor will return a v + // part of the signature that is already adjusted for EIP-155, + // so v' = v + 2 * chain_id + 35, but code further down the + // pipeline will already do this transformation, so remove it here + let adjustment = 35 + 2 * c_id as u32; + Ok(Signature::from_rsv(&r, &s, (max(v, adjustment) - adjustment) as u8)) + } else { + // If there isn't a chain_id, v will be returned as v + 27 + let adjusted_v = if v < 27 { v } else { v - 27 }; + Ok(Signature::from_rsv(&r, &s, adjusted_v as u8)) + } + } + } + MessageType::MessageType_Failure => Err(Error::Protocol("Last message sent to Trezor failed")), + _ => Err(Error::Protocol("Unexpected response from Trezor device.")), + } + } + + fn send_device_message(&self, device: &hidapi::HidDevice, msg_type: &MessageType, msg: &Message) -> Result { + let msg_id = *msg_type as u16; + let mut message = msg.write_to_bytes()?; + let msg_size = message.len(); + let mut data = Vec::new(); + let hid_version = self.probe_hid_version(device)?; + // Magic constants + data.push('#' as u8); + data.push('#' as u8); + // Convert msg_id to BE and split into bytes + data.push(((msg_id >> 8) & 0xFF) as u8); + data.push((msg_id & 0xFF) as u8); + // Convert msg_size to BE and split into bytes + data.push(((msg_size >> 24) & 0xFF) as u8); + data.push(((msg_size >> 16) & 0xFF) as u8); + data.push(((msg_size >> 8) & 0xFF) as u8); + data.push((msg_size & 0xFF) as u8); + data.append(&mut message); + while data.len() % 63 > 0 { + data.push(0); + } + let mut total_written = 0; + for chunk in data.chunks(63) { + let mut padded_chunk = match hid_version { + HidVersion::V1 => vec!['?' as u8], + HidVersion::V2 => vec![0, '?' as u8], + }; + padded_chunk.extend_from_slice(&chunk); + total_written += device.write(&padded_chunk)?; + } + Ok(total_written) + } + + fn probe_hid_version(&self, device: &hidapi::HidDevice) -> Result { + let mut buf2 = [0xFFu8; 65]; + buf2[0] = 0; + buf2[1] = 63; + let mut buf1 = [0xFFu8; 64]; + buf1[0] = 63; + if device.write(&buf2)? == 65 { + Ok(HidVersion::V2) + } else if device.write(&buf1)? == 64 { + Ok(HidVersion::V1) + } else { + Err(Error::Usb("Unable to determine HID Version")) + } + } + + fn read_device_response(&self, device: &hidapi::HidDevice) -> Result<(MessageType, Vec), Error> { + let protocol_err = Error::Protocol(&"Unexpected wire response from Trezor Device"); + let mut buf = vec![0; 64]; + + let first_chunk = device.read_timeout(&mut buf, 300_000)?; + if first_chunk < 9 || buf[0] != '?' as u8 || buf[1] != '#' as u8 || buf[2] != '#' as u8 { + return Err(protocol_err); + } + let msg_type = MessageType::from_i32(((buf[3] as i32 & 0xFF) << 8) + (buf[4] as i32 & 0xFF)).ok_or(protocol_err)?; + let msg_size = ((buf[5] as u32 & 0xFF) << 24) + ((buf[6] as u32 & 0xFF) << 16) + ((buf[7] as u32 & 0xFF) << 8) + (buf[8] as u32 & 0xFF); + let mut data = Vec::new(); + data.extend_from_slice(&buf[9..]); + while data.len() < (msg_size as usize) { + device.read_timeout(&mut buf, 10_000)?; + data.extend_from_slice(&buf[1..]); + } + Ok((msg_type, data[..msg_size as usize].to_vec())) + } +} + +// Try to connect to the device using polling in at most the time specified by the `timeout` +fn try_connect_polling(trezor: Arc, duration: Duration) -> bool { + let start_time = Instant::now(); + while start_time.elapsed() <= duration { + if let Ok(_) = trezor.update_devices() { + return true + } + } + false +} + +/// Trezor event handler +/// A separate thread is handeling incoming events +/// +/// Note, that this run to completion and race-conditions can't occur but this can +/// therefore starve other events for being process with a spinlock or similar +pub struct EventHandler { + trezor: Weak, +} + +impl EventHandler { + /// Trezor event handler constructor + pub fn new(trezor: Weak) -> Self { + Self { trezor: trezor } + } +} + +impl libusb::Hotplug for EventHandler { + fn device_arrived(&mut self, _device: libusb::Device) { + debug!(target: "hw", "Trezor V1 arrived"); + if let Some(trezor) = self.trezor.upgrade() { + if try_connect_polling(trezor, Duration::from_millis(500)) != true { + debug!(target: "hw", "Ledger connect timeout"); + } + } + } + + fn device_left(&mut self, _device: libusb::Device) { + debug!(target: "hw", "Trezor V1 left"); + if let Some(trezor) = self.trezor.upgrade() { + if try_connect_polling(trezor, Duration::from_millis(500)) != true { + debug!(target: "hw", "Ledger disconnect timeout"); + } + } + } +} + +#[test] +#[ignore] +/// This test can't be run without an actual trezor device connected +/// (and unlocked) attached to the machine that's running the test +fn test_signature() { + use ethereum_types::{H160, H256, U256}; + + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().unwrap())); + let manager = Manager::new(hidapi.clone()); + let addr: Address = H160::from("some_addr"); + + manager.update_devices().unwrap(); + + let t_info = TransactionInfo { + nonce: U256::from(1), + gas_price: U256::from(100), + gas_limit: U256::from(21_000), + to: Some(H160::from("some_other_addr")), + chain_id: Some(17), + value: U256::from(1_000_000), + data: (&[1u8; 3000]).to_vec(), + }; + let signature = manager.sign_transaction(&addr, &t_info).unwrap(); + let expected = Signature::from_rsv( + &H256::from("device_specific_r"), + &H256::from("device_specific_s"), + 0x01 + ); + + assert_eq!(signature, expected) +} diff --git a/ipc-common-types/Cargo.toml b/ipc-common-types/Cargo.toml deleted file mode 100644 index ec9b157d5c11e7285bf65d1287a14d0e81dce97e..0000000000000000000000000000000000000000 --- a/ipc-common-types/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -description = "Types that implement IPC and are common to multiple modules." -name = "ipc-common-types" -version = "1.8.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[build-dependencies] -ethcore-ipc-codegen = { path = "../ipc/codegen" } - -[dependencies] -semver = "0.6" -ethcore-ipc = { path = "../ipc/rpc" } -ethcore-util = { path = "../util" } diff --git a/ipc-common-types/build.rs b/ipc-common-types/build.rs deleted file mode 100644 index 3a51d6a215876b207501304611fc7e5ee68cb944..0000000000000000000000000000000000000000 --- a/ipc-common-types/build.rs +++ /dev/null @@ -1,21 +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 . - -extern crate ethcore_ipc_codegen; - -fn main() { - ethcore_ipc_codegen::derive_binary("src/types/mod.rs.in").unwrap(); -} diff --git a/ipc-common-types/src/types/mod.rs b/ipc-common-types/src/types/mod.rs deleted file mode 100644 index 68dfe0b252839d0b6027446bc17c3ead1ea46d7d..0000000000000000000000000000000000000000 --- a/ipc-common-types/src/types/mod.rs +++ /dev/null @@ -1,21 +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 . - -//! Types used in the public api - -#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues -include!(concat!(env!("OUT_DIR"), "/mod.rs.in")); - diff --git a/ipc-common-types/src/types/mod.rs.in b/ipc-common-types/src/types/mod.rs.in deleted file mode 100644 index f137d1d607bdba37c1c5b262bd866eb0d6249fd4..0000000000000000000000000000000000000000 --- a/ipc-common-types/src/types/mod.rs.in +++ /dev/null @@ -1,21 +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 . - -pub mod release_track; -pub mod version_info; - -pub use release_track::{ReleaseTrack}; -pub use version_info::{VersionInfo}; \ No newline at end of file diff --git a/ipc/codegen/Cargo.toml b/ipc/codegen/Cargo.toml deleted file mode 100644 index 69580e08d76f7faf55f66bc4706cc55eae324923..0000000000000000000000000000000000000000 --- a/ipc/codegen/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "ethcore-ipc-codegen" -version = "1.8.0" -authors = ["Parity Technologies "] -license = "GPL-3.0" -description = "Macros to auto-generate implementations for ipc call" -build = "build.rs" -keywords = ["ipc", "codegen"] - -[features] -default = ["with-syntex"] -nightly = ["quasi_macros"] -nightly-testing = ["clippy"] -with-syntex = ["quasi/with-syntex", "quasi_codegen", "quasi_codegen/with-syntex", "syntex", "syntex_syntax"] - -[build-dependencies] -quasi_codegen = { version = "0.32", optional = true } -syntex = { version = "0.58", optional = true } - -[dependencies] -aster = { version = "0.41", default-features = false } -clippy = { version = "^0.*", optional = true } -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 } diff --git a/ipc/codegen/build.rs b/ipc/codegen/build.rs deleted file mode 100644 index 442abf7dfba6404c05fbf2923dbe67346457b1b1..0000000000000000000000000000000000000000 --- a/ipc/codegen/build.rs +++ /dev/null @@ -1,43 +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 . - - -#[cfg(feature = "with-syntex")] -mod inner { - extern crate syntex; - extern crate quasi_codegen; - - use std::env; - use std::path::Path; - - pub fn main() { - let out_dir = env::var_os("OUT_DIR").unwrap(); - - let src = Path::new("src/lib.rs.in"); - let dst = Path::new(&out_dir).join("lib.rs"); - - quasi_codegen::expand(&src, &dst).unwrap(); - } -} - -#[cfg(not(feature = "with-syntex"))] -mod inner { - pub fn main() {} -} - -fn main() { - inner::main(); -} diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs deleted file mode 100644 index 2f4752d9716407f99e954183210960ba8803e542..0000000000000000000000000000000000000000 --- a/ipc/codegen/src/codegen.rs +++ /dev/null @@ -1,898 +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 . -use aster; - -use syntax::ast::{ - MetaItem, - Item, - ImplItemKind, - MethodSig, - Arg, - PatKind, - FunctionRetTy, - Ty, - TraitRef, - Ident, - Generics, - TraitItemKind, -}; - -use syntax::ast; -use syntax::codemap::Span; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ptr::P; - -pub struct Error; - -const RESERVED_MESSAGE_IDS: u16 = 16; - -pub fn expand_ipc_implementation( - cx: &mut ExtCtxt, - span: Span, - meta_item: &MetaItem, - annotatable: &Annotatable, - push: &mut FnMut(Annotatable) -) { - let item = match *annotatable { - Annotatable::Item(ref item) => item, - _ => { - cx.span_err(meta_item.span, "`#[ipc]` may only be applied to implementations and traits"); - return; - }, - }; - - let builder = aster::AstBuilder::new().span(span); - - let interface_map = match implement_interface(cx, &builder, &item, push, meta_item) { - Ok(interface_map) => interface_map, - Err(Error) => { return; }, - }; - - push_client(cx, &builder, &interface_map, push); - - push(Annotatable::Item(interface_map.item)); -} - -macro_rules! literal { - ($builder:ident, $($arg:tt)*) => { - $builder.expr().lit().str::<&str>(&format!($($arg)*)) - } -} - -fn field_name(builder: &aster::AstBuilder, arg: &Arg) -> ast::Ident { - match arg.pat.node { - PatKind::Ident(_, ref ident, _) => builder.id(ident.node), - _ => { panic!("unexpected param in interface: {:?}", arg.pat.node) } - } -} - -pub fn replace_slice_u8(builder: &aster::AstBuilder, ty: &P) -> P { - if ::syntax::print::pprust::ty_to_string(&strip_ptr(ty)) == "[u8]" { - return builder.ty().id("Vec") - } - ty.clone() -} - -struct NamedSignature<'a> { - sig: &'a MethodSig, - ident: &'a Ident, -} - -fn push_invoke_signature_aster( - builder: &aster::AstBuilder, - named_signature: &NamedSignature, - push: &mut FnMut(Annotatable), -) -> Dispatch { - let inputs = &named_signature.sig.decl.inputs; - let (input_type_name, input_arg_names, input_arg_tys) = if inputs.len() > 0 { - let first_field_name = field_name(builder, &inputs[0]).name.as_str(); - if &*first_field_name == "self" && inputs.len() == 1 { (None, vec![], vec![]) } - else { - let skip = if &*first_field_name == "self" { 2 } else { 1 }; - let name_str = format!("{}_input", named_signature.ident.name.as_str()); - - let mut arg_names = Vec::new(); - let mut arg_tys = Vec::new(); - - let arg_name = format!("{}", field_name(builder, &inputs[skip-1]).name); - let arg_ty = &inputs[skip-1].ty; - - let mut tree = builder.item() - .attr().word("binary") - .attr().word("allow(non_camel_case_types)") - .struct_(name_str.as_str()) - .field(arg_name.as_str()) - .ty().build(replace_slice_u8(builder, &strip_ptr(arg_ty))); - - arg_names.push(arg_name); - arg_tys.push(arg_ty.clone()); - for arg in inputs.iter().skip(skip) { - let arg_name = format!("{}", field_name(builder, &arg)); - let arg_ty = &arg.ty; - - tree = tree.field(arg_name.as_str()).ty().build(replace_slice_u8(builder, &strip_ptr(arg_ty))); - arg_names.push(arg_name); - arg_tys.push(arg_ty.clone()); - } - - push(Annotatable::Item(tree.build())); - (Some(name_str.to_owned()), arg_names, arg_tys) - } - } - else { - (None, vec![], vec![]) - }; - - let return_type_ty = match named_signature.sig.decl.output { - FunctionRetTy::Ty(ref ty) => { - let name_str = format!("{}_output", named_signature.ident.name.as_str()); - let tree = builder.item() - .attr().word("binary") - .attr().word("allow(non_camel_case_types)") - .struct_(name_str.as_str()) - .field(format!("payload")).ty().build(ty.clone()); - push(Annotatable::Item(tree.build())); - Some(ty.clone()) - } - _ => None - }; - - Dispatch { - function_name: format!("{}", named_signature.ident.name.as_str()), - input_type_name: input_type_name, - input_arg_names: input_arg_names, - input_arg_tys: input_arg_tys, - return_type_ty: return_type_ty, - } -} - -struct Dispatch { - function_name: String, - input_type_name: Option, - input_arg_names: Vec, - input_arg_tys: Vec>, - return_type_ty: Option>, -} - -// This is the expanded version of this: -// -// let invoke_serialize_stmt = quote_stmt!(cx, { -// ::bincode::serde::serialize(& $output_type_id { payload: self. $function_name ($hand_param_a, $hand_param_b) }, ::bincode::SizeLimit::Infinite).unwrap() -// }); -// -// But the above does not allow comma-separated expressions for arbitrary number -// of parameters ...$hand_param_a, $hand_param_b, ... $hand_param_n -fn implement_dispatch_arm_invoke_stmt( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - dispatch: &Dispatch, -) -> ast::Stmt -{ - use ::syntax::tokenstream::TokenTree::Token; - let function_name = builder.id(dispatch.function_name.as_str()); - - let input_args_exprs = dispatch.input_arg_names.iter().enumerate().map(|(arg_index, arg_name)| { - let arg_ident = builder.id(arg_name); - let expr = quote_expr!(cx, input. $arg_ident); - if has_ptr(&dispatch.input_arg_tys[arg_index]) { quote_expr!(cx, & $expr) } - else { expr } - }).collect::>>(); - - let ext_cx = &*cx; - ::quasi::parse_stmt_panic(&mut ::syntax::parse::new_parser_from_tts( - ext_cx.parse_sess(), - { - let _sp = ext_cx.call_site(); - let mut tt = ::std::vec::Vec::new(); - - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); - - if dispatch.return_type_ty.is_some() { - tt.push(Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("ipc")))); - tt.push(Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("binary")))); - tt.push(Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("serialize")))); - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); - tt.push(Token(_sp, ::syntax::parse::token::BinOp(::syntax::parse::token::And))); - } - - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("self")))); - tt.push(Token(_sp, ::syntax::parse::token::Dot)); - tt.extend(::quasi::ToTokens::to_tokens(&function_name, ext_cx).into_iter()); - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); - - for arg_expr in input_args_exprs { - tt.extend(::quasi::ToTokens::to_tokens(&arg_expr, ext_cx).into_iter()); - tt.push(Token(_sp, ::syntax::parse::token::Comma)); - } - - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - - if dispatch.return_type_ty.is_some() { - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - tt.push(Token(_sp, ::syntax::parse::token::Dot)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("unwrap")))); - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - } - else { - tt.push(Token(_sp, ::syntax::parse::token::Semi)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("Vec")))); - tt.push(Token(_sp, ::syntax::parse::token::ModSep)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("new")))); - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - - } - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Brace))); - - tt - } - )).unwrap() -} - -fn implement_dispatch_arm_invoke( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - dispatch: &Dispatch, - buffer: bool, -) -> P -{ - let deserialize_expr = if buffer { - quote_expr!(cx, - ::ipc::binary::deserialize(buf) - .unwrap_or_else(|e| { panic!("ipc error while deserializing payload, aborting \n payload: {:?}, \n error: {:?}", buf, e); } ) - ) - } else { - quote_expr!(cx, - ::ipc::binary::deserialize_from(r) - .unwrap_or_else(|e| { panic!("ipc error while deserializing payload, aborting \n error: {:?}", e); } ) - ) - }; - - let invoke_serialize_stmt = implement_dispatch_arm_invoke_stmt(cx, builder, dispatch); - dispatch.input_type_name.as_ref().map(|val| { - let input_type_id = builder.id(val.clone().as_str()); - quote_expr!(cx, { - let input: $input_type_id = $deserialize_expr; - $invoke_serialize_stmt - }) - }).unwrap_or(quote_expr!(cx, { $invoke_serialize_stmt })) -} - -/// generates dispatch match for method id -fn implement_dispatch_arm( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - index: u32, - dispatch: &Dispatch, - buffer: bool, -) -> ast::Arm -{ - let index_ident = builder.id(format!("{}", index + (RESERVED_MESSAGE_IDS as u32)).as_str()); - let invoke_expr = implement_dispatch_arm_invoke(cx, builder, dispatch, buffer); - let trace = literal!(builder, "Dispatching: {}", &dispatch.function_name); - quote_arm!(cx, $index_ident => { - trace!(target: "ipc", $trace); - $invoke_expr - }) -} - -fn implement_dispatch_arms( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - dispatches: &[Dispatch], - buffer: bool, -) -> Vec -{ - let mut index = -1; - dispatches.iter() - .map(|dispatch| { index = index + 1; implement_dispatch_arm(cx, builder, index as u32, dispatch, buffer) }).collect() -} - -pub fn strip_ptr(ty: &P) -> P { - if let ast::TyKind::Rptr(_, ref ptr_mut) = ty.node { - ptr_mut.ty.clone() - } - else { ty.clone() } -} - -pub fn has_ptr(ty: &P) -> bool { - if let ast::TyKind::Rptr(_, ref _ptr_mut) = ty.node { - true - } - else { false } -} - -/// returns an expression with the body for single operation that is being sent to server -/// operation itself serializes input, writes to socket and waits for socket to respond -/// (the latter only if original method signature returns anyting) -/// -/// assuming expanded class contains method -/// fn commit(&self, f: u32) -> u32 -/// -/// the expanded implementation will generate method for the client like that -/// #[binary] -/// struct Request<'a> { -/// f: &'a u32, -/// } -/// let payload = Request{f: &f,}; -/// let mut socket_ref = self.socket.borrow_mut(); -/// let mut socket = socket_ref.deref_mut(); -/// let serialized_payload = ::bincode::serde::serialize(&payload, ::bincode::SizeLimit::Infinite).unwrap(); -/// ::ipc::invoke(0, &Some(serialized_payload), &mut socket); -/// while !socket.ready().load(::std::sync::atomic::Ordering::Relaxed) { } -/// ::bincode::serde::deserialize_from::<_, u32>(&mut socket, ::bincode::SizeLimit::Infinite).unwrap() -fn implement_client_method_body( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - index: u16, - interface_map: &InterfaceMap, -) -> P -{ - use ::syntax::tokenstream::TokenTree::Token; - - let dispatch = &interface_map.dispatches[index as usize]; - let index_ident = builder.id(format!("{}", index + RESERVED_MESSAGE_IDS).as_str()); - - let request = if dispatch.input_arg_names.len() > 0 { - - let arg_name = dispatch.input_arg_names[0].as_str(); - let static_ty = strip_ptr(&dispatch.input_arg_tys[0]); - let arg_ty = builder - .ty().ref_() - .lifetime("'a") - .ty() - .build(static_ty.clone()); - - let mut tree = builder.item() - .attr().word("binary") - .struct_("Request") - .generics() - .lifetime_name("'a") - .build() - .field(arg_name).ty() - .build(arg_ty); - - for arg_idx in 1..dispatch.input_arg_names.len() { - let arg_name = dispatch.input_arg_names[arg_idx].as_str(); - let static_ty = strip_ptr(&dispatch.input_arg_tys[arg_idx]); - - let arg_ty = builder - .ty().ref_() - .lifetime("'a") - .ty() - .build(static_ty); - tree = tree.field(arg_name).ty().build(arg_ty); - - } - let mut request_serialization_statements = Vec::new(); - - let struct_tree = tree.build(); - let struct_stmt = quote_stmt!(cx, $struct_tree); - request_serialization_statements.push(struct_stmt); - - // actually this is just expanded version of this: - // request_serialization_statements.push(quote_stmt!(cx, let payload = Request { p1: &p1, p2: &p2, ... pn: &pn, })); - // again, cannot dynamically create expression with arbitrary number of comma-separated members - request_serialization_statements.push({ - let ext_cx = &*cx; - ::quasi::parse_stmt_panic(&mut ::syntax::parse::new_parser_from_tts( - ext_cx.parse_sess(), - { - let _sp = ext_cx.call_site(); - let mut tt = ::std::vec::Vec::new(); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("let")))); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("payload")))); - tt.push(Token(_sp, ::syntax::parse::token::Eq)); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("Request")))); - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); - - for arg in dispatch.input_arg_names.iter() { - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(arg.as_str())))); - tt.push(Token(_sp, ::syntax::parse::token::Colon)); - tt.push(Token(_sp, ::syntax::parse::token::BinOp(::syntax::parse::token::And))); - - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(arg.as_str())))); - tt.push(Token(_sp, ::syntax::parse::token::Comma)); - } - - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Brace))); - tt - })) - }); - - request_serialization_statements.push( - quote_stmt!(cx, let mut socket = self.socket.write().unwrap(); )); - - request_serialization_statements.push( - quote_stmt!(cx, let serialized_payload = ::ipc::binary::serialize(&payload).unwrap())); - - request_serialization_statements.push( - quote_stmt!(cx, ::ipc::invoke($index_ident, &Some(serialized_payload), &mut *socket))); - - - request_serialization_statements - } - else { - let mut request_serialization_statements = Vec::new(); - request_serialization_statements.push( - quote_stmt!(cx, let mut socket = self.socket.write().unwrap(); )); - request_serialization_statements.push( - quote_stmt!(cx, ::ipc::invoke($index_ident, &None, &mut *socket))); - request_serialization_statements - }; - - let trace = literal!(builder, "Invoking: {}", &dispatch.function_name); - if let Some(ref return_ty) = dispatch.return_type_ty { - let return_expr = quote_expr!(cx, - ::ipc::binary::deserialize_from::<$return_ty, _>(&mut *socket).unwrap() - ); - quote_expr!(cx, { - trace!(target: "ipc", $trace); - $request; - $return_expr - }) - } - else { - quote_expr!(cx, { - trace!(target: "ipc", $trace); - $request - }) - } -} - -/// Generates signature and body (see `implement_client_method_body`) -/// for the client (signature is identical to the original method) -fn implement_client_method( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - index: u16, - interface_map: &InterfaceMap, -) - -> ast::ImplItem -{ - use ::syntax::tokenstream::TokenTree::Token; - - let dispatch = &interface_map.dispatches[index as usize]; - let method_name = builder.id(dispatch.function_name.as_str()); - let body = implement_client_method_body(cx, builder, index, interface_map); - - let ext_cx = &*cx; - // expanded version of this - // pub fn $method_name(&self, p1: p1_ty, p2: p2_ty ... pn: pn_ty, ) [-> return_ty] { $body } - // looks like it's tricky to build function declaration with aster if body already generated - let signature = ::syntax::parse::parser::Parser::parse_impl_item( - &mut ::syntax::parse::new_parser_from_tts( - ext_cx.parse_sess(), - { - let _sp = ext_cx.call_site(); - let mut tt = ::std::vec::Vec::new(); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("fn")))); - tt.extend(::quasi::ToTokens::to_tokens(&method_name, ext_cx).into_iter()); - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Paren))); - tt.push(Token(_sp, ::syntax::parse::token::BinOp(::syntax::parse::token::And))); - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of("self")))); - tt.push(Token(_sp, ::syntax::parse::token::Comma)); - - for arg_idx in 0..dispatch.input_arg_names.len() { - let arg_name = dispatch.input_arg_names[arg_idx].as_str(); - let arg_ty = dispatch.input_arg_tys[arg_idx].clone(); - - tt.push(Token(_sp, ::syntax::parse::token::Ident(ext_cx.ident_of(arg_name)))); - tt.push(Token(_sp, ::syntax::parse::token::Colon)); - tt.extend(::quasi::ToTokens::to_tokens(&arg_ty, ext_cx).into_iter()); - tt.push(Token(_sp, ::syntax::parse::token::Comma)); - } - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Paren))); - - if let Some(ref return_ty) = dispatch.return_type_ty { - tt.push(Token(_sp, ::syntax::parse::token::RArrow)); - tt.extend(::quasi::ToTokens::to_tokens(return_ty, ext_cx).into_iter()); - } - - tt.push(Token(_sp, ::syntax::parse::token::OpenDelim(::syntax::parse::token::Brace))); - tt.extend(::quasi::ToTokens::to_tokens(&body, ext_cx).into_iter()); - tt.push(Token(_sp, ::syntax::parse::token::CloseDelim(::syntax::parse::token::Brace))); - - tt - })); - - signature.unwrap() -} - -fn client_generics(builder: &aster::AstBuilder, interface_map: &InterfaceMap) -> Generics { - let ty_param = aster::ty_param::TyParamBuilder::new( - builder.id("S")).trait_bound( - builder.path().global().ids(&["ipc", "IpcSocket"]).build() - ).build().build(); - - builder.from_generics(interface_map.generics.clone()) - .with_ty_param(ty_param) - .build() -} - -fn client_qualified_ident(cx: &ExtCtxt, builder: &aster::AstBuilder, interface_map: &InterfaceMap) -> P { - let generics = client_generics(builder, interface_map); - aster::ty::TyBuilder::new().path().segment(interface_map.ident_map.client_ident(cx, builder)) - .with_generics(generics).build() - .build() -} - -fn client_phantom_ident(builder: &aster::AstBuilder, interface_map: &InterfaceMap) -> P { - let generics = client_generics(builder, interface_map); - aster::ty::TyBuilder::new().phantom_data() - .tuple().with_tys(generics.ty_params.iter().map(|x| aster::ty::TyBuilder::new().id(x.ident))) - .build() -} - -/// generates client type for specified server type -/// for say `Service` it generates `ServiceClient` -fn push_client_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, interface_map: &InterfaceMap, push: &mut FnMut(Annotatable)) { - let generics = client_generics(builder, interface_map); - let client_short_ident = interface_map.ident_map.client_ident(cx, builder); - let phantom = client_phantom_ident(builder, interface_map); - - let client_struct_item = quote_item!(cx, - pub struct $client_short_ident $generics { - socket: ::std::sync::RwLock, - phantom: $phantom, - }); - - push(Annotatable::Item(client_struct_item.expect(&format!("could not generate client struct for {:?}", client_short_ident.name)))); -} - -/// pushes generated code for the client class (type declaration and method invocation implementations) -fn push_client( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - interface_map: &InterfaceMap, - push: &mut FnMut(Annotatable), -) { - push_client_struct(cx, builder, interface_map, push); - push_client_implementation(cx, builder, interface_map, push); - push_with_socket_client_implementation(cx, builder, interface_map, push); -} - -fn push_with_socket_client_implementation( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - interface_map: &InterfaceMap, - push: &mut FnMut(Annotatable)) -{ - let generics = client_generics(builder, interface_map); - let client_ident = client_qualified_ident(cx, builder, interface_map); - let where_clause = &generics.where_clause; - let client_short_ident = interface_map.ident_map.client_ident(cx, builder); - - let implement = quote_item!(cx, - impl $generics ::ipc::WithSocket for $client_ident $where_clause { - fn init(socket: S) -> $client_ident { - $client_short_ident { - socket: ::std::sync::RwLock::new(socket), - phantom: ::std::marker::PhantomData, - } - } - }).unwrap(); - push(Annotatable::Item(implement)); -} - -/// pushes full client side code for the original class exposed via ipc -fn push_client_implementation( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - interface_map: &InterfaceMap, - push: &mut FnMut(Annotatable), -) { - let mut index = -1i32; - let items = interface_map.dispatches.iter() - .map(|_| { index = index + 1; P(implement_client_method(cx, builder, index as u16, interface_map)) }) - .collect::>>(); - - let generics = client_generics(builder, interface_map); - let client_ident = client_qualified_ident(cx, builder, interface_map); - let where_clause = &generics.where_clause; - let endpoint = interface_map.endpoint; - - let handshake_item = quote_impl_item!(cx, - pub fn handshake(&self) -> Result<(), ::ipc::Error> { - let payload = ::ipc::Handshake { - protocol_version: $endpoint::protocol_version(), - api_version: $endpoint::api_version(), - }; - - ::ipc::invoke( - 0, - &Some(::ipc::binary::serialize(&::ipc::BinHandshake::from(payload)).unwrap()), - &mut *self.socket.write().unwrap()); - - let mut result = vec![0u8; 1]; - if try!(self.socket.write().unwrap().read(&mut result).map_err(|_| ::ipc::Error::HandshakeFailed)) == 1 { - match result[0] { - 1 => Ok(()), - _ => Err(::ipc::Error::RemoteServiceUnsupported), - } - } - else { Err(::ipc::Error::HandshakeFailed) } - }).unwrap(); - - let socket_item = quote_impl_item!(cx, - #[cfg(test)] - pub fn socket(&self) -> &::std::sync::RwLock { - &self.socket - }).unwrap(); - - let generic_items = vec![P(handshake_item), P(socket_item)]; - - if interface_map.impl_trait.is_some() { - let trait_ty = builder.id( - ::syntax::print::pprust::path_to_string( - &interface_map.impl_trait.as_ref().unwrap().path)); - - let implement_trait = - quote_item!(cx, - impl $generics $trait_ty for $client_ident $where_clause { - $items - } - ).unwrap(); - push(Annotatable::Item(implement_trait)); - - let implement = - quote_item!(cx, - impl $generics $client_ident $where_clause { - $generic_items - } - ).unwrap(); - push(Annotatable::Item(implement)); - } - else { - let pub_items = items.iter().map(|item| { - let pub_item = item.clone(); - pub_item.map(|mut val| { val.vis = ast::Visibility::Public; val }) - }).collect::>>(); - - let implement = quote_item!(cx, - impl $generics $client_ident $where_clause { - $pub_items - $generic_items - }).unwrap(); - push(Annotatable::Item(implement)); - } - -} - -/// implements dispatching of system handshake invocation (method_num 0) -fn implement_handshake_arm( - cx: &ExtCtxt, -) -> (ast::Arm, ast::Arm) -{ - let handshake_deserialize = quote_stmt!(&cx, - let handshake_payload = ::ipc::binary::deserialize_from::<::ipc::BinHandshake, _>(r).unwrap(); - ); - - let handshake_deserialize_buf = quote_stmt!(&cx, - let handshake_payload = ::ipc::binary::deserialize::<::ipc::BinHandshake>(buf).unwrap(); - ); - - let handshake_serialize = quote_expr!(&cx, - ::ipc::binary::serialize::(&Self::handshake(&handshake_payload.to_semver())).unwrap() - ); - - ( - quote_arm!(&cx, 0 => { - $handshake_deserialize - $handshake_serialize - }), - quote_arm!(&cx, 0 => { - $handshake_deserialize_buf - $handshake_serialize - }), - ) -} - -fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result { - match lit.node { - ast::LitKind::Str(ref s, _) => Ok(format!("{}", s)), - _ => { - cx.span_err( - lit.span, - &format!("ipc client_ident annotation `{}` must be a string, not `{}`", - name, - ::syntax::print::pprust::lit_to_string(lit))); - - return Err(()); - } - } -} - -fn client_ident_renamed(cx: &ExtCtxt, meta_item: &MetaItem) -> Option { - if let ast::MetaItemKind::List(ref list) = meta_item.node { - for nested in list { - match nested.node { - ast::NestedMetaItemKind::MetaItem(ref meta_item) => { - let is_client_ident = &*meta_item.name.as_str() == "client_ident"; - match meta_item.node { - ast::MetaItemKind::NameValue(ref lit) if is_client_ident => { - if let Ok(s) = get_str_from_lit(cx, "client_ident", lit) { - return Some(s); - } - } - _ => { - cx.span_err( - meta_item.span, - &format!("unknown client_ident container attribute `{}`", - ::syntax::print::pprust::meta_item_to_string(&meta_item))); - } - } - }, - _ => {}, - } - } - } - - None -} - -struct InterfaceMap { - pub original_item: Item, - pub item: P, - pub dispatches: Vec, - pub generics: Generics, - pub impl_trait: Option, - pub ident_map: IdentMap, - pub endpoint: Ident, -} - -struct IdentMap { - original_path: ast::Path, - meta_item: MetaItem, -} - -impl IdentMap { - fn ident(&self, builder: &aster::AstBuilder) -> Ident { - builder.id(format!("{}", ::syntax::print::pprust::path_to_string(&self.original_path))) - } - - fn client_ident(&self, cx: &ExtCtxt, builder: &aster::AstBuilder) -> Ident { - if let Some(new_name) = client_ident_renamed(cx, &self.meta_item) { - builder.id(new_name) - } - else { - builder.id(format!("{}Client", self.original_path.segments[0].identifier)) - } - } -} - -fn ty_ident_map(original_ty: &P, meta_item: &MetaItem) -> IdentMap { - let original_path = match original_ty.node { - ::syntax::ast::TyKind::Path(_, ref path) => path.clone(), - _ => { panic!("incompatible implementation"); } - }; - let ident_map = IdentMap { original_path: original_path, meta_item: meta_item.clone() }; - ident_map -} - -/// implements `IpcInterface` for the given class `C` -fn implement_interface( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, - push: &mut FnMut(Annotatable), - meta_item: &MetaItem, -) -> Result { - let (generics, impl_trait, original_ty, dispatch_table) = match item.node { - ast::ItemKind::Impl(_, _, ref generics, ref impl_trait, ref ty, ref impl_items) => { - let mut method_signatures = Vec::new(); - for impl_item in impl_items { - if let ImplItemKind::Method(ref signature, _) = impl_item.node { - method_signatures.push(NamedSignature { ident: &impl_item.ident, sig: signature }); - } - } - - let dispatch_table = method_signatures.iter().map(|named_signature| - push_invoke_signature_aster(builder, named_signature, push)) - .collect::>(); - - (generics, impl_trait.clone(), ty.clone(), dispatch_table) - }, - ast::ItemKind::Trait(_, ref generics, _, ref trait_items) => { - let mut method_signatures = Vec::new(); - for trait_item in trait_items { - if let TraitItemKind::Method(ref signature, _) = trait_item.node { - method_signatures.push(NamedSignature { ident: &trait_item.ident, sig: signature }); - } - } - - let dispatch_table = method_signatures.iter().map(|named_signature| - push_invoke_signature_aster(builder, named_signature, push)) - .collect::>(); - - ( - generics, - Some(ast::TraitRef { - path: builder.path().ids(&[item.ident.name]).build(), - ref_id: item.id, - }), - builder.ty().id(item.ident), - dispatch_table - ) - }, - _ => { - cx.span_err( - item.span, - "`#[ipc]` may only be applied to implementations and traits"); - return Err(Error); - }, - }; - let impl_generics = builder.from_generics(generics.clone()).build(); - let where_clause = &impl_generics.where_clause; - - let dispatch_arms = implement_dispatch_arms(cx, builder, &dispatch_table, false); - let dispatch_arms_buffered = implement_dispatch_arms(cx, builder, &dispatch_table, true); - - let (handshake_arm, handshake_arm_buf) = implement_handshake_arm(cx); - - let ty = ty_ident_map(&original_ty, meta_item).ident(builder); - let (interface_endpoint, host_generics) = match impl_trait { - Some(ref trait_) => (builder.id(::syntax::print::pprust::path_to_string(&trait_.path)), None), - None => (ty, Some(&impl_generics)), - }; - - let ipc_item = quote_item!(cx, - impl $host_generics ::ipc::IpcInterface for $interface_endpoint $where_clause { - fn dispatch(&self, r: &mut R) -> Vec - where R: ::std::io::Read - { - let mut method_num = vec![0u8;2]; - match r.read(&mut method_num) { - Ok(size) if size == 0 => { panic!("method id not supplied" ); } - Err(e) => { panic!("ipc read error: {:?}, aborting", e); } - _ => { } - } - - // method_num is a 16-bit little-endian unsigned number - match method_num[1] as u16 + (method_num[0] as u16)*256 { - // handshake - $handshake_arm - // user methods - $dispatch_arms - _ => vec![] - } - } - - fn dispatch_buf(&self, method_num: u16, buf: &[u8]) -> Vec - { - match method_num { - $handshake_arm_buf - $dispatch_arms_buffered - _ => vec![] - } - } - } - ).unwrap(); - - Ok(InterfaceMap { - ident_map: ty_ident_map(&original_ty, meta_item), - original_item: item.clone(), - item: ipc_item, - dispatches: dispatch_table, - generics: generics.clone(), - impl_trait: impl_trait.clone(), - endpoint: interface_endpoint, - }) -} diff --git a/ipc/codegen/src/lib.rs b/ipc/codegen/src/lib.rs deleted file mode 100644 index 6e7fc441b324f217ce883b4d184e463f25061c74..0000000000000000000000000000000000000000 --- a/ipc/codegen/src/lib.rs +++ /dev/null @@ -1,237 +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 . - -//! Codegen for IPC RPC - -#![cfg_attr(feature = "nightly-testing", plugin(clippy))] -#![cfg_attr(feature = "nightly-testing", feature(plugin))] -#![cfg_attr(feature = "nightly-testing", allow(used_underscore_binding))] -#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private, plugin))] -#![cfg_attr(not(feature = "with-syntex"), plugin(quasi_macros))] - -extern crate aster; -extern crate quasi; - -#[cfg(feature = "with-syntex")] -extern crate syntex; - -#[cfg(feature = "with-syntex")] -extern crate syntex_syntax as syntax; - -#[cfg(not(feature = "with-syntex"))] -#[macro_use] -extern crate syntax; - -#[cfg(not(feature = "with-syntex"))] -extern crate rustc_plugin; - -#[cfg(not(feature = "with-syntex"))] -use syntax::feature_gate::AttributeType; - -#[cfg(feature = "with-syntex")] -use syntax::{ast, fold}; - - -#[cfg(feature = "with-syntex")] -include!(concat!(env!("OUT_DIR"), "/lib.rs")); - -#[cfg(not(feature = "with-syntex"))] -include!("lib.rs.in"); - -#[cfg(feature = "with-syntex")] -pub fn expand(src: &std::path::Path, dst: &std::path::Path) { - let mut registry = syntex::Registry::new(); - register(&mut registry); - registry.expand("", src, dst).unwrap(); -} - -#[cfg(feature = "with-syntex")] -struct StripAttributeFolder<'a> { - attr_title: &'a str, -} - -#[cfg(feature = "with-syntex")] -impl<'a> fold::Folder for StripAttributeFolder<'a> { - fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { - let is_self = &*attr.value.name.as_str() == self.attr_title; - - match attr.value.node { - ast::MetaItemKind::List(_) if is_self => { return None; } - ast::MetaItemKind::Word if is_self => { return None; } - _ => {} - } - - Some(attr) - } - - fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { - fold::noop_fold_mac(mac, self) - } -} - -#[cfg(feature = "with-syntex")] -pub fn register_cleaner_ipc(reg: &mut syntex::Registry) { - #[cfg(feature = "with-syntex")] - fn strip_attributes(krate: ast::Crate) -> ast::Crate { - let mut folder = StripAttributeFolder { attr_title: "ipc" }; - fold::Folder::fold_crate(&mut folder, krate) - } - - reg.add_post_expansion_pass(strip_attributes); -} - -#[cfg(feature = "with-syntex")] -pub fn register_cleaner_binary(reg: &mut syntex::Registry) { - #[cfg(feature = "with-syntex")] - fn strip_attributes(krate: ast::Crate) -> ast::Crate { - let mut folder = StripAttributeFolder { attr_title: "binary" }; - fold::Folder::fold_crate(&mut folder, krate) - } - - reg.add_post_expansion_pass(strip_attributes); -} - -#[cfg(feature = "with-syntex")] -pub fn register(reg: &mut syntex::Registry) { - reg.add_attr("feature(custom_derive)"); - reg.add_attr("feature(custom_attribute)"); - - reg.add_decorator("ipc", codegen::expand_ipc_implementation); - reg.add_decorator("binary", serialization::expand_serialization_implementation); - - register_cleaner_ipc(reg); - register_cleaner_binary(reg); -} - -#[cfg(not(feature = "with-syntex"))] -pub fn register(reg: &mut rustc_plugin::Registry) { - reg.register_syntax_extension( - syntax::parse::token::intern("ipc"), - syntax::ext::base::MultiDecorator( - Box::new(codegen::expand_ipc_implementation))); - reg.register_syntax_extension( - syntax::parse::token::intern("binary"), - syntax::ext::base::MultiDecorator( - Box::new(serialization::expand_serialization_implementation))); - - reg.register_attribute("ipc".to_owned(), AttributeType::Normal); - reg.register_attribute("binary".to_owned(), AttributeType::Normal); -} - -#[derive(Debug)] -pub enum Error { InvalidFileName, ExpandFailure, Io(std::io::Error) } - -impl std::convert::From for Error { - fn from(err: std::io::Error) -> Self { - Error::Io(err) - } -} - -pub fn derive_ipc_cond(src_path: &str, has_feature: bool) -> Result<(), Error> { - if has_feature { derive_ipc(src_path) } - else { cleanup_ipc(src_path) } -} - -pub fn cleanup_ipc(src_path: &str) -> Result<(), Error> { - cleanup(src_path, AttributeKind::Ipc) -} - -pub fn cleanup_binary(src_path: &str) -> Result<(), Error> { - cleanup(src_path, AttributeKind::Binary) -} - -enum AttributeKind { - Ipc, - Binary, -} - -fn cleanup(src_path: &str, attr: AttributeKind) -> Result<(), Error> { - use std::env; - use std::path::{Path, PathBuf}; - - let out_dir = env::var_os("OUT_DIR").unwrap(); - let file_name = PathBuf::from(src_path).file_name().ok_or(Error::InvalidFileName).map(|val| val.to_str().unwrap().to_owned())?; - let mut registry = syntex::Registry::new(); - - match attr { - AttributeKind::Ipc => { register_cleaner_ipc(&mut registry); } - AttributeKind::Binary => { register_cleaner_binary(&mut registry); } - } - - if let Err(_) = registry.expand("", &Path::new(src_path), &Path::new(&out_dir).join(&file_name)) - { - // will be reported by compiler - return Err(Error::ExpandFailure) - } - Ok(()) -} - -pub fn derive_ipc(src_path: &str) -> Result<(), Error> { - use std::env; - use std::path::{Path, PathBuf}; - - let out_dir = env::var_os("OUT_DIR").unwrap(); - let file_name = PathBuf::from(src_path).file_name().ok_or(Error::InvalidFileName).map(|val| val.to_str().unwrap().to_owned())?; - - let final_path = Path::new(&out_dir).join(&file_name); - - let mut intermediate_file_name = file_name.clone(); - intermediate_file_name.push_str(".rpc.in"); - let intermediate_path = Path::new(&out_dir).join(&intermediate_file_name); - - { - let mut registry = syntex::Registry::new(); - register(&mut registry); - if let Err(_) = registry.expand("", &Path::new(src_path), &intermediate_path) { - // will be reported by compiler - return Err(Error::ExpandFailure) - } - } - - { - let mut registry = syntex::Registry::new(); - register(&mut registry); - if let Err(_) = registry.expand("", &intermediate_path, &final_path) { - // will be reported by compiler - return Err(Error::ExpandFailure) - } - } - - Ok(()) -} - -pub fn derive_binary(src_path: &str) -> Result<(), Error> { - use std::env; - use std::path::{Path, PathBuf}; - - let out_dir = env::var_os("OUT_DIR").unwrap(); - let file_name = PathBuf::from(src_path).file_name().ok_or(Error::InvalidFileName).map(|val| val.to_str().unwrap().to_owned())?; - let final_path = Path::new(&out_dir).join(&file_name); - - let mut registry = syntex::Registry::new(); - register(&mut registry); - if let Err(_) = registry.expand("", &Path::new(src_path), &final_path) { - // will be reported by compiler - return Err(Error::ExpandFailure) - } - - Ok(()) -} - -pub fn derive_binary_cond(src_path: &str, has_feature: bool) -> Result<(), Error> { - if has_feature { derive_binary(src_path) } - else { cleanup_binary(src_path) } -} diff --git a/ipc/codegen/src/lib.rs.in b/ipc/codegen/src/lib.rs.in deleted file mode 100644 index c8aa8ebf27416c489965c6490cc98a7081ab5070..0000000000000000000000000000000000000000 --- a/ipc/codegen/src/lib.rs.in +++ /dev/null @@ -1,18 +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 . - -mod codegen; -mod serialization; diff --git a/ipc/codegen/src/serialization.rs b/ipc/codegen/src/serialization.rs deleted file mode 100644 index fd908725c9b54e98b46d94d81ff5616f55a19df2..0000000000000000000000000000000000000000 --- a/ipc/codegen/src/serialization.rs +++ /dev/null @@ -1,810 +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 . -use aster; - -use syntax::ast::{ - MetaItem, - Item, - Ident, -}; - -use syntax::ast; -use syntax::codemap::Span; -use syntax::ext::base::{Annotatable, ExtCtxt}; -use syntax::ptr::P; - -pub struct Error; - -use super::codegen; - -pub fn expand_serialization_implementation( - cx: &mut ExtCtxt, - span: Span, - meta_item: &MetaItem, - annotatable: &Annotatable, - push: &mut FnMut(Annotatable) -) { - let item = match *annotatable { - Annotatable::Item(ref item) => item, - _ => { - cx.span_err(meta_item.span, "`#[derive(Binary)]` may only be applied to structs and enums"); - return; - }, - }; - - let builder = aster::AstBuilder::new().span(span); - - let impl_item = match serialize_item(cx, &builder, &item) { - Ok(item) => item, - Err(Error) => { - // An error occurred, but it should have been reported already. - return; - }, - }; - - push(Annotatable::Item(impl_item)) -} - -fn serialize_item( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, -) -> Result, Error> { - let generics = match item.node { - ast::ItemKind::Struct(_, ref generics) => generics, - ast::ItemKind::Enum(_, ref generics) => generics, - _ => { - cx.span_err( - item.span, - "`#[derive(Binary)]` may only be applied to structs and enums"); - return Err(Error); - }, - }; - - let ty = builder.ty().path() - .segment(item.ident).with_generics(generics.clone()).build() - .build(); - - let where_clause = &generics.where_clause; - - let binary_expressions = try!(binary_expr(cx, - &builder, - &item, - &generics, - ty.clone())); - - let (size_expr, read_expr, write_expr) = - (binary_expressions.size, binary_expressions.read, binary_expressions.write); - - match quote_item!(cx, - impl $generics ::ipc::BinaryConvertable for $ty $where_clause { - fn size(&self) -> usize { - $size_expr - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut ::std::collections::VecDeque) -> Result<(), ::ipc::BinaryConvertError> { - $write_expr - } - - fn from_bytes(buffer: &[u8], length_stack: &mut ::std::collections::VecDeque) -> Result { - $read_expr - } - - fn len_params() -> usize { - 1 - } - }) - { - Some(item) => Ok(item), - None => { - cx.span_err( - item.span, - "syntax error expanding serialization implementation"); - Err(Error) - } - } -} - -#[allow(unreachable_code)] -fn binary_expr( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - item: &Item, - impl_generics: &ast::Generics, - ty: P, -) -> Result { - match item.node { - ast::ItemKind::Struct(ref variant_data, _) => { - binary_expr_item_struct( - cx, - builder, - impl_generics, - ty, - item.span, - variant_data, - ) - }, - ast::ItemKind::Enum(ref enum_def, _) => { - binary_expr_enum( - cx, - builder, - item.ident, - impl_generics, - ty, - item.span, - enum_def, - ) - }, - _ => { - cx.span_bug(item.span, - "expected ItemStruct or ItemEnum in #[derive(Binary)]"); - Err(Error) as Result - }, - } -} - -struct BinaryExpressions { - pub size: P, - pub write: P, - pub read: P, -} - -fn replace_qualified(s: &str) -> String { - if let Some(pos) = s.find("<") { - let mut source = s.to_owned(); - source.insert(pos, ':'); - source.insert(pos, ':'); - source - } - else { s.to_owned() } -} - -fn binary_expr_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - ty: P, - fields: &[ast::StructField], - value_ident: Option, - instance_ident: Option, -) -> Result { - - let size_exprs: Vec> = fields.iter().enumerate().map(|(index, field)| { - let raw_ident = ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)); - let index_ident = builder.id(format!("__field{}", index)); - let field_id = match field.ident { - Some(ident) => builder.id(ident), - None => builder.id(format!("{}", index)), - }; - - match raw_ident.as_ref() { - "u8" => { - quote_expr!(cx, 1) - }, - "[u8]" => { - value_ident.and_then(|x| { - Some(quote_expr!(cx, $x. $field_id .len())) - }) - .unwrap_or_else(|| { - quote_expr!(cx, $index_ident .len()) - } - ) - } - _ => { - let field_type_ident = builder.id( - &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); - - let field_type_ident_qualified = builder.id( - replace_qualified(&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)))); - - value_ident.and_then(|x| - { - Some(quote_expr!(cx, - match $field_type_ident_qualified::len_params() { - 0 => ::std::mem::size_of::<$field_type_ident>(), - _ => $x. $field_id .size(), - })) - }) - .unwrap_or_else(|| { - quote_expr!(cx, match $field_type_ident_qualified::len_params() { - 0 => ::std::mem::size_of::<$field_type_ident>(), - _ => $index_ident .size(), - }) - }) - } - } - }).collect(); - - let first_size_expr = size_exprs[0].clone(); - let mut total_size_expr = quote_expr!(cx, 0usize + $first_size_expr); - for index in 1..size_exprs.len() { - let next_expr = size_exprs[index].clone(); - total_size_expr = quote_expr!(cx, $total_size_expr + $next_expr); - } - - let mut write_stmts = Vec::::new(); - write_stmts.push(quote_stmt!(cx, let mut offset = 0usize;).expect("stmt1")); - - let mut map_stmts = Vec::::new(); - let field_amount = builder.id(&format!("{}",fields.len())); - map_stmts.push(quote_stmt!(cx, let mut map = vec![0usize; $field_amount];).expect("stmt2")); - map_stmts.push(quote_stmt!(cx, let mut total = 0usize;).expect("stmt3")); - - let mut post_write_stmts = Vec::::new(); - - for (index, field) in fields.iter().enumerate() { - let field_type_ident = builder.id( - &::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty))); - - let field_type_ident_qualified = builder.id( - replace_qualified(&::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)))); - - let field_id = match field.ident { - Some(ident) => builder.id(ident), - None => builder.id(format!("{}", index)), - }; - let member_expr = match value_ident { - Some(x) => { - quote_expr!(cx, $x . $field_id) - }, - None => { - let index_ident = builder.id(format!("__field{}", index)); - quote_expr!(cx, $index_ident) - }, - }; - - let raw_ident = ::syntax::print::pprust::ty_to_string(&codegen::strip_ptr(&field.ty)); - let range_ident = builder.id(format!("r{}", index)); - - let error_message = "Error serializing member: ".to_owned() + &::syntax::print::pprust::expr_to_string(&member_expr); - let _error_message_literal = builder.expr().lit().str::<&str>(&error_message); - - match raw_ident.as_ref() { - "u8" => { - write_stmts.push(quote_stmt!(cx, let next_line = offset + 1;).expect("stmt4")); - write_stmts.push(quote_stmt!(cx, buffer[offset] = $member_expr; ).expect("stm5")); - }, - "[u8]" => { - write_stmts.push(quote_stmt!(cx, let size = $member_expr .len();).unwrap()); - write_stmts.push(quote_stmt!(cx, let next_line = offset + size;).unwrap()); - write_stmts.push(quote_stmt!(cx, length_stack.push_back(size);).unwrap()); - write_stmts.push(quote_stmt!(cx, let $range_ident = offset..next_line; ).unwrap()); - post_write_stmts.push(quote_stmt!(cx, buffer[$range_ident].clone_from_slice($member_expr); ).unwrap()); - } - _ => { - write_stmts.push(quote_stmt!(cx, let next_line = offset + match $field_type_ident_qualified::len_params() { - 0 => ::std::mem::size_of::<$field_type_ident>(), - _ => { let size = $member_expr .size(); length_stack.push_back(size); size }, - }).unwrap()); - write_stmts.push(quote_stmt!(cx, let $range_ident = offset..next_line; ).unwrap()); - post_write_stmts.push(quote_stmt!(cx, - if $range_ident.end - $range_ident.start > 0 { - if let Err(e) = $member_expr .to_bytes(&mut buffer[$range_ident], length_stack) { - return Err(e) - }; - } - ).unwrap()); - } - } - - write_stmts.push(quote_stmt!(cx, offset = next_line; ).unwrap()); - - let field_index = builder.id(&format!("{}", index)); - map_stmts.push(quote_stmt!(cx, map[$field_index] = total;).unwrap()); - - match raw_ident.as_ref() { - "u8" => { - map_stmts.push(quote_stmt!(cx, total += 1;).unwrap()); - }, - "[u8]" => { - map_stmts.push(quote_stmt!(cx, let size = length_stack.pop_front().unwrap();).unwrap()); - map_stmts.push(quote_stmt!(cx, total += size;).unwrap()); - }, - _ => { - map_stmts.push(quote_stmt!(cx, let size = match $field_type_ident_qualified::len_params() { - 0 => ::std::mem::size_of::<$field_type_ident>(), - _ => length_stack.pop_front().unwrap(), - }).unwrap()); - map_stmts.push(quote_stmt!(cx, total += size;).unwrap()); - } - } - }; - - let read_expr = match fields.iter().any(|f| codegen::has_ptr(&f.ty)) { - true => { - // cannot create structs with pointers - quote_expr!(cx, Err(::ipc::binary::BinaryConvertError::not_supported())) - }, - false => { - if value_ident.is_some() { - let instance_create = named_fields_sequence(cx, &ty, fields); - quote_expr!(cx, { $map_stmts; $instance_create; Ok(result) }) - } - else { - let map_variant = P(fields_sequence(cx, &ty, fields, &instance_ident.unwrap_or(builder.id("Self")))); - quote_expr!(cx, { $map_stmts; Ok($map_variant) }) - } - }, - }; - - Ok(BinaryExpressions { - size: total_size_expr, - write: quote_expr!(cx, { $write_stmts; $post_write_stmts; Ok(()) } ), - read: read_expr, - }) -} - -#[allow(unreachable_code)] -fn binary_expr_item_struct( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - _impl_generics: &ast::Generics, - ty: P, - span: Span, - variant_data: &ast::VariantData, -) -> Result { - match *variant_data { - ast::VariantData::Tuple(ref fields, _) => { - binary_expr_struct( - cx, - &builder, - ty, - fields, - Some(builder.id("self")), - None, - ) - }, - ast::VariantData::Struct(ref fields, _) => { - binary_expr_struct( - cx, - &builder, - ty, - fields, - Some(builder.id("self")), - None, - ) - }, - _ => { - cx.span_bug(span, - &format!("#[derive(Binary)] Unsupported struct content, expected tuple/struct, found: {:?}", - variant_data)); - Err(Error) as Result - }, - } -} - -fn binary_expr_enum( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - impl_generics: &ast::Generics, - ty: P, - span: Span, - enum_def: &ast::EnumDef, -) -> Result { - let arms: Vec<_> = try!(enum_def.variants.iter() - .enumerate() - .map(|(variant_index, variant)| { - binary_expr_variant( - cx, - builder, - type_ident, - impl_generics, - ty.clone(), - span, - variant, - variant_index, - ) - }) - .collect()); - - let (size_arms, write_arms, mut read_arms) = ( - arms.iter().map(|x| x.size.clone()).collect::>(), - arms.iter().map(|x| x.write.clone()).collect::>(), - arms.iter().map(|x| x.read.clone()).collect::>()); - - read_arms.push(quote_arm!(cx, _ => { Err(::ipc::BinaryConvertError::variant(buffer[0])) } )); - - Ok(BinaryExpressions { - size: quote_expr!(cx, 1usize + match *self { $size_arms }), - write: quote_expr!(cx, match *self { $write_arms }; ), - read: quote_expr!(cx, match buffer[0] { $read_arms }), - }) -} - -struct BinaryArm { - size: ast::Arm, - write: ast::Arm, - read: ast::Arm, -} - -fn fields_sequence( - ext_cx: &ExtCtxt, - _ty: &P, - fields: &[ast::StructField], - variant_ident: &ast::Ident, -) -> ast::Expr { - use syntax::parse::token; - use syntax::tokenstream::TokenTree::Token; - - let named_members = fields.iter().any(|f| f.ident.is_some()); - - ::quasi::parse_expr_panic(&mut ::syntax::parse::new_parser_from_tts( - ext_cx.parse_sess(), - { - let _sp = ext_cx.call_site(); - let mut tt = ::std::vec::Vec::new(); - tt.push(Token(_sp, token::Ident(variant_ident.clone()))); - if named_members { - tt.push(Token(_sp, token::OpenDelim(token::Brace))); - } - else { - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - } - - for (idx, field) in fields.iter().enumerate() { - if field.ident.is_some() { - tt.push(Token(_sp, token::Ident(field.ident.clone().unwrap()))); - tt.push(Token(_sp, token::Colon)); - } - - // special case for u8, it just takes byte form sequence - if ::syntax::print::pprust::ty_to_string(&field.ty) == "u8" { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); - - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - - tt.push(Token(_sp, token::Comma)); - continue; - } - - // special case for [u8], it just takes a byte sequence - if ::syntax::print::pprust::ty_to_string(&field.ty) == "[u8]" { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); - - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - tt.push(Token(_sp, token::DotDot)); - - if idx+1 != fields.len() { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - } - - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - - tt.push(Token(_sp, token::Comma)); - continue; - } - - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - tt.push( - Token( - _sp, - token::Ident(ext_cx.ident_of(&replace_qualified(&::syntax::print::pprust::ty_to_string(&field.ty)))) - )); - tt.push(Token(_sp, token::ModSep)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - - tt.push(Token(_sp, token::BinOp(token::And))); - - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); - - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - tt.push(Token(_sp, token::DotDot)); - - if idx+1 != fields.len() { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - } - - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - - tt.push(Token(_sp, token::Comma)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("length_stack")))); - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - - // name member if it has resulted in the error - tt.push(Token(_sp, token::Dot)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map_err")))); - - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - tt.push(Token(_sp, token::BinOp(token::Or))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("e")))); - tt.push(Token(_sp, token::BinOp(token::Or))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("e")))); - tt.push(Token(_sp, token::Dot)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("named")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - tt.push(Token(_sp, token::Literal(token::Lit::Str_( - field.ident.unwrap_or(ext_cx.ident_of(&format!("f{}", idx))).name), - None)) - ); - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - - tt.push(Token(_sp, token::Comma)); - } - if named_members { - tt.push(Token(_sp, token::CloseDelim(token::Brace))); - } - else { - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - } - tt - }) - ).unwrap() -} - -fn named_fields_sequence( - ext_cx: &ExtCtxt, - ty: &P, - fields: &[ast::StructField], -) -> ast::Stmt { - use syntax::parse::token; - use syntax::tokenstream::TokenTree::Token; - - ::quasi::parse_stmt_panic(&mut ::syntax::parse::new_parser_from_tts( - ext_cx.parse_sess(), - { - let _sp = ext_cx.call_site(); - let mut tt = ::std::vec::Vec::new(); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("let")))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("result")))); - tt.push(Token(_sp, token::Eq)); - - tt.push(Token( - _sp, - token::Ident( - ext_cx.ident_of(&::syntax::print::pprust::ty_to_string(ty)) - ))); - - tt.push(Token(_sp, token::OpenDelim(token::Brace))); - - for (idx, field) in fields.iter().enumerate() { - tt.push(Token(_sp, match field.ident { - Some(ident) => token::Ident(ident), - None => token::Ident(ext_cx.ident_of(&format!("{}", idx))), - })); - tt.push(Token(_sp, token::Colon)); - - // special case for u8, it just takes byte form sequence - if ::syntax::print::pprust::ty_to_string(&field.ty) == "u8" { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); - - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - - tt.push(Token(_sp, token::Comma)); - continue; - } - - // special case for [u8], it just takes a byte sequence - if ::syntax::print::pprust::ty_to_string(&field.ty) == "[u8]" { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); - - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - tt.push(Token(_sp, token::DotDot)); - - if idx+1 != fields.len() { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - } - - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - - tt.push(Token(_sp, token::Comma)); - continue; - } - - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("try!")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - tt.push(Token( - _sp, - token::Ident( - ext_cx.ident_of(&replace_qualified(&::syntax::print::pprust::ty_to_string(&field.ty))) - ))); - tt.push(Token(_sp, token::ModSep)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("from_bytes")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - - tt.push(Token(_sp, token::BinOp(token::And))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("buffer")))); - - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - tt.push(Token(_sp, token::DotDot)); - if idx + 1 != fields.len() { - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map")))); - tt.push(Token(_sp, token::OpenDelim(token::Bracket))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of(&format!("{}", idx+1))))); - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - } - - tt.push(Token(_sp, token::CloseDelim(token::Bracket))); - - tt.push(Token(_sp, token::Comma)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("length_stack")))); - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - - // name member if it has resulted in the error - tt.push(Token(_sp, token::Dot)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("map_err")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - tt.push(Token(_sp, token::BinOp(token::Or))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("e")))); - tt.push(Token(_sp, token::BinOp(token::Or))); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("e")))); - tt.push(Token(_sp, token::Dot)); - tt.push(Token(_sp, token::Ident(ext_cx.ident_of("named")))); - tt.push(Token(_sp, token::OpenDelim(token::Paren))); - tt.push(Token(_sp, token::Literal(token::Lit::Str_( - field.ident.unwrap_or(ext_cx.ident_of(&format!("f{}", idx))).name), - None)) - ); - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - - tt.push(Token(_sp, token::CloseDelim(token::Paren))); - tt.push(Token(_sp, token::Comma)); - } - - tt.push(Token(_sp, token::CloseDelim(token::Brace))); - tt - }) - ).unwrap() -} - -fn binary_expr_variant( - cx: &ExtCtxt, - builder: &aster::AstBuilder, - type_ident: Ident, - _generics: &ast::Generics, - ty: P, - _span: Span, - variant: &ast::Variant, - variant_index: usize, -) -> Result { - let variant_ident = variant.node.name; - let variant_index_ident = builder.id(format!("{}", variant_index)); - - match variant.node.data { - ast::VariantData::Unit(_) => { - let pat = builder.pat().path() - .id(type_ident).id(variant_ident) - .build(); - - let variant_val = builder.id(format!("{}::{}", type_ident, variant_ident)); - - Ok(BinaryArm { - size: quote_arm!(cx, $pat => { 0usize } ), - write: quote_arm!(cx, $pat => { buffer[0] = $variant_index_ident; Ok(()) } ), - read: quote_arm!(cx, $variant_index_ident => { Ok($variant_val) } ), - }) - }, - ast::VariantData::Tuple(ref fields, _) => { - let field_names: Vec = (0 .. fields.len()) - .map(|i| builder.id(format!("__field{}", i))) - .collect(); - - let pat = builder.pat().enum_() - .id(type_ident).id(variant_ident).build() - .with_pats( - field_names.iter() - .map(|field| builder.pat().ref_id(field)) - ) - .build(); - - let binary_expr = try!(binary_expr_struct( - cx, - &builder, - ty, - fields, - None, - Some(builder.id(format!("{}::{}", type_ident, variant_ident))), - )); - - let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); - Ok(BinaryArm { - size: quote_arm!(cx, $pat => { $size_expr } ), - write: quote_arm!(cx, - $pat => { - buffer[0] = $variant_index_ident; - let buffer = &mut buffer[1..]; - $write_expr - }), - read: quote_arm!(cx, - $variant_index_ident => { - let buffer = &buffer[1..]; - $read_expr - } - ), - }) - }, - ast::VariantData::Struct(ref fields, _) => { - let field_names: Vec<_> = (0 .. fields.len()) - .map(|i| builder.id(format!("__field{}", i))) - .collect(); - - let pat = builder.pat().struct_() - .id(type_ident).id(variant_ident).build() - .with_pats( - field_names.iter() - .zip(fields.iter()) - .map(|(id, field)|(field.ident.unwrap(), builder.pat().ref_id(id)))) - .build(); - - let binary_expr = try!(binary_expr_struct( - cx, - &builder, - ty, - fields, - None, - Some(builder.id(format!("{}::{}", type_ident, variant_ident))), - )); - - let (size_expr, write_expr, read_expr) = (binary_expr.size, vec![binary_expr.write], binary_expr.read); - - Ok(BinaryArm { - size: quote_arm!(cx, $pat => { $size_expr } ), - write: quote_arm!(cx, - $pat => { - buffer[0] = $variant_index_ident; - let buffer = &mut buffer[1..]; - $write_expr - }), - read: quote_arm!(cx, - $variant_index_ident => { - let buffer = &buffer[1..]; - $read_expr - } - ), - }) - }, - } -} diff --git a/ipc/hypervisor/Cargo.toml b/ipc/hypervisor/Cargo.toml deleted file mode 100644 index 1db60c904e67a612ace957ec983eb36bfbfdcf4f..0000000000000000000000000000000000000000 --- a/ipc/hypervisor/Cargo.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -name = "ethcore-ipc-hypervisor" -version = "1.2.0" -authors = ["Parity Technologies "] -license = "GPL-3.0" -build = "build.rs" - -[features] - -[dependencies] -ethcore-ipc = { path = "../rpc" } -nanomsg = { git = "https://github.com/paritytech/nanomsg.rs.git", branch = "parity-1.7" } -ethcore-ipc-nano = { path = "../nano" } -semver = "0.6" -log = "0.3" -time = "0.1" - -[build-dependencies] -ethcore-ipc-codegen = { path = "../codegen" } diff --git a/ipc/hypervisor/build.rs b/ipc/hypervisor/build.rs deleted file mode 100644 index 097aba0464ba18220fb5d00c85682199f43c0c5a..0000000000000000000000000000000000000000 --- a/ipc/hypervisor/build.rs +++ /dev/null @@ -1,21 +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 . - -extern crate ethcore_ipc_codegen; - -fn main() { - ethcore_ipc_codegen::derive_ipc("src/service.rs.in").unwrap(); -} diff --git a/ipc/hypervisor/src/lib.rs b/ipc/hypervisor/src/lib.rs deleted file mode 100644 index b522122b5b87d1c379e9e8b57555564098569ac4..0000000000000000000000000000000000000000 --- a/ipc/hypervisor/src/lib.rs +++ /dev/null @@ -1,273 +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 . - -//! Parity interprocess hypervisor module - -#![cfg_attr(feature="dev", allow(used_underscore_binding))] - -extern crate ethcore_ipc as ipc; -extern crate ethcore_ipc_nano as nanoipc; -extern crate semver; -#[macro_use] extern crate log; -extern crate time; - -pub mod service; - -/// Default value for hypervisor ipc listener -pub const HYPERVISOR_IPC_URL: &'static str = "parity-internal-hyper-status.ipc"; - -use std::sync::{Arc,RwLock}; -use service::{HypervisorService, IpcModuleId}; -use std::process::{Command,Child}; -use std::collections::HashMap; - -pub use service::{HypervisorServiceClient, ControlService, CLIENT_MODULE_ID, SYNC_MODULE_ID}; - -pub type BinaryId = &'static str; - -pub struct Hypervisor { - ipc_addr: String, - service: Arc, - ipc_worker: RwLock>, - processes: RwLock>, - modules: HashMap, - pub io_path: String, -} - -/// Boot arguments for binary -pub struct BootArgs { - cli: Option>, - stdin: Option>, -} - -impl BootArgs { - /// New empty boot arguments - pub fn new() -> BootArgs { - BootArgs { - cli: None, - stdin: None, - } - } - - /// Set command-line arguments for boot - pub fn cli(mut self, cli: Vec) -> BootArgs { - self.cli = Some(cli); - self - } - - /// Set std-in stream for boot - pub fn stdin(mut self, stdin: Vec) -> BootArgs { - self.stdin = Some(stdin); - self - } -} - -impl Hypervisor { - /// initializes the Hypervisor service with the open ipc socket for incoming clients - pub fn new() -> Hypervisor { - Hypervisor::with_url(HYPERVISOR_IPC_URL) - } - - pub fn module(mut self, module_id: IpcModuleId, args: BootArgs) -> Hypervisor { - self.modules.insert(module_id, args); - self.service.add_module(module_id); - self - } - - pub fn local_module(self, module_id: IpcModuleId) -> Hypervisor { - self.service.add_module(module_id); - self - } - - pub fn io_path(mut self, directory: &str) -> Hypervisor { - self.io_path = directory.to_owned(); - self - } - - /// Starts with the specified address for the ipc listener and - /// the specified list of modules in form of created service - pub fn with_url(addr: &str) -> Hypervisor { - let service = HypervisorService::new(); - let worker = nanoipc::Worker::new(&service); - Hypervisor{ - ipc_addr: addr.to_owned(), - service: service, - ipc_worker: RwLock::new(worker), - processes: RwLock::new(HashMap::new()), - modules: HashMap::new(), - io_path: "/tmp".to_owned(), - } - } - - /// Since one binary can host multiple modules - /// we match binaries - fn match_module(&self, module_id: &IpcModuleId) -> Option<&BootArgs> { - self.modules.get(module_id) - } - - /// Creates IPC listener and starts all binaries - pub fn start(&self) { - let mut worker = self.ipc_worker.write().unwrap(); - worker.add_reqrep(&self.ipc_addr).unwrap_or_else(|e| panic!("Hypervisor ipc worker can not start - critical! ({:?})", e)); - - for module_id in self.service.module_ids() { - self.start_module(module_id); - } - } - - /// Start binary for the specified module - /// Does nothing when it is already started on module is inside the - /// main binary - fn start_module(&self, module_id: IpcModuleId) { - use std::io::Write; - - self.match_module(&module_id).map(|boot_args| { - let mut processes = self.processes.write().unwrap(); - { - if processes.get(&module_id).is_some() { - // already started for another module - return; - } - } - - let mut command = Command::new(&std::env::current_exe().unwrap()); - command.stderr(std::process::Stdio::inherit()); - - if let Some(ref cli_args) = boot_args.cli { - for arg in cli_args { command.arg(arg); } - } - - command.stdin(std::process::Stdio::piped()); - - trace!(target: "hypervisor", "Spawn executable: {:?}", command); - - let mut child = command.spawn().unwrap_or_else( - |e| panic!("Hypervisor cannot execute command ({:?}): {}", command, e)); - - if let Some(ref std_in) = boot_args.stdin { - trace!(target: "hypervisor", "Pushing std-in payload..."); - child.stdin.as_mut() - .expect("std-in should be piped above") - .write(std_in) - .unwrap_or_else(|e| panic!(format!("Error trying to pipe stdin for {:?}: {:?}", &command, e))); - drop(child.stdin.take()); - } - - processes.insert(module_id, child); - }); - } - - /// Reports if all modules are checked in - pub fn modules_ready(&self) -> bool { - self.service.unchecked_count() == 0 - } - - pub fn modules_shutdown(&self) -> bool { - self.service.running_count() == 0 - } - - /// Waits for every required module to check in - pub fn wait_for_startup(&self) { - let mut worker = self.ipc_worker.write().unwrap(); - while !self.modules_ready() { - worker.poll() - } - } - - /// Waits for every required module to check in - pub fn wait_for_shutdown(&self) -> bool { - use time::{PreciseTime, Duration}; - - let mut worker = self.ipc_worker.write().unwrap(); - let start = PreciseTime::now(); - while !self.modules_shutdown() { - worker.poll(); - if start.to(PreciseTime::now()) > Duration::seconds(30) { - warn!("Some modules failed to shutdown gracefully, they will be terminated."); - break; - } - } - self.modules_shutdown() - } - - /// Shutdown the ipc and all managed child processes - pub fn shutdown(&self) { - let mut childs = self.processes.write().unwrap(); - for (ref module, _) in childs.iter() { - trace!(target: "hypervisor", "Stopping process module: {}", module); - self.service.send_shutdown(**module); - } - trace!(target: "hypervisor", "Waiting for shutdown..."); - if self.wait_for_shutdown() { - trace!(target: "hypervisor", "All modules reported shutdown"); - return; - } - - for (ref module, ref mut process) in childs.iter_mut() { - if self.service.is_running(**module) { - process.kill().unwrap(); - trace!("Terminated {}", module); - } - } - } -} - -impl Drop for Hypervisor { - fn drop(&mut self) { - self.shutdown(); - } -} - -#[cfg(test)] -mod tests { - use super::*; - use std::sync::atomic::{AtomicBool,Ordering}; - use std::sync::Arc; - use nanoipc; - - #[test] - fn can_init() { - let url = "ipc:///tmp/test-parity-hypervisor-10.ipc"; - let test_module_id = 8080u64; - - let hypervisor = Hypervisor::with_url(url).local_module(test_module_id); - assert_eq!(false, hypervisor.modules_ready()); - } - - #[test] - fn can_wait_for_startup() { - let url = "ipc:///tmp/test-parity-hypervisor-20.ipc"; - let test_module_id = 8080u64; - - let hypervisor_ready = Arc::new(AtomicBool::new(false)); - let hypervisor_ready_local = hypervisor_ready.clone(); - - ::std::thread::spawn(move || { - while !hypervisor_ready.load(Ordering::Relaxed) { } - - let client = nanoipc::fast_client::>(url).unwrap(); - client.handshake().unwrap(); - client.module_ready(test_module_id, url.to_owned()); - }); - - let hypervisor = Hypervisor::with_url(url).local_module(test_module_id); - hypervisor.start(); - hypervisor_ready_local.store(true, Ordering::Relaxed); - hypervisor.wait_for_startup(); - - assert_eq!(true, hypervisor.modules_ready()); - } -} diff --git a/ipc/hypervisor/src/service.rs b/ipc/hypervisor/src/service.rs deleted file mode 100644 index 59040251e6452018c4a99454e842c54cb26a969f..0000000000000000000000000000000000000000 --- a/ipc/hypervisor/src/service.rs +++ /dev/null @@ -1,20 +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 . - -//! Parity interprocess hypervisor IPC service -#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues - -include!(concat!(env!("OUT_DIR"), "/service.rs.in")); diff --git a/ipc/hypervisor/src/service.rs.in b/ipc/hypervisor/src/service.rs.in deleted file mode 100644 index 6d6f382680cd6632060d3a0d6f4783b3099141bb..0000000000000000000000000000000000000000 --- a/ipc/hypervisor/src/service.rs.in +++ /dev/null @@ -1,125 +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 . - -use std::sync::{RwLock,Arc}; -use ipc::IpcConfig; -use std::collections::HashMap; -use nanoipc; - -pub type IpcModuleId = u64; - -/// Blockhain database module id -pub const CLIENT_MODULE_ID: IpcModuleId = 2000; - -/// Sync module id -pub const SYNC_MODULE_ID: IpcModuleId = 2100; - -/// IPC service that handles module management -pub struct HypervisorService { - modules: RwLock>, -} - -#[derive(Default)] -pub struct ModuleState { - started: bool, - control_url: String, - shutdown: bool, -} - -#[ipc] -pub trait ControlService { - fn shutdown(&self) -> bool; -} - -#[ipc] -impl HypervisorService { - // return type for making method synchronous - fn module_ready(&self, module_id: u64, control_url: String) -> bool { - let mut modules = self.modules.write().unwrap(); - modules.get_mut(&module_id).map(|mut module| { - module.started = true; - module.control_url = control_url; - }); - trace!(target: "hypervisor", "Module ready: {}", module_id); - true - } - - // return type for making method synchronous - fn module_shutdown(&self, module_id: u64) -> bool { - let mut modules = self.modules.write().unwrap(); - modules.get_mut(&module_id).map(|mut module| { - module.shutdown = true; - }); - trace!(target: "hypervisor", "Module shutdown: {}", module_id); - true - } -} - -impl HypervisorService { - /// New service with the default list of modules - pub fn new() -> Arc { - HypervisorService::with_modules(vec![]) - } - - /// New service with list of modules that will report for being ready - pub fn with_modules(module_ids: Vec) -> Arc { - let mut modules = HashMap::new(); - for module_id in module_ids { - modules.insert(module_id, ModuleState::default()); - } - Arc::new(HypervisorService { - modules: RwLock::new(modules), - }) - } - - /// Add the module to the check-list - pub fn add_module(&self, module_id: IpcModuleId) { - self.modules.write().unwrap().insert(module_id, ModuleState::default()); - } - - /// Number of modules still being waited for check-in - pub fn unchecked_count(&self) -> usize { - self.modules.read().unwrap().iter().filter(|&(_, module)| !module.started).count() - } - - /// List of all modules within this service - pub fn module_ids(&self) -> Vec { - self.modules.read().unwrap().iter().map(|(module_id, _)| module_id).cloned().collect() - } - - /// Number of modules started and running - pub fn running_count(&self) -> usize { - self.modules.read().unwrap().iter().filter(|&(_, module)| module.started && !module.shutdown).count() - } - - pub fn is_running(&self, id: IpcModuleId) -> bool { - self.modules.read().unwrap().get(&id).map(|module| module.started && !module.shutdown).unwrap_or(false) - } - - pub fn send_shutdown(&self, module_id: IpcModuleId) { - let modules = self.modules.read().unwrap(); - modules.get(&module_id).map(|module| { - trace!(target: "hypervisor", "Sending shutdown to {}({})", module_id, &module.control_url); - let client = nanoipc::fast_client::>(&module.control_url).unwrap(); - client.shutdown(); - trace!(target: "hypervisor", "Sent shutdown to {}", module_id); - }); - } -} - -impl ::ipc::IpcConfig for HypervisorService {} - -impl ::ipc::IpcConfig for ControlService {} diff --git a/ipc/nano/Cargo.toml b/ipc/nano/Cargo.toml deleted file mode 100644 index a714e1d008da60ab0f91167e1a3558dc1074ac27..0000000000000000000000000000000000000000 --- a/ipc/nano/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "ethcore-ipc-nano" -version = "1.8.0" -authors = ["Parity Technologies "] -license = "GPL-3.0" - -[features] - -[dependencies] -ethcore-ipc = { path = "../rpc" } -nanomsg = { git = "https://github.com/paritytech/nanomsg.rs.git", branch = "parity-1.7" } -log = "0.3" -lazy_static = "0.2" diff --git a/ipc/nano/src/lib.rs b/ipc/nano/src/lib.rs deleted file mode 100644 index 9be3d2b1d26a3fd660eb0613d4747f0ea5c198a9..0000000000000000000000000000000000000000 --- a/ipc/nano/src/lib.rs +++ /dev/null @@ -1,355 +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 . - -//! IPC over nanomsg transport - -extern crate ethcore_ipc as ipc; -extern crate nanomsg; -#[macro_use] extern crate log; -#[macro_use] extern crate lazy_static; - -pub use ipc::{WithSocket, IpcInterface, IpcConfig}; -pub use nanomsg::Socket as NanoSocket; - -use std::sync::*; -use nanomsg::{Socket, Protocol, Error, Endpoint, PollRequest, PollFd, PollInOut}; -use std::ops::Deref; - -const POLL_TIMEOUT: isize = 200; -const DEFAULT_CONNECTION_TIMEOUT: isize = 30000; -const DEBUG_CONNECTION_TIMEOUT: isize = 5000; - -/// Generic worker to handle service (binded) sockets -pub struct Worker where S: IpcInterface { - service: Arc, - sockets: Vec<(Socket, Endpoint)>, - polls: Vec, - buf: Vec, -} - -/// struct for guarding `_endpoint` (so that it wont drop) -/// derefs to client `S` -pub struct GuardedSocket where S: WithSocket { - client: Arc, - _endpoint: Endpoint, -} - -impl GuardedSocket where S: WithSocket { - pub fn service(&self) -> Arc { - self.client.clone() - } -} - -impl Deref for GuardedSocket where S: WithSocket { - type Target = Arc; - - fn deref(&self) -> &Arc { - &self.client - } -} - -/// Spawns client <`S`> over specified address -/// creates socket and connects endpoint to it -/// for duplex (paired) connections with the service -pub fn init_duplex_client(socket_addr: &str) -> Result, SocketError> where S: WithSocket { - let mut socket = Socket::new(Protocol::Pair).map_err(|e| { - warn!(target: "ipc", "Failed to create ipc socket: {:?}", e); - SocketError::DuplexLink - })?; - - socket.set_receive_timeout(DEFAULT_CONNECTION_TIMEOUT).unwrap(); - - let endpoint = socket.connect(socket_addr).map_err(|e| { - warn!(target: "ipc", "Failed to bind socket to address '{}': {:?}", socket_addr, e); - SocketError::DuplexLink - })?; - - Ok(GuardedSocket { - client: Arc::new(S::init(socket)), - _endpoint: endpoint, - }) -} - -/// Spawns client <`S`> over specified address -/// creates socket and connects endpoint to it -/// for request-reply connections to the service -pub fn client(socket_addr: &str, receive_timeout: Option) -> Result, SocketError> where S: WithSocket { - let mut socket = Socket::new(Protocol::Req).map_err(|e| { - warn!(target: "ipc", "Failed to create ipc socket: {:?}", e); - SocketError::RequestLink - })?; - - if let Some(timeout) = receive_timeout { - socket.set_receive_timeout(timeout).unwrap(); - } - - let endpoint = socket.connect(socket_addr).map_err(|e| { - warn!(target: "ipc", "Failed to bind socket to address '{}': {:?}", socket_addr, e); - SocketError::RequestLink - })?; - - trace!(target: "ipc", "Created client for {}", socket_addr); - Ok(GuardedSocket { - client: Arc::new(S::init(socket)), - _endpoint: endpoint, - }) -} - -lazy_static! { - /// Set PARITY_IPC_DEBUG=1 for fail-fast connectivity problems diagnostic - pub static ref DEBUG_FLAG: bool = { - use std::env; - - if let Ok(debug) = env::var("PARITY_IPC_DEBUG") { - debug == "1" || debug.to_uppercase() == "TRUE" - } - else { false } - }; -} - -/// Client with no default timeout on operations -pub fn generic_client(socket_addr: &str) -> Result, SocketError> where S: WithSocket { - if *DEBUG_FLAG { - client(socket_addr, Some(DEBUG_CONNECTION_TIMEOUT)) - } else { - client(socket_addr, None) - } -} - -/// Client over interface that is supposed to give quick almost non-blocking responses -pub fn fast_client(socket_addr: &str) -> Result, SocketError> where S: WithSocket { - if *DEBUG_FLAG { - client(socket_addr, Some(DEBUG_CONNECTION_TIMEOUT)) - } else { - client(socket_addr, Some(DEFAULT_CONNECTION_TIMEOUT)) - } -} - -/// Error occurred while establising socket or endpoint -#[derive(Debug)] -pub enum SocketError { - /// Error establising duplex (paired) socket and/or endpoint - DuplexLink, - /// Error establising duplex (paired) socket and/or endpoint - RequestLink, -} - -impl Worker where S: IpcInterface { - /// New worker over specified `service` - pub fn new(service: &Arc) -> Worker { - Worker:: { - service: service.clone(), - sockets: Vec::new(), - polls: Vec::new(), - buf: Vec::new(), - } - } - - /// Polls all sockets, reads and dispatches method invocations - pub fn poll(&mut self) { - use std::io::Write; - - let mut request = PollRequest::new(&mut self.polls[..]); - let _result_guard = Socket::poll(&mut request, POLL_TIMEOUT); - - for (fd_index, fd) in request.get_fds().iter().enumerate() { - if fd.can_read() { - let (ref mut socket, _) = self.sockets[fd_index]; - unsafe { self.buf.set_len(0); } - match socket.nb_read_to_end(&mut self.buf) { - Ok(method_sign_len) => { - if method_sign_len >= 2 { - - // method_num - let method_num = self.buf[0] as u16 * 256 + self.buf[1] as u16; - // payload - let payload = &self.buf[2..]; - - // dispatching for ipc interface - let result = self.service.dispatch_buf(method_num, payload); - - if let Err(e) = socket.write(&result) { - warn!(target: "ipc", "Failed to write response: {:?}", e); - } - } - else { - warn!(target: "ipc", "Failed to read method signature from socket: unexpected message length({})", method_sign_len); - } - }, - Err(Error::TryAgain) => { - }, - Err(x) => { - warn!(target: "ipc", "Error polling connections {:?}", x); - panic!(); - } - } - } - } - } - - /// Stores nanomsg poll request for reuse - fn rebuild_poll_request(&mut self) { - self.polls = self.sockets.iter() - .map(|&(ref socket, _)| socket.new_pollfd(PollInOut::In)) - .collect::>(); - } - - /// Add exclusive socket for paired client - /// Only one connection over this address is allowed - pub fn add_duplex(&mut self, addr: &str) -> Result<(), SocketError> { - let mut socket = Socket::new(Protocol::Pair).map_err(|e| { - warn!(target: "ipc", "Failed to create ipc socket: {:?}", e); - SocketError::DuplexLink - })?; - - let endpoint = socket.bind(addr).map_err(|e| { - warn!(target: "ipc", "Failed to bind socket to address '{}': {:?}", addr, e); - SocketError::DuplexLink - })?; - - self.sockets.push((socket, endpoint)); - - self.rebuild_poll_request(); - - trace!(target: "ipc", "Started duplex worker at {}", addr); - - Ok(()) - } - - /// Add generic socket for request-reply style communications - /// with multiple clients - pub fn add_reqrep(&mut self, addr: &str) -> Result<(), SocketError> { - let mut socket = Socket::new(Protocol::Rep).map_err(|e| { - warn!(target: "ipc", "Failed to create ipc socket: {:?}", e); - SocketError::DuplexLink - })?; - - - let endpoint = socket.bind(addr).map_err(|e| { - warn!(target: "ipc", "Failed to bind socket to address '{}': {:?}", addr, e); - SocketError::DuplexLink - })?; - - self.sockets.push((socket, endpoint)); - - self.rebuild_poll_request(); - - trace!(target: "ipc", "Started request-reply worker at {}", addr); - Ok(()) - } -} - -#[cfg(test)] -mod service_tests { - - use super::Worker; - use ipc::*; - use std::io::{Read, Write}; - use std::sync::{Arc, RwLock}; - use nanomsg::{Socket, Protocol, Endpoint}; - - struct TestInvoke { - method_num: u16, - params: Vec, - } - - struct DummyService { - methods_stack: RwLock>, - } - - impl DummyService { - fn new() -> DummyService { - DummyService { methods_stack: RwLock::new(Vec::new()) } - } - } - - impl IpcInterface for DummyService { - fn dispatch(&self, _r: &mut R) -> Vec where R: Read { - vec![] - } - fn dispatch_buf(&self, method_num: u16, buf: &[u8]) -> Vec { - self.methods_stack.write().unwrap().push( - TestInvoke { - method_num: method_num, - params: buf.to_vec(), - }); - vec![] - } - } - - impl IpcConfig for DummyService {} - - fn dummy_write(addr: &str, buf: &[u8]) -> (Socket, Endpoint) { - let mut socket = Socket::new(Protocol::Pair).unwrap(); - let endpoint = socket.connect(addr).unwrap(); - socket.write(buf).unwrap(); - (socket, endpoint) - } - - #[test] - fn can_create_worker() { - let worker = Worker::::new(&Arc::new(DummyService::new())); - assert_eq!(0, worker.sockets.len()); - } - - #[test] - fn can_add_duplex_socket_to_worker() { - let mut worker = Worker::::new(&Arc::new(DummyService::new())); - worker.add_duplex("ipc:///tmp/parity-test10.ipc").unwrap(); - assert_eq!(1, worker.sockets.len()); - } - - #[test] - fn worker_can_poll_empty() { - let service = Arc::new(DummyService::new()); - let mut worker = Worker::::new(&service); - worker.add_duplex("ipc:///tmp/parity-test20.ipc").unwrap(); - worker.poll(); - assert_eq!(0, service.methods_stack.read().unwrap().len()); - } - - #[test] - fn worker_can_poll() { - let url = "ipc:///tmp/parity-test30.ipc"; - - let mut worker = Worker::::new(&Arc::new(DummyService::new())); - worker.add_duplex(url).unwrap(); - - let (_socket, _endpoint) = dummy_write(url, &vec![0, 0, 7, 7, 6, 6]); - worker.poll(); - - assert_eq!(1, worker.service.methods_stack.read().unwrap().len()); - assert_eq!(0, worker.service.methods_stack.read().unwrap()[0].method_num); - assert_eq!([7, 7, 6, 6], worker.service.methods_stack.read().unwrap()[0].params[..]); - } - - #[test] - fn worker_can_poll_long() { - let url = "ipc:///tmp/parity-test40.ipc"; - - let mut worker = Worker::::new(&Arc::new(DummyService::new())); - worker.add_duplex(url).unwrap(); - - let message = [0u8; 1024*1024]; - - let (_socket, _endpoint) = dummy_write(url, &message); - worker.poll(); - - assert_eq!(1, worker.service.methods_stack.read().unwrap().len()); - assert_eq!(0, worker.service.methods_stack.read().unwrap()[0].method_num); - assert_eq!(vec![0u8; 1024*1024-2], worker.service.methods_stack.read().unwrap()[0].params); - } -} diff --git a/ipc/rpc/Cargo.toml b/ipc/rpc/Cargo.toml deleted file mode 100644 index edfcdf103d41768be4855c2414e6c7f99aa5b3f3..0000000000000000000000000000000000000000 --- a/ipc/rpc/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "ethcore-ipc" -version = "1.8.0" -authors = ["Parity Technologies "] -license = "GPL-3.0" - -[features] - -[dependencies] -ethcore-devtools = { path = "../../devtools" } -nanomsg = { git = "https://github.com/paritytech/nanomsg.rs.git", branch = "parity-1.7" } -ethcore-util = { path = "../../util" } -semver = "0.6" diff --git a/ipc/rpc/src/binary.rs b/ipc/rpc/src/binary.rs deleted file mode 100644 index b2fc4bb4b422810e175e4b999c7388deb259a430..0000000000000000000000000000000000000000 --- a/ipc/rpc/src/binary.rs +++ /dev/null @@ -1,1194 +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 . - -//! Binary representation of types - -use util::{U256, U512, H256, H512, H2048, Address}; -use std::mem; -use std::collections::{VecDeque, BTreeMap}; -use std::ops::Range; -use super::Handshake; - -#[derive(Debug)] -pub enum BinaryConvertErrorKind { - SizeMismatch { - expected: usize, - found: usize, - }, - TargetPayloadEmpty, - UnexpectedVariant(u8), - MissingLengthValue, - InconsistentBoundaries, - NotSupported, -} - -#[derive(Debug)] -pub struct BinaryConvertError { - member_tree: Vec<&'static str>, - kind: BinaryConvertErrorKind, -} - -impl BinaryConvertError { - pub fn size(expected: usize, found: usize) -> BinaryConvertError { - BinaryConvertError { - member_tree: Vec::new(), - kind: BinaryConvertErrorKind::SizeMismatch { - expected: expected, - found: found, - } - } - } - - pub fn empty() -> BinaryConvertError { - BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::TargetPayloadEmpty } - } - - pub fn variant(val: u8) -> BinaryConvertError { - BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::UnexpectedVariant(val) } - } - - pub fn length() -> BinaryConvertError { - BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::MissingLengthValue } - } - - pub fn boundaries() -> BinaryConvertError { - BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::InconsistentBoundaries } - } - - pub fn not_supported() -> BinaryConvertError { - BinaryConvertError { member_tree: Vec::new(), kind: BinaryConvertErrorKind::NotSupported } - } - - pub fn named(mut self, name: &'static str) -> BinaryConvertError { - self.member_tree.push(name); - self - } -} - -#[derive(Debug)] -pub enum BinaryError { - Serialization(BinaryConvertError), - Io(::std::io::Error), -} - -impl From<::std::io::Error> for BinaryError { - fn from(err: ::std::io::Error) -> Self { BinaryError::Io(err) } -} - -impl From for BinaryError { - fn from(err: BinaryConvertError) -> Self { BinaryError::Serialization(err) } -} - -pub trait BinaryConvertable : Sized { - fn size(&self) -> usize { - mem::size_of::() - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError>; - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result; - - fn from_empty_bytes() -> Result { - Err(BinaryConvertError::size(mem::size_of::(), 0)) - } - - fn len_params() -> usize { - 0 - } -} - -impl BinaryConvertable for Option where T: BinaryConvertable { - fn size(&self) -> usize { - match * self { None => 0, Some(ref val) => val.size() } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - match *self { None => Err(BinaryConvertError::empty()), Some(ref val) => val.to_bytes(buffer, length_stack) } - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - if buffer.len() == 0 { return Self::from_empty_bytes(); } - Ok(Some(T::from_bytes(buffer, length_stack)?)) - } - - fn from_empty_bytes() -> Result { - Ok(None) - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for Result<(), E> { - fn size(&self) -> usize { - match *self { - Ok(_) => 0, - Err(ref e) => e.size(), - } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - match *self { - Ok(_) => Err(BinaryConvertError::empty()), - Err(ref e) => Ok(e.to_bytes(buffer, length_stack)?), - } - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - Ok(Err(E::from_bytes(&buffer, length_stack)?)) - } - - fn from_empty_bytes() -> Result { - Ok(Ok(())) - } - - fn len_params() -> usize { - 1 - } -} - - -impl BinaryConvertable for Result { - fn size(&self) -> usize { - match *self { - Ok(ref r) => r.size(), - Err(_) => 0, - } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - match *self { - Ok(ref r) => Ok(r.to_bytes(buffer, length_stack)?), - Err(_) => Err(BinaryConvertError::empty()), - } - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - Ok(Ok(R::from_bytes(&buffer, length_stack)?)) - } - - fn from_empty_bytes() -> Result { - Ok(Err(())) - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for Result { - fn size(&self) -> usize { - 1usize + match *self { - Ok(ref r) => r.size(), - Err(ref e) => e.size(), - } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - match *self { - Ok(ref r) => { - buffer[0] = 0; - if r.size() > 0 { - Ok(r.to_bytes(&mut buffer[1..], length_stack)?) - } - else { Ok(()) } - }, - Err(ref e) => { - buffer[0] = 1; - if e.size() > 0 { - Ok(e.to_bytes(&mut buffer[1..], length_stack)?) - } - else { Ok(()) } - }, - } - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - match buffer[0] { - 0 => { - match buffer.len() { - 1 => Ok(Ok(R::from_empty_bytes()?)), - _ => Ok(Ok(R::from_bytes(&buffer[1..], length_stack)?)), - } - } - 1 => Ok(Err(E::from_bytes(&buffer[1..], length_stack)?)), - _ => Err(BinaryConvertError::variant(buffer[0])) - } - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for BTreeMap where K : BinaryConvertable + Ord, V: BinaryConvertable { - fn size(&self) -> usize { - 0usize + match K::len_params() { - 0 => mem::size_of::() * self.len(), - _ => self.iter().fold(0usize, |acc, (k, _)| acc + k.size()) - } + match V::len_params() { - 0 => mem::size_of::() * self.len(), - _ => self.iter().fold(0usize, |acc, (_, v)| acc + v.size()) - } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - let mut offset = 0usize; - for (key, val) in self.iter() { - let key_size = match K::len_params() { - 0 => mem::size_of::(), - _ => { let size = key.size(); length_stack.push_back(size); size } - }; - let val_size = match K::len_params() { - 0 => mem::size_of::(), - _ => { let size = val.size(); length_stack.push_back(size); size } - }; - - if key_size > 0 { - let item_end = offset + key_size; - key.to_bytes(&mut buffer[offset..item_end], length_stack)?; - offset = item_end; - } - - if val_size > 0 { - let item_end = offset + key_size; - val.to_bytes(&mut buffer[offset..item_end], length_stack)?; - offset = item_end; - } - } - Ok(()) - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - let mut index = 0; - let mut result = Self::new(); - - if buffer.len() == 0 { return Ok(result); } - - loop { - let key_size = match K::len_params() { - 0 => mem::size_of::(), - _ => length_stack.pop_front().ok_or(BinaryConvertError::length())?, - }; - let key = if key_size == 0 { - K::from_empty_bytes()? - } else { - if index + key_size > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - K::from_bytes(&buffer[index..index+key_size], length_stack)? - }; - index = index + key_size; - - let val_size = match V::len_params() { - 0 => mem::size_of::(), - _ => length_stack.pop_front().ok_or(BinaryConvertError::length())?, - }; - let val = if val_size == 0 { - V::from_empty_bytes()? - } else { - if index + val_size > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - V::from_bytes(&buffer[index..index+val_size], length_stack)? - }; - result.insert(key, val); - index = index + val_size; - - if index == buffer.len() { break; } - if index > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - } - - Ok(result) - } - - fn from_empty_bytes() -> Result { - Ok(Self::new()) - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for VecDeque where T: BinaryConvertable { - fn size(&self) -> usize { - match T::len_params() { - 0 => mem::size_of::() * self.len(), - _ => self.iter().fold(0usize, |acc, t| acc + t.size()), - } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - let mut offset = 0usize; - for item in self.iter() { - let next_size = match T::len_params() { - 0 => mem::size_of::(), - _ => { let size = item.size(); length_stack.push_back(size); size }, - }; - if next_size > 0 { - let item_end = offset + next_size; - item.to_bytes(&mut buffer[offset..item_end], length_stack)?; - offset = item_end; - } - } - Ok(()) - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - let mut index = 0; - let mut result = Self::with_capacity( - match T::len_params() { - 0 => buffer.len() / mem::size_of::(), - _ => 128, - }); - - if buffer.len() == 0 { return Ok(result); } - - loop { - let next_size = match T::len_params() { - 0 => mem::size_of::(), - _ => length_stack.pop_front().ok_or(BinaryConvertError::length())?, - }; - let item = if next_size == 0 { - T::from_empty_bytes()? - } - else { - if index + next_size > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - T::from_bytes(&buffer[index..index+next_size], length_stack)? - }; - result.push_back(item); - - index = index + next_size; - if index == buffer.len() { break; } - if index > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - } - - Ok(result) - } - - fn from_empty_bytes() -> Result { - Ok(Self::new()) - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for Vec where T: BinaryConvertable { - fn size(&self) -> usize { - match T::len_params() { - 0 => mem::size_of::() * self.len(), - _ => self.iter().fold(0usize, |acc, t| acc + t.size()), - } - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - let mut offset = 0usize; - for item in self.iter() { - let next_size = match T::len_params() { - 0 => mem::size_of::(), - _ => { let size = item.size(); length_stack.push_back(size); size }, - }; - if next_size > 0 { - let item_end = offset + next_size; - item.to_bytes(&mut buffer[offset..item_end], length_stack)?; - offset = item_end; - } - } - Ok(()) - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - let mut index = 0; - let mut result = Self::with_capacity( - match T::len_params() { - 0 => buffer.len() / mem::size_of::(), - _ => 128, - }); - - if buffer.len() == 0 { return Ok(result); } - - loop { - let next_size = match T::len_params() { - 0 => mem::size_of::(), - _ => length_stack.pop_front().ok_or(BinaryConvertError::length())?, - }; - let item = if next_size == 0 { - T::from_empty_bytes()? - } - else { - if index + next_size > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - T::from_bytes(&buffer[index..index+next_size], length_stack)? - }; - result.push(item); - - index = index + next_size; - if index == buffer.len() { break; } - if index > buffer.len() { - return Err(BinaryConvertError::boundaries()) - } - } - - Ok(result) - } - - fn from_empty_bytes() -> Result { - Ok(Self::new()) - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for String { - fn size(&self) -> usize { - self.as_bytes().len() - } - - fn from_empty_bytes() -> Result { - Ok(String::new()) - } - - fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - buffer[..].clone_from_slice(self.as_bytes()); - Ok(()) - } - - fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque) -> Result { - Ok(::std::str::from_utf8(buffer).unwrap().to_owned()) - } - - fn len_params() -> usize { - 1 - } -} - -impl BinaryConvertable for Range where T: BinaryConvertable { - fn size(&self) -> usize { - mem::size_of::() * 2 - } - - fn from_empty_bytes() -> Result { - Err(BinaryConvertError::empty()) - } - - fn to_bytes(&self, buffer: &mut[u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - self.start.to_bytes(&mut buffer[..mem::size_of::()], length_stack)?; - self.end.to_bytes(&mut buffer[mem::size_of::() + 1..], length_stack)?; - Ok(()) - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - Ok(T::from_bytes(&buffer[..mem::size_of::()], length_stack)?..T::from_bytes(&buffer[mem::size_of::()+1..], length_stack)?) - } - - fn len_params() -> usize { - assert_eq!(0, T::len_params()); - 0 - } -} - -impl BinaryConvertable for ::std::cell::RefCell where T: BinaryConvertable { - fn size(&self) -> usize { - self.borrow().size() - } - - fn from_empty_bytes() -> Result { - Ok(::std::cell::RefCell::new(T::from_empty_bytes()?)) - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - Ok(::std::cell::RefCell::new(T::from_bytes(buffer, length_stack)?)) - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - self.borrow().to_bytes(buffer, length_stack)?; - Ok(()) - } - - fn len_params() -> usize { - T::len_params() - } -} - -impl BinaryConvertable for ::std::cell::Cell where T: BinaryConvertable + Copy { - fn size(&self) -> usize { - self.get().size() - } - - fn from_empty_bytes() -> Result { - Ok(::std::cell::Cell::new(T::from_empty_bytes()?)) - } - - fn from_bytes(buffer: &[u8], length_stack: &mut VecDeque) -> Result { - Ok(::std::cell::Cell::new(T::from_bytes(buffer, length_stack)?)) - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - self.get().to_bytes(buffer, length_stack)?; - Ok(()) - } - - fn len_params() -> usize { - T::len_params() - } -} - -impl BinaryConvertable for Vec { - fn size(&self) -> usize { - self.len() - } - - fn from_empty_bytes() -> Result { - Ok(Vec::new()) - } - - fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut VecDeque) -> Result<(), BinaryConvertError> { - buffer[..].clone_from_slice(&self[..]); - Ok(()) - } - - fn from_bytes(buffer: &[u8], _length_stack: &mut VecDeque) -> Result { - let mut res = Self::with_capacity(buffer.len()); - unsafe { res.set_len(buffer.len()) } - res[..].clone_from_slice(&buffer[..]); - Ok(res) - } - - fn len_params() -> usize { - 1 - } -} - -pub fn deserialize_from(r: &mut R) -> Result - where R: ::std::io::Read, - T: BinaryConvertable -{ - let mut fake_stack = VecDeque::new(); - - match T::len_params() { - 0 => { - let fixed_size = mem::size_of::(); - let mut payload_buffer = Vec::with_capacity(fixed_size); - unsafe { payload_buffer.set_len(fixed_size); } - let bytes_read = r.read(&mut payload_buffer)?; - if bytes_read != mem::size_of::() { - return Err(BinaryError::Serialization(BinaryConvertError::size(fixed_size, bytes_read))) - } - Ok(T::from_bytes(&payload_buffer[..], &mut fake_stack)?) - }, - _ => { - let mut payload = Vec::new(); - r.read_to_end(&mut payload)?; - - let stack_len = u64::from_bytes(&payload[0..8], &mut fake_stack)? as usize; - let mut length_stack = VecDeque::::with_capacity(stack_len); - - if stack_len > 0 { - for idx in 0..stack_len { - let stack_item = u64::from_bytes(&payload[8 + idx*8..8 + (idx+1)*8], &mut fake_stack)?; - length_stack.push_back(stack_item as usize); - } - } - - let size = u64::from_bytes(&payload[8+stack_len*8..16+stack_len*8], &mut fake_stack)? as usize; - match size { - 0 => { - Ok(T::from_empty_bytes()?) - }, - _ => { - Ok(T::from_bytes(&payload[16+stack_len*8..], &mut length_stack)?) - } - } - }, - } -} - -pub fn deserialize(buffer: &[u8]) -> Result { - use std::io::Cursor; - let mut buff = Cursor::new(buffer); - deserialize_from::(&mut buff) -} - -pub fn serialize_into(t: &T, w: &mut W) -> Result<(), BinaryError> - where W: ::std::io::Write, - T: BinaryConvertable -{ - let mut fake_stack = VecDeque::new(); - - match T::len_params() { - 0 => { - let fixed_size = mem::size_of::(); - let mut buffer = Vec::with_capacity(fixed_size); - unsafe { buffer.set_len(fixed_size); } - t.to_bytes(&mut buffer[..], &mut fake_stack)?; - w.write(&buffer[..])?; - Ok(()) - }, - _ => { - let mut length_stack = VecDeque::::new(); - let mut size_buffer = [0u8; 8]; - - let size = t.size(); - if size == 0 { - w.write(&size_buffer)?; - w.write(&size_buffer)?; - return Ok(()); - } - - let mut buffer = Vec::with_capacity(size); - unsafe { buffer.set_len(size); } - t.to_bytes(&mut buffer[..], &mut length_stack)?; - - let stack_len = length_stack.len(); - (stack_len as u64).to_bytes(&mut size_buffer[..], &mut fake_stack)?; - w.write(&size_buffer[..])?; - if stack_len > 0 { - let mut header_buffer = Vec::with_capacity(stack_len * 8); - unsafe { header_buffer.set_len(stack_len * 8); }; - (stack_len as u64).to_bytes(&mut header_buffer[0..8], &mut fake_stack)?; - let mut idx = 0; - loop { - match length_stack.pop_front() { - Some(val) => (val as u64).to_bytes(&mut header_buffer[idx * 8..(idx+1) * 8], &mut fake_stack)?, - None => { break; } - } - idx = idx + 1; - } - w.write(&header_buffer[..])?; - } - - (size as u64).to_bytes(&mut size_buffer[..], &mut fake_stack)?; - w.write(&size_buffer[..])?; - - w.write(&buffer[..])?; - - Ok(()) - }, - } -} - -pub fn serialize(t: &T) -> Result, BinaryError> { - use std::io::Cursor; - let mut buff = Cursor::new(Vec::new()); - serialize_into(t, &mut buff)?; - let into_inner = buff.into_inner(); - Ok(into_inner) -} - -#[macro_export] -macro_rules! binary_fixed_size { - ($target_ty: ty) => { - impl BinaryConvertable for $target_ty where $target_ty: Copy { - fn from_bytes(bytes: &[u8], _length_stack: &mut ::std::collections::VecDeque) -> Result { - let size = ::std::mem::size_of::<$target_ty>(); - match bytes.len().cmp(&size) { - ::std::cmp::Ordering::Equal => (), - _ => return Err(BinaryConvertError::size(size, bytes.len())), - }; - let res: Self = unsafe { - let mut temp = ::std::mem::zeroed(); - let temp_ptr = &mut temp as *mut _ as *mut u8; - ::std::ptr::copy_nonoverlapping(bytes.as_ptr(), temp_ptr, size); - - temp - }; - - Ok(res) - } - - fn to_bytes(&self, buffer: &mut [u8], _length_stack: &mut ::std::collections::VecDeque) -> Result<(), BinaryConvertError> { - let sz = ::std::mem::size_of::<$target_ty>(); - let ip: *const $target_ty = self; - let ptr: *const u8 = ip as *const _; - unsafe { - ::std::ptr::copy(ptr, buffer.as_mut_ptr(), sz); - } - Ok(()) - } - } - } -} - -/// Fixed-sized version of Handshake struct -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct BinHandshake { - api_version: BinVersion, - protocol_version: BinVersion, -} - -/// Shorten version of semver Version without `pre` and `build` information -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct BinVersion { - pub major: u64, - pub minor: u64, - pub patch: u64, -} - -impl From for BinHandshake { - fn from(other: Handshake) -> Self { - BinHandshake { - api_version: BinVersion::from(other.api_version), - protocol_version: BinVersion::from(other.protocol_version), - } - } -} - -impl BinHandshake { - pub fn to_semver(self) -> Handshake { - Handshake { - api_version: self.api_version.to_semver(), - protocol_version: self.protocol_version.to_semver(), - } - } -} - -impl BinVersion { - pub fn to_semver(self) -> ::semver::Version { - ::semver::Version { - major: self.major, - minor: self.minor, - patch: self.patch, - pre: vec![], - build: vec![], - } - } -} - -impl From<::semver::Version> for BinVersion { - fn from(other: ::semver::Version) -> Self { - BinVersion { - major: other.major, - minor: other.minor, - patch: other.patch, - } - } -} - -binary_fixed_size!(u16); -binary_fixed_size!(u64); -binary_fixed_size!(u32); -binary_fixed_size!(usize); -binary_fixed_size!(i32); -binary_fixed_size!(bool); -binary_fixed_size!(U256); -binary_fixed_size!(U512); -binary_fixed_size!(H256); -binary_fixed_size!(H512); -binary_fixed_size!(H2048); -binary_fixed_size!(Address); -binary_fixed_size!(BinHandshake); -binary_fixed_size!(BinVersion); - -impl BinaryConvertable for ::semver::Version { - fn from_bytes(bytes: &[u8], length_stack: &mut ::std::collections::VecDeque) -> Result { - BinVersion::from_bytes(bytes, length_stack).map(BinVersion::to_semver) - } - - fn to_bytes(&self, buffer: &mut [u8], length_stack: &mut ::std::collections::VecDeque) -> Result<(), BinaryConvertError> { - BinVersion::from(self.clone()).to_bytes(buffer, length_stack) - } -} - -#[test] -fn vec_serialize() { - let mut v = Vec::new(); - v.push(5u64); - v.push(10u64); - let mut length_stack = VecDeque::new(); - let mut data = Vec::with_capacity(v.size()); - unsafe { data.set_len(v.size()); } - let result = v.to_bytes(&mut data[..], &mut length_stack); - - assert!(result.is_ok()); - assert_eq!(5, data[0]); - assert_eq!(0, data[1]); - assert_eq!(10, data[8]); - assert_eq!(0, data[12]); -} - -#[test] -fn calculates_size() { - let mut v = Vec::new(); - v.push(5u64); - v.push(10u64); - - assert_eq!(16, v.size()); -} - -#[test] -fn vec_deserialize() { - let data = [ - 10u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - ]; - - let mut length_stack = VecDeque::new(); - let vec = Vec::::from_bytes(&data[..], &mut length_stack).unwrap(); - - assert_eq!(vec![10u64, 5u64], vec); -} - -#[test] -fn vec_deserialize_chained() { - let mut v = Vec::new(); - v.push(Some(5u64)); - v.push(Some(10u64)); - v.push(None); - v.push(Some(12u64)); - - let mut length_stack = VecDeque::new(); - let mut data = Vec::with_capacity(v.size()); - unsafe { data.set_len(v.size()); } - let result = v.to_bytes(&mut data[..], &mut length_stack); - - assert!(result.is_ok()); - assert_eq!(4, length_stack.len()); -} - -#[test] -fn vec_serialize_deserialize() { - let mut v = Vec::new(); - v.push(Some(5u64)); - v.push(None); - v.push(Some(10u64)); - v.push(None); - v.push(Some(12u64)); - - - let mut data = Vec::with_capacity(v.size()); - unsafe { data.set_len(v.size()); } - let mut length_stack = VecDeque::new(); - - v.to_bytes(&mut data[..], &mut length_stack).unwrap(); - let de_v = Vec::>::from_bytes(&data[..], &mut length_stack).unwrap(); - - assert_eq!(v, de_v); -} - -#[test] -fn serialize_into_ok() { - use std::io::Cursor; - let mut buff = Cursor::new(vec![0; 128]); - - let mut v = Vec::new(); - v.push(Some(5u64)); - v.push(None); - v.push(Some(10u64)); - v.push(None); - v.push(Some(12u64)); - - serialize_into(&v, &mut buff).unwrap(); - assert_eq!(5, buff.get_ref()[0]); - assert_eq!(8, buff.get_ref()[8]); - assert_eq!(0, buff.get_ref()[16]); - assert_eq!(8, buff.get_ref()[24]); -} - -#[test] -fn deserialize_from_ok() { - use std::io::Cursor; - let mut buff = Cursor::new(vec![ - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 16u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 10u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 5u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - ]); - - let vec = deserialize_from::, _>(&mut buff).unwrap(); - - assert_eq!(vec![10u64, 5u64], vec); -} - -#[test] -fn serialize_into_deserialize_from() { - use std::io::{Cursor, SeekFrom, Seek}; - - let mut buff = Cursor::new(Vec::new()); - let mut v = Vec::new(); - v.push(Some(5u64)); - v.push(None); - v.push(Some(10u64)); - v.push(None); - v.push(Some(12u64)); - - serialize_into(&v, &mut buff).unwrap(); - buff.seek(SeekFrom::Start(0)).unwrap(); - let de_v = deserialize_from::>, _>(&mut buff).unwrap(); - assert_eq!(v, de_v); -} - -#[test] -fn serialize_vec_str() { - // empty - let source = Vec::::new(); - let serialized = serialize(&source).unwrap(); - let deserialized = deserialize::>(&serialized).unwrap(); - - assert_eq!(source, deserialized); - - // with few values - let mut source = Vec::::new(); - source.push("val1".to_owned()); - source.push("val2".to_owned()); - let serialized = serialize(&source).unwrap(); - let deserialized = deserialize::>(&serialized).unwrap(); - - assert_eq!(source, deserialized); -} - -#[test] -fn serialize_opt_str() { - // none - let source: Option = None; - let serialized = serialize(&source).unwrap(); - let deserialized = deserialize::>(&serialized).unwrap(); - - assert_eq!(source, deserialized); - - // value - let source: Option = Some("i have value".to_owned()); - let serialized = serialize(&source).unwrap(); - let deserialized = deserialize::>(&serialized).unwrap(); - - assert_eq!(source, deserialized); -} - -#[test] -fn serialize_opt_vec() { - use std::io::Cursor; - - let mut buff = Cursor::new(Vec::new()); - let optional_vec: Option> = None; - serialize_into(&optional_vec, &mut buff).unwrap(); - - assert_eq!(&vec![0u8; 16], buff.get_ref()); -} - -#[test] -fn serialize_opt_vec_payload() { - let optional_vec: Option> = None; - let payload = serialize(&optional_vec).unwrap(); - - assert_eq!(vec![0u8;16], payload); -} - -#[test] -fn deserialize_opt_vec() { - use std::io::Cursor; - let mut buff = Cursor::new(vec![0u8; 16]); - - let vec = deserialize_from::>, _>(&mut buff).unwrap(); - - assert!(vec.is_none()); -} - -#[test] -fn deserialize_simple_err() { - use std::io::Cursor; - let mut buff = Cursor::new(vec![0u8; 16]); - - let result = deserialize_from::, _>(&mut buff).unwrap(); - - assert!(result.is_ok()); -} - -#[test] -fn serialize_opt_vec_in_out() { - use std::io::{Cursor, SeekFrom, Seek}; - - let mut buff = Cursor::new(Vec::new()); - let optional_vec: Option> = None; - serialize_into(&optional_vec, &mut buff).unwrap(); - - buff.seek(SeekFrom::Start(0)).unwrap(); - let vec = deserialize_from::>, _>(&mut buff).unwrap(); - - assert!(vec.is_none()); -} - -#[test] -fn serialize_err_opt_vec_in_out() { - use std::io::{Cursor, SeekFrom, Seek}; - - let mut buff = Cursor::new(Vec::new()); - let optional_vec: Result>, u32> = Ok(None); - serialize_into(&optional_vec, &mut buff).unwrap(); - - buff.seek(SeekFrom::Start(0)).unwrap(); - let vec = deserialize_from::>, u32>, _>(&mut buff).unwrap(); - - assert!(vec.is_ok()); -} - -#[test] -fn serialize_btree() { - use std::io::{Cursor, SeekFrom, Seek}; - - let mut buff = Cursor::new(Vec::new()); - let mut btree = BTreeMap::new(); - btree.insert(1u64, 5u64); - serialize_into(&btree, &mut buff).unwrap(); - - buff.seek(SeekFrom::Start(0)).unwrap(); - let res = deserialize_from::, _>(&mut buff).unwrap(); - - assert_eq!(res[&1u64], 5u64); -} - -#[test] -fn serialize_refcell() { - use std::cell::RefCell; - - let source = RefCell::new(vec![5u32, 12u32, 19u32]); - let serialized = serialize(&source).unwrap(); - let deserialized = deserialize::>>(&serialized).unwrap(); - - assert_eq!(source, deserialized); -} - -#[test] -fn serialize_cell() { - use std::cell::Cell; - use std::str::FromStr; - - let source = Cell::new(U256::from_str("01231231231239999").unwrap()); - let serialized = serialize(&source).unwrap(); - let deserialized = deserialize::>(&serialized).unwrap(); - - assert_eq!(source, deserialized); -} - -#[test] -fn serialize_handshake() { - use std::io::{Cursor, SeekFrom, Seek}; - - let mut buff = Cursor::new(Vec::new()); - - let handshake = Handshake { - api_version: ::semver::Version::parse("1.2.0").unwrap(), - protocol_version: ::semver::Version::parse("1.2.0").unwrap(), - }; - - serialize_into(&BinHandshake::from(handshake.clone()), &mut buff).unwrap(); - - buff.seek(SeekFrom::Start(0)).unwrap(); - let res = deserialize_from::(&mut buff).unwrap().to_semver(); - - assert_eq!(res, handshake); -} - -#[test] -fn serialize_invalid_size() { - // value - let deserialized = deserialize::(&[]); - match deserialized { - Err(BinaryError::Serialization( - BinaryConvertError { - kind: BinaryConvertErrorKind::SizeMismatch { expected: 8, found: 0 }, - member_tree: _ - })) => {}, - other => panic!("Not a size mismatched error but: {:?}", other), - } -} - -#[test] -fn serialize_boundaries() { - // value - let deserialized = deserialize::>( - &[ - // payload header - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - // - 0u8, 0u8, 0u8, 5u8, - 0u8, 0u8, 0u8, 4u8, - 1u8, 1u8, /* not 4 bytes */ - ] - ); - match deserialized { - Err(BinaryError::Serialization( - BinaryConvertError { - kind: BinaryConvertErrorKind::InconsistentBoundaries, - member_tree: _ - })) => {}, - other => panic!("Not an inconsistent boundaries error but: {:?}", other), - } -} - -#[test] -fn serialize_empty_try() { - // value - let mut stack = VecDeque::new(); - let mut data = vec![0u8; 16]; - let sample: Option> = None; - let serialized = sample.to_bytes(&mut data, &mut stack); - match serialized { - Err(BinaryConvertError { - kind: BinaryConvertErrorKind::TargetPayloadEmpty, - member_tree: _ - }) => {}, - other => panic!("Not an error about empty payload to be produced but: {:?}", other), - } -} - -#[test] -fn serialize_not_enough_lengths() { - // value - let deserialized = deserialize::>>( - &[ - // payload header - 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - 2u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, - // does not matter because no length param for the first option - 0u8, - ] - ); - match deserialized { - Err(BinaryError::Serialization( - BinaryConvertError { - kind: BinaryConvertErrorKind::MissingLengthValue, - member_tree: _ - })) => {}, - other => panic!("Not an missing length param error but: {:?}", other), - } -} - -#[test] -fn vec_of_vecs() { - let sample = vec![vec![5u8, 10u8], vec![], vec![9u8, 11u8]]; - let serialized = serialize(&sample).unwrap(); - let deserialized = deserialize::>>(&serialized).unwrap(); - assert_eq!(sample, deserialized); - - // empty - let sample: Vec> = vec![]; - let serialized = serialize(&sample).unwrap(); - let deserialized = deserialize::>>(&serialized).unwrap(); - assert_eq!(sample, deserialized); -} diff --git a/ipc/rpc/src/interface.rs b/ipc/rpc/src/interface.rs deleted file mode 100644 index c3e82fef4a63cbc029695d8fe3a7c7a7ad59654a..0000000000000000000000000000000000000000 --- a/ipc/rpc/src/interface.rs +++ /dev/null @@ -1,106 +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 . - -//! IPC RPC interface - -use std::io::{Read, Write}; -use std::marker::Sync; -use semver::Version; - -#[derive(Debug, PartialEq, Eq, Clone)] -/// Handshake for client and server to negotiate api/protocol version -pub struct Handshake { - pub protocol_version: Version, - pub api_version: Version, -} - -/// Allows to configure custom version and custom handshake response for -/// ipc host -pub trait IpcConfig { - /// Current service api version - /// Should be increased if any of the methods changes signature - fn api_version() -> Version { - Version::parse("1.0.0").unwrap() - } - - /// Current ipc protocol version - /// Should be increased only if signature of system methods changes - fn protocol_version() -> Version { - Version::parse("1.0.0").unwrap() - } - - /// Default handshake requires exact versions match - fn handshake(handshake: &Handshake) -> bool { - handshake.protocol_version == Self::protocol_version() && - handshake.api_version == Self::api_version() - } -} - -/// Error in dispatching or invoking methods via IPC -#[derive(Debug)] -pub enum Error { - UnkownSystemCall, - ClientUnsupported, - RemoteServiceUnsupported, - HandshakeFailed, -} - -/// Allows implementor to be attached to generic worker and dispatch rpc requests -/// over IPC -pub trait IpcInterface : IpcConfig { - /// reads the message from io, dispatches the call and returns serialized result - fn dispatch(&self, r: &mut R) -> Vec where R: Read; - - /// deserializes the payload from buffer, dispatches invoke and returns serialized result - /// (for non-blocking io) - fn dispatch_buf(&self, method_num: u16, buf: &[u8]) -> Vec; -} - -/// serializes method invocation (method_num and parameters) to the stream specified by `w` -pub fn invoke(method_num: u16, params: &Option>, w: &mut W) where W: Write { - // creating buffer to contain all message - let buf_len = match *params { None => 2, Some(ref val) => val.len() + 2 }; - let mut buf = vec![0u8; buf_len]; - - // writing method_num as u16 - buf[1] = (method_num & 255) as u8; - buf[0] = (method_num >> 8) as u8; - - // serializing parameters only if provided with any - if params.is_some() { - buf[2..buf_len].clone_from_slice(params.as_ref().unwrap()); - } - - if w.write(&buf).unwrap() != buf_len - { - // if write was inconsistent - panic!("failed to write to socket"); - } -} - -/// IpcSocket, read/write generalization -pub trait IpcSocket: Read + Write + Sync + Send { -} - -/// Basically something that needs only socket to be spawned -pub trait WithSocket { - fn init(socket: S) -> Self; -} - - -impl IpcSocket for ::devtools::TestSocket {} - -impl IpcSocket for ::nanomsg::Socket {} diff --git a/ipc/rpc/src/lib.rs b/ipc/rpc/src/lib.rs deleted file mode 100644 index 61493ea362cc7ded00424f1b818d8cdf4caf4b17..0000000000000000000000000000000000000000 --- a/ipc/rpc/src/lib.rs +++ /dev/null @@ -1,27 +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 . - -//! IPC RPC interface - -extern crate ethcore_devtools as devtools; -extern crate semver; -extern crate nanomsg; -extern crate ethcore_util as util; - -pub mod interface; -pub mod binary; -pub use interface::{IpcInterface, IpcSocket, invoke, IpcConfig, Handshake, Error, WithSocket}; -pub use binary::{BinaryConvertable, BinaryConvertError, BinVersion, BinHandshake}; diff --git a/ipc/tests/Cargo.toml b/ipc/tests/Cargo.toml deleted file mode 100644 index 89a4f98c5b5cb17f3294d10669710196e6fa5b0d..0000000000000000000000000000000000000000 --- a/ipc/tests/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "ethcore-ipc-tests" -version = "0.1.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[lib] -path = "run.rs" - -[dependencies] -ethcore-ipc = { path = "../rpc" } -ethcore-devtools = { path = "../../devtools" } -semver = "0.6" -nanomsg = { git = "https://github.com/paritytech/nanomsg.rs.git", branch = "parity-1.7" } -ethcore-ipc-nano = { path = "../nano" } -ethcore-util = { path = "../../util" } -log = "0.3" - -[build-dependencies] -ethcore-ipc-codegen = { path = "../codegen" } diff --git a/ipc/tests/binary.rs b/ipc/tests/binary.rs deleted file mode 100644 index 6eb1da8522546cd68a9e23a54c3622013784b5c3..0000000000000000000000000000000000000000 --- a/ipc/tests/binary.rs +++ /dev/null @@ -1,19 +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 . - -#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues - -include!(concat!(env!("OUT_DIR"), "/binary.rs.in")); diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in deleted file mode 100644 index dfc020c454b8d69ef3ce0e412d2311b3c1cff3cf..0000000000000000000000000000000000000000 --- a/ipc/tests/binary.rs.in +++ /dev/null @@ -1,169 +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 . - - -use util::Bytes; - -#[binary] -pub enum Root { - Top, - Middle(u32, u64), -} - -#[derive(PartialEq, Debug)] -#[binary] -pub struct DoubleRoot { - pub x1: u32, - pub x2: u64, - pub x3: u32, -} - -#[derive(PartialEq, Debug)] -#[binary] -pub struct ReferenceStruct<'a> { - pub ref_data: &'a u64, -} - -#[derive(PartialEq, Debug)] -#[binary] -pub enum EnumWithStruct { - Left, - Right { how_much: u64 }, -} - -#[binary] -pub struct TwoVec { - v1: Vec, - v2: Vec, -} - -#[binary] -struct ChunkSet { - items: Vec, -} - -#[test] -fn opt_two_vec() { - let example: Option = None; - - let serialized = ::ipc::binary::serialize(&example).unwrap(); - assert_eq!(serialized, vec![0u8; 16]); -} - -#[test] -fn enum_with_struct() { - let example = EnumWithStruct::Right { how_much: 15 }; - let serialized = ::ipc::binary::serialize(&example).unwrap(); - let deserialized = ::ipc::binary::deserialize::(&serialized).unwrap(); - assert_eq!(example, deserialized); -} - -#[test] -fn chunks() { - let sample: Vec = vec! [ - 15, 0, 0, 0, 0, 0, 0, 0, 81, 6, 0, 0, 0, 0, 0, 0, - 110, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, - 112, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, - 173, 0, 0, 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, - 112, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, - 107, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, - 114, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, - 114, 0, 0, 0, 0, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, - 81, 6, 0, 0, 0, 0, 0, 0, - - 248, 108, 58, 133, 4, 168, 23, 200, 0, 130, 82, 8, 148, 182, 54, - 177, 224, 198, 163, 123, 250, 122, 157, 158, 75, 138, 30, 7, 83, 91, 141, 56, 46, 136, 2, - 197, 12, 243, 220, 69, 192, 0, 128, 28, 160, 32, 232, 123, 221, 90, 116, 93, 94, 136, 78, - 235, 200, 167, 154, 3, 175, 74, 53, 133, 32, 239, 199, 169, 46, 95, 111, 114, 204, 19, 138, - 15, 167, 160, 103, 72, 60, 241, 165, 248, 130, 213, 45, 166, 249, 102, 83, 87, 98, 153, - 68, 58, 13, 83, 193, 182, 217, 182, 9, 241, 217, 28, 162, 152, 114, 136, 248, 110, 130, 6, - 96, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, 100, 131, 212, 219, 190, 174, 5, 47, - 105, 201, 11, 11, 210, 108, 207, 242, 164, 74, 218, 19, 135, 6, 10, 36, 24, 30, 64, 0, - 128, 27, 160, 206, 145, 163, 186, 24, 122, 126, 115, 80, 203, 152, 219, 160, 243, 1, 139, - 109, 199, 115, 50, 159, 197, 95, 184, 174, 53, 150, 3, 200, 82, 138, 22, 160, 119, 226, - 202, 208, 136, 165, 174, 240, 216, 222, 27, 214, 12, 213, 250, 68, 214, 144, 120, 53, 158, - 46, 124, 105, 87, 220, 213, 192, 28, 81, 118, 6, 248, 110, 130, 6, 95, 133, 4, 168, 23, - 200, 0, 131, 1, 95, 144, 148, 100, 131, 212, 219, 190, 174, 5, 47, 105, 201, 11, 11, 210, - 108, 207, 242, 164, 74, 218, 19, 135, 6, 10, 36, 24, 30, 64, 0, 128, 27, 160, 19, 172, 66, - 208, 28, 189, 213, 239, 125, 170, 127, 147, 190, 97, 171, 194, 229, 241, 178, 176, 111, - 3, 201, 217, 9, 179, 23, 159, 159, 64, 55, 225, 160, 7, 123, 227, 76, 149, 80, 48, 130, - 122, 23, 165, 175, 24, 89, 228, 128, 25, 106, 160, 195, 82, 204, 206, 150, 83, 70, 127, - 34, 221, 169, 80, 43, 248, 110, 130, 6, 102, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, - 100, 131, 212, 219, 190, 174, 5, 47, 105, 201, 11, 11, 210, 108, 207, 242, 164, 74, 218, - 19, 135, 6, 10, 36, 24, 30, 64, 0, 128, 27, 160, 29, 6, 237, 5, 67, 42, 51, 65, 172, 133, - 9, 222, 160, 39, 202, 88, 230, 123, 232, 135, 234, 5, 244, 215, 99, 129, 242, 59, 63, 36, - 26, 253, 160, 104, 178, 37, 227, 142, 255, 186, 41, 91, 108, 206, 13, 108, 24, 73, 229, - 96, 224, 142, 230, 93, 214, 27, 60, 119, 149, 119, 56, 62, 5, 204, 179, 248, 171, 129, 136, - 133, 4, 168, 23, 200, 0, 131, 2, 77, 248, 148, 137, 32, 90, 58, 59, 42, 105, 222, 109, 191, - 127, 1, 237, 19, 178, 16, 139, 44, 67, 231, 128, 184, 68, 169, 5, 156, 187, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 105, 4, 134, 47, 167, 212, 79, 177, 44, 91, 97, 85, 184, 182, 222, 59, 231, 242, - 110, 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2, 28, 160, 98, 5, 133, 180, 19, 27, 159, 186, 76, 27, 159, 143, 186, 97, 124, 253, 123, 40, - 87, 35, 184, 115, 99, 176, 68, 85, 191, 210, 218, 132, 220, 52, 160, 48, 160, 79, 26, 47, 127, 253, - 55, 252, 196, 196, 129, 87, 131, 132, 84, 74, 166, 33, 85, 134, 25, 34, 244, 14, 1, 16, 1, 205, 34, - 30, 3, 248, 101, 3, 133, 13, 43, 184, 47, 225, 131, 1, 95, 144, 148, 202, 110, 19, 32, 65, 111, 158, - 204, 235, 91, 252, 213, 35, 215, 54, 91, 165, 67, 183, 171, 1, 128, 28, 160, 182, 194, 27, 223, 136, - 182, 189, 146, 57, 61, 173, 62, 58, 241, 42, 80, 125, 174, 84, 191, 82, 124, 228, 62, 216, 233, 116, - 117, 227, 207, 138, 56, 160, 31, 210, 242, 212, 31, 156, 129, 155, 166, 64, 102, 140, 134, 35, 176, - 137, 201, 206, 213, 199, 238, 132, 185, 145, 220, 217, 151, 80, 243, 93, 71, 211, 248, 110, 130, - 6, 101, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, 100, 131, 212, 219, 190, 174, 5, 47, 105, - 201, 11, 11, 210, 108, 207, 242, 164, 74, 218, 19, 135, 6, 10, 36, 24, 30, 64, 0, 128, 27, 160, - 86, 37, 61, 45, 13, 251, 9, 19, 188, 242, 233, 83, 77, 137, 28, 185, 141, 105, 217, 54, 182, 156, - 119, 223, 213, 112, 240, 20, 119, 167, 4, 7, 160, 95, 53, 122, 159, 6, 209, 70, 155, 122, 153, 165, - 192, 249, 223, 219, 83, 159, 40, 242, 39, 44, 132, 182, 208, 232, 77, 64, 178, 241, 233, 230, 253, - 248, 110, 130, 6, 99, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, 100, 131, 212, 219, 190, 174, - 5, 47, 105, 201, 11, 11, 210, 108, 207, 242, 164, 74, 218, 19, 135, 6, 10, 36, 24, 30, 64, 0, 128, - 27, 160, 114, 33, 104, 64, 195, 12, 156, 235, 56, 59, 210, 102, 183, 210, 216, 137, 223, 207, 134, - 63, 65, 36, 204, 121, 38, 175, 214, 106, 184, 197, 26, 173, 160, 39, 94, 238, 34, 106, 190, 22, - 225, 95, 211, 192, 249, 95, 231, 1, 111, 8, 204, 133, 35, 84, 242, 134, 75, 61, 50, 26, 150, 46, - 209, 129, 155, 248, 105, 106, 133, 5, 103, 130, 1, 225, 131, 2, 130, 119, 148, 191, 78, 215, 178, - 127, 29, 102, 101, 70, 227, 13, 116, 213, 13, 23, 61, 32, 188, 167, 84, 128, 132, 60, 207, 214, - 11, 28, 160, 3, 83, 228, 182, 32, 30, 183, 26, 157, 247, 32, 142, 60, 192, 100, 175, 106, 216, - 144, 16, 100, 165, 95, 91, 135, 138, 14, 41, 82, 251, 207, 159, 160, 74, 160, 161, 187, 63, 216, - 18, 23, 64, 172, 216, 238, 192, 134, 191, 204, 206, 236, 197, 134, 116, 130, 15, 85, 113, 173, - 130, 39, 50, 160, 49, 222, 248, 110, 130, 6, 98, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, - 100, 131, 212, 219, 190, 174, 5, 47, 105, 201, 11, 11, 210, 108, 207, 242, 164, 74, 218, 19, 135, - 6, 10, 36, 24, 30, 64, 0, 128, 28, 160, 138, 12, 20, 188, 112, 66, 91, 30, 216, 44, 24, 124, 242, - 200, 111, 179, 32, 26, 37, 221, 239, 110, 1, 84, 48, 89, 86, 61, 169, 129, 90, 21, 160, 44, 172, - 112, 11, 130, 45, 247, 188, 207, 91, 247, 195, 58, 188, 110, 127, 59, 227, 41, 151, 244, 41, 120, - 68, 185, 238, 41, 236, 195, 141, 38, 16, 248, 112, 131, 5, 238, 44, 133, 4, 168, 23, 200, 0, 131, - 1, 95, 144, 148, 5, 113, 9, 145, 204, 89, 103, 32, 126, 46, 182, 84, 47, 76, 28, 159, 77, 184, - 154, 59, 136, 1, 100, 240, 147, 154, 69, 101, 18, 128, 27, 160, 130, 0, 124, 82, 177, 112, 241, - 14, 47, 186, 67, 117, 176, 187, 147, 94, 4, 177, 218, 198, 55, 59, 245, 9, 142, 95, 88, 220, 63, - 98, 175, 49, 160, 17, 204, 228, 24, 242, 38, 166, 219, 17, 56, 103, 244, 33, 125, 223, 45, 43, - 252, 215, 163, 40, 1, 187, 152, 34, 229, 82, 180, 213, 148, 129, 32, 248, 110, 130, 6, 100, 133, - 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, 100, 131, 212, 219, 190, 174, 5, 47, 105, 201, 11, 11, - 210, 108, 207, 242, 164, 74, 218, 19, 135, 6, 10, 36, 24, 30, 64, 0, 128, 27, 160, 149, 149, 154, - 6, 198, 127, 14, 11, 164, 0, 244, 4, 74, 83, 9, 108, 164, 66, 186, 26, 109, 69, 98, 41, 149, 33, - 238, 137, 23, 175, 124, 226, 160, 39, 249, 210, 237, 52, 83, 110, 229, 138, 84, 199, 64, 19, 209, - 156, 195, 9, 50, 184, 64, 78, 67, 158, 167, 121, 220, 80, 137, 104, 240, 50, 60, 248, 112, 131, 5, - 238, 45, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, 247, 0, 201, 156, 113, 12, 158, 3, 208, 61, - 221, 91, 236, 235, 235, 195, 40, 46, 100, 73, 136, 13, 230, 68, 67, 114, 161, 197, 100, 128, 27, - 160, 123, 206, 0, 221, 2, 87, 197, 156, 109, 157, 133, 31, 26, 145, 223, 150, 235, 160, 54, 144, - 210, 146, 31, 173, 221, 128, 233, 148, 73, 82, 191, 220, 160, 57, 62, 114, 94, 77, 8, 116, 150, - 51, 112, 241, 70, 149, 157, 209, 193, 213, 109, 248, 102, 177, 27, 132, 226, 77, 141, 128, 122, - 185, 238, 188, 114, 248, 110, 130, 6, 97, 133, 4, 168, 23, 200, 0, 131, 1, 95, 144, 148, 100, - 131, 212, 219, 190, 174, 5, 47, 105, 201, 11, 11, 210, 108, 207, 242, 164, 74, 218, 19, 135, 6, - 10, 36, 24, 30, 64, 0, 128, 28, 160, 53, 222, 41, 101, 73, 44, 103, 26, 39, 165, 120, 194, 128, - 67, 109, 151, 96, 42, 193, 47, 255, 23, 27, 247, 8, 125, 200, 53, 129, 69, 103, 64, 160, 49, 12, - 64, 143, 74, 149, 161, 245, 68, 83, 89, 101, 212, 254, 81, 16, 170, 176, 33, 87, 6, 112, 34, 153, - 6, 192, 98, 126, 188, 17, 199, 155]; - - let chunks = ::ipc::binary::deserialize::(&sample).unwrap(); - let total_length = chunks.items.iter().fold(0usize, |total, item| total + item.len()); - - assert_eq!(1617, total_length); -} diff --git a/ipc/tests/build.rs b/ipc/tests/build.rs deleted file mode 100644 index 7f68b16a892bb30e110906863186831add5e00de..0000000000000000000000000000000000000000 --- a/ipc/tests/build.rs +++ /dev/null @@ -1,24 +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 . - -extern crate ethcore_ipc_codegen as codegen; - -pub fn main() { - codegen::derive_ipc("nested.rs.in").unwrap(); - codegen::derive_ipc("service.rs.in").unwrap(); - codegen::derive_ipc("with_attrs.rs.in").unwrap(); - codegen::derive_binary("binary.rs.in").unwrap(); -} diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs deleted file mode 100644 index 8cd2d2ea5c6bceb0029253db654b6d57e1c9b4c3..0000000000000000000000000000000000000000 --- a/ipc/tests/examples.rs +++ /dev/null @@ -1,173 +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 . - -#[cfg(test)] -mod tests { - - use super::super::service::*; - use super::super::binary::*; - use super::super::nested::{DBClient, DBWriter}; - use ipc::*; - use devtools::*; - use semver::Version; - use std::sync::Arc; - - #[test] - fn call_service() { - // method_num = 0, f = 10 (method Service::commit) - let mut socket = TestSocket::new_ready(vec![ - 0, 16, - 0, 0, 0, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 0, 0, 0, 0, - 10, 0, 0, 0]); - - let service = Arc::new(Service::new()); - assert_eq!(0, *service.commits.read().unwrap()); - - service.dispatch(&mut socket); - - assert_eq!(10, *service.commits.read().unwrap()); - } - - #[test] - fn call_service_client() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![10, 0, 0, 0]; - let service_client = ServiceClient::init(socket); - - let result = service_client.commit(5); - - assert_eq!( - vec![0, 16, - 0, 0, 0, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0], - service_client.socket().write().unwrap().write_buffer.clone()); - assert_eq!(10, result); - } - - #[test] - fn call_service_client_optional() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![10, 0, 0, 0]; - let service_client = ServiceClient::init(socket); - - let result = service_client.rollback(Some(5), 10); - - assert_eq!(vec![ - 0, 17, - 1, 0, 0, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 10, 0, 0, 0], service_client.socket().write().unwrap().write_buffer.clone()); - assert_eq!(10, result); - } - - #[test] - fn query_default_version() { - let ver = Service::protocol_version(); - assert_eq!(ver, Version::parse("1.0.0").unwrap()); - let ver = Service::api_version(); - assert_eq!(ver, Version::parse("1.0.0").unwrap()); - } - - #[test] - fn call_service_client_handshake() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![1]; - let service_client = ServiceClient::init(socket); - - let result = service_client.handshake(); - - assert!(result.is_ok()); - } - - #[test] - fn can_use_custom_params() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![1]; - let service_client = ServiceClient::init(socket); - - let result = service_client.push_custom(CustomData { a: 3, b: 11}); - - assert_eq!(vec![ - // message num.. - 0, 18, - // variable size length-s - 1, 0, 0, 0, 0, 0, 0, 0, - 16, 0, 0, 0, 0, 0, 0, 0, - // total length - 16, 0, 0, 0, 0, 0, 0, 0, - // items - 3, 0, 0, 0, 0, 0, 0, 0, - 11, 0, 0, 0, 0, 0, 0, 0], - service_client.socket().write().unwrap().write_buffer.clone()); - assert_eq!(true, result); - } - - #[test] - fn can_invoke_generic_service() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; - let db_client = DBClient::::init(socket); - let result = db_client.write(vec![1u8; 1]); - assert_eq!(vec![0, 16, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1], - db_client.socket().write().unwrap().write_buffer.clone()); - assert!(result.is_ok()); - } - - #[test] - fn can_handshake_generic_service() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![1]; - let db_client = DBClient::::init(socket); - - let result = db_client.handshake(); - - assert!(result.is_ok()); - } - - #[test] - fn can_serialize_dummy_structs() { - let mut socket = TestSocket::new(); - - let struct_ = DoubleRoot { x1: 0, x2: 100, x3: 100000}; - let res = ::ipc::binary::serialize_into(&struct_, &mut socket); - - assert!(res.is_ok()); - - let mut read_socket = TestSocket::new_ready(socket.write_buffer.clone()); - let new_struct: DoubleRoot = ::ipc::binary::deserialize_from(&mut read_socket).unwrap(); - - assert_eq!(struct_, new_struct); - } - - #[test] - fn can_call_void_method() { - let mut socket = TestSocket::new(); - socket.read_buffer = vec![1]; - let service_client = ServiceClient::init(socket); - - service_client.void(99); - - assert_eq!(vec![ - 0, 19, - 0, 0, 0, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, - 99, 0, 0, 0, 0, 0, 0, 0], - service_client.socket().write().unwrap().write_buffer.clone()); - } -} diff --git a/ipc/tests/nested.rs b/ipc/tests/nested.rs deleted file mode 100644 index ab3f9fc1b9cd8595fc2ba9abdc7ee9a1528792de..0000000000000000000000000000000000000000 --- a/ipc/tests/nested.rs +++ /dev/null @@ -1,18 +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 . - -#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues -include!(concat!(env!("OUT_DIR"), "/nested.rs.in")); diff --git a/ipc/tests/nested.rs.in b/ipc/tests/nested.rs.in deleted file mode 100644 index e68bec0d764f84dea6dea385fee3f13c695ce5e1..0000000000000000000000000000000000000000 --- a/ipc/tests/nested.rs.in +++ /dev/null @@ -1,56 +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 . - -use std::sync::RwLock; -use ipc::IpcConfig; - -pub struct DB { - pub writes: RwLock, - pub reads: RwLock, - pub holdings: L, -} - -pub trait DBWriter { - fn write(&self, data: Vec) -> Result<(), DBError>; - fn write_slice(&self, data: &[u8]) -> Result<(), DBError>; -} - -impl IpcConfig for DBWriter {} - -#[binary] -pub enum DBError { Write, Read } - -#[ipc] -impl DBWriter for DB { - fn write(&self, data: Vec) -> Result<(), DBError> { - let mut writes = self.writes.write().unwrap(); - *writes = *writes + data.len() as u64; - Ok(()) - } - - fn write_slice(&self, data: &[u8]) -> Result<(), DBError> { - let mut writes = self.writes.write().unwrap(); - *writes = *writes + data.len() as u64; - Ok(()) - } -} - -#[ipc] -trait DBNotify { - fn notify(&self, a: u64, b: u64) -> bool; -} - -impl IpcConfig for DBNotify { } diff --git a/ipc/tests/over_nano.rs b/ipc/tests/over_nano.rs deleted file mode 100644 index 6f45dd24552a5c7117533bef4d0f6bcbb27e7bea..0000000000000000000000000000000000000000 --- a/ipc/tests/over_nano.rs +++ /dev/null @@ -1,77 +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 . - -#[cfg(test)] -mod tests { - - use super::super::service::*; - use super::super::with_attrs::PrettyNamedClient; - use nanoipc; - use std::sync::Arc; - use std::io::Write; - use std::sync::atomic::{Ordering, AtomicBool}; - - fn dummy_write(addr: &str, buf: &[u8]) -> (::nanomsg::Socket, ::nanomsg::Endpoint) { - let mut socket = ::nanomsg::Socket::new(::nanomsg::Protocol::Pair).unwrap(); - let endpoint = socket.connect(addr).unwrap(); - socket.write(buf).unwrap(); - (socket, endpoint) - } - - - fn init_worker(addr: &str) -> nanoipc::Worker { - let mut worker = nanoipc::Worker::::new(&Arc::new(Service::new())); - worker.add_duplex(addr).unwrap(); - worker - } - - #[test] - fn can_create_client() { - let client = nanoipc::init_duplex_client::>("ipc:///tmp/parity-nano-test10.ipc"); - assert!(client.is_ok()); - } - - #[test] - fn can_create_renamed_client() { - let client = nanoipc::init_duplex_client::>("ipc:///tmp/parity-nano-test10.ipc"); - assert!(client.is_ok()); - } - - #[test] - fn can_call_handshake() { - let url = "ipc:///tmp/parity-test-nano-20.ipc"; - let worker_should_exit = Arc::new(AtomicBool::new(false)); - let worker_is_ready = Arc::new(AtomicBool::new(false)); - let c_worker_should_exit = worker_should_exit.clone(); - let c_worker_is_ready = worker_is_ready.clone(); - - ::std::thread::spawn(move || { - let mut worker = init_worker(url); - while !c_worker_should_exit.load(Ordering::Relaxed) { - worker.poll(); - c_worker_is_ready.store(true, Ordering::Relaxed); - } - }); - - while !worker_is_ready.load(Ordering::Relaxed) { } - let client = nanoipc::init_duplex_client::>(url).unwrap(); - - let hs = client.handshake(); - - worker_should_exit.store(true, Ordering::Relaxed); - assert!(hs.is_ok()); - } -} diff --git a/ipc/tests/run.rs b/ipc/tests/run.rs deleted file mode 100644 index 607e20636734843459f8d997254ca3de4e6f5fdf..0000000000000000000000000000000000000000 --- a/ipc/tests/run.rs +++ /dev/null @@ -1,32 +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 . - -#![allow(dead_code)] - -extern crate ethcore_ipc as ipc; -extern crate ethcore_devtools as devtools; -extern crate semver; -extern crate nanomsg; -extern crate ethcore_ipc_nano as nanoipc; -extern crate ethcore_util as util; -#[macro_use] extern crate log; - -pub mod service; -mod examples; -mod over_nano; -mod nested; -mod binary; -mod with_attrs; diff --git a/ipc/tests/service.rs b/ipc/tests/service.rs deleted file mode 100644 index 56b9915db660ed1d75b219e5d19e000d8c23684a..0000000000000000000000000000000000000000 --- a/ipc/tests/service.rs +++ /dev/null @@ -1,18 +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 . - -#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues -include!(concat!(env!("OUT_DIR"), "/service.rs.in")); diff --git a/ipc/tests/service.rs.in b/ipc/tests/service.rs.in deleted file mode 100644 index 68d40efc402e8f4696c19fc0cc85e0cc6e441973..0000000000000000000000000000000000000000 --- a/ipc/tests/service.rs.in +++ /dev/null @@ -1,69 +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 . - -use std::sync::RwLock; -use ipc::IpcConfig; - -pub struct Service { - pub commits: RwLock, - pub rollbacks: RwLock, -} - -#[binary] -pub struct CustomData { - pub a: u64, - pub b: u64, -} - -#[ipc] -impl Service { - fn commit(&self, f: u32) -> u32 { - let mut lock = self.commits.write().unwrap(); - *lock = *lock + f as usize; - f - } - - pub fn rollback(&self, a: Option, b: u32) -> i32 { - let a_0 = a.unwrap_or_else(|| 0); - let mut lock = self.rollbacks.write().unwrap(); - *lock = *lock + a_0 as usize - b as usize; - (a_0 - b) as i32 - } - - pub fn push_custom(&self, data: CustomData) -> bool { - let mut clock = self.commits.write().unwrap(); - let mut rlock = self.commits.write().unwrap(); - - *clock = data.a as usize; - *rlock = data.b as usize; - - true - } - - pub fn void(&self, a: u64) { - } -} - -impl Service { - pub fn new() -> Service { - Service { - commits: RwLock::new(0usize), - rollbacks: RwLock::new(0usize), - } - } -} - -impl ::ipc::IpcConfig for Service {} diff --git a/ipc/tests/with_attrs.rs b/ipc/tests/with_attrs.rs deleted file mode 100644 index 89f3575f74fb655fb84e6813461720a2ea1bb5b0..0000000000000000000000000000000000000000 --- a/ipc/tests/with_attrs.rs +++ /dev/null @@ -1,18 +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 . - -#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues -include!(concat!(env!("OUT_DIR"), "/with_attrs.rs.in")); diff --git a/ipc/tests/with_attrs.rs.in b/ipc/tests/with_attrs.rs.in deleted file mode 100644 index f18dedf9aa7ed5364f452673322cd17d53f40dc1..0000000000000000000000000000000000000000 --- a/ipc/tests/with_attrs.rs.in +++ /dev/null @@ -1,28 +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 . - -use ipc::IpcConfig; - -pub struct BadlyNamedService; - -#[ipc(client_ident="PrettyNamedClient")] -impl BadlyNamedService { - fn is_zero(&self, x: u64) -> bool { - x == 0 - } -} - -impl IpcConfig for BadlyNamedService {} diff --git a/ipfs/Cargo.toml b/ipfs/Cargo.toml index 4b438efe7d182d3e8fcf745ce8bda23738ca568f..d8e3ef2a95bd9b4be9d51ff562a501a9fb1b40fb 100644 --- a/ipfs/Cargo.toml +++ b/ipfs/Cargo.toml @@ -1,15 +1,17 @@ [package] description = "Parity IPFS-compatible API" name = "parity-ipfs-api" -version = "1.8.0" +version = "1.11.0" license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] ethcore = { path = "../ethcore" } -ethcore-util = { path = "../util" } -jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } +ethcore-bytes = { path = "../util/bytes" } +ethereum-types = "0.2" +jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" } +jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" } rlp = { path = "../util/rlp" } -mime = "0.2" cid = "0.2" -multihash = "0.6" +multihash = "0.7" +unicase = "2.0" diff --git a/ipfs/src/lib.rs b/ipfs/src/lib.rs index 104c7db19ed9d4d3b74c9646a6bb768a1733f0cf..bb7d0c3897c923fb0518199de4cabb7f1796387f 100644 --- a/ipfs/src/lib.rs +++ b/ipfs/src/lib.rs @@ -14,41 +14,39 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -#[macro_use] -extern crate mime; extern crate multihash; extern crate cid; +extern crate unicase; extern crate rlp; extern crate ethcore; -extern crate ethcore_util as util; +extern crate ethcore_bytes as bytes; +extern crate ethereum_types; +extern crate jsonrpc_core as core; extern crate jsonrpc_http_server as http; pub mod error; mod route; -use std::io::Write; -use std::sync::Arc; +use std::thread; +use std::sync::{mpsc, Arc}; use std::net::{SocketAddr, IpAddr}; + +use core::futures::future::{self, FutureResult}; +use core::futures::{self, Future}; +use ethcore::client::BlockChainClient; +use http::hyper::header::{self, Vary, ContentType}; +use http::hyper::{Method, StatusCode}; +use http::hyper::{self, server}; +use unicase::Ascii; + use error::ServerError; use route::Out; -use http::hyper::server::{Handler, Request, Response}; -use http::hyper::net::HttpStream; -use http::hyper::header::{self, Vary, ContentLength, ContentType}; -use http::hyper::{Next, Encoder, Decoder, Method, RequestUri, StatusCode}; -use ethcore::client::BlockChainClient; -pub use http::hyper::server::Listening; pub use http::{AccessControlAllowOrigin, Host, DomainsValidation}; /// Request/response handler pub struct IpfsHandler { - /// Response to send out - out: Out, - /// How many bytes from the response have been written - out_progress: usize, - /// CORS response header - cors_header: Option, /// Allowed CORS domains cors_domains: Option>, /// Hostnames allowed in the `Host` request header @@ -64,124 +62,68 @@ impl IpfsHandler { pub fn new(cors: DomainsValidation, hosts: DomainsValidation, client: Arc) -> Self { IpfsHandler { - out: Out::Bad("Invalid Request"), - out_progress: 0, - cors_header: None, cors_domains: cors.into(), allowed_hosts: hosts.into(), client: client, } } -} - -/// Implement Hyper's HTTP handler -impl Handler for IpfsHandler { - fn on_request(&mut self, req: Request) -> Next { + pub fn on_request(&self, req: hyper::Request) -> (Option, Out) { match *req.method() { Method::Get | Method::Post => {}, - _ => return Next::write() + _ => return (None, Out::Bad("Invalid Request")), } if !http::is_host_allowed(&req, &self.allowed_hosts) { - self.out = Out::Bad("Disallowed Host header"); - - return Next::write(); + return (None, Out::Bad("Disallowed Host header")); } let cors_header = http::cors_header(&req, &self.cors_domains); if cors_header == http::CorsHeader::Invalid { - self.out = Out::Bad("Disallowed Origin header"); - - return Next::write(); + return (None, Out::Bad("Disallowed Origin header")); } - self.cors_header = cors_header.into(); - let (path, query) = match *req.uri() { - RequestUri::AbsolutePath { ref path, ref query } => (path, query.as_ref().map(AsRef::as_ref)), - _ => return Next::write(), - }; - - self.out = self.route(path, query); - - Next::write() + let path = req.uri().path(); + let query = req.uri().query(); + return (cors_header.into(), self.route(path, query)); } +} - fn on_request_readable(&mut self, _decoder: &mut Decoder) -> Next { - Next::write() - } - - fn on_response(&mut self, res: &mut Response) -> Next { - use Out::*; - - match self.out { - OctetStream(ref bytes) => { - use mime::{Mime, TopLevel, SubLevel}; - - // `OctetStream` is not a valid variant, so need to construct - // the type manually. - let content_type = Mime( - TopLevel::Application, - SubLevel::Ext("octet-stream".into()), - vec![] - ); - - res.headers_mut().set(ContentLength(bytes.len() as u64)); - res.headers_mut().set(ContentType(content_type)); - +impl server::Service for IpfsHandler { + type Request = hyper::Request; + type Response = hyper::Response; + type Error = hyper::Error; + type Future = FutureResult; + + fn call(&self, request: Self::Request) -> Self::Future { + let (cors_header, out) = self.on_request(request); + + let mut res = match out { + Out::OctetStream(bytes) => { + hyper::Response::new() + .with_status(StatusCode::Ok) + .with_header(ContentType::octet_stream()) + .with_body(bytes) }, - NotFound(reason) => { - res.set_status(StatusCode::NotFound); - - res.headers_mut().set(ContentLength(reason.len() as u64)); - res.headers_mut().set(ContentType(mime!(Text/Plain))); + Out::NotFound(reason) => { + hyper::Response::new() + .with_status(StatusCode::NotFound) + .with_header(ContentType::plaintext()) + .with_body(reason) }, - Bad(reason) => { - res.set_status(StatusCode::BadRequest); - - res.headers_mut().set(ContentLength(reason.len() as u64)); - res.headers_mut().set(ContentType(mime!(Text/Plain))); + Out::Bad(reason) => { + hyper::Response::new() + .with_status(StatusCode::BadRequest) + .with_header(ContentType::plaintext()) + .with_body(reason) } - } + }; - if let Some(cors_header) = self.cors_header.take() { + if let Some(cors_header) = cors_header { res.headers_mut().set(cors_header); - res.headers_mut().set(Vary::Items(vec!["Origin".into()])); + res.headers_mut().set(Vary::Items(vec![Ascii::new("Origin".into())])); } - Next::write() - } - - fn on_response_writable(&mut self, transport: &mut Encoder) -> Next { - use Out::*; - - // Get the data to write as a byte slice - let data = match self.out { - OctetStream(ref bytes) => &bytes, - NotFound(reason) | Bad(reason) => reason.as_bytes(), - }; - - write_chunk(transport, &mut self.out_progress, data) - } -} - -/// Attempt to write entire `data` from current `progress` -fn write_chunk(transport: &mut W, progress: &mut usize, data: &[u8]) -> Next { - // Skip any bytes that have already been written - let chunk = &data[*progress..]; - - // Write an get the amount of bytes written. End the connection in case of an error. - let written = match transport.write(chunk) { - Ok(written) => written, - Err(_) => return Next::end(), - }; - - *progress += written; - - // Close the connection if the entire remaining chunk has been written - if written < chunk.len() { - Next::write() - } else { - Next::end() + future::ok(res) } } @@ -195,6 +137,19 @@ fn include_current_interface(mut hosts: Vec, interface: String, port: u16) hosts } +#[derive(Debug)] +pub struct Listening { + close: Option>, + thread: Option>, +} + +impl Drop for Listening { + fn drop(&mut self) { + self.close.take().unwrap().send(()).unwrap(); + let _ = self.thread.take().unwrap().join(); + } +} + pub fn start_server( port: u16, interface: String, @@ -208,67 +163,31 @@ pub fn start_server( let hosts: Option> = hosts.into(); let hosts: DomainsValidation<_> = hosts.map(move |hosts| include_current_interface(hosts, interface, port)).into(); - Ok( - http::hyper::Server::http(&addr)? - .handle(move |_| IpfsHandler::new(cors.clone(), hosts.clone(), client.clone())) - .map(|(listening, srv)| { - - ::std::thread::spawn(move || { - srv.run(); - }); - - listening - })? - ) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn write_chunk_to_vec() { - let mut transport = Vec::new(); - let mut progress = 0; - - let _ = write_chunk(&mut transport, &mut progress, b"foobar"); - - assert_eq!(b"foobar".to_vec(), transport); - assert_eq!(6, progress); - } - - #[test] - fn write_chunk_to_vec_part() { - let mut transport = Vec::new(); - let mut progress = 3; - - let _ = write_chunk(&mut transport, &mut progress, b"foobar"); - - assert_eq!(b"bar".to_vec(), transport); - assert_eq!(6, progress); - } - - #[test] - fn write_chunk_to_array() { - use std::io::Cursor; - - let mut buf = [0u8; 3]; - let mut progress = 0; - - { - let mut transport: Cursor<&mut [u8]> = Cursor::new(&mut buf); - let _ = write_chunk(&mut transport, &mut progress, b"foobar"); - } + let (close, shutdown_signal) = futures::sync::oneshot::channel::<()>(); + let (tx, rx) = mpsc::sync_channel(1); + let thread = thread::spawn(move || { + let send = |res| tx.send(res).expect("rx end is never dropped; qed"); + let server = match server::Http::new().bind(&addr, move || { + Ok(IpfsHandler::new(cors.clone(), hosts.clone(), client.clone())) + }) { + Ok(server) => { + send(Ok(())); + server + }, + Err(err) => { + send(Err(err)); + return; + } + }; - assert_eq!(*b"foo", buf); - assert_eq!(3, progress); + let _ = server.run_until(shutdown_signal.map_err(|_| {})); + }); - { - let mut transport: Cursor<&mut [u8]> = Cursor::new(&mut buf); - let _ = write_chunk(&mut transport, &mut progress, b"foobar"); - } + // Wait for server to start successfuly. + rx.recv().expect("tx end is never dropped; qed")?; - assert_eq!(*b"bar", buf); - assert_eq!(6, progress); - } + Ok(Listening { + close: close.into(), + thread: thread.into(), + }) } diff --git a/ipfs/src/route.rs b/ipfs/src/route.rs index c72ca53c11b52e318c440844aaabc1d08d46e0ea..2beb4ccc3716d03c30ee715148074c83cfdba46b 100644 --- a/ipfs/src/route.rs +++ b/ipfs/src/route.rs @@ -19,7 +19,8 @@ use error::{Error, Result}; use cid::{ToCid, Codec}; use multihash::Hash; -use util::{Bytes, H256}; +use ethereum_types::H256; +use bytes::Bytes; use ethcore::client::{BlockId, TransactionId}; type Reason = &'static str; diff --git a/js/.babelrc b/js/.babelrc deleted file mode 100644 index 127abf1436306a1dfabc24c81b7e8de3116348d4..0000000000000000000000000000000000000000 --- a/js/.babelrc +++ /dev/null @@ -1,34 +0,0 @@ -{ - "presets": [ - "es2017", "es2016", "es2015", - "stage-0", "react" - ], - "plugins": [ - "transform-decorators-legacy", - "transform-class-properties", - "transform-object-rest-spread", - "transform-es2015-modules-commonjs", - "transform-runtime", - "lodash", - "recharts" - ], - "retainLines": true, - "env": { - "production": { - "plugins": [ - "transform-react-remove-prop-types" - ] - }, - "development": { - "plugins": [ - [ "react-intl", { "messagesDir": "./.build/i18n/" } ], - "react-hot-loader/babel" - ] - }, - "test": { - "plugins": [ - [ "babel-plugin-webpack-alias", { "config": "webpack/test.js" } ] - ] - } - } -} diff --git a/js/.codeclimate.yml b/js/.codeclimate.yml deleted file mode 100644 index ca6414f5883de71b270a7f6de829837da85a2e4d..0000000000000000000000000000000000000000 --- a/js/.codeclimate.yml +++ /dev/null @@ -1,8 +0,0 @@ -engines: - eslint: - enabled: true - channel: "eslint-2" - -ratings: - paths: - - "**.js" diff --git a/js/.editorconfig b/js/.editorconfig deleted file mode 100644 index 3c229b5dc188afe95adfd59e57d14cc599ead1eb..0000000000000000000000000000000000000000 --- a/js/.editorconfig +++ /dev/null @@ -1,10 +0,0 @@ -root = true -[*] -indent_style=space -indent_size=2 -tab_width=2 -end_of_line=lf -charset=utf-8 -trim_trailing_whitespace=true -max_line_length=120 -insert_final_newline=true diff --git a/js/.eslintrc.json b/js/.eslintrc.json deleted file mode 100644 index ffd4f03f3bfd4baa1e9f6c9b278a37d98307d266..0000000000000000000000000000000000000000 --- a/js/.eslintrc.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "extends": ["semistandard", "standard-react"], - "parser": "babel-eslint", - "env": { - "browser": true, - "mocha": true, - "node": true - }, - "globals": { - "expect": true, - "FileReader": true - }, - "rules": { - "curly": ["error", "all"], - "jsx-quotes": ["error", "prefer-single"], - "newline-after-var": ["error", "always"], - "no-alert": "error", - "no-debugger": "error", - "no-duplicate-imports": ["error", { - "includeExports": true - }], - "object-curly-spacing": ["error", "always"], - "object-property-newline": 0, - "one-var-declaration-per-line": ["error", "always"], - "padded-blocks": ["error", { - "blocks": "never", - "classes": "never", - "switches": "never" - }], - "react/jsx-closing-bracket-location": "error", - "react/jsx-curly-spacing": ["error", "always"] - } -} diff --git a/js/.gitignore b/js/.gitignore deleted file mode 100644 index 555c4b4bbd451223f4c6402fed37641e70b8edf7..0000000000000000000000000000000000000000 --- a/js/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -node_modules -npm-debug.log -build -docs -.build -.coverage -.dist -.happypack -.npmjs -.eslintcache diff --git a/js/.istanbul.yml b/js/.istanbul.yml deleted file mode 100644 index 4535167dbff60cc20d1452fde48a0e4aac5c841b..0000000000000000000000000000000000000000 --- a/js/.istanbul.yml +++ /dev/null @@ -1,6 +0,0 @@ -instrumentation: - root: src - extensions: - - .js -reporting: - dir: ./.coverage diff --git a/js/.npmignore b/js/.npmignore deleted file mode 100644 index 5093a29b859a5e7a79413a37ad397761ec16415a..0000000000000000000000000000000000000000 --- a/js/.npmignore +++ /dev/null @@ -1 +0,0 @@ -scripts/ diff --git a/js/.npmrc b/js/.npmrc deleted file mode 100644 index 5dce03c654cc25b7ca3434856903175edb8e6ff3..0000000000000000000000000000000000000000 --- a/js/.npmrc +++ /dev/null @@ -1,2 +0,0 @@ -save-prefix='' -unsafe-perm=true diff --git a/js/.stylelintrc.json b/js/.stylelintrc.json deleted file mode 100644 index 9248483c6ed9b2b1f78d5890a7592d3090dd4343..0000000000000000000000000000000000000000 --- a/js/.stylelintrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "stylelint-config-standard", - "rules": { - "selector-pseudo-class-no-unknown": [ - true, { "ignorePseudoClasses": ["global"] } - ] - } -} diff --git a/js/Cargo.precompiled.toml b/js/Cargo.precompiled.toml deleted file mode 100644 index 87369005c7afec0718f5d5c55740b5456eb1d2d7..0000000000000000000000000000000000000000 --- a/js/Cargo.precompiled.toml +++ /dev/null @@ -1,19 +0,0 @@ -[package] -description = "Parity built-in dapps." -name = "parity-ui-precompiled" -version = "1.4.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[features] -default = ["with-syntex", "use-precompiled-js"] -use-precompiled-js = ["parity-dapps-glue/use-precompiled-js"] -with-syntex = ["parity-dapps-glue/with-syntex"] - -[build-dependencies] -parity-dapps-glue = "1.7" - -[dependencies] -parity-dapps-glue = "1.7" - diff --git a/js/Cargo.toml b/js/Cargo.toml deleted file mode 100644 index cf7ba957b865a836e8839397b66c0b6b21cff91e..0000000000000000000000000000000000000000 --- a/js/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -description = "Parity built-in dapps." -name = "parity-ui-dev" -version = "1.8.0" -license = "GPL-3.0" -authors = ["Parity Technologies "] -build = "build.rs" - -[features] -default = ["with-syntex"] -with-syntex = ["parity-dapps-glue/with-syntex"] - -[build-dependencies] -parity-dapps-glue = "1.7" - -[dependencies] -parity-dapps-glue = "1.7" - diff --git a/js/LICENSE b/js/LICENSE deleted file mode 100644 index 9cecc1d4669ee8af2ca727a5d8cde10cd8b2d7cc..0000000000000000000000000000000000000000 --- a/js/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {one line to give the program's name and a brief idea of what it does.} - Copyright (C) {year} {name of author} - - This program 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. - - This program 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 this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - {project} Copyright (C) {year} {fullname} - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/js/README.md b/js/README.md deleted file mode 100644 index 5ed26e0cfd3a385cb22e1c761c64e888cf179e2b..0000000000000000000000000000000000000000 --- a/js/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# parity.js - -JavaScript APIs and UIs for Parity. - -## development - -0. Install [Node](https://nodejs.org/) if not already available -0. Change to the `js` directory inside `parity/` -0. Install the npm modules via `npm install` -0. Parity should be run with `parity --ui-no-validation [...options]` (where `options` can be `--chain testnet`) -0. Start the development environment via `npm start` -0. Connect to the [UI](http://localhost:3000) diff --git a/js/assets/fonts/Roboto/LICENSE.txt b/js/assets/fonts/Roboto/LICENSE.txt deleted file mode 100755 index 75b52484ea471f882c29e02693b4f02dba175b5e..0000000000000000000000000000000000000000 --- a/js/assets/fonts/Roboto/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/js/assets/fonts/Roboto/font.css b/js/assets/fonts/Roboto/font.css deleted file mode 100644 index 75226e62185177b5dd8fa2102aeb36da94b69269..0000000000000000000000000000000000000000 --- a/js/assets/fonts/Roboto/font.css +++ /dev/null @@ -1,56 +0,0 @@ -/* cyrillic-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/0eC6fl06luXEYWpBSJvXCIX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2'); - unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; -} -/* cyrillic */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/Fl4y0QdOxyyTHEGMXX8kcYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/-L14Jk06m6pUHB-5mXQQnYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2'); - unicode-range: U+1F00-1FFF; -} -/* greek */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/I3S1wsgSg9YCurV6PUkTOYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/NYDWBdD4gIq26G5XYbHsFIX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2'); - unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/Pru33qjShpZSmG3z6VYwnYX0hVgzZQUfRDuZrPvH3D8.woff2) format('woff2'); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(./v15/Hgo13k-tfSpn0qi1SFdUfZBw1xU1rKptJj_0jans920.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; -} diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Black.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Black.ttf deleted file mode 100755 index fbde625d403cc1fe3be06e15ae90c448c013eee5..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Black.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-BlackItalic.ttf b/js/assets/fonts/Roboto/ttf/Roboto-BlackItalic.ttf deleted file mode 100755 index 60f7782a2e4aba9bbc96d7634799eaa05512c927..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-BlackItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Bold.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Bold.ttf deleted file mode 100755 index a355c27cde02b13da43c30ae060c5fb164b36b76..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Bold.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-BoldItalic.ttf b/js/assets/fonts/Roboto/ttf/Roboto-BoldItalic.ttf deleted file mode 100755 index 3c9a7a37361b6ae0571b33f09b6b55367e188cfe..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-BoldItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Italic.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Italic.ttf deleted file mode 100755 index ff6046d5bfa7cd4498ad4a549d2d9028f6c73372..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Italic.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Light.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Light.ttf deleted file mode 100755 index 94c6bcc67e09602f6d90ac10f449b5c05c2f7021..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Light.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-LightItalic.ttf b/js/assets/fonts/Roboto/ttf/Roboto-LightItalic.ttf deleted file mode 100755 index 04cc002302024c4e032d32319f0d40a32b54aada..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-LightItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Medium.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Medium.ttf deleted file mode 100755 index 39c63d7461796094c0b8889ee8fe2706d344a99a..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Medium.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-MediumItalic.ttf b/js/assets/fonts/Roboto/ttf/Roboto-MediumItalic.ttf deleted file mode 100755 index dc743f0a66cf3741e90f712aba22a91197b7e59c..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-MediumItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Regular.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Regular.ttf deleted file mode 100755 index 8c082c8de090865264d37594e396c4d6c0099fe4..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Regular.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-Thin.ttf b/js/assets/fonts/Roboto/ttf/Roboto-Thin.ttf deleted file mode 100755 index d69555029c3e184189c6cf9961c9cb21205bda96..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-Thin.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/ttf/Roboto-ThinItalic.ttf b/js/assets/fonts/Roboto/ttf/Roboto-ThinItalic.ttf deleted file mode 100755 index 07172ff666ad2d590e29324165b6c7b8e2be72ee..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/ttf/Roboto-ThinItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/-L14Jk06m6pUHB-5mXQQnYX0hVgzZQUfRDuZrPvH3D8.woff2 b/js/assets/fonts/Roboto/v15/-L14Jk06m6pUHB-5mXQQnYX0hVgzZQUfRDuZrPvH3D8.woff2 deleted file mode 100644 index 58fd4bcd24711c74b7c0ecf045cef580471f02f1..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/-L14Jk06m6pUHB-5mXQQnYX0hVgzZQUfRDuZrPvH3D8.woff2 and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/0eC6fl06luXEYWpBSJvXCIX0hVgzZQUfRDuZrPvH3D8.woff2 b/js/assets/fonts/Roboto/v15/0eC6fl06luXEYWpBSJvXCIX0hVgzZQUfRDuZrPvH3D8.woff2 deleted file mode 100644 index eacda321c795555dcaf46c05373bff8ddd7b11a8..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/0eC6fl06luXEYWpBSJvXCIX0hVgzZQUfRDuZrPvH3D8.woff2 and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/Fl4y0QdOxyyTHEGMXX8kcYX0hVgzZQUfRDuZrPvH3D8.woff2 b/js/assets/fonts/Roboto/v15/Fl4y0QdOxyyTHEGMXX8kcYX0hVgzZQUfRDuZrPvH3D8.woff2 deleted file mode 100644 index cc16b36c5848dbd0175f6fa5b4d57966f9b61a39..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/Fl4y0QdOxyyTHEGMXX8kcYX0hVgzZQUfRDuZrPvH3D8.woff2 and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/Hgo13k-tfSpn0qi1SFdUfZBw1xU1rKptJj_0jans920.woff2 b/js/assets/fonts/Roboto/v15/Hgo13k-tfSpn0qi1SFdUfZBw1xU1rKptJj_0jans920.woff2 deleted file mode 100644 index 4411cbc8754cf7ec78501ba711efabe15b936675..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/Hgo13k-tfSpn0qi1SFdUfZBw1xU1rKptJj_0jans920.woff2 and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/I3S1wsgSg9YCurV6PUkTOYX0hVgzZQUfRDuZrPvH3D8.woff2 b/js/assets/fonts/Roboto/v15/I3S1wsgSg9YCurV6PUkTOYX0hVgzZQUfRDuZrPvH3D8.woff2 deleted file mode 100644 index 0028bd81e9db90411095790d72c9568f1778bd66..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/I3S1wsgSg9YCurV6PUkTOYX0hVgzZQUfRDuZrPvH3D8.woff2 and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/NYDWBdD4gIq26G5XYbHsFIX0hVgzZQUfRDuZrPvH3D8.woff2 b/js/assets/fonts/Roboto/v15/NYDWBdD4gIq26G5XYbHsFIX0hVgzZQUfRDuZrPvH3D8.woff2 deleted file mode 100644 index a5cefc9c67e2f5e20dccc3408988f16cbd6336ea..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/NYDWBdD4gIq26G5XYbHsFIX0hVgzZQUfRDuZrPvH3D8.woff2 and /dev/null differ diff --git a/js/assets/fonts/Roboto/v15/Pru33qjShpZSmG3z6VYwnYX0hVgzZQUfRDuZrPvH3D8.woff2 b/js/assets/fonts/Roboto/v15/Pru33qjShpZSmG3z6VYwnYX0hVgzZQUfRDuZrPvH3D8.woff2 deleted file mode 100644 index feec9f1e6a187f63cbb826958bbc01c050b5b9c8..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/Roboto/v15/Pru33qjShpZSmG3z6VYwnYX0hVgzZQUfRDuZrPvH3D8.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/LICENSE.txt b/js/assets/fonts/RobotoMono/LICENSE.txt deleted file mode 100755 index 75b52484ea471f882c29e02693b4f02dba175b5e..0000000000000000000000000000000000000000 --- a/js/assets/fonts/RobotoMono/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/js/assets/fonts/RobotoMono/font.css b/js/assets/fonts/RobotoMono/font.css deleted file mode 100644 index 6a86af729e4fb38974843b3c1309d9dd3eabda49..0000000000000000000000000000000000000000 --- a/js/assets/fonts/RobotoMono/font.css +++ /dev/null @@ -1,56 +0,0 @@ -/* cyrillic-ext */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59Fz0ExlR2MysFCBK8OirNw2kM.woff2) format('woff2'); - unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; -} -/* cyrillic */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59Fz2dsm03krrxlabhmVQFB99s.woff2) format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek-ext */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59FzyJ0caWjaSBdV-xZbEgst_k.woff2) format('woff2'); - unicode-range: U+1F00-1FFF; -} -/* greek */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59Fz2MSHb9EAJwuSzGfuRChQzQ.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59Fz-pRBTtN4E2_qSPBnw6AgMc.woff2) format('woff2'); - unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59Fz9Dnm4qiMZlH5rhYv_7LI2Y.woff2) format('woff2'); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Roboto Mono'; - font-style: normal; - font-weight: 300; - src: local('Roboto Mono Light'), local('RobotoMono-Light'), url(./v4/N4duVc9C58uwPiY8_59Fz9TIkQYohD4BpHvJ3NvbHoA.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; -} diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Bold.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-Bold.ttf deleted file mode 100755 index 07ef607d50c2e0b48d251910fc75c7eb83a41b34..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Bold.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-BoldItalic.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-BoldItalic.ttf deleted file mode 100755 index 1cca0bf456a3b6b42b3c92e81b4f4ebfa7d41f95..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-BoldItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Italic.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-Italic.ttf deleted file mode 100755 index ef92c372cf47ec6ac92644bdc52ef131867037b3..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Italic.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Light.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-Light.ttf deleted file mode 100755 index 63229b2805b102f626c06e29752fe28e1ce9471f..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Light.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-LightItalic.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-LightItalic.ttf deleted file mode 100755 index f25bed56adba942784c953710324ef0bba7577fa..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-LightItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Medium.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-Medium.ttf deleted file mode 100755 index 88ff0c15a56bd3275b7938d7e7bedc56f71ccb8f..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Medium.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-MediumItalic.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-MediumItalic.ttf deleted file mode 100755 index 307efad8fcaa533cdc695b8f1aae696ba662431e..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-MediumItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Regular.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-Regular.ttf deleted file mode 100755 index b158a334eb372a9ab2ecd4f2566e60d561e71a9f..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Regular.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Thin.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-Thin.ttf deleted file mode 100755 index 309484d3239a307904ad64f95d87c38fb6d24b7b..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-Thin.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/ttf/RobotoMono-ThinItalic.ttf b/js/assets/fonts/RobotoMono/ttf/RobotoMono-ThinItalic.ttf deleted file mode 100755 index e1bb9121ec6568d6b8772d121eafeaa5da0db928..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/ttf/RobotoMono-ThinItalic.ttf and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz-pRBTtN4E2_qSPBnw6AgMc.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz-pRBTtN4E2_qSPBnw6AgMc.woff2 deleted file mode 100644 index f1fdb93524e7a84934cc4f6d4b731006059705f1..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz-pRBTtN4E2_qSPBnw6AgMc.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz0ExlR2MysFCBK8OirNw2kM.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz0ExlR2MysFCBK8OirNw2kM.woff2 deleted file mode 100644 index 501a4d77720aec360723de2ad0292c49eb10caf9..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz0ExlR2MysFCBK8OirNw2kM.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz2MSHb9EAJwuSzGfuRChQzQ.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz2MSHb9EAJwuSzGfuRChQzQ.woff2 deleted file mode 100644 index 54484b1e3edcbac1fc80f13cfa4a03cb29c84bf1..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz2MSHb9EAJwuSzGfuRChQzQ.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz2dsm03krrxlabhmVQFB99s.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz2dsm03krrxlabhmVQFB99s.woff2 deleted file mode 100644 index c3f35ca2911c1db7e8afb85f28e23f7db0ae986c..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz2dsm03krrxlabhmVQFB99s.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz9Dnm4qiMZlH5rhYv_7LI2Y.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz9Dnm4qiMZlH5rhYv_7LI2Y.woff2 deleted file mode 100644 index 72a43ab3c0332b0539f230c402090fdbab079956..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz9Dnm4qiMZlH5rhYv_7LI2Y.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz9TIkQYohD4BpHvJ3NvbHoA.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz9TIkQYohD4BpHvJ3NvbHoA.woff2 deleted file mode 100644 index 62b3a15f698a5e966f5f6b4a5b6d5081e340c654..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59Fz9TIkQYohD4BpHvJ3NvbHoA.woff2 and /dev/null differ diff --git a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59FzyJ0caWjaSBdV-xZbEgst_k.woff2 b/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59FzyJ0caWjaSBdV-xZbEgst_k.woff2 deleted file mode 100644 index 2d4fda538a22e1046718d4d158e7512eae086f69..0000000000000000000000000000000000000000 Binary files a/js/assets/fonts/RobotoMono/v4/N4duVc9C58uwPiY8_59FzyJ0caWjaSBdV-xZbEgst_k.woff2 and /dev/null differ diff --git a/js/assets/images/certifications/unknown.svg b/js/assets/images/certifications/unknown.svg deleted file mode 100644 index 1554bcc258119e20eba68341d5b81e26867aff93..0000000000000000000000000000000000000000 --- a/js/assets/images/certifications/unknown.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/js/assets/images/contracts/ethereum-black-64x64.png b/js/assets/images/contracts/ethereum-black-64x64.png deleted file mode 100644 index 8e80e4ff134759b9cfbbc6f535791b93aac64a49..0000000000000000000000000000000000000000 Binary files a/js/assets/images/contracts/ethereum-black-64x64.png and /dev/null differ diff --git a/js/assets/images/contracts/ethereum-black.png b/js/assets/images/contracts/ethereum-black.png deleted file mode 100644 index d7bdc4c904012b2224306216f1d36c78eb29122a..0000000000000000000000000000000000000000 Binary files a/js/assets/images/contracts/ethereum-black.png and /dev/null differ diff --git a/js/assets/images/contracts/ethereum-white.png b/js/assets/images/contracts/ethereum-white.png deleted file mode 100644 index 0691d09aeaffaa78db1a267f3527a79072d71b73..0000000000000000000000000000000000000000 Binary files a/js/assets/images/contracts/ethereum-white.png and /dev/null differ diff --git a/js/assets/images/contracts/unknown-64x64.png b/js/assets/images/contracts/unknown-64x64.png deleted file mode 100644 index c2b39a80a372151cb98f216568917953a2b76727..0000000000000000000000000000000000000000 Binary files a/js/assets/images/contracts/unknown-64x64.png and /dev/null differ diff --git a/js/assets/images/contracts/unknown.png b/js/assets/images/contracts/unknown.png deleted file mode 100644 index 204ffa486372bfed2b04aca09f3f5eaa63115845..0000000000000000000000000000000000000000 Binary files a/js/assets/images/contracts/unknown.png and /dev/null differ diff --git a/js/assets/images/dapps/blocks-350.jpg b/js/assets/images/dapps/blocks-350.jpg deleted file mode 100644 index 524f9267c50777c162f3f2081933716329926907..0000000000000000000000000000000000000000 Binary files a/js/assets/images/dapps/blocks-350.jpg and /dev/null differ diff --git a/js/assets/images/dapps/close.svg b/js/assets/images/dapps/close.svg deleted file mode 100644 index d46acd872988a41bca4206aafb783e42d3d41d55..0000000000000000000000000000000000000000 --- a/js/assets/images/dapps/close.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/js/assets/images/dapps/plus.svg b/js/assets/images/dapps/plus.svg deleted file mode 100644 index 0fce86130ad3291c4930981069081102ffdd6657..0000000000000000000000000000000000000000 --- a/js/assets/images/dapps/plus.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/js/assets/images/dapps/signature.png b/js/assets/images/dapps/signature.png deleted file mode 100644 index 36b341a036642764e48a0a958077b2440f370cbe..0000000000000000000000000000000000000000 Binary files a/js/assets/images/dapps/signature.png and /dev/null differ diff --git a/js/assets/images/parity-logo-black-no-text.ico b/js/assets/images/parity-logo-black-no-text.ico deleted file mode 100644 index 8edfa3e6a9d902ee4b9f9ff54659a61a1b52a55c..0000000000000000000000000000000000000000 Binary files a/js/assets/images/parity-logo-black-no-text.ico and /dev/null differ diff --git a/js/assets/images/parity-logo-black-no-text.png b/js/assets/images/parity-logo-black-no-text.png deleted file mode 100644 index b2aea789e82472d574be6e74a9f3bb9dc92004df..0000000000000000000000000000000000000000 Binary files a/js/assets/images/parity-logo-black-no-text.png and /dev/null differ diff --git a/js/assets/images/parity-logo-black-no-text.svg b/js/assets/images/parity-logo-black-no-text.svg deleted file mode 100644 index a4f104838702e3a6c431cf3113f866101ddecafc..0000000000000000000000000000000000000000 --- a/js/assets/images/parity-logo-black-no-text.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/js/assets/images/parity-logo-black.svg b/js/assets/images/parity-logo-black.svg deleted file mode 100644 index f2b2fa72633bd2de0d810e99bdc2365ebcdf4882..0000000000000000000000000000000000000000 --- a/js/assets/images/parity-logo-black.svg +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/js/assets/images/parity-logo-white-no-text.svg b/js/assets/images/parity-logo-white-no-text.svg deleted file mode 100644 index 213ab1db441d60a7bb04e4a84fef845c97020eec..0000000000000000000000000000000000000000 --- a/js/assets/images/parity-logo-white-no-text.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/js/assets/images/parity-logo-white.svg b/js/assets/images/parity-logo-white.svg deleted file mode 100644 index 7360ef6a6d7c36ded131a370c71fd146226a5a84..0000000000000000000000000000000000000000 --- a/js/assets/images/parity-logo-white.svg +++ /dev/null @@ -1,100 +0,0 @@ - - - -image/svg+xml diff --git a/js/assets/images/paritybar.png b/js/assets/images/paritybar.png deleted file mode 100644 index f0b0e1457409c386690e52ab1091393de19aedc4..0000000000000000000000000000000000000000 Binary files a/js/assets/images/paritybar.png and /dev/null differ diff --git a/js/assets/images/shapeshift-btn.png b/js/assets/images/shapeshift-btn.png deleted file mode 100644 index 1650ecf375660f706f59ae7bf2f4455dedeb8aae..0000000000000000000000000000000000000000 Binary files a/js/assets/images/shapeshift-btn.png and /dev/null differ diff --git a/js/assets/images/shapeshift-logo.png b/js/assets/images/shapeshift-logo.png deleted file mode 100644 index 586a01ef13a7ce480d46b88fe6dc457d3083c966..0000000000000000000000000000000000000000 Binary files a/js/assets/images/shapeshift-logo.png and /dev/null differ diff --git a/js/build.rs b/js/build.rs deleted file mode 100644 index a9a5ba8a6924ba4e3432829512fc1831de0ddfcf..0000000000000000000000000000000000000000 --- a/js/build.rs +++ /dev/null @@ -1,22 +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 . - -extern crate parity_dapps_glue; - -fn main() { - parity_dapps_glue::js::build(env!("CARGO_MANIFEST_DIR"), "build"); - parity_dapps_glue::generate(); -} diff --git a/js/npm/etherscan/README.md b/js/npm/etherscan/README.md deleted file mode 100644 index 730cb7e1d0e94744eeca3e8d33750e0a74f3d5e3..0000000000000000000000000000000000000000 --- a/js/npm/etherscan/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# @parity/etherscan - -A thin, lightweight promise wrapper for the api.etherscan.io/apis service, exposing a common endpoint for use in JavaScript applications. - -[https://github.com/paritytech/parity/tree/master/js/src/3rdparty/etherscan](https://github.com/paritytech/parity/tree/master/js/src/3rdparty/etherscan) - -## usage - -installation - - -``` -npm install --save @parity/etherscan -``` - -Usage - - -``` -const etherscan = require('@parity/etherscan'); - -// api calls goes here -``` - -## api - -account (exposed on etherscan.account) - - -- `balance(address)` -- `balances(addresses)` (array or addresses) -- `transactions(address, page)` (page offset starts at 0, returns 25) - -stats (exposed on etherscan.stats) - - -- `price()` -- `supply()` diff --git a/js/npm/etherscan/package.json b/js/npm/etherscan/package.json deleted file mode 100644 index 1aed97171dd9d4816a0378e641887ef176c7ffc3..0000000000000000000000000000000000000000 --- a/js/npm/etherscan/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "@parity/etherscan", - "description": "The Parity Promise-based library for interfacing with Etherscan over HTTP", - "version": "0.0.0", - "main": "library.js", - "author": "Parity Team ", - "maintainers": [ - "Jaco Greeff" - ], - "contributors": [], - "license": "GPL-3.0", - "repository": { - "type": "git", - "url": "git+https://github.com/paritytech/parity.git" - }, - "keywords": [ - "Ethereum", - "ABI", - "API", - "RPC", - "Parity", - "Promise" - ], - "scripts": { - }, - "devDependencies": { - "chai": "3.5.0", - "mocha": "3.2.0" - }, - "dependencies": { - "node-fetch": "~1.6.3" - } -} diff --git a/js/npm/jsonrpc/README.md b/js/npm/jsonrpc/README.md deleted file mode 100644 index e9678864b4d9f9ad13bb7eee8a0174e4f5c13919..0000000000000000000000000000000000000000 --- a/js/npm/jsonrpc/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# @parity/jsonrpc - -JSON and JS interface defintions for RPC calls. - -[https://github.com/paritytech/parity/tree/master/js/src/jsonrpc](https://github.com/paritytech/parity/tree/master/js/src/jsonrpc) diff --git a/js/npm/jsonrpc/package.json b/js/npm/jsonrpc/package.json deleted file mode 100644 index 90ebe1577b7e3b2b4352b463e36096936298ae16..0000000000000000000000000000000000000000 --- a/js/npm/jsonrpc/package.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "@parity/jsonrpc", - "description": "JSON and JS interface defintions for RPC", - "version": "0.0.0", - "main": "library.js", - "author": "Parity Team ", - "maintainers": [ - "Jaco Greeff" - ], - "contributors": [], - "license": "GPL-3.0", - "repository": { - "type": "git", - "url": "git+https://github.com/paritytech/parity.git" - }, - "keywords": [ - "Ethereum", - "ABI", - "API", - "RPC", - "Parity" - ], - "scripts": { - }, - "devDependencies": { - }, - "dependencies": { - } -} diff --git a/js/npm/parity/README.md b/js/npm/parity/README.md deleted file mode 100644 index 2c5396e2d6b9b54ef981f56917b5e15a1fc3cf69..0000000000000000000000000000000000000000 --- a/js/npm/parity/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# @parity/parity.js - -Parity.js is a thin, fast, Promise-based wrapper around the Ethereum APIs. - -[https://github.com/paritytech/parity/tree/master/js/src/api](https://github.com/paritytech/parity/tree/master/js/src/api) - -## installation - -Install the package with `npm install --save @parity/parity.js` - -## usage - -### initialisation - -```javascript -// import the actual Api class -import { Api } from '@parity/parity.js'; - -// do the setup -const transport = new Api.Transport.Http('http://localhost:8545'); -const api = new Api(transport); -``` - -### making calls - -perform a call - -```javascript -api.eth - .coinbase() - .then((coinbase) => { - console.log(`The coinbase is ${coinbase}`); - }); -``` - -multiple promises - -```javascript -Promise - .all([ - api.eth.coinbase(), - api.net.listening() - ]) - .then(([coinbase, listening]) => { - // do stuff here - }); -``` - -chaining promises - -```javascript -api.eth - .newFilter({...}) - .then((filterId) => api.eth.getFilterChanges(filterId)) - .then((changes) => { - console.log(changes); - }); -``` - -### contracts - -attach contract - -```javascript -const abi = [{ name: 'callMe', inputs: [{ type: 'bool', ...}, { type: 'string', ...}]}, ...abi...]; -const address = '0x123456...9abc'; -const contract = new api.newContract(abi, address); -``` - -find & call a function - -```javascript -contract.instance - .callMe - .call({ gas: 21000 }, [true, 'someString']) // or estimateGas or postTransaction - .then((result) => { - console.log(`the result was ${result}`); - }); -``` - -## apis - -APIs implement the calls as exposed in the [Ethcore JSON Ethereum RPC](https://github.com/paritytech/ethereum-rpc-json/) definitions. Mapping follows the naming conventions of the originals, i.e. `eth_call` becomes `eth.call`, `personal_accounts` becomes `personal.accounts`, etc. diff --git a/js/npm/parity/package.json b/js/npm/parity/package.json deleted file mode 100644 index c43da096d3e6ad36f8a99e585cffa51a83789c91..0000000000000000000000000000000000000000 --- a/js/npm/parity/package.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "name": "@parity/parity.js", - "description": "The Parity Promise-based API & ABI library for interfacing with Ethereum over RPC", - "version": "0.0.0", - "main": "library.js", - "author": "Parity Team ", - "maintainers": [ - "Jaco Greeff" - ], - "contributors": [], - "license": "GPL-3.0", - "repository": { - "type": "git", - "url": "git+https://github.com/paritytech/parity.git" - }, - "keywords": [ - "Ethereum", - "ABI", - "API", - "RPC", - "Parity", - "Promise" - ], - "scripts": { - }, - "devDependencies": { - }, - "dependencies": { - "bignumber.js": "~2.3.0", - "js-sha3": "~0.5.2", - "node-fetch": "~1.6.3" - } -} diff --git a/js/npm/parity/test/smoke.spec.js b/js/npm/parity/test/smoke.spec.js deleted file mode 100644 index fb1ae0d4d52a29538f50a64238d78e159aac5ffe..0000000000000000000000000000000000000000 --- a/js/npm/parity/test/smoke.spec.js +++ /dev/null @@ -1,26 +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 . - -const parity = require('../'); - -describe('load the Parity library', function () { - it('should no throw any error', () => { - expect(parity).to.be.ok; - - expect(parity.Api).to.be.ok; - expect(parity.Abi).to.be.ok; - }); -}); diff --git a/js/npm/shapeshift/README.md b/js/npm/shapeshift/README.md deleted file mode 100644 index 0f9a190abc13f2c6f7431f8de22eaa6c21590b18..0000000000000000000000000000000000000000 --- a/js/npm/shapeshift/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# @parity/shapeshift - -A thin ES6 promise wrapper around the shapeshift.io APIs as documented at https://shapeshift.io/api - -[https://github.com/paritytech/parity/tree/master/js/src/3rdparty/shapeshift](https://github.com/paritytech/parity/tree/master/js/src/3rdparty/shapeshift) - -## usage - -installation - - -``` -npm install --save @parity/shapeshift -``` - -Usage - - -``` -const APIKEY = 'private affiliate key or undefined'; -const shapeshift = require('@parity/shapeshift')(APIKEY); - -// api calls goes here -``` - -## api - -queries - - -- `getCoins()` [https://shapeshift.io/api#api-104](https://shapeshift.io/api#api-104) -- `getMarketInfo(pair)` [https://shapeshift.io/api#api-103](https://shapeshift.io/api#api-103) -- `getStatus(depositAddress)` [https://shapeshift.io/api#api-5](https://shapeshift.io/api#api-5) - -transactions - - -- `shift(toAddress, returnAddress, pair)` [https://shapeshift.io/api#api-7](https://shapeshift.io/api#api-7) diff --git a/js/npm/shapeshift/package.json b/js/npm/shapeshift/package.json deleted file mode 100644 index 1aa2d38f315ed4ccc46fba82422e232bb6bf0d8a..0000000000000000000000000000000000000000 --- a/js/npm/shapeshift/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@parity/shapeshift", - "description": "The Parity Promise-based library for interfacing with ShapeShift over HTTP", - "version": "0.0.0", - "main": "library.js", - "author": "Parity Team ", - "maintainers": [ - "Jaco Greeff" - ], - "contributors": [], - "license": "GPL-3.0", - "repository": { - "type": "git", - "url": "git+https://github.com/paritytech/parity.git" - }, - "keywords": [ - "Ethereum", - "ABI", - "API", - "RPC", - "Parity", - "Promise" - ], - "scripts": { - }, - "devDependencies": { - }, - "dependencies": { - "node-fetch": "~1.6.3" - } -} diff --git a/js/npm/test/mocha.config.js b/js/npm/test/mocha.config.js deleted file mode 100644 index fc21631b0a811e8c150e1168cea160b00380a61b..0000000000000000000000000000000000000000 --- a/js/npm/test/mocha.config.js +++ /dev/null @@ -1,29 +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 . - -const chai = require('chai'); -// const chaiAsPromised from 'chai-as-promised'; -// const chaiEnzyme from 'chai-enzyme'; -// const sinonChai from 'sinon-chai'; - -// chai.use(chaiAsPromised); -// chai.use(chaiEnzyme()); -// chai.use(sinonChai); - -// expose expect to global so we won't have to manually import & define it in every test -global.expect = chai.expect; - -module.exports = {}; diff --git a/js/npm/test/mocha.opts b/js/npm/test/mocha.opts deleted file mode 100644 index 0ed8269b4ff3676c83c4819eb7046804ef55804a..0000000000000000000000000000000000000000 --- a/js/npm/test/mocha.opts +++ /dev/null @@ -1 +0,0 @@ --r ./test/mocha.config diff --git a/js/package-lock.json b/js/package-lock.json deleted file mode 100644 index 707e5a67dac2e454283cc33abbd075ea17d39968..0000000000000000000000000000000000000000 --- a/js/package-lock.json +++ /dev/null @@ -1,13048 +0,0 @@ -{ - "name": "parity.js", - "version": "1.8.17", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@parity/wordlist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@parity/wordlist/-/wordlist-1.0.1.tgz", - "integrity": "sha1-wn5A4as2OKCe1TtKLoHVMbXrWjE=" - }, - "abab": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.3.tgz", - "integrity": "sha1-uB3l9ydOxOdW15fNg08wNkJyTl0=", - "dev": true - }, - "abbrev": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", - "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" - }, - "accepts": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "dev": true, - "requires": { - "mime-types": "2.1.16", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", - "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", - "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", - "dev": true, - "requires": { - "acorn": "4.0.13" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, - "acorn-globals": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", - "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", - "dev": true, - "requires": { - "acorn": "4.0.13" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "3.3.0" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz", - "integrity": "sha1-R8aNaehvXZUxA7AHSpQw3GPaXjk=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "json-schema-traverse": "0.3.1", - "json-stable-stringify": "1.0.1" - }, - "dependencies": { - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - } - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" - } - }, - "alphanum-sort": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", - "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", - "dev": true - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" - }, - "ansi-escapes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", - "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=" - }, - "ansi-html": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", - "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "any-promise": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-0.1.0.tgz", - "integrity": "sha1-gwtoCqflbzNFHUsEnzvYBESY7ic=", - "dev": true - }, - "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", - "dev": true, - "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" - } - }, - "append-transform": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", - "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", - "dev": true, - "requires": { - "default-require-extensions": "1.0.0" - } - }, - "aproba": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.1.2.tgz", - "integrity": "sha512-ZpYajIfO0j2cOFTO955KUMIKNmj6zhX8kVztMAxFsDaMwz+9Z9SV0uou2pC9HJqcfpffOsjnbrDMvkNy+9RXPw==" - }, - "archive-type": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", - "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", - "requires": { - "file-type": "3.9.0" - } - }, - "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.3" - } - }, - "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true, - "requires": { - "sprintf-js": "1.0.3" - } - }, - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "requires": { - "arr-flatten": "1.1.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" - }, - "array-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", - "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "1.0.3" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" - }, - "array.prototype.find": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", - "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.7.0" - } - }, - "arraybuffer-loader": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/arraybuffer-loader/-/arraybuffer-loader-0.2.2.tgz", - "integrity": "sha1-jnKU0VGqyO1wqC53Pq0FWQ23Dik=", - "requires": { - "loader-utils": "0.2.17" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" - }, - "asn1.js": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz", - "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", - "dev": true, - "requires": { - "util": "0.10.3" - } - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" - }, - "assertion-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", - "dev": true - }, - "ast-types": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", - "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-each-series": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", - "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "attr-accept": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-1.1.0.tgz", - "integrity": "sha1-tc01In8WOTWo8d4Q7T66FpQfa+Y=" - }, - "autoprefixer": { - "version": "6.7.7", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", - "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000708", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" - }, - "babel-cli": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.23.0.tgz", - "integrity": "sha1-Uv+UaisPZGRcNee9XuomeqCUjA8=", - "dev": true, - "requires": { - "babel-core": "6.23.1", - "babel-polyfill": "6.23.0", - "babel-register": "6.23.0", - "babel-runtime": "6.23.0", - "chokidar": "1.7.0", - "commander": "2.8.1", - "convert-source-map": "1.5.0", - "fs-readdir-recursive": "1.0.0", - "glob": "7.1.2", - "lodash": "4.17.2", - "output-file-sync": "1.1.2", - "path-is-absolute": "1.0.1", - "slash": "1.0.0", - "source-map": "0.5.6", - "v8flags": "2.1.1" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "babel-code-frame": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", - "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", - "requires": { - "chalk": "1.1.3", - "esutils": "2.0.2", - "js-tokens": "3.0.2" - } - }, - "babel-core": { - "version": "6.23.1", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.23.1.tgz", - "integrity": "sha1-wUPLYhuy9iFxDCIMXVedFbikQt8=", - "dev": true, - "requires": { - "babel-code-frame": "6.22.0", - "babel-generator": "6.25.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.23.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "convert-source-map": "1.5.0", - "debug": "2.6.8", - "json5": "0.5.1", - "lodash": "4.17.2", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.7", - "slash": "1.0.0", - "source-map": "0.5.6" - } - }, - "babel-eslint": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.1.1.tgz", - "integrity": "sha1-imqITwhapwYK9pz8dzQcL5k3D7I=", - "dev": true, - "requires": { - "babel-code-frame": "6.22.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "lodash.pickby": "4.6.0" - } - }, - "babel-generator": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.25.0.tgz", - "integrity": "sha1-M6GvcNXyiQrrRlpKd5PB32qeqfw=", - "requires": { - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "detect-indent": "4.0.0", - "jsesc": "1.3.0", - "lodash": "4.17.2", - "source-map": "0.5.6", - "trim-right": "1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" - } - } - }, - "babel-helper-bindify-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", - "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true, - "requires": { - "babel-helper-explode-assignable-expression": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-builder-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz", - "integrity": "sha1-CteRfjPI11HmRtrKTnfMGTd9LLw=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "esutils": "2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-define-map": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz", - "integrity": "sha1-epdH8ljYlH0y1RX2qhx70CIEoIA=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "lodash": "4.17.2" - } - }, - "babel-helper-explode-assignable-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-explode-class": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", - "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", - "dev": true, - "requires": { - "babel-helper-bindify-decorators": "6.24.1", - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "requires": { - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", - "integrity": "sha1-024i+rEAjXnYhkjjIRaGgShFbOg=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "lodash": "4.17.2" - } - }, - "babel-helper-remap-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "requires": { - "babel-helper-optimise-call-expression": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-helpers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "requires": { - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-loader": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-6.3.2.tgz", - "integrity": "sha1-GN5FZjhVeMG0+P/my8Zo9eKl7wM=", - "dev": true, - "requires": { - "find-cache-dir": "0.1.1", - "loader-utils": "0.2.17", - "mkdirp": "0.5.1", - "object-assign": "4.1.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-lodash": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/babel-plugin-lodash/-/babel-plugin-lodash-3.2.11.tgz", - "integrity": "sha1-Icj97J/hg176pzeHPjkCvdZtVwE=", - "dev": true, - "requires": { - "glob": "7.1.2", - "lodash": "4.17.2" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "babel-plugin-react-intl": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/babel-plugin-react-intl/-/babel-plugin-react-intl-2.3.1.tgz", - "integrity": "sha1-PUORLoJNoAXgjo6COdW6eEN0uwA=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0", - "intl-messageformat-parser": "1.2.0", - "mkdirp": "0.5.1" - } - }, - "babel-plugin-recharts": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-recharts/-/babel-plugin-recharts-1.1.0.tgz", - "integrity": "sha1-gSzISxPrWN1AWyxjoo6m97JqtKc=", - "dev": true, - "requires": { - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4" - } - }, - "babel-plugin-syntax-async-functions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-async-generators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", - "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=", - "dev": true - }, - "babel-plugin-syntax-class-constructor-call": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", - "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=", - "dev": true - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-syntax-decorators": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", - "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=", - "dev": true - }, - "babel-plugin-syntax-do-expressions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz", - "integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=", - "dev": true - }, - "babel-plugin-syntax-dynamic-import": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", - "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-export-extensions": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", - "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=", - "dev": true - }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-function-bind": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz", - "integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, - "babel-plugin-syntax-object-rest-spread": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", - "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-generator-functions": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", - "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-generators": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-async-to-generator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true, - "requires": { - "babel-helper-remap-async-to-generator": "6.24.1", - "babel-plugin-syntax-async-functions": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-class-constructor-call": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", - "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", - "dev": true, - "requires": { - "babel-plugin-syntax-class-constructor-call": "6.18.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-class-properties": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.23.0.tgz", - "integrity": "sha1-GHt0fuQEOZATVjyZPbA480dUrDs=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-decorators": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", - "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", - "dev": true, - "requires": { - "babel-helper-explode-class": "6.24.1", - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-decorators-legacy": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators-legacy/-/babel-plugin-transform-decorators-legacy-1.3.4.tgz", - "integrity": "sha1-dBtY9sW86eYCfgiC2cmU8E82aSU=", - "dev": true, - "requires": { - "babel-plugin-syntax-decorators": "6.13.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-do-expressions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz", - "integrity": "sha1-KMyvkoEtlJws0SgfaQyP3EaK6bs=", - "dev": true, - "requires": { - "babel-plugin-syntax-do-expressions": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", - "integrity": "sha1-dsKV3DpHQbFmWt/TFnIV3P8ypXY=", - "requires": { - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "lodash": "4.17.2" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "requires": { - "babel-helper-define-map": "6.24.1", - "babel-helper-function-name": "6.24.1", - "babel-helper-optimise-call-expression": "6.24.1", - "babel-helper-replace-supers": "6.24.1", - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "requires": { - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", - "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=", - "requires": { - "babel-plugin-transform-strict-mode": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "requires": { - "babel-helper-hoist-variables": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "requires": { - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "requires": { - "babel-helper-replace-supers": "6.24.1", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "requires": { - "babel-helper-call-delegate": "6.24.1", - "babel-helper-get-function-arity": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "requires": { - "babel-helper-regex": "6.24.1", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "requires": { - "babel-helper-regex": "6.24.1", - "babel-runtime": "6.23.0", - "regexpu-core": "2.0.0" - } - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true, - "requires": { - "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", - "babel-plugin-syntax-exponentiation-operator": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-export-extensions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", - "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", - "dev": true, - "requires": { - "babel-plugin-syntax-export-extensions": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "6.18.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-function-bind": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz", - "integrity": "sha1-xvuOlqwpajELjPjqQBRiQH3fapc=", - "dev": true, - "requires": { - "babel-plugin-syntax-function-bind": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-object-rest-spread": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz", - "integrity": "sha1-h11ryb52HFiirj/u5dxIldjH+SE=", - "dev": true, - "requires": { - "babel-plugin-syntax-object-rest-spread": "6.13.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "6.24.1", - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-react-remove-prop-types": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.3.2.tgz", - "integrity": "sha1-bajYNMbXrYqwL5VlCXkM+qAf/hk=", - "dev": true - }, - "babel-plugin-transform-regenerator": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz", - "integrity": "sha1-uNowWtQ8PJm0hI5P5AN7dw0jxBg=", - "requires": { - "regenerator-transform": "0.9.11" - } - }, - "babel-plugin-transform-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", - "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0" - } - }, - "babel-plugin-webpack-alias": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/babel-plugin-webpack-alias/-/babel-plugin-webpack-alias-2.1.2.tgz", - "integrity": "sha1-BaG6I8KFlWYPtupXNkJPxZa0okc=", - "dev": true, - "requires": { - "babel-types": "6.25.0", - "find-up": "2.1.0", - "lodash.some": "4.6.0", - "lodash.template": "4.4.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - }, - "lodash.template": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", - "integrity": "sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.templatesettings": "4.1.0" - } - }, - "lodash.templatesettings": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz", - "integrity": "sha1-K01OlbpEDZFf8IvImeRVNmZxMxY=", - "dev": true, - "requires": { - "lodash._reinterpolate": "3.0.0" - } - } - } - }, - "babel-polyfill": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", - "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", - "dev": true, - "requires": { - "babel-runtime": "6.23.0", - "core-js": "2.4.1", - "regenerator-runtime": "0.10.5" - } - }, - "babel-preset-env": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.1.9.tgz", - "integrity": "sha1-SUQ9zW71K0i3GR6jOGniRZCp60o=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.24.1", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1", - "browserslist": "1.7.7", - "electron-to-chromium": "1.3.16", - "invariant": "2.2.2" - } - }, - "babel-preset-es2015": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz", - "integrity": "sha1-r1qY7LNeuK92StiloF6zbcQ4aDU=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.24.1", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1" - } - }, - "babel-preset-es2016": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-preset-es2016/-/babel-preset-es2016-6.22.0.tgz", - "integrity": "sha1-sGGqo5g9QMn7rPo3Q7XfN/M2FWw=", - "dev": true, - "requires": { - "babel-plugin-transform-exponentiation-operator": "6.24.1" - } - }, - "babel-preset-es2017": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-preset-es2017/-/babel-preset-es2017-6.22.0.tgz", - "integrity": "sha1-3i+dpaMMUNKT+1SguhXW3cVz8PI=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-to-generator": "6.24.1" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "6.22.0" - } - }, - "babel-preset-react": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.23.0.tgz", - "integrity": "sha1-63zuTemKP5RQLChWUzLamBlFUZU=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "6.18.0", - "babel-plugin-transform-react-display-name": "6.25.0", - "babel-plugin-transform-react-jsx": "6.24.1", - "babel-plugin-transform-react-jsx-self": "6.22.0", - "babel-plugin-transform-react-jsx-source": "6.22.0", - "babel-preset-flow": "6.23.0" - } - }, - "babel-preset-stage-0": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.22.0.tgz", - "integrity": "sha1-cH7rW0Fdp2nv+cQvRUf2RPkpbvk=", - "dev": true, - "requires": { - "babel-plugin-transform-do-expressions": "6.22.0", - "babel-plugin-transform-function-bind": "6.22.0", - "babel-preset-stage-1": "6.24.1" - } - }, - "babel-preset-stage-1": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", - "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", - "dev": true, - "requires": { - "babel-plugin-transform-class-constructor-call": "6.24.1", - "babel-plugin-transform-export-extensions": "6.22.0", - "babel-preset-stage-2": "6.24.1" - } - }, - "babel-preset-stage-2": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", - "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", - "dev": true, - "requires": { - "babel-plugin-syntax-dynamic-import": "6.18.0", - "babel-plugin-transform-class-properties": "6.24.1", - "babel-plugin-transform-decorators": "6.24.1", - "babel-preset-stage-3": "6.24.1" - }, - "dependencies": { - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "6.24.1", - "babel-plugin-syntax-class-properties": "6.13.0", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0" - } - } - } - }, - "babel-preset-stage-3": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", - "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", - "dev": true, - "requires": { - "babel-plugin-syntax-trailing-function-commas": "6.22.0", - "babel-plugin-transform-async-generator-functions": "6.24.1", - "babel-plugin-transform-async-to-generator": "6.24.1", - "babel-plugin-transform-exponentiation-operator": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.23.0" - } - }, - "babel-register": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.23.0.tgz", - "integrity": "sha1-yao9TMqUtR2jSCbEoPnggUXXT/M=", - "dev": true, - "requires": { - "babel-core": "6.23.1", - "babel-runtime": "6.23.0", - "core-js": "2.4.1", - "home-or-tmp": "2.0.0", - "lodash": "4.17.2", - "mkdirp": "0.5.1", - "source-map-support": "0.4.15" - } - }, - "babel-runtime": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", - "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", - "requires": { - "core-js": "2.4.1", - "regenerator-runtime": "0.10.5" - } - }, - "babel-template": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.25.0.tgz", - "integrity": "sha1-ZlJBFmt8KqTGGdceGSlpVSsQwHE=", - "requires": { - "babel-runtime": "6.23.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "lodash": "4.17.2" - } - }, - "babel-traverse": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.25.0.tgz", - "integrity": "sha1-IldJfi/NGbie3BPEyROB+VEklvE=", - "requires": { - "babel-code-frame": "6.22.0", - "babel-messages": "6.23.0", - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "debug": "2.6.8", - "globals": "9.18.0", - "invariant": "2.2.2", - "lodash": "4.17.2" - } - }, - "babel-types": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.25.0.tgz", - "integrity": "sha1-cK+ySNVmDl0Y+BHZHIMDtUE0oY4=", - "requires": { - "babel-runtime": "6.23.0", - "esutils": "2.0.2", - "lodash": "4.17.2", - "to-fast-properties": "1.0.3" - } - }, - "babelify": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", - "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", - "requires": { - "babel-core": "6.25.0", - "object-assign": "4.1.1" - }, - "dependencies": { - "babel-core": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.25.0.tgz", - "integrity": "sha1-fdQrBGPHQunVKW3rPsZ6kyLa1yk=", - "requires": { - "babel-code-frame": "6.22.0", - "babel-generator": "6.25.0", - "babel-helpers": "6.24.1", - "babel-messages": "6.23.0", - "babel-register": "6.24.1", - "babel-runtime": "6.23.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "convert-source-map": "1.5.0", - "debug": "2.6.8", - "json5": "0.5.1", - "lodash": "4.17.2", - "minimatch": "3.0.4", - "path-is-absolute": "1.0.1", - "private": "0.1.7", - "slash": "1.0.0", - "source-map": "0.5.6" - } - }, - "babel-register": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", - "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", - "requires": { - "babel-core": "6.25.0", - "babel-runtime": "6.23.0", - "core-js": "2.4.1", - "home-or-tmp": "2.0.0", - "lodash": "4.17.2", - "mkdirp": "0.5.1", - "source-map-support": "0.4.15" - } - } - } - }, - "babylon": { - "version": "6.17.4", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.17.4.tgz", - "integrity": "sha512-kChlV+0SXkjE0vUn9OZ7pBMWRFd8uq3mZe8x1K6jhuNcAFAtEnjchFAqB+dYEXKyd+JpT6eppRR78QAr5gTsUw==" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base32.js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/base32.js/-/base32.js-0.1.0.tgz", - "integrity": "sha1-tYLexpPC8R6JPPBk7mrFthMaIgI=" - }, - "base64-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", - "dev": true - }, - "batch-processor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", - "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=" - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" - }, - "big.js": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.1.3.tgz", - "integrity": "sha1-TK2iGTZS6zyp7I5VyQFWacmAaXg=" - }, - "bignumber.js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-3.0.1.tgz", - "integrity": "sha1-gHZS0Q453jfp40lyR+3HmLt0b3Y=" - }, - "bin-build": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", - "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", - "dev": true, - "requires": { - "archive-type": "3.2.0", - "decompress": "3.0.0", - "download": "4.4.3", - "exec-series": "1.0.3", - "rimraf": "2.6.1", - "tempfile": "1.1.1", - "url-regex": "3.2.0" - }, - "dependencies": { - "tempfile": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", - "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", - "dev": true, - "requires": { - "os-tmpdir": "1.0.2", - "uuid": "2.0.3" - } - }, - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } - } - }, - "bin-check": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", - "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", - "dev": true, - "requires": { - "executable": "1.1.0" - } - }, - "bin-version": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", - "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", - "dev": true, - "requires": { - "find-versions": "1.2.1" - } - }, - "bin-version-check": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", - "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", - "dev": true, - "requires": { - "bin-version": "1.0.4", - "minimist": "1.2.0", - "semver": "4.3.6", - "semver-truncate": "1.1.2" - }, - "dependencies": { - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - } - } - }, - "bin-wrapper": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", - "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", - "dev": true, - "requires": { - "bin-check": "2.0.0", - "bin-version-check": "2.1.0", - "download": "4.4.3", - "each-async": "1.1.1", - "lazy-req": "1.1.0", - "os-filter-obj": "1.0.3" - } - }, - "binary-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.9.0.tgz", - "integrity": "sha1-ZlBsFs5vTWkopbPNajPKQelB43s=", - "dev": true - }, - "bindings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" - }, - "bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "bl": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", - "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", - "requires": { - "readable-stream": "2.3.3" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "2.0.3" - } - }, - "blockies": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/blockies/-/blockies-0.0.2.tgz", - "integrity": "sha1-Iq1Y2k9rOCvHm/Q4bFggxwBH5O0=" - }, - "bluebird": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", - "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", - "dev": true - }, - "bn.js": { - "version": "4.11.7", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.7.tgz", - "integrity": "sha512-LxFiV5mefv0ley0SzqkOPR1bC4EbpPx8LkOz5vMe/Yi15t5hzwgO/G+tc7wOtL4PZTYjwHu8JnEiSLumuSjSfA==" - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", - "dev": true - }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "requires": { - "hoek": "2.16.3" - } - }, - "bowser": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.7.1.tgz", - "integrity": "sha1-pN6PGKGg3JUx6yqSoVIftqm6lqU=" - }, - "brace": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/brace/-/brace-0.9.0.tgz", - "integrity": "sha1-rQNLrmUiDrZ22UnLKAOD+o4S+nI=", - "requires": { - "w3c-blob": "0.0.1" - } - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "browserify-aes": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.6.tgz", - "integrity": "sha1-Xncl297x/Vkw1OurSFZ85FHEigo=", - "requires": { - "buffer-xor": "1.0.3", - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-cipher": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", - "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", - "dev": true, - "requires": { - "browserify-aes": "1.0.6", - "browserify-des": "1.0.0", - "evp_bytestokey": "1.0.0" - } - }, - "browserify-des": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", - "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", - "dev": true, - "requires": { - "cipher-base": "1.0.4", - "des.js": "1.0.0", - "inherits": "2.0.3" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "randombytes": "2.0.5" - } - }, - "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "elliptic": "6.4.0", - "inherits": "2.0.3", - "parse-asn1": "5.1.0" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "0.2.9" - } - }, - "browserslist": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", - "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", - "dev": true, - "requires": { - "caniuse-db": "1.0.30000708", - "electron-to-chromium": "1.3.16" - } - }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "1.2.1", - "ieee754": "1.1.8", - "isarray": "1.0.0" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" - }, - "buffer-to-vinyl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", - "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", - "requires": { - "file-type": "3.9.0", - "readable-stream": "2.3.3", - "uuid": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" - } - } - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "bytes": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-2.4.0.tgz", - "integrity": "sha1-fZcZb51br39pNeJZhVSe3SpsIzk=" - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "2.3.1", - "upper-case": "1.1.3" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" - } - }, - "caniuse-api": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", - "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000708", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" - } - }, - "caniuse-db": { - "version": "1.0.30000708", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000708.tgz", - "integrity": "sha1-wuc2vTt/xfbBTkxt/mK5jtFeils=", - "dev": true - }, - "capture-stack-trace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, - "caw": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", - "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", - "requires": { - "get-proxy": "1.1.0", - "is-obj": "1.0.1", - "object-assign": "3.0.0", - "tunnel-agent": "0.4.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" - } - } - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" - } - }, - "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "1.0.2", - "deep-eql": "0.1.3", - "type-detect": "1.0.0" - } - }, - "chai-as-promised": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", - "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=", - "dev": true, - "requires": { - "check-error": "1.0.2" - } - }, - "chai-enzyme": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/chai-enzyme/-/chai-enzyme-0.6.1.tgz", - "integrity": "sha1-WFyWPG6hMxRG79Eu6DkegH11hiA=", - "dev": true, - "requires": { - "html": "1.0.0", - "react-element-to-jsx-string": "5.0.7" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "react-element-to-jsx-string": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-5.0.7.tgz", - "integrity": "sha1-xmOkgAqccSEVwNhRnLAhWkah8PI=", - "dev": true, - "requires": { - "collapse-white-space": "1.0.3", - "is-plain-object": "2.0.4", - "lodash": "4.17.4", - "sortobject": "1.1.1", - "stringify-object": "2.4.0", - "traverse": "0.6.6" - } - }, - "stringify-object": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-2.4.0.tgz", - "integrity": "sha1-xi0RAj6yH+LZsIe+A5om3zsioJ0=", - "dev": true, - "requires": { - "is-plain-obj": "1.1.0", - "is-regexp": "1.0.0" - } - } - } - }, - "chain-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chain-function/-/chain-function-1.0.0.tgz", - "integrity": "sha1-DUqzfn4Y6tC9xHuSB2QRjOWHM9w=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "change-emitter": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/change-emitter/-/change-emitter-0.1.6.tgz", - "integrity": "sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=" - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "cheerio": { - "version": "0.22.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", - "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-serializer": "0.1.0", - "entities": "1.1.1", - "htmlparser2": "3.9.2", - "lodash.assignin": "4.2.0", - "lodash.bind": "4.2.1", - "lodash.defaults": "4.2.0", - "lodash.filter": "4.6.0", - "lodash.flatten": "4.4.0", - "lodash.foreach": "4.5.0", - "lodash.map": "4.6.0", - "lodash.merge": "4.6.0", - "lodash.pick": "4.4.0", - "lodash.reduce": "4.6.0", - "lodash.reject": "4.6.0", - "lodash.some": "4.6.0" - } - }, - "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", - "dev": true, - "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" - }, - "ci-info": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.0.0.tgz", - "integrity": "sha1-3FKF8rTiUYIWg2gcOBwziPRuxTQ=" - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "2.0.3", - "safe-buffer": "5.1.1" - } - }, - "circular-dependency-plugin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-2.0.0.tgz", - "integrity": "sha1-wQeWyDOQSIqbzdQvAy1uZOmE9mA=", - "dev": true - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "clap": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.0.tgz", - "integrity": "sha1-WckP4+E3EEdG/xlGmiemNP9oyFc=", - "dev": true, - "requires": { - "chalk": "1.1.3" - } - }, - "classnames": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.5.tgz", - "integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0=" - }, - "clean-css": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.7.tgz", - "integrity": "sha1-ua6k+FZ5iJzz6ui0A0nsTr390DI=", - "dev": true, - "requires": { - "source-map": "0.5.6" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { - "restore-cursor": "2.0.0" - } - }, - "cli-width": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", - "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=" - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - } - }, - "clone": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" - }, - "clone-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.0.tgz", - "integrity": "sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw=", - "dev": true, - "requires": { - "is-regexp": "1.0.0", - "is-supported-regexp-flag": "1.0.0" - } - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" - }, - "cmd-shim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-2.0.2.tgz", - "integrity": "sha1-b8vamUg6j9FdfTChlspp1oii79s=", - "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1" - } - }, - "co": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", - "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=" - }, - "coa": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", - "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", - "dev": true, - "requires": { - "q": "1.5.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "codemirror": { - "version": "5.28.0", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.28.0.tgz", - "integrity": "sha512-E/Z6050shti9v9ivl0dUClVRM4xaH204jsJmEpNYC6KDTlQwAz+5DdhLzn0tjaL/Mp1P0J1uhZokcSP2RFSwlA==" - }, - "collapse-white-space": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.3.tgz", - "integrity": "sha1-S5BvZw5aljqHt2sOFolkM0G2Ajw=" - }, - "color": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", - "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", - "dev": true, - "requires": { - "clone": "1.0.2", - "color-convert": "1.9.0", - "color-string": "0.3.0" - } - }, - "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", - "requires": { - "color-name": "1.1.3" - } - }, - "color-diff": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/color-diff/-/color-diff-0.1.7.tgz", - "integrity": "sha1-bbeM2UgqjkWdQIIer0tQMoPcuOI=", - "dev": true - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "color-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", - "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "colorguard": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/colorguard/-/colorguard-1.2.0.tgz", - "integrity": "sha1-8/rK9cquuk71RlPZ+yW7cxd8DYQ=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "color-diff": "0.1.7", - "log-symbols": "1.0.2", - "object-assign": "4.1.1", - "pipetteur": "2.0.3", - "plur": "2.1.2", - "postcss": "5.2.17", - "postcss-reporter": "1.4.1", - "text-table": "0.2.0", - "yargs": "1.3.3" - }, - "dependencies": { - "postcss-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", - "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "lodash": "4.17.2", - "log-symbols": "1.0.2", - "postcss": "5.2.17" - } - }, - "yargs": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", - "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", - "dev": true - } - } - }, - "colormin": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", - "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", - "dev": true, - "requires": { - "color": "0.11.4", - "css-color-names": "0.0.4", - "has": "1.0.1" - } - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "requires": { - "delayed-stream": "1.0.0" - } - }, - "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "commonmark": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.24.0.tgz", - "integrity": "sha1-uA3gGCxUY1VkOqFdsSv7KCNoJ48=", - "requires": { - "entities": "1.1.1", - "mdurl": "1.0.1", - "string.prototype.repeat": "0.2.0" - } - }, - "commonmark-react-renderer": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/commonmark-react-renderer/-/commonmark-react-renderer-4.3.3.tgz", - "integrity": "sha1-nEvKE4vIMoe655LM8TNzi+nLxvo=", - "requires": { - "in-publish": "2.0.0", - "lodash.assign": "4.2.0", - "lodash.isplainobject": "4.0.6", - "pascalcase": "0.1.1", - "xss-filters": "1.2.7" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "typedarray": "0.0.6" - } - }, - "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "0.1.4" - }, - "dependencies": { - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - } - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" - }, - "console-stream": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", - "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "content-disposition": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true - }, - "content-type": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", - "dev": true - }, - "content-type-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/content-type-parser/-/content-type-parser-1.0.1.tgz", - "integrity": "sha1-w+VpiMU8ZRJ/tG1AMqOpACRv3JQ=", - "dev": true - }, - "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=" - }, - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-to-clipboard": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz", - "integrity": "sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw==", - "requires": { - "toggle-selection": "1.0.6" - } - }, - "copy-webpack-plugin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.0.1.tgz", - "integrity": "sha1-lyjjg7lDFgUNDHRjlY8rhcCqggA=", - "dev": true, - "requires": { - "bluebird": "2.11.0", - "fs-extra": "0.26.7", - "glob": "6.0.4", - "is-glob": "3.1.0", - "loader-utils": "0.2.17", - "lodash": "4.17.2", - "minimatch": "3.0.4", - "node-dir": "0.1.17" - }, - "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "core-js": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", - "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "cosmiconfig": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", - "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", - "dev": true, - "requires": { - "is-directory": "0.3.1", - "js-yaml": "3.6.1", - "minimist": "1.2.0", - "object-assign": "4.1.1", - "os-homedir": "1.0.2", - "parse-json": "2.2.0", - "require-from-string": "1.2.1" - } - }, - "coveralls": { - "version": "2.11.16", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.11.16.tgz", - "integrity": "sha1-2pBhJlFC3e6VT2g3kSK+l76KtLE=", - "dev": true, - "requires": { - "js-yaml": "3.6.1", - "lcov-parse": "0.0.10", - "log-driver": "1.2.5", - "minimist": "1.2.0", - "request": "2.79.0" - }, - "dependencies": { - "caseless": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "har-validator": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.16.0", - "pinkie-promise": "2.0.1" - } - }, - "request": { - "version": "2.79.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.11.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "2.0.6", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.16", - "oauth-sign": "0.8.2", - "qs": "6.3.0", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.4.3", - "uuid": "3.0.0" - } - }, - "tunnel-agent": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - } - } - }, - "create-ecdh": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", - "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "elliptic": "6.4.0" - } - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "requires": { - "capture-stack-trace": "1.0.0" - } - }, - "create-hash": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", - "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", - "requires": { - "cipher-base": "1.0.4", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "sha.js": "2.4.8" - } - }, - "create-hmac": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", - "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", - "requires": { - "cipher-base": "1.0.4", - "create-hash": "1.1.3", - "inherits": "2.0.3", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.8" - } - }, - "create-thenable": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/create-thenable/-/create-thenable-1.0.2.tgz", - "integrity": "sha1-4gMXIMzJV12M+jH1wUbnYqgMBTQ=", - "dev": true, - "requires": { - "object.omit": "2.0.1", - "unique-concat": "0.2.2" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "4.1.1", - "shebang-command": "1.2.0", - "which": "1.2.14" - } - }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "requires": { - "boom": "2.10.1" - } - }, - "crypto-browserify": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz", - "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==", - "dev": true, - "requires": { - "browserify-cipher": "1.0.0", - "browserify-sign": "4.0.4", - "create-ecdh": "4.0.0", - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "diffie-hellman": "5.0.2", - "inherits": "2.0.3", - "pbkdf2": "3.0.12", - "public-encrypt": "4.0.0", - "randombytes": "2.0.5" - } - }, - "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", - "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", - "dev": true - }, - "css-loader": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.26.1.tgz", - "integrity": "sha1-K6fyATG5NZdJaz6btQB4WknNKeo=", - "dev": true, - "requires": { - "babel-code-frame": "6.22.0", - "css-selector-tokenizer": "0.7.0", - "cssnano": "3.10.0", - "loader-utils": "0.2.17", - "lodash.camelcase": "4.3.0", - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-modules-extract-imports": "1.1.0", - "postcss-modules-local-by-default": "1.2.0", - "postcss-modules-scope": "1.1.0", - "postcss-modules-values": "1.3.0", - "source-list-map": "0.1.8" - } - }, - "css-rule-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/css-rule-stream/-/css-rule-stream-1.1.0.tgz", - "integrity": "sha1-N4bnGYmD2WWibjGVfgkHjLt3BaI=", - "dev": true, - "requires": { - "css-tokenize": "1.0.1", - "duplexer2": "0.0.2", - "ldjson-stream": "1.2.1", - "through2": "0.6.5" - }, - "dependencies": { - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "dev": true, - "requires": { - "boolbase": "1.0.0", - "css-what": "2.1.0", - "domutils": "1.5.1", - "nth-check": "1.0.1" - } - }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "dev": true, - "requires": { - "cssesc": "0.1.0", - "fastparse": "1.1.1", - "regexpu-core": "1.0.0" - }, - "dependencies": { - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "dev": true, - "requires": { - "regenerate": "1.3.2", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - } - } - }, - "css-tokenize": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz", - "integrity": "sha1-RiXLHtohwUOFi3+B1oA8HSb8FL4=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "1.1.14" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "css-what": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", - "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", - "dev": true - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", - "dev": true - }, - "cssnano": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", - "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", - "dev": true, - "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" - } - }, - "csso": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", - "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", - "dev": true, - "requires": { - "clap": "1.2.0", - "source-map": "0.5.6" - } - }, - "cssom": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.2.tgz", - "integrity": "sha1-uANhcMefB6kP8vFuIihAJ6JDhIs=", - "dev": true - }, - "cssstyle": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", - "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", - "dev": true, - "requires": { - "cssom": "0.3.2" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "requires": { - "array-find-index": "1.0.2" - } - }, - "d": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "0.10.24" - } - }, - "d3-array": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.0.tgz", - "integrity": "sha1-FH0mlyDhdMQFen9CvosPPyulMQg=" - }, - "d3-collection": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", - "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=" - }, - "d3-color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", - "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" - }, - "d3-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.0.tgz", - "integrity": "sha1-a0gLqohohdRlHcJIqPSsnaFtsHo=" - }, - "d3-interpolate": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.5.tgz", - "integrity": "sha1-aeCZ/zkhRxblY8muw+qdHqS4p58=", - "requires": { - "d3-color": "1.0.3" - } - }, - "d3-path": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", - "integrity": "sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q=" - }, - "d3-scale": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.0.tgz", - "integrity": "sha1-C0F1yjHL5l4lRCfkZi3678NzRi0=", - "requires": { - "d3-array": "1.2.0", - "d3-collection": "1.0.4", - "d3-color": "1.0.3", - "d3-format": "1.2.0", - "d3-interpolate": "1.1.5", - "d3-time": "1.0.7", - "d3-time-format": "2.0.5" - } - }, - "d3-shape": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.0.0.tgz", - "integrity": "sha1-zKMySHV55Fc1TIg4oKKDvmOEWbo=", - "requires": { - "d3-path": "1.0.5" - } - }, - "d3-time": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.7.tgz", - "integrity": "sha1-lMr27bt4ebuAnQ0fdXK8SEgvcnA=" - }, - "d3-time-format": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.0.5.tgz", - "integrity": "sha1-nXeAIE98kRnJFwsaVttN6aivly4=", - "requires": { - "d3-time": "1.0.7" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "date-difference": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/date-difference/-/date-difference-1.0.0.tgz", - "integrity": "sha1-0+bog8DK0tydv8vxLgYpe5cpiXQ=", - "requires": { - "get-stdin": "3.0.2", - "meow": "3.7.0" - } - }, - "date-now": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-1.0.1.tgz", - "integrity": "sha1-u30IZDjevkGCpIX7PfP7+5nWFTw=" - }, - "dateformat": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", - "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=" - }, - "death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" - }, - "debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.0.0.tgz", - "integrity": "sha1-CUivUT0uTOQHkW+FBqQj0/nPctg=", - "requires": { - "date-now": "1.0.1" - } - }, - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decompress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", - "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", - "requires": { - "buffer-to-vinyl": "1.1.0", - "concat-stream": "1.6.0", - "decompress-tar": "3.1.0", - "decompress-tarbz2": "3.1.0", - "decompress-targz": "3.1.0", - "decompress-unzip": "3.4.0", - "stream-combiner2": "1.1.1", - "vinyl-assign": "1.2.1", - "vinyl-fs": "2.4.4" - } - }, - "decompress-tar": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", - "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", - "requires": { - "is-tar": "1.0.0", - "object-assign": "2.1.1", - "strip-dirs": "1.1.1", - "tar-stream": "1.5.4", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=" - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "decompress-tarbz2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", - "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", - "requires": { - "is-bzip2": "1.0.0", - "object-assign": "2.1.1", - "seek-bzip": "1.0.5", - "strip-dirs": "1.1.1", - "tar-stream": "1.5.4", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=" - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "decompress-targz": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", - "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", - "requires": { - "is-gzip": "1.0.0", - "object-assign": "2.1.1", - "strip-dirs": "1.1.1", - "tar-stream": "1.5.4", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" - }, - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=" - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } - } - }, - "decompress-unzip": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", - "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", - "requires": { - "is-zip": "1.0.0", - "read-all-stream": "3.1.0", - "stat-mode": "0.2.2", - "strip-dirs": "1.1.1", - "through2": "2.0.3", - "vinyl": "1.2.0", - "yauzl": "2.8.0" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - } - } - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", - "dev": true - }, - "deep-extend": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "default-require-extensions": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", - "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", - "dev": true, - "requires": { - "strip-bom": "2.0.0" - } - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { - "clone": "1.0.2" - } - }, - "define-properties": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true, - "requires": { - "foreach": "2.0.5", - "object-keys": "1.0.11" - } - }, - "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", - "dev": true - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" - }, - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "requires": { - "repeating": "2.0.1" - } - }, - "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", - "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "miller-rabin": "4.0.0", - "randombytes": "2.0.5" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" - } - }, - "doiuse": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/doiuse/-/doiuse-2.6.0.tgz", - "integrity": "sha1-GJLRC2Gpo1at2/K2FJM+gfi7ODQ=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000708", - "css-rule-stream": "1.1.0", - "duplexer2": "0.0.2", - "jsonfilter": "1.1.2", - "ldjson-stream": "1.2.1", - "lodash": "4.17.2", - "multimatch": "2.1.0", - "postcss": "5.2.17", - "source-map": "0.4.4", - "through2": "0.6.5", - "yargs": "3.32.0" - }, - "dependencies": { - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "1.1.14" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "window-size": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", - "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", - "dev": true - }, - "yargs": { - "version": "3.32.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", - "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", - "dev": true, - "requires": { - "camelcase": "2.1.1", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "os-locale": "1.4.0", - "string-width": "1.0.2", - "window-size": "0.1.4", - "y18n": "3.2.1" - } - } - } - }, - "dom-converter": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", - "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", - "dev": true, - "requires": { - "utila": "0.3.3" - }, - "dependencies": { - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", - "dev": true - } - } - }, - "dom-helpers": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.2.1.tgz", - "integrity": "sha1-MgPgf+0he9H0JLAZc1WC/Deyglo=" - }, - "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", - "dev": true, - "requires": { - "domelementtype": "1.1.3", - "entities": "1.1.1" - }, - "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - } - } - }, - "dom-walk": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", - "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=", - "dev": true - }, - "domain-browser": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", - "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", - "dev": true - }, - "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", - "dev": true - }, - "domhandler": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.1.tgz", - "integrity": "sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "dev": true, - "requires": { - "dom-serializer": "0.1.0", - "domelementtype": "1.3.0" - } - }, - "download": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", - "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", - "requires": { - "caw": "1.2.0", - "concat-stream": "1.6.0", - "each-async": "1.1.1", - "filenamify": "1.2.1", - "got": "5.7.1", - "gulp-decompress": "1.2.0", - "gulp-rename": "1.2.2", - "is-url": "1.2.2", - "object-assign": "4.1.1", - "read-all-stream": "3.1.0", - "readable-stream": "2.3.3", - "stream-combiner2": "1.1.1", - "vinyl": "1.2.0", - "vinyl-fs": "2.4.4", - "ware": "1.3.0" - } - }, - "drbg.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", - "integrity": "sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs=", - "requires": { - "browserify-aes": "1.0.6", - "create-hash": "1.1.3", - "create-hmac": "1.1.6" - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "requires": { - "readable-stream": "2.3.3" - } - }, - "duplexify": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", - "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", - "requires": { - "end-of-stream": "1.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "stream-shift": "1.0.0" - }, - "dependencies": { - "end-of-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", - "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", - "requires": { - "once": "1.3.3" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "requires": { - "wrappy": "1.0.2" - } - } - } - }, - "each-async": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", - "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", - "requires": { - "onetime": "1.1.0", - "set-immediate-shim": "1.0.1" - } - }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "editions": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.3.tgz", - "integrity": "sha1-CQcQG92iD6w8vjNMJ8vQaI3Jmls=" - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "ejs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-1.0.0.tgz", - "integrity": "sha1-ycYKSKRu5FL7MqccMXuV5aofyz0=", - "dev": true - }, - "ejs-loader": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ejs-loader/-/ejs-loader-0.3.0.tgz", - "integrity": "sha1-aHNv3CMaSQ7fkZpkRq2dkFWlh74=", - "dev": true, - "requires": { - "loader-utils": "0.2.17", - "lodash": "3.10.1" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } - } - }, - "ejsify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ejsify/-/ejsify-1.0.0.tgz", - "integrity": "sha1-NxlPWoXBKuQ4QpOVeZ7Ee0O8RT8=", - "dev": true, - "requires": { - "ejs": "1.0.0", - "through": "2.3.8" - } - }, - "electron-to-chromium": { - "version": "1.3.16", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.16.tgz", - "integrity": "sha1-0OAmc1dUdwkBrjAaIWZMukXZL30=", - "dev": true - }, - "element-resize-detector": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.1.12.tgz", - "integrity": "sha1-iz/W7t2hf5wAs2Cg6i35knroC6I=", - "requires": { - "batch-processor": "1.0.0" - } - }, - "elliptic": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", - "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", - "requires": { - "bn.js": "4.11.7", - "brorand": "1.1.0", - "hash.js": "1.1.3", - "hmac-drbg": "1.0.1", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" - }, - "empty-module": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/empty-module/-/empty-module-0.0.2.tgz", - "integrity": "sha1-E7TdjUr+3dNeUMGNzXiMUQh/FUU=", - "dev": true - }, - "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", - "dev": true - }, - "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", - "requires": { - "iconv-lite": "0.4.18" - } - }, - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", - "requires": { - "once": "1.4.0" - } - }, - "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "memory-fs": "0.4.1", - "object-assign": "4.1.1", - "tapable": "0.2.7" - } - }, - "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" - }, - "enzyme": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-2.7.1.tgz", - "integrity": "sha1-djcOHZnpH3MJG7jEMUt8EozC1iE=", - "dev": true, - "requires": { - "cheerio": "0.22.0", - "function.prototype.name": "1.0.3", - "is-subset": "0.1.1", - "lodash": "4.17.2", - "object-is": "1.0.1", - "object.assign": "4.0.4", - "object.entries": "1.0.4", - "object.values": "1.0.4", - "uuid": "2.0.3" - }, - "dependencies": { - "uuid": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", - "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", - "dev": true - } - } - }, - "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", - "dev": true, - "requires": { - "prr": "0.0.0" - } - }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "requires": { - "is-arrayish": "0.2.1" - } - }, - "error-stack-parser": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-1.3.6.tgz", - "integrity": "sha1-4Oc7k+QXE40c18C3RrGkoUhUwpI=", - "dev": true, - "requires": { - "stackframe": "0.3.1" - } - }, - "es-abstract": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", - "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", - "dev": true, - "requires": { - "es-to-primitive": "1.1.1", - "function-bind": "1.1.0", - "is-callable": "1.1.3", - "is-regex": "1.0.4" - } - }, - "es-to-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true, - "requires": { - "is-callable": "1.1.3", - "is-date-object": "1.0.1", - "is-symbol": "1.0.1" - } - }, - "es5-ext": { - "version": "0.10.24", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.24.tgz", - "integrity": "sha1-pVh3yZJLwMjZvTwsvhdJWsFwmxQ=", - "dev": true, - "requires": { - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" - } - }, - "es6-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.0.0.tgz", - "integrity": "sha1-8JTHBB9mJZm7EnINoFnWucf/D0A=" - }, - "es6-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", - "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.24", - "es6-symbol": "3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.24", - "es6-iterator": "2.0.1", - "es6-set": "0.1.5", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-promise": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", - "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=" - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.24", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.24" - } - }, - "es6-templates": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", - "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", - "dev": true, - "requires": { - "recast": "0.11.23", - "through": "2.3.8" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.24", - "es6-iterator": "2.0.1", - "es6-symbol": "3.1.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "2.7.3", - "estraverse": "1.9.3", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.2.0" - }, - "dependencies": { - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "0.1.5", - "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", - "estraverse": "4.2.0" - } - }, - "eslint": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.16.1.tgz", - "integrity": "sha1-m8MfxzQWks93LoBgdQj2fXEcVgk=", - "dev": true, - "requires": { - "babel-code-frame": "6.22.0", - "chalk": "1.1.3", - "concat-stream": "1.6.0", - "debug": "2.6.8", - "doctrine": "1.5.0", - "escope": "3.6.0", - "espree": "3.4.3", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "file-entry-cache": "2.0.0", - "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.3", - "imurmurhash": "0.1.4", - "inquirer": "0.12.0", - "is-my-json-valid": "2.16.0", - "is-resolvable": "1.0.0", - "js-yaml": "3.6.1", - "json-stable-stringify": "1.0.1", - "levn": "0.3.0", - "lodash": "4.17.2", - "mkdirp": "0.5.1", - "natural-compare": "1.4.0", - "optionator": "0.8.2", - "path-is-inside": "1.0.2", - "pluralize": "1.2.1", - "progress": "1.1.8", - "require-uncached": "1.0.3", - "shelljs": "0.7.8", - "strip-bom": "3.0.0", - "strip-json-comments": "2.0.1", - "table": "3.8.3", - "text-table": "0.2.0", - "user-home": "2.0.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "1.0.1" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "inquirer": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "1.4.0", - "ansi-regex": "2.1.1", - "chalk": "1.1.3", - "cli-cursor": "1.0.2", - "cli-width": "2.1.0", - "figures": "1.7.0", - "lodash": "4.17.2", - "readline2": "1.0.1", - "run-async": "0.1.0", - "rx-lite": "3.1.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "through": "2.3.8" - } - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "1.1.1", - "onetime": "1.1.0" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "1.4.0" - } - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "1.0.2" - } - } - } - }, - "eslint-config-semistandard": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-semistandard/-/eslint-config-semistandard-7.0.0.tgz", - "integrity": "sha1-+ANJP1alFy9/WcNa5kg2C0Hy/3E=", - "dev": true - }, - "eslint-config-standard": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-6.2.1.tgz", - "integrity": "sha1-06aKr8cZFjnn7kQec0hzkCY1QpI=", - "dev": true - }, - "eslint-config-standard-jsx": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.3.0.tgz", - "integrity": "sha1-yrCAGhWjYL9j+suXqyL73YjYpeA=", - "dev": true - }, - "eslint-config-standard-react": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard-react/-/eslint-config-standard-react-4.2.0.tgz", - "integrity": "sha1-0V/SXoN+IK/w2zL2T7VdEYgOuNA=", - "dev": true, - "requires": { - "eslint-config-standard-jsx": "3.3.0" - } - }, - "eslint-plugin-promise": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", - "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", - "dev": true - }, - "eslint-plugin-react": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.0.tgz", - "integrity": "sha1-nEi0jRAVVLU1VBPnxkI4q95u8e8=", - "dev": true, - "requires": { - "array.prototype.find": "2.0.4", - "doctrine": "1.5.0", - "has": "1.0.1", - "jsx-ast-utils": "1.4.1", - "object.assign": "4.0.4" - } - }, - "eslint-plugin-standard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", - "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", - "dev": true - }, - "espree": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", - "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", - "dev": true, - "requires": { - "acorn": "5.1.1", - "acorn-jsx": "3.0.1" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", - "dev": true, - "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" - }, - "etag": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.7.0.tgz", - "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=", - "dev": true - }, - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" - }, - "ethereumjs-tx": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.2.5.tgz", - "integrity": "sha1-7TbX/+uXvIicYe7xq3b0emE9goY=", - "requires": { - "ethereum-common": "0.0.18", - "ethereumjs-util": "5.1.2" - } - }, - "ethereumjs-util": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.2.tgz", - "integrity": "sha1-JboCFcu0wvCxCKb5avKi5i5Fkh8=", - "requires": { - "babel-preset-es2015": "6.24.1", - "babelify": "7.3.0", - "bn.js": "4.11.7", - "create-hash": "1.1.3", - "ethjs-util": "0.1.4", - "keccak": "1.3.0", - "rlp": "2.0.0", - "secp256k1": "3.3.0" - }, - "dependencies": { - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "requires": { - "babel-plugin-check-es2015-constants": "6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", - "babel-plugin-transform-es2015-block-scoping": "6.24.1", - "babel-plugin-transform-es2015-classes": "6.24.1", - "babel-plugin-transform-es2015-computed-properties": "6.24.1", - "babel-plugin-transform-es2015-destructuring": "6.23.0", - "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", - "babel-plugin-transform-es2015-for-of": "6.23.0", - "babel-plugin-transform-es2015-function-name": "6.24.1", - "babel-plugin-transform-es2015-literals": "6.22.0", - "babel-plugin-transform-es2015-modules-amd": "6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", - "babel-plugin-transform-es2015-modules-umd": "6.24.1", - "babel-plugin-transform-es2015-object-super": "6.24.1", - "babel-plugin-transform-es2015-parameters": "6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", - "babel-plugin-transform-es2015-spread": "6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "6.24.1", - "babel-plugin-transform-es2015-template-literals": "6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", - "babel-plugin-transform-es2015-unicode-regex": "6.24.1", - "babel-plugin-transform-regenerator": "6.24.1" - } - } - } - }, - "ethjs-util": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.4.tgz", - "integrity": "sha1-HItoeSV0RO9NPz+7rC3tEs2ZfZM=", - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1.0.0", - "es5-ext": "0.10.24" - } - }, - "eventemitter3": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.2.tgz", - "integrity": "sha1-IM5IkZCc6fNbCIyU+rQOLJb0c6w=" - }, - "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.0.tgz", - "integrity": "sha1-SXtmrZ/vZc18CKYYCCS6FHa2blM=", - "requires": { - "create-hash": "1.1.3" - } - }, - "exec-buffer": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", - "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", - "dev": true, - "requires": { - "execa": "0.7.0", - "p-finally": "1.0.0", - "pify": "3.0.0", - "rimraf": "2.6.1", - "tempfile": "2.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "exec-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", - "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", - "dev": true, - "requires": { - "async-each-series": "1.1.0", - "object-assign": "4.1.1" - } - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "5.1.0", - "get-stream": "3.0.0", - "is-stream": "1.1.0", - "npm-run-path": "2.0.2", - "p-finally": "1.0.0", - "signal-exit": "3.0.2", - "strip-eof": "1.0.0" - } - }, - "execall": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", - "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", - "dev": true, - "requires": { - "clone-regexp": "1.0.0" - } - }, - "executable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", - "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", - "dev": true, - "requires": { - "meow": "3.7.0" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "requires": { - "is-posix-bracket": "0.1.1" - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "requires": { - "fill-range": "2.2.3" - } - }, - "expand-template": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.0.3.tgz", - "integrity": "sha1-bDAzIxd6YrGyLAcCefeGEoe2mxo=" - }, - "express": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.14.1.tgz", - "integrity": "sha1-ZGwjf3ZvFIwhIK/wc4F7nk1+DTM=", - "dev": true, - "requires": { - "accepts": "1.3.3", - "array-flatten": "1.1.1", - "content-disposition": "0.5.2", - "content-type": "1.0.2", - "cookie": "0.3.1", - "cookie-signature": "1.0.6", - "debug": "2.2.0", - "depd": "1.1.1", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.7.0", - "finalhandler": "0.5.1", - "fresh": "0.3.0", - "merge-descriptors": "1.0.1", - "methods": "1.1.2", - "on-finished": "2.3.0", - "parseurl": "1.3.1", - "path-to-regexp": "0.1.7", - "proxy-addr": "1.1.5", - "qs": "6.2.0", - "range-parser": "1.2.0", - "send": "0.14.2", - "serve-static": "1.11.2", - "type-is": "1.6.15", - "utils-merge": "1.0.0", - "vary": "1.1.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "qs": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.0.tgz", - "integrity": "sha1-O3hIwDwt7OaalSKw+ujEEm10Xzs=", - "dev": true - } - } - }, - "extend": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", - "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "0.1.1" - } - }, - "external-editor": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", - "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", - "requires": { - "iconv-lite": "0.4.18", - "jschardet": "1.5.0", - "tmp": "0.0.31" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "requires": { - "is-extglob": "1.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - } - } - }, - "extract-loader": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/extract-loader/-/extract-loader-0.1.0.tgz", - "integrity": "sha1-ocFGkVJBzEhtUpImPHVV1aoZdm4=", - "dev": true, - "requires": { - "loader-utils": "0.2.17" - } - }, - "extract-text-webpack-plugin": { - "version": "2.0.0-beta.4", - "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.0.0-beta.4.tgz", - "integrity": "sha1-0yOTBp59kMgxjUg5IwJhi1a8G6k=", - "dev": true, - "requires": { - "async": "1.5.2", - "loader-utils": "0.2.17", - "webpack-sources": "0.1.5" - } - }, - "extsprintf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" - }, - "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" - } - }, - "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastparse": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", - "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", - "dev": true - }, - "fbjs": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz", - "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw=", - "requires": { - "core-js": "1.2.7", - "isomorphic-fetch": "2.2.1", - "loose-envify": "1.3.1", - "object-assign": "4.1.1", - "promise": "7.3.1", - "setimmediate": "1.0.5", - "ua-parser-js": "0.7.14" - }, - "dependencies": { - "core-js": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" - } - } - }, - "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", - "requires": { - "pend": "1.2.0" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "1.2.2", - "object-assign": "4.1.1" - } - }, - "file-loader": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.10.0.tgz", - "integrity": "sha1-u+bbdHSsksf1T9wZfPVH6YtrjhI=", - "dev": true, - "requires": { - "loader-utils": "0.2.17" - } - }, - "file-saver": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.3.tgz", - "integrity": "sha1-zdTETTqiZOrC9o7BZbx5HDSvEjI=" - }, - "file-type": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", - "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=" - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" - }, - "filename-reserved-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", - "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=" - }, - "filenamify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", - "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", - "requires": { - "filename-reserved-regex": "1.0.0", - "strip-outer": "1.0.0", - "trim-repeated": "1.0.0" - } - }, - "fileset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", - "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", - "dev": true, - "requires": { - "glob": "7.1.2", - "minimatch": "3.0.4" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "filesize": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.5.10.tgz", - "integrity": "sha1-/I+iPdtO+eXgq24eZPZ5okpWdh8=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" - } - }, - "finalhandler": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.1.tgz", - "integrity": "sha1-LEANjUUwk1vCMlScX6OF7Afeb80=", - "dev": true, - "requires": { - "debug": "2.2.0", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "statuses": "1.3.1", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "dev": true, - "requires": { - "commondir": "1.0.1", - "mkdirp": "0.5.1", - "pkg-dir": "1.0.0" - } - }, - "find-parent-dir": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz", - "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=", - "dev": true - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "find-versions": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", - "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", - "dev": true, - "requires": { - "array-uniq": "1.0.3", - "get-stdin": "4.0.1", - "meow": "3.7.0", - "semver-regex": "1.0.0" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - } - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" - }, - "flat": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-2.0.1.tgz", - "integrity": "sha1-cOKRiKdL4MPIlAnu0fqVd5B64y8=", - "requires": { - "is-buffer": "1.1.5" - } - }, - "flat-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", - "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", - "dev": true, - "requires": { - "circular-json": "0.3.3", - "del": "2.2.2", - "graceful-fs": "4.1.11", - "write": "0.2.1" - } - }, - "flatten": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", - "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", - "dev": true - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "requires": { - "for-in": "1.0.2" - } - }, - "foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.16" - } - }, - "format-json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/format-json/-/format-json-1.0.3.tgz", - "integrity": "sha1-Jo49PhaXkv9Ju1sDDyLIfKHCzZ8=" - }, - "format-number": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/format-number/-/format-number-2.0.1.tgz", - "integrity": "sha1-6SMah0PKZLR9CVVdzkApY0O+Zus=" - }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "1.1.2" - } - }, - "forwarded": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", - "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", - "dev": true - }, - "fresh": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.3.0.tgz", - "integrity": "sha1-ZR+DjiJCTnVm3hYdg1jKoZn4PU8=", - "dev": true - }, - "fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1", - "path-is-absolute": "1.0.1", - "rimraf": "2.6.1" - } - }, - "fs-readdir-recursive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz", - "integrity": "sha1-jNF0XItPiinIyuw5JHaSG6GV9WA=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-1.0.5.tgz", - "integrity": "sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=", - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "function-bind": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", - "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", - "dev": true - }, - "function.prototype.name": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.0.3.tgz", - "integrity": "sha512-5EblxZUdioXi2JiMZ9FUbwYj40eQ9MFHyzFLBSPdlRl3SO8l7SLWuAnQ/at/1Wi4hjJwME/C5WpF2ZfAc8nGNw==", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.0", - "is-callable": "1.1.3" - } - }, - "gather-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gather-stream/-/gather-stream-1.0.0.tgz", - "integrity": "sha1-szmUr0V6gRVwDUEPMXczy+egkEs=", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "requires": { - "aproba": "1.1.2", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "generate-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "1.0.2" - } - }, - "geopattern": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/geopattern/-/geopattern-1.2.3.tgz", - "integrity": "sha1-3pZgLkbbqQlcpXdL+zs2MI9+Y/4=", - "requires": { - "extend": "1.2.1" - } - }, - "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" - }, - "get-own-enumerable-property-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-1.0.1.tgz", - "integrity": "sha1-8dTjrRQC4DmJjlbR6bmqkkwm5IQ=" - }, - "get-proxy": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", - "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", - "requires": { - "rc": "1.2.1" - } - }, - "get-stdin": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-3.0.2.tgz", - "integrity": "sha1-wc7SS5A5s43thb3xYeV3E7bdSr4=" - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "gifsicle": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", - "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" - } - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "requires": { - "is-glob": "2.0.1" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "requires": { - "extend": "3.0.1", - "glob": "5.0.15", - "glob-parent": "3.1.0", - "micromatch": "2.3.11", - "ordered-read-streams": "0.3.0", - "through2": "0.6.5", - "to-absolute-glob": "0.1.1", - "unique-stream": "2.2.1" - }, - "dependencies": { - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - } - } - }, - "global": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", - "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", - "dev": true, - "requires": { - "min-document": "2.19.0", - "process": "0.5.2" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", - "dev": true - }, - "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "requires": { - "sparkles": "1.0.0" - } - }, - "got": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", - "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", - "requires": { - "create-error-class": "3.0.2", - "duplexer2": "0.1.4", - "is-redirect": "1.0.0", - "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", - "lowercase-keys": "1.0.0", - "node-status-codes": "1.0.0", - "object-assign": "4.1.1", - "parse-json": "2.2.0", - "pinkie-promise": "2.0.1", - "read-all-stream": "3.1.0", - "readable-stream": "2.3.3", - "timed-out": "3.1.3", - "unzip-response": "1.0.2", - "url-parse-lax": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gulp-decompress": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", - "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", - "requires": { - "archive-type": "3.2.0", - "decompress": "3.0.0", - "gulp-util": "3.0.8", - "readable-stream": "2.3.3" - } - }, - "gulp-rename": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", - "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=" - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "through2": "2.0.3", - "vinyl": "1.2.0" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - } - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.0.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" - }, - "dependencies": { - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" - }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "requires": { - "glogg": "1.0.0" - } - }, - "handlebars": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", - "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", - "dev": true, - "requires": { - "async": "1.5.2", - "optimist": "0.6.1", - "source-map": "0.4.4", - "uglify-js": "2.8.16" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "happypack": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/happypack/-/happypack-3.0.3.tgz", - "integrity": "sha1-IveMh6MlzbeYyVjPTsOD/NTW/cc=", - "dev": true, - "requires": { - "async": "1.5.0", - "json-stringify-safe": "5.0.1", - "loader-utils": "0.2.16", - "mkdirp": "0.5.1" - }, - "dependencies": { - "async": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.0.tgz", - "integrity": "sha1-J5ZkJyNXOFlWVjP8YnRES+4vjOM=", - "dev": true - }, - "loader-utils": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.16.tgz", - "integrity": "sha1-8IYyBm7YKCg13/iN+1JwR2Wt7m0=", - "dev": true, - "requires": { - "big.js": "3.1.3", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - } - } - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" - } - } - }, - "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true, - "requires": { - "function-bind": "1.1.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "requires": { - "sparkles": "1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" - }, - "hash-base": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", - "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", - "requires": { - "inherits": "2.0.3" - } - }, - "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "requires": { - "inherits": "2.0.3", - "minimalistic-assert": "1.0.0" - } - }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "history": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/history/-/history-3.3.0.tgz", - "integrity": "sha1-/O3M6PEpdTcVRdc1RhAzV5ptrpw=", - "requires": { - "invariant": "2.2.2", - "loose-envify": "1.3.1", - "query-string": "4.3.4", - "warning": "3.0.0" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "requires": { - "hash.js": "1.1.3", - "minimalistic-assert": "1.0.0", - "minimalistic-crypto-utils": "1.0.1" - } - }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" - }, - "hoist-non-react-statics": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", - "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=" - }, - "home-or-tmp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" - }, - "html": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/html/-/html-1.0.0.tgz", - "integrity": "sha1-pUT6nqVJK/s6LMqCEKEL57WvH2E=", - "dev": true, - "requires": { - "concat-stream": "1.6.0" - } - }, - "html-comment-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", - "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", - "dev": true - }, - "html-encoding-sniffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.1.tgz", - "integrity": "sha1-eb96eF6klf5mFl5zQVPzY/9UN9o=", - "dev": true, - "requires": { - "whatwg-encoding": "1.0.1" - } - }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", - "dev": true - }, - "html-loader": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.4.4.tgz", - "integrity": "sha1-8rW5rNXgNf86tf02nBPJenuwFNo=", - "dev": true, - "requires": { - "es6-templates": "0.2.3", - "fastparse": "1.1.1", - "html-minifier": "3.5.3", - "loader-utils": "0.2.17", - "object-assign": "4.1.1" - } - }, - "html-minifier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.3.tgz", - "integrity": "sha512-iKRzQQDuTCsq0Ultbi/mfJJnR0D3AdZKTq966Gsp92xkmAPCV4Xi08qhJ0Dl3ZAWemSgJ7qZK+UsZc0gFqK6wg==", - "dev": true, - "requires": { - "camel-case": "3.0.0", - "clean-css": "4.1.7", - "commander": "2.11.0", - "he": "1.1.1", - "ncname": "1.0.0", - "param-case": "2.1.1", - "relateurl": "0.2.7", - "uglify-js": "3.0.27" - }, - "dependencies": { - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", - "dev": true - }, - "uglify-js": { - "version": "3.0.27", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.27.tgz", - "integrity": "sha512-HD8CmxPXUI62v5tweiulMcP/apAtx1DXGcNZkhKQZyC+MTrTsoCBb8yPAwVrbvpgw3EpRU76bRe6axjIiCYcQg==", - "dev": true, - "requires": { - "commander": "2.11.0", - "source-map": "0.5.6" - } - } - } - }, - "html-tags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-1.2.0.tgz", - "integrity": "sha1-x43mW1Zjqll5id0rerSSANfk25g=", - "dev": true - }, - "html-webpack-plugin": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-2.28.0.tgz", - "integrity": "sha1-LnhjtX5f1I/iYzA+L/yTTDBk0Ak=", - "dev": true, - "requires": { - "bluebird": "3.5.0", - "html-minifier": "3.5.3", - "loader-utils": "0.2.17", - "lodash": "4.17.4", - "pretty-error": "2.1.1", - "toposort": "1.0.3" - }, - "dependencies": { - "bluebird": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", - "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=", - "dev": true - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - } - } - }, - "htmlparser2": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", - "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.4.1", - "domutils": "1.5.1", - "entities": "1.1.1", - "inherits": "2.0.3", - "readable-stream": "2.3.3" - } - }, - "http-errors": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.5.1.tgz", - "integrity": "sha1-eIwNLB3iyBuebowBhDtrl+uSB1A=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "setprototypeof": "1.0.2", - "statuses": "1.3.1" - } - }, - "http-proxy": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", - "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", - "dev": true, - "requires": { - "eventemitter3": "1.2.0", - "requires-port": "1.0.0" - }, - "dependencies": { - "eventemitter3": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", - "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", - "dev": true - } - } - }, - "http-proxy-middleware": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.3.tgz", - "integrity": "sha1-lAOCFHFJuFYIT1U0dS1bWoFozR0=", - "dev": true, - "requires": { - "http-proxy": "1.16.2", - "is-glob": "3.1.0", - "lodash": "4.17.2", - "micromatch": "2.3.11" - } - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.1" - } - }, - "https-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", - "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", - "dev": true - }, - "humanize": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz", - "integrity": "sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ=", - "dev": true - }, - "husky": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/husky/-/husky-0.13.1.tgz", - "integrity": "sha1-Ee/G/BDg7E54l3b2WCvjfXG6TM8=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "find-parent-dir": "0.3.0", - "is-ci": "1.0.10", - "normalize-path": "1.0.0" - }, - "dependencies": { - "normalize-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz", - "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k=", - "dev": true - } - } - }, - "hyphenate-style-name": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz", - "integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es=" - }, - "iconv-lite": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" - }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, - "ieee754": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", - "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", - "dev": true - }, - "ignore": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", - "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", - "dev": true - }, - "ignore-styles": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-styles/-/ignore-styles-5.0.1.tgz", - "integrity": "sha1-tJ7yJ0va/NikiAqWa/440aC/RnE=", - "dev": true - }, - "image-webpack-loader": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/image-webpack-loader/-/image-webpack-loader-3.2.0.tgz", - "integrity": "sha1-8mMG1gSNOi9ajYROyu3StxSPCk4=", - "dev": true, - "requires": { - "file-loader": "0.9.0", - "imagemin": "5.3.1", - "imagemin-gifsicle": "5.2.0", - "imagemin-mozjpeg": "6.0.0", - "imagemin-optipng": "5.2.1", - "imagemin-pngquant": "5.0.1", - "imagemin-svgo": "5.2.2", - "loader-utils": "0.2.17" - }, - "dependencies": { - "file-loader": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.9.0.tgz", - "integrity": "sha1-HS2t3UJM5tGwfP4/eXMb7TYXq0I=", - "dev": true, - "requires": { - "loader-utils": "0.2.17" - } - } - } - }, - "imagemin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", - "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", - "dev": true, - "requires": { - "file-type": "4.4.0", - "globby": "6.1.0", - "make-dir": "1.0.0", - "p-pipe": "1.2.0", - "pify": "2.3.0", - "replace-ext": "1.0.0" - }, - "dependencies": { - "file-type": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", - "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - } - } - }, - "imagemin-gifsicle": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", - "integrity": "sha512-K01m5QuPK+0en8oVhiOOAicF7KjrHlCZxS++mfLI2mV/Ksfq/Y9nCXCWDz6jRv13wwlqe5T7hXT+ji2DnLc2yQ==", - "dev": true, - "requires": { - "exec-buffer": "3.2.0", - "gifsicle": "3.0.4", - "is-gif": "1.0.0" - } - }, - "imagemin-mozjpeg": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/imagemin-mozjpeg/-/imagemin-mozjpeg-6.0.0.tgz", - "integrity": "sha1-caMqRXqhsmEXpo7u8tmxkMLlCR4=", - "dev": true, - "requires": { - "exec-buffer": "3.2.0", - "is-jpg": "1.0.0", - "mozjpeg": "4.1.1" - } - }, - "imagemin-optipng": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", - "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", - "dev": true, - "requires": { - "exec-buffer": "3.2.0", - "is-png": "1.1.0", - "optipng-bin": "3.1.4" - } - }, - "imagemin-pngquant": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/imagemin-pngquant/-/imagemin-pngquant-5.0.1.tgz", - "integrity": "sha1-2KMp2lU6+iJrEc5i3r4Lfje0OeY=", - "dev": true, - "requires": { - "exec-buffer": "3.2.0", - "is-png": "1.1.0", - "pngquant-bin": "3.1.1" - } - }, - "imagemin-svgo": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-5.2.2.tgz", - "integrity": "sha1-UBaZ9XiXMKV5IrhzbqFcU/e1WDg=", - "dev": true, - "requires": { - "is-svg": "2.1.0", - "svgo": "0.7.2" - } - }, - "immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" - }, - "in-publish": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=" - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "requires": { - "repeating": "2.0.1" - } - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" - }, - "inline-style-prefixer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz", - "integrity": "sha1-wVPH6I/YT+9cYC6VqBaLJ3BnH+c=", - "requires": { - "bowser": "1.7.1", - "hyphenate-style-name": "1.0.2" - } - }, - "inquirer": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.1.tgz", - "integrity": "sha512-QgW3eiPN8gpj/K5vVpHADJJgrrF0ho/dZGylikGX7iqAdRgC9FVKYKWFLx6hZDBFcOLEoSqINYrVPeFAeG/PdA==", - "requires": { - "ansi-escapes": "2.0.0", - "chalk": "2.0.1", - "cli-cursor": "2.1.0", - "cli-width": "2.1.0", - "external-editor": "2.0.4", - "figures": "2.0.0", - "lodash": "4.17.2", - "mute-stream": "0.0.7", - "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", - "string-width": "2.1.1", - "strip-ansi": "4.0.0", - "through": "2.3.8" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==", - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "3.0.0" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "interpret": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", - "dev": true - }, - "intl-format-cache": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/intl-format-cache/-/intl-format-cache-2.0.5.tgz", - "integrity": "sha1-tITO/Lk1PzdPJd44mjzuoa8Y18k=" - }, - "intl-messageformat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-1.3.0.tgz", - "integrity": "sha1-99kmre16OrGbLcYB79VOmaS9Tq4=", - "requires": { - "intl-messageformat-parser": "1.2.0" - } - }, - "intl-messageformat-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/intl-messageformat-parser/-/intl-messageformat-parser-1.2.0.tgz", - "integrity": "sha1-WQa3+VOrdHDg3IVJCXtki5kYkv8=" - }, - "intl-relativeformat": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/intl-relativeformat/-/intl-relativeformat-1.3.0.tgz", - "integrity": "sha1-iT3HB2/M04DPCRojAMOA+les5Fs=", - "requires": { - "intl-messageformat": "1.3.0" - } - }, - "invariant": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "requires": { - "loose-envify": "1.3.1" - } - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" - }, - "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", - "dev": true - }, - "ipaddr.js": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz", - "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=", - "dev": true - }, - "irregular-plurals": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.3.0.tgz", - "integrity": "sha512-njf5A+Mxb3kojuHd1DzISjjIl+XhyzovXEOyPPSzdQozq/Lf2tN27mOrAAsxEPZxpn6I4MGzs1oo9TxXxPFpaA==", - "dev": true - }, - "is-absolute": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", - "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", - "requires": { - "is-relative": "0.1.3" - } - }, - "is-absolute-url": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", - "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "1.9.0" - } - }, - "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "requires": { - "builtin-modules": "1.1.1" - } - }, - "is-bzip2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", - "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=" - }, - "is-callable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, - "is-ci": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", - "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", - "requires": { - "ci-info": "1.0.0" - } - }, - "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-dom": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.0.9.tgz", - "integrity": "sha1-SDgy1SlyBz3hK5/j9gMghw2oNw0=" - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "requires": { - "is-primitive": "2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-gif": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", - "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "2.1.1" - } - }, - "is-gzip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", - "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=" - }, - "is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" - }, - "is-jpg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.0.tgz", - "integrity": "sha1-KVnBfnNDDbOCZNp1uQ3VTy2G2hw=", - "dev": true - }, - "is-my-json-valid": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", - "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", - "dev": true, - "requires": { - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "jsonpointer": "4.0.1", - "xtend": "4.0.1" - } - }, - "is-natural-number": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", - "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=" - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "requires": { - "kind-of": "3.2.2" - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true, - "requires": { - "is-path-inside": "1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "dev": true, - "requires": { - "path-is-inside": "1.0.2" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "requires": { - "isobject": "3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" - } - } - }, - "is-png": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", - "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", - "dev": true - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" - }, - "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, - "requires": { - "has": "1.0.1" - } - }, - "is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" - }, - "is-relative": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", - "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=" - }, - "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-subset": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", - "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", - "dev": true - }, - "is-supported-regexp-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz", - "integrity": "sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g=", - "dev": true - }, - "is-svg": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", - "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", - "dev": true, - "requires": { - "html-comment-regex": "1.1.1" - } - }, - "is-symbol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-tar": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", - "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=" - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "is-url": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.2.tgz", - "integrity": "sha1-SYkFpZO/R8wtnn9zg3K792lsfyY=" - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" - }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=" - }, - "is-zip": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", - "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=" - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", - "requires": { - "node-fetch": "1.7.1", - "whatwg-fetch": "2.0.1" - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, - "istanbul": { - "version": "1.0.0-alpha.2", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-1.0.0-alpha.2.tgz", - "integrity": "sha1-BglrwI6Yuq10Sq5Gli2N+frGPQg=", - "dev": true, - "requires": { - "abbrev": "1.0.9", - "async": "1.5.2", - "istanbul-api": "1.1.11", - "js-yaml": "3.6.1", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "which": "1.2.14", - "wordwrap": "1.0.0" - }, - "dependencies": { - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } - }, - "istanbul-api": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.1.11.tgz", - "integrity": "sha1-/MC0YeKzvaceMFFVE4I4doJX2d4=", - "dev": true, - "requires": { - "async": "2.5.0", - "fileset": "2.0.3", - "istanbul-lib-coverage": "1.1.1", - "istanbul-lib-hook": "1.0.7", - "istanbul-lib-instrument": "1.7.4", - "istanbul-lib-report": "1.1.1", - "istanbul-lib-source-maps": "1.2.1", - "istanbul-reports": "1.1.1", - "js-yaml": "3.9.1", - "mkdirp": "0.5.1", - "once": "1.4.0" - }, - "dependencies": { - "async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", - "dev": true, - "requires": { - "lodash": "4.17.2" - } - }, - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - }, - "js-yaml": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "4.0.0" - } - } - } - }, - "istanbul-lib-coverage": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz", - "integrity": "sha512-0+1vDkmzxqJIn5rcoEqapSB4DmPxE31EtI2dF2aCkV5esN9EWHxZ0dwgDClivMXJqE7zaYQxq30hj5L0nlTN5Q==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz", - "integrity": "sha512-3U2HB9y1ZV9UmFlE12Fx+nPtFqIymzrqCksrXujm3NVbAZIJg/RfYgO1XiIa0mbmxTjWpVEVlkIZJ25xVIAfkQ==", - "dev": true, - "requires": { - "append-transform": "0.4.0" - } - }, - "istanbul-lib-instrument": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.4.tgz", - "integrity": "sha1-6f2SDkdn89Ge3HZeLWs/XMvQ7qg=", - "dev": true, - "requires": { - "babel-generator": "6.25.0", - "babel-template": "6.25.0", - "babel-traverse": "6.25.0", - "babel-types": "6.25.0", - "babylon": "6.17.4", - "istanbul-lib-coverage": "1.1.1", - "semver": "5.4.1" - } - }, - "istanbul-lib-report": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz", - "integrity": "sha512-tvF+YmCmH4thnez6JFX06ujIA19WPa9YUiwjc1uALF2cv5dmE3It8b5I8Ob7FHJ70H9Y5yF+TDkVa/mcADuw1Q==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "1.1.1", - "mkdirp": "0.5.1", - "path-parse": "1.0.5", - "supports-color": "3.2.3" - }, - "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz", - "integrity": "sha512-mukVvSXCn9JQvdJl8wP/iPhqig0MRtuWuD4ZNKo6vB2Ik//AmhAKe3QnPN02dmkRe3lTudFk3rzoHhwU4hb94w==", - "dev": true, - "requires": { - "debug": "2.6.8", - "istanbul-lib-coverage": "1.1.1", - "mkdirp": "0.5.1", - "rimraf": "2.6.1", - "source-map": "0.5.6" - } - }, - "istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-P8G873A0kW24XRlxHVGhMJBhQ8gWAec+dae7ZxOBzxT4w+a9ATSPvRVK3LB1RAJ9S8bg2tOyWHAGW40Zd2dKfw==", - "dev": true, - "requires": { - "handlebars": "4.0.10" - } - }, - "js-base64": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", - "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=", - "dev": true - }, - "js-sha3": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz", - "integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko=" - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" - }, - "js-yaml": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "2.7.3" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "optional": true - }, - "jschardet": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.0.tgz", - "integrity": "sha512-+Q8JsoEQbrdE+a/gg1F9XO92gcKXgpE5UACqr0sIubjDmBEkd+OOWPGzQeMrWSLxd73r4dHxBeRW7edHu5LmJQ==" - }, - "jsdom": { - "version": "9.11.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-9.11.0.tgz", - "integrity": "sha1-qVsDBOUhospaY8bqR793CKeoRZE=", - "dev": true, - "requires": { - "abab": "1.0.3", - "acorn": "4.0.13", - "acorn-globals": "3.1.0", - "array-equal": "1.0.0", - "content-type-parser": "1.0.1", - "cssom": "0.3.2", - "cssstyle": "0.2.37", - "escodegen": "1.8.1", - "html-encoding-sniffer": "1.0.1", - "nwmatcher": "1.4.1", - "parse5": "1.5.1", - "request": "2.81.0", - "sax": "1.2.4", - "symbol-tree": "3.2.2", - "tough-cookie": "2.3.2", - "webidl-conversions": "4.0.1", - "whatwg-encoding": "1.0.1", - "whatwg-url": "4.8.0", - "xml-name-validator": "2.0.1" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - } - } - }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - }, - "json-loader": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.4.tgz", - "integrity": "sha1-i6oTZaYy9Yo8RtIBdfxgAsluN94=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11" - } - }, - "jsonfilter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", - "integrity": "sha1-Ie987cdRk4E8dZMulqmL4gW6WhE=", - "dev": true, - "requires": { - "JSONStream": "0.8.4", - "minimist": "1.2.0", - "stream-combiner": "0.2.2", - "through2": "0.6.5" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "JSONStream": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", - "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", - "dev": true, - "requires": { - "jsonparse": "0.0.5", - "through": "2.3.8" - } - }, - "jsprim": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "jsqr": { - "version": "git+https://github.com/JodusNodus/jsQR.git#5ba1acefa1cbb9b2bc92b49f503f2674e2ec212b" - }, - "jsx-ast-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", - "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", - "dev": true - }, - "keccak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.3.0.tgz", - "integrity": "sha512-JgsKPxYhcJxKrV+TrCyg/GwZbOjhpRPrz2kG8xbAsUaIDelUlKjm08YcwBO9Fm8sqf/Kg8ZWkk6nWujhLykfvw==", - "requires": { - "bindings": "1.3.0", - "inherits": "2.0.3", - "nan": "2.6.2", - "prebuild-install": "2.2.1", - "safe-buffer": "5.1.1" - } - }, - "keycode": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.1.9.tgz", - "integrity": "sha1-lkojxU5IiUBbSGGlyfBIDUUUHfo=" - }, - "keythereum": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/keythereum/-/keythereum-0.4.6.tgz", - "integrity": "sha1-D97Hz5OK455eMGGy9uFmd7dmxdo=", - "requires": { - "elliptic": "6.4.0", - "ethereumjs-util": "5.1.1", - "sjcl": "1.0.6", - "uuid": "3.0.0", - "validator": "4.0.2" - }, - "dependencies": { - "ethereumjs-util": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.1.tgz", - "integrity": "sha1-Ei+zjep0fcYrOuv8Nl0b1Ivktz4=", - "requires": { - "bn.js": "4.11.7", - "create-hash": "1.1.3", - "ethjs-util": "0.1.4", - "keccak": "1.3.0", - "rlp": "2.0.0", - "secp256k1": "3.3.0" - } - }, - "validator": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/validator/-/validator-4.0.2.tgz", - "integrity": "sha1-cKHCUl7EdE5AmXHBspiqaadTQlE=" - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.5" - } - }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11" - } - }, - "known-css-properties": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.0.6.tgz", - "integrity": "sha1-caC4/eG240McRx77w9lzP667z78=", - "dev": true - }, - "laggard": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/laggard/-/laggard-0.1.0.tgz", - "integrity": "sha1-Lv1kX38tjz0nrICAOcqGqO40EHU=", - "dev": true, - "requires": { - "minimist": "1.2.0", - "pixrem": "3.0.2", - "postcss": "5.2.17", - "postcss-color-rgba-fallback": "2.2.0", - "postcss-opacity": "3.0.0", - "postcss-pseudoelements": "3.0.0", - "postcss-reporter": "1.4.1", - "postcss-vmin": "2.0.0", - "postcss-will-change": "1.1.0", - "read-file-stdin": "0.2.1", - "write-file-stdout": "0.0.2" - }, - "dependencies": { - "postcss-opacity": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-opacity/-/postcss-opacity-3.0.0.tgz", - "integrity": "sha1-eHm8xzRAW/dKpsgcORdiBS/FWyk=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", - "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "lodash": "4.17.2", - "log-symbols": "1.0.2", - "postcss": "5.2.17" - } - } - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" - }, - "lazy-req": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", - "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", - "dev": true - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "requires": { - "readable-stream": "2.3.3" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "requires": { - "invert-kv": "1.0.0" - } - }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, - "ldjson-stream": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ldjson-stream/-/ldjson-stream-1.2.1.tgz", - "integrity": "sha1-kb7O2lrE7SsX5kn7d356v6AYnCs=", - "dev": true, - "requires": { - "split2": "0.2.1", - "through2": "0.6.5" - } - }, - "leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha1-wuep93IJTe6dNCAq6KzORoeHVYA=" - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" - } - }, - "lie": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", - "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", - "requires": { - "immediate": "3.0.6" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - } - }, - "loader-runner": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", - "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", - "dev": true - }, - "loader-utils": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", - "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", - "requires": { - "big.js": "3.1.3", - "emojis-list": "2.1.0", - "json5": "0.5.1", - "object-assign": "4.1.1" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "2.0.0", - "path-exists": "3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.2.tgz", - "integrity": "sha1-NKMFW6vgTOQkZ7YH1wAHLH/2v0I=" - }, - "lodash-es": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", - "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" - }, - "lodash.assign": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", - "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" - }, - "lodash.assignin": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", - "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=", - "dev": true - }, - "lodash.bind": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", - "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=", - "dev": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._basecreate": "3.0.3", - "lodash._isiterateecall": "3.0.9" - } - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "requires": { - "lodash._root": "3.0.1" - } - }, - "lodash.filter": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", - "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.foreach": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", - "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" - } - }, - "lodash.map": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", - "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", - "dev": true - }, - "lodash.merge": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.0.tgz", - "integrity": "sha1-aYhLoUSsM/5plzemCG3v+t0PicU=" - }, - "lodash.pad": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", - "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=" - }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" - }, - "lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" - }, - "lodash.pick": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "lodash.pickby": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", - "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=", - "dev": true - }, - "lodash.reduce": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", - "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=", - "dev": true - }, - "lodash.reject": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", - "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=", - "dev": true - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" - }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" - } - }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" - }, - "lodash.toarray": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "log-driver": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", - "dev": true - }, - "log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true, - "requires": { - "chalk": "1.1.3" - } - }, - "logalot": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", - "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", - "dev": true, - "requires": { - "figures": "1.7.0", - "squeak": "1.3.0" - }, - "dependencies": { - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "1.0.5", - "object-assign": "4.1.1" - } - } - } - }, - "loglevel": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.4.1.tgz", - "integrity": "sha1-lbOD+Ro8J1b9SrCTZn5DCRYfK80=" - }, - "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" - }, - "loose-envify": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "requires": { - "js-tokens": "3.0.2" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", - "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" - }, - "lpad-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", - "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "indent-string": "2.1.0", - "longest": "1.0.1", - "meow": "3.7.0" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - } - } - }, - "lru-cache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", - "dev": true, - "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" - } - }, - "macaddress": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", - "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", - "dev": true - }, - "make-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", - "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" - }, - "markdown-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-loader/-/markdown-loader-2.0.0.tgz", - "integrity": "sha1-Qhhi04xCJP02FetkgBfqOFtWLXg=", - "dev": true, - "requires": { - "loader-utils": "0.2.17", - "marked": "0.3.6" - } - }, - "marked": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", - "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=" - }, - "material-ui": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/material-ui/-/material-ui-0.16.5.tgz", - "integrity": "sha1-u4ZhqsfKyMsiOj529PV+4YpK78E=", - "requires": { - "babel-runtime": "6.23.0", - "inline-style-prefixer": "2.0.5", - "keycode": "2.1.9", - "lodash.merge": "4.6.0", - "lodash.throttle": "4.1.1", - "react-addons-create-fragment": "15.6.0", - "react-addons-transition-group": "15.6.0", - "react-event-listener": "0.4.1", - "recompose": "0.20.2", - "simple-assign": "0.1.0", - "warning": "3.0.0" - } - }, - "material-ui-chip-input": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/material-ui-chip-input/-/material-ui-chip-input-0.11.1.tgz", - "integrity": "sha1-6Sssxcl0HNddaxgi8cd3GtTObBA=" - }, - "math-expression-evaluator": { - "version": "1.2.17", - "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", - "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=" - }, - "mdurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", - "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "0.1.4", - "readable-stream": "2.3.3" - } - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "requires": { - "readable-stream": "2.3.3" - } - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.3" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "miller-rabin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz", - "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "brorand": "1.1.0" - } - }, - "mime": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, - "mime-db": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.29.0.tgz", - "integrity": "sha1-SNJtI1WJZRcErFkWygYAGRQmaHg=" - }, - "mime-types": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.16.tgz", - "integrity": "sha1-K4WKUuXs1RbbiXrCvodIeDBpjiM=", - "requires": { - "mime-db": "1.29.0" - } - }, - "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" - }, - "min-document": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", - "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", - "dev": true, - "requires": { - "dom-walk": "0.1.1" - } - }, - "minimalistic-assert": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", - "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "requires": { - "brace-expansion": "1.1.8" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - } - } - }, - "mobx": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/mobx/-/mobx-2.6.4.tgz", - "integrity": "sha1-4FqRpbLJfaw/2rNAJOa3Sn9DEas=" - }, - "mobx-react": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-4.0.3.tgz", - "integrity": "sha1-QOsx0l4LjWMEjtojdsxWv6vRT3U=", - "requires": { - "hoist-non-react-statics": "1.2.0" - } - }, - "mobx-react-devtools": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/mobx-react-devtools/-/mobx-react-devtools-4.2.10.tgz", - "integrity": "sha1-eSdL2NRLoE2VByhzihRFQfoqYBI=" - }, - "mocha": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.2.0.tgz", - "integrity": "sha1-fcT0XlCIB1FxpoiWgU5q6et6heM=", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.5", - "glob": "7.0.5", - "growl": "1.9.2", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } - }, - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "glob": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.5.tgz", - "integrity": "sha1-tCAqaQmbu00pKnwblbZoK2fr3JU=", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "mock-local-storage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/mock-local-storage/-/mock-local-storage-1.0.2.tgz", - "integrity": "sha1-plplzdq0cHQz1Suk6fa2MIS4wpg=", - "dev": true, - "requires": { - "core-js": "0.8.4" - }, - "dependencies": { - "core-js": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-0.8.4.tgz", - "integrity": "sha1-wiZl8eDRucPF4bCNq9HxCGleT88=", - "dev": true - } - } - }, - "mock-socket": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-6.0.4.tgz", - "integrity": "sha1-hfWKCqg7wdtMp9FLQtj53WY+dWk=", - "dev": true - }, - "moment": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.17.0.tgz", - "integrity": "sha1-pMKS4CqsXd77Kabu0k9Rk43Tt08=" - }, - "mozjpeg": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-4.1.1.tgz", - "integrity": "sha1-hZAwsk9omlPbm0DwFg2JGVuI/VA=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "3.0.4" - } - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "requires": { - "duplexer2": "0.0.2" - }, - "dependencies": { - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "requires": { - "readable-stream": "1.1.14" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" - }, - "nan": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.6.2.tgz", - "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=" - }, - "napa": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/napa/-/napa-2.3.0.tgz", - "integrity": "sha1-QZZUbRoLa7lPNwQgU8xd3XlzHlM=", - "requires": { - "download": "4.4.3", - "extend": "3.0.1", - "load-json-file": "1.1.0", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "npm-cache-filename": "1.0.2", - "npmlog": "2.0.4", - "rimraf": "2.6.1", - "tar-pack": "3.4.0", - "write-json-file": "1.2.0" - }, - "dependencies": { - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "requires": { - "ansi": "0.3.1", - "has-unicode": "2.0.1", - "lodash.pad": "4.5.1", - "lodash.padend": "4.6.1", - "lodash.padstart": "4.6.1" - } - }, - "npmlog": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", - "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", - "requires": { - "ansi": "0.3.1", - "are-we-there-yet": "1.1.4", - "gauge": "1.2.7" - } - } - } - }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "ncname": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", - "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", - "dev": true, - "requires": { - "xml-char-classes": "1.0.0" - } - }, - "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - }, - "no-case": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.1.tgz", - "integrity": "sha1-euuhxzpSGEJlVUt9wDuvcg34AIE=", - "dev": true, - "requires": { - "lower-case": "1.1.4" - } - }, - "nock": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/nock/-/nock-9.0.7.tgz", - "integrity": "sha1-zJNIG7FfOL7Co5xEQr4HglI1saE=", - "dev": true, - "requires": { - "chai": "3.5.0", - "debug": "2.6.8", - "deep-equal": "1.0.1", - "json-stringify-safe": "5.0.1", - "lodash": "4.17.2", - "mkdirp": "0.5.1", - "propagate": "0.4.0", - "qs": "6.3.0" - } - }, - "node-abi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.1.0.tgz", - "integrity": "sha512-AbW35CPRE4vdieOse46V+16dKispLNv3PQwgqlcfg7GQeQHcLu3gvp3fbU2gTh7d8NfGjp5CJh+j4Hpyb0XzaA==" - }, - "node-dir": { - "version": "0.1.17", - "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", - "integrity": "sha1-X1Zl2TNRM1yqvvjxxVRRbPXx5OU=", - "dev": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "node-emoji": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", - "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", - "requires": { - "lodash.toarray": "4.4.0" - } - }, - "node-fetch": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz", - "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==", - "requires": { - "encoding": "0.1.12", - "is-stream": "1.1.0" - } - }, - "node-gyp": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", - "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", - "requires": { - "fstream": "1.0.11", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "nopt": "3.0.6", - "npmlog": "4.1.2", - "osenv": "0.1.4", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "which": "1.2.14" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - } - } - }, - "node-libs-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.0.0.tgz", - "integrity": "sha1-o6WeyXAkmFtG6Vg3lkb5bEthZkY=", - "dev": true, - "requires": { - "assert": "1.4.1", - "browserify-zlib": "0.1.4", - "buffer": "4.9.1", - "console-browserify": "1.1.0", - "constants-browserify": "1.0.0", - "crypto-browserify": "3.11.1", - "domain-browser": "1.1.7", - "events": "1.1.1", - "https-browserify": "0.0.1", - "os-browserify": "0.2.1", - "path-browserify": "0.0.0", - "process": "0.11.10", - "punycode": "1.4.1", - "querystring-es3": "0.2.1", - "readable-stream": "2.3.3", - "stream-browserify": "2.0.1", - "stream-http": "2.7.2", - "string_decoder": "0.10.31", - "timers-browserify": "2.0.3", - "tty-browserify": "0.0.0", - "url": "0.11.0", - "util": "0.10.3", - "vm-browserify": "0.0.4" - }, - "dependencies": { - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "node-status-codes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", - "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=" - }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1.1.0" - } - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "requires": { - "remove-trailing-separator": "1.0.2" - } - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-selector": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", - "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" - } - }, - "npm-cache-filename": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz", - "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "2.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "nth-check": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", - "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", - "dev": true, - "requires": { - "boolbase": "1.0.0" - } - }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", - "dev": true - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" - }, - "nwmatcher": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.1.tgz", - "integrity": "sha1-eumwew6oBNt+JfBctf5Al9TklJ8=", - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" - }, - "object-is": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true - }, - "object-keys": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=" - }, - "object.assign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.0.4.tgz", - "integrity": "sha1-scnMBE7xuf5jYG/BQau7MuFHMMw=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "function-bind": "1.1.0", - "object-keys": "1.0.11" - } - }, - "object.entries": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", - "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.7.0", - "function-bind": "1.1.0", - "has": "1.0.1" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, - "object.values": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", - "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", - "dev": true, - "requires": { - "define-properties": "1.1.2", - "es-abstract": "1.7.0", - "function-bind": "1.1.0", - "has": "1.0.1" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1.0.2" - } - }, - "onecolor": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-3.0.4.tgz", - "integrity": "sha1-daRvgNpseqpbTarhekcZi9llJJQ=", - "dev": true - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.2" - }, - "dependencies": { - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - } - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" - }, - "dependencies": { - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - } - } - }, - "optipng-bin": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", - "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" - } - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "requires": { - "is-stream": "1.1.0", - "readable-stream": "2.3.3" - } - }, - "os-browserify": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz", - "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=", - "dev": true - }, - "os-filter-obj": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", - "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "requires": { - "lcid": "1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "osenv": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", - "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "output-file-sync": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", - "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "1.1.0" - } - }, - "p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "2.3.1" - } - }, - "parse-asn1": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", - "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", - "dev": true, - "requires": { - "asn1.js": "4.9.1", - "browserify-aes": "1.0.6", - "create-hash": "1.1.3", - "evp_bytestokey": "1.0.0", - "pbkdf2": "3.0.12" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "requires": { - "is-extglob": "1.0.0" - } - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } - }, - "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", - "dev": true - }, - "parseurl": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" - }, - "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "requires": { - "pinkie-promise": "2.0.1" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - } - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "pbkdf2": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.12.tgz", - "integrity": "sha1-vjZ4XFBn6kjYBv+SMojF91C2uKI=", - "dev": true, - "requires": { - "create-hash": "1.1.3", - "create-hmac": "1.1.6", - "ripemd160": "2.0.1", - "safe-buffer": "5.1.1", - "sha.js": "2.4.8" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, - "phoneformat.js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/phoneformat.js/-/phoneformat.js-1.0.3.tgz", - "integrity": "sha1-Eb40dOdkdFQP43NMwz8aZYQdX4c=" - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "requires": { - "pinkie": "2.0.4" - } - }, - "pipetteur": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pipetteur/-/pipetteur-2.0.3.tgz", - "integrity": "sha1-GVV2CVno0aEcsqUOyD7sRwYz5J8=", - "dev": true, - "requires": { - "onecolor": "3.0.4", - "synesthesia": "1.0.1" - } - }, - "pixrem": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-3.0.2.tgz", - "integrity": "sha1-MNG6+0w73Ojpu0vVahOYVhkyDDQ=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "postcss": "5.2.17", - "reduce-css-calc": "1.3.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "1.1.2" - } - }, - "plur": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", - "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", - "dev": true, - "requires": { - "irregular-plurals": "1.3.0" - } - }, - "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "pngquant-bin": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-3.1.1.tgz", - "integrity": "sha1-0STZinWpSH9AwWQLTb/Lsr1aH9E=", - "dev": true, - "requires": { - "bin-build": "2.2.0", - "bin-wrapper": "3.0.2", - "logalot": "2.1.0" - } - }, - "postcss": { - "version": "5.2.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", - "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "js-base64": "2.1.9", - "source-map": "0.5.6", - "supports-color": "3.2.3" - }, - "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "postcss-alias": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-alias/-/postcss-alias-1.0.0.tgz", - "integrity": "sha1-Bwxh7hGXr27l63XSat9IiZudL3s=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-calc": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", - "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" - } - }, - "postcss-clearfix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-clearfix/-/postcss-clearfix-1.0.0.tgz", - "integrity": "sha1-r+xqDgHSXaw2pUrbif/Uv+HSGa8=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-color-rgba-fallback": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-color-rgba-fallback/-/postcss-color-rgba-fallback-2.2.0.tgz", - "integrity": "sha1-bSlJG+WZCpMXPUfnx29YELCUAro=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0", - "rgb-hex": "1.0.0" - } - }, - "postcss-colormin": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", - "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", - "dev": true, - "requires": { - "colormin": "1.1.2", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-convert-values": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", - "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-discard-comments": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", - "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-duplicates": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", - "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-empty": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", - "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-overridden": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", - "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-discard-unused": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", - "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "uniqs": "2.0.0" - } - }, - "postcss-easings": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/postcss-easings/-/postcss-easings-0.3.0.tgz", - "integrity": "sha1-I9zL+XWH4o1doZw7rktQaYxarV4=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-filter-plugins": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", - "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "uniqid": "4.1.1" - } - }, - "postcss-fontpath": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/postcss-fontpath/-/postcss-fontpath-0.3.0.tgz", - "integrity": "sha1-KBQqed0Y8snwv1yH96PreUxTkp4=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.17" - } - }, - "postcss-hexrgba": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/postcss-hexrgba/-/postcss-hexrgba-0.2.1.tgz", - "integrity": "sha1-XGGrukOcCjjknn+8CzzZNhGewiU=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-import": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-9.1.0.tgz", - "integrity": "sha1-lf6YdqHnmvSfvcNYnwH+WqfMHoA=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0", - "promise-each": "2.2.0", - "read-cache": "1.0.0", - "resolve": "1.4.0" - } - }, - "postcss-input-style": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/postcss-input-style/-/postcss-input-style-0.3.0.tgz", - "integrity": "sha1-47T9sKpEG+0ZMMu0TYrVY0zzhUA=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-less": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-0.14.0.tgz", - "integrity": "sha1-xjGwicbM5CK5oQ86lY0r7dOBkyQ=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-load-config": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", - "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", - "dev": true, - "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1", - "postcss-load-options": "1.2.0", - "postcss-load-plugins": "2.3.0" - } - }, - "postcss-load-options": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", - "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", - "dev": true, - "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" - } - }, - "postcss-load-plugins": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", - "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", - "dev": true, - "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" - } - }, - "postcss-loader": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-1.3.2.tgz", - "integrity": "sha1-xWi2HC5I4nThwiSiWH+1ZvTsJvU=", - "dev": true, - "requires": { - "loader-utils": "1.1.0", - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-load-config": "1.2.0" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "dev": true, - "requires": { - "big.js": "3.1.3", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - } - } - }, - "postcss-media-query-parser": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", - "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", - "dev": true - }, - "postcss-merge-idents": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", - "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-merge-longhand": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", - "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-merge-rules": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", - "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.17", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.1" - } - }, - "postcss-message-helpers": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", - "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", - "dev": true - }, - "postcss-minify-font-values": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", - "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", - "dev": true, - "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-minify-gradients": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", - "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-minify-params": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", - "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" - } - }, - "postcss-minify-selectors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", - "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.17", - "postcss-selector-parser": "2.2.3" - } - }, - "postcss-modules-extract-imports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.1.0.tgz", - "integrity": "sha1-thTJcgvmgW6u41+zpfqh26agXds=", - "dev": true, - "requires": { - "postcss": "6.0.8" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "postcss": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", - "dev": true, - "requires": { - "chalk": "2.0.1", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "dev": true, - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.8" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "postcss": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", - "dev": true, - "requires": { - "chalk": "2.0.1", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "dev": true, - "requires": { - "css-selector-tokenizer": "0.7.0", - "postcss": "6.0.8" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "postcss": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", - "dev": true, - "requires": { - "chalk": "2.0.1", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "dev": true, - "requires": { - "icss-replace-symbols": "1.1.0", - "postcss": "6.0.8" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, - "chalk": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.0.1.tgz", - "integrity": "sha512-Mp+FXEI+FrwY/XYV45b2YD3E8i3HwnEAoFcM0qlZzq/RZ9RwWitt2Y/c7cqRAz70U7hfekqx6qNYthuKFO6K0g==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.2.1" - } - }, - "postcss": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.8.tgz", - "integrity": "sha512-G6WnRmdTt2jvJvY+aY+M0AO4YlbxE+slKPZb+jG2P2U9Tyxi3h1fYZ/DgiFU6DC6bv3XIEJoZt+f/kNh8BrWFw==", - "dev": true, - "requires": { - "chalk": "2.0.1", - "source-map": "0.5.6", - "supports-color": "4.2.1" - } - }, - "supports-color": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", - "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } - } - } - }, - "postcss-nested": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-1.0.0.tgz", - "integrity": "sha1-0Ta9S1dr1WMt8ULBKyGYqcz3lN8=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-normalize-charset": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", - "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-normalize-url": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", - "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", - "dev": true, - "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-opacity": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-opacity/-/postcss-opacity-4.0.0.tgz", - "integrity": "sha1-qlYgQ9ozlMlKOs7c9D8MMj0JhqE=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-ordered-values": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", - "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-position": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/postcss-position/-/postcss-position-0.5.0.tgz", - "integrity": "sha1-hlPU8LhP+wflRPt/fq4IxlUbc6A=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-pseudoelements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudoelements/-/postcss-pseudoelements-3.0.0.tgz", - "integrity": "sha1-bGghd8eQC6BTtt8X+MWQKEx7i7w=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-quantity-queries": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/postcss-quantity-queries/-/postcss-quantity-queries-0.4.0.tgz", - "integrity": "sha1-vhNwp76TEqFzY5wIaapCECRPhs4=", - "dev": true, - "requires": { - "balanced-match": "0.2.1", - "postcss": "5.2.17" - }, - "dependencies": { - "balanced-match": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.2.1.tgz", - "integrity": "sha1-e8ZYtL7WHu5CStdPdfXD4sTfPMc=", - "dev": true - } - } - }, - "postcss-reduce-idents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", - "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", - "dev": true, - "requires": { - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reduce-initial": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", - "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-reduce-transforms": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", - "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0" - } - }, - "postcss-reporter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-2.0.0.tgz", - "integrity": "sha1-0l50un/OkR4qpy7BrlkvrebsNnE=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "lodash": "4.17.2", - "log-symbols": "1.0.2", - "postcss": "5.2.17" - } - }, - "postcss-resolve-nested-selector": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", - "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", - "dev": true - }, - "postcss-responsive-type": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/postcss-responsive-type/-/postcss-responsive-type-0.5.1.tgz", - "integrity": "sha1-J0EzvARjWeVCpYu8YhhH0ED9EOY=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-scss": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-0.4.1.tgz", - "integrity": "sha1-rXcbgfD3L19IRdCKpg+TVXZT1Uw=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-selector-parser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", - "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", - "dev": true, - "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" - } - }, - "postcss-simple-vars": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-3.0.0.tgz", - "integrity": "sha1-H6TMtLcVHZ8NUvuOoZoVwTGVmdY=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-svgo": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", - "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", - "dev": true, - "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.17", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" - } - }, - "postcss-unique-selectors": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", - "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", - "dev": true, - "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.17", - "uniqs": "2.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", - "dev": true - }, - "postcss-vmin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-vmin/-/postcss-vmin-2.0.0.tgz", - "integrity": "sha1-UyfCEZE3ElaGj9enOZF/FHTVf+4=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-will-change": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-will-change/-/postcss-will-change-1.1.0.tgz", - "integrity": "sha1-plHdWoHoLEEtOabPkKkrsyaa8Yw=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "postcss-zindex": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", - "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", - "dev": true, - "requires": { - "has": "1.0.1", - "postcss": "5.2.17", - "uniqs": "2.0.0" - } - }, - "prebuild-install": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.2.1.tgz", - "integrity": "sha512-y/sgNJ49vjXQ3qYdSI/jTRZq6D7g5Q2euK6x0/L8dvwK1EGvNLidtg2t4PZzTgkR6LahkzpYVshOmHKYtp0AlQ==", - "requires": { - "expand-template": "1.0.3", - "github-from-package": "0.0.0", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "node-abi": "2.1.0", - "noop-logger": "0.1.1", - "npmlog": "4.1.2", - "os-homedir": "1.0.2", - "pump": "1.0.2", - "rc": "1.2.1", - "simple-get": "1.4.3", - "tar-fs": "1.15.3", - "tunnel-agent": "0.6.0", - "xtend": "4.0.1" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" - }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", - "dev": true, - "requires": { - "renderkid": "2.0.1", - "utila": "0.4.0" - } - }, - "private": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", - "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=" - }, - "process": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", - "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" - }, - "progress": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "progress-bar-webpack-plugin": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/progress-bar-webpack-plugin/-/progress-bar-webpack-plugin-1.9.3.tgz", - "integrity": "sha1-gfuL2OONpu2vmiC+7Xm9l43WPCo=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "object.assign": "4.0.4", - "progress": "1.1.8" - } - }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "2.0.6" - } - }, - "promise-each": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/promise-each/-/promise-each-2.2.0.tgz", - "integrity": "sha1-M1MXTv8mlEgQN+BOAfd6oPttG2A=", - "dev": true, - "requires": { - "any-promise": "0.1.0" - } - }, - "promise-worker": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/promise-worker/-/promise-worker-1.1.1.tgz", - "integrity": "sha1-wrddBF0kliXAImTi3/mtIuAxxps=", - "requires": { - "is-promise": "2.1.0", - "lie": "3.1.1" - } - }, - "prop-types": { - "version": "15.5.10", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", - "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1" - } - }, - "propagate": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-0.4.0.tgz", - "integrity": "sha1-8/zKCm/gZzanulcpZgaWF8EwtIE=", - "dev": true - }, - "proper-lockfile": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-2.0.1.tgz", - "integrity": "sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0=", - "requires": { - "graceful-fs": "4.1.11", - "retry": "0.10.1" - } - }, - "proxy-addr": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz", - "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=", - "dev": true, - "requires": { - "forwarded": "0.1.0", - "ipaddr.js": "1.4.0" - } - }, - "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", - "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", - "dev": true, - "requires": { - "bn.js": "4.11.7", - "browserify-rsa": "4.0.1", - "create-hash": "1.1.3", - "parse-asn1": "5.1.0", - "randombytes": "2.0.5" - } - }, - "pump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", - "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", - "requires": { - "end-of-stream": "1.4.0", - "once": "1.4.0" - } - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "push.js": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/push.js/-/push.js-0.0.11.tgz", - "integrity": "sha1-T606n5CEQhLiqmfQc6I9Rw4yqJE=" - }, - "q": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.0.tgz", - "integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=", - "dev": true - }, - "qs": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.0.tgz", - "integrity": "sha1-9AOyZPI7wBIox0ExtAfxjV6l1EI=" - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "raf": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.3.2.tgz", - "integrity": "sha1-DBO+C1tJtG921maSSNUnzysC/ic=", - "requires": { - "performance-now": "2.1.0" - } - }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", - "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "3.2.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "1.1.5" - } - } - } - }, - "randombytes": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz", - "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "range-parser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "raw-loader": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", - "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", - "dev": true - }, - "rc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", - "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - } - }, - "react": { - "version": "15.4.2", - "resolved": "https://registry.npmjs.org/react/-/react-15.4.2.tgz", - "integrity": "sha1-QfeZGyYYU5K6m66WyIiefgGDl+8=", - "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "react-ace": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-4.1.0.tgz", - "integrity": "sha1-ZZ+qAQ0XP2DWqJQPCzJcXkIsq1Q=", - "requires": { - "brace": "0.8.0", - "lodash.isequal": "4.5.0" - }, - "dependencies": { - "brace": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/brace/-/brace-0.8.0.tgz", - "integrity": "sha1-6CbG1QVMrl9getexyBI23SzwGXg=", - "requires": { - "w3c-blob": "0.0.1" - } - } - } - }, - "react-addons-create-fragment": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/react-addons-create-fragment/-/react-addons-create-fragment-15.6.0.tgz", - "integrity": "sha1-r5GiKx+wld0B8a+6Q7/Q71idiyA=", - "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "react-addons-css-transition-group": { - "version": "15.4.2", - "resolved": "https://registry.npmjs.org/react-addons-css-transition-group/-/react-addons-css-transition-group-15.4.2.tgz", - "integrity": "sha1-t4KINN+hQin+B3UOMx6KjLb7d0U=", - "requires": { - "fbjs": "0.8.14", - "object-assign": "4.1.1" - } - }, - "react-addons-perf": { - "version": "15.4.2", - "resolved": "https://registry.npmjs.org/react-addons-perf/-/react-addons-perf-15.4.2.tgz", - "integrity": "sha1-EQvc9cRZxPd8uF7WNLzTOXU2ODs=", - "dev": true, - "requires": { - "fbjs": "0.8.14", - "object-assign": "4.1.1" - } - }, - "react-addons-shallow-compare": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/react-addons-shallow-compare/-/react-addons-shallow-compare-15.6.0.tgz", - "integrity": "sha1-t6Tl/58nBMIM9obdigXdCLJt4lI=", - "requires": { - "fbjs": "0.8.14", - "object-assign": "4.1.1" - } - }, - "react-addons-test-utils": { - "version": "15.4.2", - "resolved": "https://registry.npmjs.org/react-addons-test-utils/-/react-addons-test-utils-15.4.2.tgz", - "integrity": "sha1-k7yqcY/K5zYNQuj7HAl1bMNjAqI=", - "dev": true, - "requires": { - "fbjs": "0.8.14", - "object-assign": "4.1.1" - } - }, - "react-addons-transition-group": { - "version": "15.6.0", - "resolved": "https://registry.npmjs.org/react-addons-transition-group/-/react-addons-transition-group-15.6.0.tgz", - "integrity": "sha1-DyILn5WX2zqAqI29b+gF/GRM4hw=", - "requires": { - "react-transition-group": "1.2.0" - } - }, - "react-codemirror": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/react-codemirror/-/react-codemirror-0.3.0.tgz", - "integrity": "sha1-zWvW70WOweA1z9iz/nswyMeIPGw=", - "requires": { - "classnames": "2.2.5", - "codemirror": "5.28.0", - "lodash.debounce": "4.0.8" - } - }, - "react-container-dimensions": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/react-container-dimensions/-/react-container-dimensions-1.2.0.tgz", - "integrity": "sha1-v7XnDhCqgtLsukkUfRS7TCLK/ao=", - "requires": { - "element-resize-detector": "1.1.12", - "invariant": "2.2.2" - } - }, - "react-copy-to-clipboard": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-4.2.3.tgz", - "integrity": "sha1-JoxaD73pqV2WFFAU5/hRELDn+44=", - "requires": { - "copy-to-clipboard": "3.0.8" - } - }, - "react-deep-force-update": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/react-deep-force-update/-/react-deep-force-update-2.0.1.tgz", - "integrity": "sha1-T39sEsPn3kLzRZkqPFGCNvoeytM=", - "dev": true - }, - "react-dom": { - "version": "15.4.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.4.2.tgz", - "integrity": "sha1-AVNj8FsKH9Uq6e/dOgBg2QaVII8=", - "requires": { - "fbjs": "0.8.14", - "loose-envify": "1.3.1", - "object-assign": "4.1.1" - } - }, - "react-dropzone": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-3.7.3.tgz", - "integrity": "sha1-eFK2ZSpDr8f6ByAh8zaRI+pKYeA=", - "requires": { - "attr-accept": "1.1.0" - } - }, - "react-element-to-jsx-string": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-6.0.0.tgz", - "integrity": "sha1-8sFRR27o3YF4ke01K+Ss6fs2McI=", - "requires": { - "collapse-white-space": "1.0.3", - "is-plain-object": "2.0.4", - "lodash": "4.17.4", - "sortobject": "1.1.1", - "stringify-object": "3.2.0", - "traverse": "0.6.6" - }, - "dependencies": { - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" - } - } - }, - "react-event-listener": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/react-event-listener/-/react-event-listener-0.4.1.tgz", - "integrity": "sha1-hrU5dMPfZRhXdmt7F3aC7Xx8gxg=", - "requires": { - "babel-runtime": "6.23.0", - "react-addons-shallow-compare": "15.6.0", - "warning": "3.0.0" - } - }, - "react-hot-loader": { - "version": "3.0.0-beta.6", - "resolved": "https://registry.npmjs.org/react-hot-loader/-/react-hot-loader-3.0.0-beta.6.tgz", - "integrity": "sha1-Rj+sC/yLY6g4UlivIMkWNqvOdfQ=", - "dev": true, - "requires": { - "babel-template": "6.25.0", - "global": "4.3.2", - "react-deep-force-update": "2.0.1", - "react-proxy": "3.0.0-alpha.1", - "redbox-react": "1.4.3", - "source-map": "0.4.4" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } - } - } - }, - "react-inspector": { - "version": "github:paritytech/react-inspector#73b5214261a5131821eb9088f58d7e5f31210c23", - "requires": { - "babel-runtime": "6.23.0", - "is-dom": "1.0.9" - } - }, - "react-intl": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-2.1.5.tgz", - "integrity": "sha1-+Xleo0t5DctdDY73Bg3dvoW/h2M=", - "requires": { - "intl-format-cache": "2.0.5", - "intl-messageformat": "1.3.0", - "intl-relativeformat": "1.3.0", - "invariant": "2.2.2" - } - }, - "react-intl-aggregate-webpack-plugin": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/react-intl-aggregate-webpack-plugin/-/react-intl-aggregate-webpack-plugin-0.0.1.tgz", - "integrity": "sha1-wplYhg17zfpvRg3sefVa4CIEiMY=", - "dev": true, - "requires": { - "mkdirp": "0.5.1" - } - }, - "react-markdown": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-2.4.4.tgz", - "integrity": "sha1-JtglQ40pLnym4pL+diAeHb8s/u4=", - "requires": { - "commonmark": "0.24.0", - "commonmark-react-renderer": "4.3.3", - "in-publish": "2.0.0" - } - }, - "react-portal": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-portal/-/react-portal-3.0.0.tgz", - "integrity": "sha1-kwT86DbooyFrIliPjckbRHco8K4=" - }, - "react-proxy": { - "version": "3.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-3.0.0-alpha.1.tgz", - "integrity": "sha1-RABCa8+oDKpnJMd1VpUxUgn6Swc=", - "dev": true, - "requires": { - "lodash": "4.17.2" - } - }, - "react-qr-reader": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/react-qr-reader/-/react-qr-reader-1.1.3.tgz", - "integrity": "sha1-dDmnZvyZPLj17u/HLCnblh1AswI=", - "requires": { - "jsqr": "git+https://github.com/JodusNodus/jsQR.git#5ba1acefa1cbb9b2bc92b49f503f2674e2ec212b", - "prop-types": "15.5.10", - "webrtc-adapter": "2.1.0" - } - }, - "react-redux": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-4.4.6.tgz", - "integrity": "sha1-S50ymFMHoRCWot1hVhmABE/MYgk=", - "requires": { - "hoist-non-react-statics": "1.2.0", - "invariant": "2.2.2", - "lodash": "4.17.2", - "loose-envify": "1.3.1" - } - }, - "react-router": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-3.0.0.tgz", - "integrity": "sha1-PzE+Tbr1cEjEjdCow8rCTZNmff8=", - "requires": { - "history": "3.3.0", - "hoist-non-react-statics": "1.2.0", - "invariant": "2.2.2", - "loose-envify": "1.3.1", - "warning": "3.0.0" - } - }, - "react-router-redux": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/react-router-redux/-/react-router-redux-4.0.7.tgz", - "integrity": "sha1-mx/eTnAQbFD0chThK92IjPuW4qY=" - }, - "react-smooth": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-0.1.11.tgz", - "integrity": "sha1-84n45Yy7VGq7SSHKDL57B5vFGg0=", - "requires": { - "lodash": "4.13.1", - "raf": "3.3.2", - "react-addons-transition-group": "15.6.0" - }, - "dependencies": { - "lodash": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz", - "integrity": "sha1-g+SxCRP0hJbU0W/sSlYK8u50S2g=" - } - } - }, - "react-tap-event-plugin": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/react-tap-event-plugin/-/react-tap-event-plugin-2.0.1.tgz", - "integrity": "sha1-MWvrO8ZVbinshppyk+icgmqQdNI=", - "requires": { - "fbjs": "0.8.14" - } - }, - "react-tooltip": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-3.2.2.tgz", - "integrity": "sha1-OlmcDqu9nrlZeqLXKyF/17o1h2c=", - "requires": { - "classnames": "2.2.5" - } - }, - "react-transition-group": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-1.2.0.tgz", - "integrity": "sha1-tR/JIbDDg1p+98Vxx5/ILHPpIE8=", - "requires": { - "chain-function": "1.0.0", - "dom-helpers": "3.2.1", - "loose-envify": "1.3.1", - "prop-types": "15.5.10", - "warning": "3.0.0" - } - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "requires": { - "mute-stream": "0.0.7" - } - }, - "read-all-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", - "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", - "requires": { - "pinkie-promise": "2.0.1", - "readable-stream": "2.3.3" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", - "dev": true, - "requires": { - "pify": "2.3.0" - } - }, - "read-file-stdin": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/read-file-stdin/-/read-file-stdin-0.2.1.tgz", - "integrity": "sha1-JezP86FTtoCa+ssj7hU4fbng7mE=", - "dev": true, - "requires": { - "gather-stream": "1.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.3", - "set-immediate-shim": "1.0.1" - } - }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "mute-stream": "0.0.5" - }, - "dependencies": { - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - } - } - }, - "recast": { - "version": "0.11.23", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", - "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", - "dev": true, - "requires": { - "ast-types": "0.9.6", - "esprima": "3.1.3", - "private": "0.1.7", - "source-map": "0.5.6" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "dev": true - } - } - }, - "recharts": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-0.15.2.tgz", - "integrity": "sha1-Y28ho0HwCzHJJXOe1K73CttV2A8=", - "requires": { - "classnames": "2.2.5", - "core-js": "2.4.0", - "d3-scale": "1.0.0", - "d3-shape": "1.0.0", - "lodash": "4.13.1", - "react-container-dimensions": "1.2.0", - "react-smooth": "0.1.11", - "recharts-scale": "0.2.1", - "reduce-css-calc": "1.3.0" - }, - "dependencies": { - "core-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.4.0.tgz", - "integrity": "sha1-30CKtG0Br/kcAcPnlxk11CLFT4E=" - }, - "lodash": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz", - "integrity": "sha1-g+SxCRP0hJbU0W/sSlYK8u50S2g=" - } - } - }, - "recharts-scale": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.2.1.tgz", - "integrity": "sha1-N49UPtF8MkXk2a+xCq9imCQNL8s=" - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "1.4.0" - } - }, - "recompose": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/recompose/-/recompose-0.20.2.tgz", - "integrity": "sha1-ET1qx+KcpmTP/+wWtoHd3fFSULw=", - "requires": { - "change-emitter": "0.1.6", - "fbjs": "0.8.14", - "hoist-non-react-statics": "1.2.0", - "symbol-observable": "0.2.4" - } - }, - "redbox-react": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/redbox-react/-/redbox-react-1.4.3.tgz", - "integrity": "sha512-P/N+y57/FVUQWbgpfTf/2wjgxEhxQuA6FRLv0ipZKLFv5v8mp6qs5inFyBwJQYAgaMrntZRCvKdz1vGwkCNs7A==", - "dev": true, - "requires": { - "error-stack-parser": "1.3.6", - "object-assign": "4.1.1", - "prop-types": "15.5.10", - "sourcemapped-stacktrace": "1.1.7" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" - } - }, - "reduce-css-calc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", - "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", - "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "reduce-function-call": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", - "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", - "requires": { - "balanced-match": "0.4.2" - }, - "dependencies": { - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=" - } - } - }, - "reduce-reducers": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.1.2.tgz", - "integrity": "sha1-+htHGLxSkqcd3R5dg5yb6pdw8Us=" - }, - "redux": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-3.6.0.tgz", - "integrity": "sha1-iHwrPQub2G7KK+cFccJ2VMGeGI0=", - "requires": { - "lodash": "4.17.2", - "lodash-es": "4.17.4", - "loose-envify": "1.3.1", - "symbol-observable": "1.0.4" - }, - "dependencies": { - "symbol-observable": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", - "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" - } - } - }, - "redux-actions": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/redux-actions/-/redux-actions-1.1.0.tgz", - "integrity": "sha1-347HkdniZ1ROWKi6K3L8XDCvujs=", - "requires": { - "invariant": "2.2.2", - "lodash": "4.17.2", - "reduce-reducers": "0.1.2" - } - }, - "redux-thunk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.1.0.tgz", - "integrity": "sha1-xyS/7nXb41LaLjupvBQwK63Ympg=" - }, - "regenerate": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", - "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=" - }, - "regenerator-runtime": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" - }, - "regenerator-transform": { - "version": "0.9.11", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", - "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", - "requires": { - "babel-runtime": "6.23.0", - "babel-types": "6.25.0", - "private": "0.1.7" - } - }, - "regex-cache": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "requires": { - "is-equal-shallow": "0.1.3", - "is-primitive": "2.0.0" - } - }, - "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "requires": { - "regenerate": "1.3.2", - "regjsgen": "0.2.0", - "regjsparser": "0.1.5" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "requires": { - "jsesc": "0.5.0" - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", - "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=" - }, - "renderkid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", - "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", - "dev": true, - "requires": { - "css-select": "1.2.0", - "dom-converter": "0.1.4", - "htmlparser2": "3.3.0", - "strip-ansi": "3.0.1", - "utila": "0.3.3" - }, - "dependencies": { - "domhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", - "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "domutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", - "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", - "dev": true, - "requires": { - "domelementtype": "1.3.0" - } - }, - "htmlparser2": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", - "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", - "dev": true, - "requires": { - "domelementtype": "1.3.0", - "domhandler": "2.1.0", - "domutils": "1.1.6", - "readable-stream": "1.0.34" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "utila": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", - "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", - "dev": true - } - } - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "requires": { - "is-finite": "1.0.2" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" - }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.16", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.0" - }, - "dependencies": { - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" - }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" - }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" - } - } - }, - "request-capture-har": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/request-capture-har/-/request-capture-har-1.2.2.tgz", - "integrity": "sha1-zWks+yzHRP2EozWKrG7lFSjPcg0=" - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" - }, - "require-from-string": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", - "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=" - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "0.1.0", - "resolve-from": "1.0.1" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", - "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", - "dev": true, - "requires": { - "path-parse": "1.0.5" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "2.0.1", - "signal-exit": "3.0.2" - }, - "dependencies": { - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "requires": { - "mimic-fn": "1.1.0" - } - } - } - }, - "retry": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" - }, - "rgb-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rgb-hex/-/rgb-hex-1.0.0.tgz", - "integrity": "sha1-v6+M2c2RZLWibXHrTxWgllMks8E=", - "dev": true - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "requires": { - "align-text": "0.1.4" - } - }, - "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "requires": { - "glob": "7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "ripemd160": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", - "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", - "requires": { - "hash-base": "2.0.2", - "inherits": "2.0.3" - } - }, - "rlp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", - "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=" - }, - "roadrunner": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/roadrunner/-/roadrunner-1.1.0.tgz", - "integrity": "sha1-EYCjDWThlw2PVd2MsNqP/M7K1x4=" - }, - "rucksack-css": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/rucksack-css/-/rucksack-css-0.9.1.tgz", - "integrity": "sha1-2n66TGe9BbAMv0yDQwXF/lU3XeE=", - "dev": true, - "requires": { - "autoprefixer": "6.7.7", - "laggard": "0.1.0", - "minimist": "1.2.0", - "postcss": "5.2.17", - "postcss-alias": "1.0.0", - "postcss-clearfix": "1.0.0", - "postcss-color-rgba-fallback": "2.2.0", - "postcss-easings": "0.3.0", - "postcss-fontpath": "0.3.0", - "postcss-hexrgba": "0.2.1", - "postcss-input-style": "0.3.0", - "postcss-opacity": "4.0.0", - "postcss-position": "0.5.0", - "postcss-pseudoelements": "3.0.0", - "postcss-quantity-queries": "0.4.0", - "postcss-reporter": "2.0.0", - "postcss-responsive-type": "0.5.1", - "postcss-vmin": "2.0.0", - "read-file-stdin": "0.2.1", - "write-file-stdout": "0.0.2" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "requires": { - "is-promise": "2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "requires": { - "rx-lite": "4.0.8" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" - }, - "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "requires": { - "ajv": "5.2.2" - } - }, - "script-ext-html-webpack-plugin": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/script-ext-html-webpack-plugin/-/script-ext-html-webpack-plugin-1.7.1.tgz", - "integrity": "sha1-rpwOJtd2fUqnk8duNVA0TsCLbRA=", - "dev": true, - "requires": { - "debug": "2.6.8" - } - }, - "scryptsy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.0.0.tgz", - "integrity": "sha1-Jiw28CMc+nZU4jY/o5TNLexm83g=" - }, - "sdp": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/sdp/-/sdp-1.5.4.tgz", - "integrity": "sha1-jgOPbdsUvXZa4fS1IW4SCUUR4NA=" - }, - "secp256k1": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.3.0.tgz", - "integrity": "sha512-CbrQoeGG5V0kQ1ohEMGI+J7oKerapLTpivLICBaXR0R4HyQcN3kM9itLsV5fdpV1UR1bD14tOkJ1xughmlDIiQ==", - "requires": { - "bindings": "1.3.0", - "bip66": "1.1.5", - "bn.js": "4.11.7", - "create-hash": "1.1.3", - "drbg.js": "1.0.1", - "elliptic": "6.4.0", - "nan": "2.6.2", - "prebuild-install": "2.2.1", - "safe-buffer": "5.1.1" - } - }, - "seek-bzip": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", - "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", - "requires": { - "commander": "2.8.1" - } - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" - }, - "semver-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", - "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", - "dev": true - }, - "semver-truncate": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", - "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", - "dev": true, - "requires": { - "semver": "5.4.1" - } - }, - "send": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.14.2.tgz", - "integrity": "sha1-ObBDiz9RC+Xcb2Z6EfcWiTaM3u8=", - "dev": true, - "requires": { - "debug": "2.2.0", - "depd": "1.1.1", - "destroy": "1.0.4", - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "etag": "1.7.0", - "fresh": "0.3.0", - "http-errors": "1.5.1", - "mime": "1.3.4", - "ms": "0.7.2", - "on-finished": "2.3.0", - "range-parser": "1.2.0", - "statuses": "1.3.1" - }, - "dependencies": { - "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", - "dev": true, - "requires": { - "ms": "0.7.1" - }, - "dependencies": { - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", - "dev": true - } - } - }, - "ms": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - } - } - }, - "serve-static": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.11.2.tgz", - "integrity": "sha1-LPmIm9RDWjIMw2iVyapXvWYuasc=", - "dev": true, - "requires": { - "encodeurl": "1.0.1", - "escape-html": "1.0.3", - "parseurl": "1.3.1", - "send": "0.14.2" - } - }, - "serviceworker-cache-polyfill": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serviceworker-cache-polyfill/-/serviceworker-cache-polyfill-4.0.0.tgz", - "integrity": "sha1-3hnuc77yGrPAdAo3sz22JGS6ves=" - }, - "serviceworker-webpack-plugin": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/serviceworker-webpack-plugin/-/serviceworker-webpack-plugin-0.2.0.tgz", - "integrity": "sha1-beneyC7RRMdUxvFbND57h2SsWyg=", - "dev": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" - }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" - }, - "setprototypeof": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.2.tgz", - "integrity": "sha1-gaVSFB7BBLiOic44MQOtXGZWTQg=", - "dev": true - }, - "sha.js": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz", - "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=", - "requires": { - "inherits": "2.0.3" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "shelljs": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true, - "requires": { - "glob": "7.1.2", - "interpret": "1.0.3", - "rechoir": "0.6.2" - }, - "dependencies": { - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - } - } - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "simple-assign": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/simple-assign/-/simple-assign-0.1.0.tgz", - "integrity": "sha1-F/0wZqXz13OPUDIbsPFMooHMS6o=" - }, - "simple-get": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz", - "integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=", - "requires": { - "once": "1.4.0", - "unzip-response": "1.0.2", - "xtend": "4.0.1" - } - }, - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": "0.10.3" - } - }, - "sinon-as-promised": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/sinon-as-promised/-/sinon-as-promised-4.0.2.tgz", - "integrity": "sha1-Eg6c4DPao5ZI3EKQYv5mC+G1tBI=", - "dev": true, - "requires": { - "create-thenable": "1.0.2", - "native-promise-only": "0.8.1" - } - }, - "sinon-chai": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.8.0.tgz", - "integrity": "sha1-Qyqbv9Uab8AHmPTSUmqCnAYGh6w=", - "dev": true - }, - "sjcl": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/sjcl/-/sjcl-1.0.6.tgz", - "integrity": "sha1-ZBVGKmPMDUIVxJuuydP6DBtTUg8=" - }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" - }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "requires": { - "hoek": "2.16.3" - } - }, - "solc": { - "version": "github:ngotchac/solc-js#04eb38cc3003fba8cb3656653a7941ed36408818", - "requires": { - "memorystream": "0.3.1", - "require-from-string": "1.2.1", - "yargs": "4.8.1" - }, - "dependencies": { - "yargs": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", - "integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", - "requires": { - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "lodash.assign": "4.2.0", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "window-size": "0.2.0", - "y18n": "3.2.1", - "yargs-parser": "2.4.1" - } - } - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "requires": { - "is-plain-obj": "1.1.0" - } - }, - "sortobject": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sortobject/-/sortobject-1.1.1.tgz", - "integrity": "sha1-T2ldTUTtCkwGSCw0wlgqLc3CqzQ=", - "requires": { - "editions": "1.3.3" - } - }, - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", - "dev": true - }, - "source-map": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" - }, - "source-map-support": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", - "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", - "requires": { - "source-map": "0.5.6" - } - }, - "sourcemapped-stacktrace": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/sourcemapped-stacktrace/-/sourcemapped-stacktrace-1.1.7.tgz", - "integrity": "sha512-pgHNUACbafkQ+M5zR00NSOtSKBc/i40prgN+SY07J/pghClwVNWNTTMa0JuXj4lriR2TvMKcPAHw5KN9tVFRhA==", - "dev": true, - "requires": { - "source-map": "0.5.6" - } - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=" - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "requires": { - "spdx-license-ids": "1.2.2" - } - }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" - }, - "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" - }, - "specificity": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.1.tgz", - "integrity": "sha1-8bBoQkzjF64HR42V3jwhz4Xo1Wc=", - "dev": true - }, - "split2": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz", - "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=", - "dev": true, - "requires": { - "through2": "0.6.5" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "squeak": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", - "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "console-stream": "0.1.1", - "lpad-align": "1.1.2" - } - }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - } - } - }, - "stackframe": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-0.3.1.tgz", - "integrity": "sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ=", - "dev": true - }, - "stat-mode": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", - "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=" - }, - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - }, - "store": { - "version": "1.3.20", - "resolved": "https://registry.npmjs.org/store/-/store-1.3.20.tgz", - "integrity": "sha1-E+p+P7LWwjmGgmXWhrHYTpnFvj4=" - }, - "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.3" - } - }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", - "dev": true, - "requires": { - "duplexer": "0.1.1", - "through": "2.3.8" - } - }, - "stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", - "requires": { - "duplexer2": "0.1.4", - "readable-stream": "2.3.3" - } - }, - "stream-http": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.7.2.tgz", - "integrity": "sha512-c0yTD2rbQzXtSsFSVhtpvY/vS6u066PcXOX9kBB3mSO76RiUQzL340uJkGBWnlBg4/HZzqiUXtaVA7wcRcJgEw==", - "dev": true, - "requires": { - "builtin-status-codes": "3.0.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "to-arraybuffer": "1.0.1", - "xtend": "4.0.1" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string.prototype.repeat": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-0.2.0.tgz", - "integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=" - }, - "stringify-object": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.0.tgz", - "integrity": "sha1-lDcKE15BvASDWIE7+ZSB8TFcaqY=", - "requires": { - "get-own-enumerable-property-symbols": "1.0.1", - "is-obj": "1.0.1", - "is-regexp": "1.0.0" - } - }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "0.2.1" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - } - }, - "strip-dirs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", - "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", - "requires": { - "chalk": "1.1.3", - "get-stdin": "4.0.1", - "is-absolute": "0.1.7", - "is-natural-number": "2.1.1", - "minimist": "1.2.0", - "sum-up": "1.0.3" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - } - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha1-DF8VX+8RUTczd96du1iNoFUA428=", - "requires": { - "is-hex-prefixed": "1.0.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "requires": { - "get-stdin": "4.0.1" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" - } - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" - }, - "strip-outer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.0.tgz", - "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "style-loader": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.13.1.tgz", - "integrity": "sha1-RoKA77wEcwI806bNVuM7Wh1/w6k=", - "dev": true, - "requires": { - "loader-utils": "0.2.17" - } - }, - "style-search": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", - "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", - "dev": true - }, - "stylehacks": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-2.3.2.tgz", - "integrity": "sha1-ZMg+BDimjJ7fRJ6MVSp9mrYAmws=", - "dev": true, - "requires": { - "browserslist": "1.7.7", - "chalk": "1.1.3", - "log-symbols": "1.0.2", - "minimist": "1.2.0", - "plur": "2.1.2", - "postcss": "5.2.17", - "postcss-reporter": "1.4.1", - "postcss-selector-parser": "2.2.3", - "read-file-stdin": "0.2.1", - "text-table": "0.2.0", - "write-file-stdout": "0.0.2" - }, - "dependencies": { - "postcss-reporter": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", - "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "lodash": "4.17.2", - "log-symbols": "1.0.2", - "postcss": "5.2.17" - } - } - } - }, - "stylelint": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-7.9.0.tgz", - "integrity": "sha1-uNnqIPiHqzUQdcat7ZUo3iRQkyc=", - "dev": true, - "requires": { - "autoprefixer": "6.7.7", - "balanced-match": "0.4.2", - "chalk": "1.1.3", - "colorguard": "1.2.0", - "cosmiconfig": "2.2.2", - "doiuse": "2.6.0", - "execall": "1.0.0", - "get-stdin": "5.0.1", - "globby": "6.1.0", - "globjoin": "0.1.4", - "html-tags": "1.2.0", - "ignore": "3.3.3", - "known-css-properties": "0.0.6", - "lodash": "4.17.4", - "log-symbols": "1.0.2", - "meow": "3.7.0", - "micromatch": "2.3.11", - "normalize-selector": "0.2.0", - "postcss": "5.2.17", - "postcss-less": "0.14.0", - "postcss-media-query-parser": "0.2.3", - "postcss-reporter": "3.0.0", - "postcss-resolve-nested-selector": "0.1.1", - "postcss-scss": "0.4.1", - "postcss-selector-parser": "2.2.3", - "postcss-value-parser": "3.3.0", - "resolve-from": "2.0.0", - "specificity": "0.3.1", - "string-width": "2.1.1", - "style-search": "0.1.0", - "stylehacks": "2.3.2", - "sugarss": "0.2.0", - "svg-tags": "1.0.0", - "table": "4.0.1" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "balanced-match": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "postcss-reporter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-3.0.0.tgz", - "integrity": "sha1-CeoPN6RExWk4eGBuCbAY6+/3z48=", - "dev": true, - "requires": { - "chalk": "1.1.3", - "lodash": "4.17.4", - "log-symbols": "1.0.2", - "postcss": "5.2.17" - } - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - }, - "table": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", - "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", - "dev": true, - "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.4", - "slice-ansi": "0.0.4", - "string-width": "2.1.1" - } - } - } - }, - "stylelint-config-standard": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-16.0.0.tgz", - "integrity": "sha1-u3OHv/HX3XGGpSs+v4hbJAXWkb8=", - "dev": true - }, - "sugarss": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-0.2.0.tgz", - "integrity": "sha1-rDQjdWMyfG/4l7ZHQr9q7BkK054=", - "dev": true, - "requires": { - "postcss": "5.2.17" - } - }, - "sum-up": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", - "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", - "requires": { - "chalk": "1.1.3" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "svg-tags": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", - "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", - "dev": true - }, - "svgo": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", - "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", - "dev": true, - "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" - }, - "dependencies": { - "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", - "dev": true, - "requires": { - "argparse": "1.0.9", - "esprima": "2.7.3" - } - } - } - }, - "sw-toolbox": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/sw-toolbox/-/sw-toolbox-3.6.0.tgz", - "integrity": "sha1-Jt8dHHA0hljk3qKIQxkUm3sxg7U=", - "requires": { - "path-to-regexp": "1.7.0", - "serviceworker-cache-polyfill": "4.0.0" - } - }, - "symbol-observable": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-0.2.4.tgz", - "integrity": "sha1-lag9smGG1q9+ehjb2XYKL4bQj0A=" - }, - "symbol-tree": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", - "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", - "dev": true - }, - "synesthesia": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/synesthesia/-/synesthesia-1.0.1.tgz", - "integrity": "sha1-XvlepUjA1cbm+btLDQcx3/hkp3c=", - "dev": true, - "requires": { - "css-color-names": "0.0.3" - }, - "dependencies": { - "css-color-names": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.3.tgz", - "integrity": "sha1-3gzvFvTYqoIioyDVttfpu62nufY=", - "dev": true - } - } - }, - "table": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", - "lodash": "4.17.2", - "slice-ansi": "0.0.4", - "string-width": "2.1.1" - }, - "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0", - "strip-ansi": "4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "3.0.0" - } - } - } - }, - "tapable": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.7.tgz", - "integrity": "sha1-5GwNqsuyuKmLmwzqD0BSEFgX7Vw=", - "dev": true - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-fs": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.15.3.tgz", - "integrity": "sha1-7M+TXpQUk9gVECjmNuUc5MPKfyA=", - "requires": { - "chownr": "1.0.1", - "mkdirp": "0.5.1", - "pump": "1.0.2", - "tar-stream": "1.5.4" - } - }, - "tar-pack": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-3.4.0.tgz", - "integrity": "sha1-I74tf2cagzk3bL2wuP4/3r8xeYQ=", - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.3.3", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tar-stream": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.4.tgz", - "integrity": "sha1-NlSc8E7RrumyowwBQyUiONr5QBY=", - "requires": { - "bl": "1.2.1", - "end-of-stream": "1.4.0", - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true - }, - "tempfile": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", - "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", - "dev": true, - "requires": { - "temp-dir": "1.0.0", - "uuid": "3.1.0" - }, - "dependencies": { - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", - "dev": true - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" - } - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "requires": { - "through2": "2.0.3", - "xtend": "4.0.1" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - } - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" - }, - "timed-out": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", - "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=" - }, - "timers-browserify": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.3.tgz", - "integrity": "sha512-+JAqyNgg+M8+gXIrq2EeUr4kZqRz47Ysco7X5QKRGScRE9HIHckyHD1asozSFGeqx2nmPCgA8T5tIGVO0ML7/w==", - "dev": true, - "requires": { - "global": "4.3.2", - "setimmediate": "1.0.5" - } - }, - "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", - "requires": { - "os-tmpdir": "1.0.2" - } - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "requires": { - "extend-shallow": "2.0.1" - } - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" - }, - "to-source": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/to-source/-/to-source-2.0.3.tgz", - "integrity": "sha1-U4f4JZzzV2Kz4+m1wtzY49uaLRU=", - "dev": true - }, - "toggle-selection": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", - "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" - }, - "toposort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.3.tgz", - "integrity": "sha1-8CzYp0vYvi/A6YYRw7rLlaFxhpw=", - "dev": true - }, - "tough-cookie": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "requires": { - "punycode": "1.4.1" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "dev": true - }, - "traverse": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", - "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" - }, - "trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", - "requires": { - "escape-string-regexp": "1.0.5" - } - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" - }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "1.1.2" - } - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "2.1.16" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" - }, - "typedarray-to-buffer": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz", - "integrity": "sha1-EBezLZhP9VbroQD1AViauhrOLgQ=", - "dev": true, - "requires": { - "is-typedarray": "1.0.0" - } - }, - "u2f-api": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/u2f-api/-/u2f-api-0.0.9.tgz", - "integrity": "sha1-ve1Fe6Wpqe6bWLPeKR+MH4/qy3o=" - }, - "u2f-api-polyfill": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/u2f-api-polyfill/-/u2f-api-polyfill-0.4.3.tgz", - "integrity": "sha1-t60WWm+WJVhReoZ8XEv5OZ/Pfpg=" - }, - "ua-parser-js": { - "version": "0.7.14", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.14.tgz", - "integrity": "sha1-EQ1T+kw/MmwSEpK76skE0uAzh8o=" - }, - "uglify-js": { - "version": "2.8.16", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.16.tgz", - "integrity": "sha1-0oYZC27vxv1l6w7KxlUeCw6IOaQ=", - "requires": { - "source-map": "0.5.6", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" - } - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "uniqid": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", - "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", - "dev": true, - "requires": { - "macaddress": "0.2.8" - } - }, - "uniqs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", - "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", - "dev": true - }, - "unique-concat": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/unique-concat/-/unique-concat-0.2.2.tgz", - "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", - "dev": true - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "requires": { - "json-stable-stringify": "1.0.1", - "through2-filter": "2.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unzip-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", - "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=" - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "url-loader": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.5.7.tgz", - "integrity": "sha1-Z+h3l1n4AA2nSZSQZoDJQ6mwkl0=", - "dev": true, - "requires": { - "loader-utils": "0.2.17", - "mime": "1.2.11" - }, - "dependencies": { - "mime": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", - "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", - "dev": true - } - } - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "requires": { - "prepend-http": "1.0.4" - } - }, - "url-regex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", - "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", - "dev": true, - "requires": { - "ip-regex": "1.0.3" - } - }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "useragent.js": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/useragent.js/-/useragent.js-0.5.6.tgz", - "integrity": "sha1-p2rvEB4kg3AlI/9vtYpACvd+Iqk=" - }, - "utf8": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", - "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", - "dev": true - }, - "utils-merge": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - }, - "uuid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.0.0.tgz", - "integrity": "sha1-Zyj8BFnEUNeWqZwxg3VpvfZy1yg=" - }, - "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true, - "requires": { - "user-home": "1.1.1" - } - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=" - }, - "valid-url": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", - "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" - }, - "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" - } - }, - "validator": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-6.2.0.tgz", - "integrity": "sha1-sszNxJ/w9LjuTmHbot3T3eE/I+c=" - }, - "vary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", - "dev": true - }, - "vendors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", - "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", - "dev": true - }, - "verror": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", - "requires": { - "extsprintf": "1.0.2" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "requires": { - "clone": "1.0.2", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-assign": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", - "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", - "requires": { - "object-assign": "4.1.1", - "readable-stream": "2.3.3" - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "requires": { - "duplexify": "3.5.0", - "glob-stream": "5.3.5", - "graceful-fs": "4.1.11", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "0.3.0", - "lazystream": "1.0.0", - "lodash.isequal": "4.5.0", - "merge-stream": "1.0.1", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "through2": "2.0.3", - "through2-filter": "2.0.0", - "vali-date": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - } - } - } - }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } - }, - "w3c-blob": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/w3c-blob/-/w3c-blob-0.0.1.tgz", - "integrity": "sha1-sM01KhpQ9RVWNCD/1YYflQ8dhbg=" - }, - "ware": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", - "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", - "requires": { - "wrap-fn": "0.1.5" - } - }, - "warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "requires": { - "loose-envify": "1.3.1" - } - }, - "watchpack": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", - "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", - "dev": true, - "requires": { - "async": "2.5.0", - "chokidar": "1.7.0", - "graceful-fs": "4.1.11" - }, - "dependencies": { - "async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", - "dev": true, - "requires": { - "lodash": "4.17.2" - } - } - } - }, - "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.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.1.tgz", - "integrity": "sha1-gBWherg+fhsxFjhIas6B2mziBqA=", - "dev": true - }, - "webpack": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-2.2.1.tgz", - "integrity": "sha1-e7HXKuIIfdGkr1Jq/sFe7RfdpHU=", - "dev": true, - "requires": { - "acorn": "4.0.13", - "acorn-dynamic-import": "2.0.2", - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "async": "2.5.0", - "enhanced-resolve": "3.4.1", - "interpret": "1.0.3", - "json-loader": "0.5.4", - "loader-runner": "2.3.0", - "loader-utils": "0.2.17", - "memory-fs": "0.4.1", - "mkdirp": "0.5.1", - "node-libs-browser": "2.0.0", - "source-map": "0.5.6", - "supports-color": "3.2.3", - "tapable": "0.2.7", - "uglify-js": "2.8.16", - "watchpack": "1.4.0", - "webpack-sources": "0.1.5", - "yargs": "6.6.0" - }, - "dependencies": { - "acorn": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "async": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", - "dev": true, - "requires": { - "lodash": "4.17.2" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "1.0.0" - } - } - } - }, - "webpack-bundle-size-analyzer": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/webpack-bundle-size-analyzer/-/webpack-bundle-size-analyzer-2.5.0.tgz", - "integrity": "sha1-k56kZeRVk1Op/OQK9RGCDyFqnIA=", - "dev": true, - "requires": { - "commander": "2.8.1", - "filesize": "3.5.10", - "humanize": "0.0.9" - } - }, - "webpack-dev-middleware": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.10.1.tgz", - "integrity": "sha1-xrTPQoE5zxrvvgagwA/bT42i+JM=", - "dev": true, - "requires": { - "memory-fs": "0.4.1", - "mime": "1.3.4", - "path-is-absolute": "1.0.1", - "range-parser": "1.2.0" - } - }, - "webpack-error-notification": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/webpack-error-notification/-/webpack-error-notification-0.1.6.tgz", - "integrity": "sha1-6/y9TvRrg0ZrWcEv3oeQFo9Holc=", - "dev": true - }, - "webpack-hot-middleware": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.17.1.tgz", - "integrity": "sha1-DI+/b5P/KcCV1oSwerbWwPL5Udc=", - "dev": true, - "requires": { - "ansi-html": "0.0.7", - "html-entities": "1.2.1", - "querystring": "0.2.0", - "strip-ansi": "3.0.1" - } - }, - "webpack-sources": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-0.1.5.tgz", - "integrity": "sha1-qh86vw8NdNtxEcQOUAuE+WZkB1A=", - "dev": true, - "requires": { - "source-list-map": "0.1.8", - "source-map": "0.5.6" - } - }, - "webrtc-adapter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-2.1.0.tgz", - "integrity": "sha1-YStbxs6Oc8nQZgA4oh+SVahnvz4=", - "requires": { - "sdp": "1.5.4" - } - }, - "websocket": { - "version": "1.0.24", - "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.24.tgz", - "integrity": "sha1-dJA+dfJUW2suHeFCW8HJBZF6GJA=", - "dev": true, - "requires": { - "debug": "2.6.8", - "nan": "2.6.2", - "typedarray-to-buffer": "3.1.2", - "yaeti": "0.0.6" - } - }, - "whatwg-encoding": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz", - "integrity": "sha1-PGxFGhmO567FWx7GHQkgxngBpfQ=", - "dev": true, - "requires": { - "iconv-lite": "0.4.13" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.13.tgz", - "integrity": "sha1-H4irpKsLFQjoMSrMOTRfNumS4vI=", - "dev": true - } - } - }, - "whatwg-fetch": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.1.tgz", - "integrity": "sha1-B4uUYbvpHOpzy86LsSKgX56St3I=" - }, - "whatwg-url": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-4.8.0.tgz", - "integrity": "sha1-0pgaqRSMHgCkHFphMRZqtGg7vMA=", - "dev": true, - "requires": { - "tr46": "0.0.3", - "webidl-conversions": "3.0.1" - }, - "dependencies": { - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", - "dev": true - } - } - }, - "whet.extend": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", - "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", - "dev": true - }, - "which": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "requires": { - "isexe": "2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" - }, - "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", - "requires": { - "string-width": "1.0.2" - } - }, - "window-size": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", - "integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU=" - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" - }, - "worker-loader": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-0.8.1.tgz", - "integrity": "sha1-6OmVMx6jTfW/aCloJL+38K1XjUM=", - "requires": { - "loader-utils": "1.1.0", - "schema-utils": "0.3.0" - }, - "dependencies": { - "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", - "requires": { - "big.js": "3.1.3", - "emojis-list": "2.1.0", - "json5": "0.5.1" - } - } - } - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1" - } - }, - "wrap-fn": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", - "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", - "requires": { - "co": "3.1.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "0.5.1" - } - }, - "write-file-atomic": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", - "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", - "requires": { - "graceful-fs": "4.1.11", - "imurmurhash": "0.1.4", - "slide": "1.1.6" - } - }, - "write-file-stdout": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/write-file-stdout/-/write-file-stdout-0.0.2.tgz", - "integrity": "sha1-wlLXx8WxtAKJdjDjRTx7/mkNnKE=", - "dev": true - }, - "write-json-file": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-1.2.0.tgz", - "integrity": "sha1-LV3+lqvDyIkFfJOXGqQAXvtUgTQ=", - "requires": { - "graceful-fs": "4.1.11", - "mkdirp": "0.5.1", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "sort-keys": "1.1.2", - "write-file-atomic": "1.3.4" - } - }, - "xml-char-classes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", - "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", - "dev": true - }, - "xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "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", - "integrity": "sha1-Wfod4gHzby80cNysX1jMwoMLCpo=" - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" - }, - "yaeti": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", - "integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", - "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", - "dev": true, - "requires": { - "camelcase": "3.0.0", - "cliui": "3.2.0", - "decamelize": "1.2.0", - "get-caller-file": "1.0.2", - "os-locale": "1.4.0", - "read-pkg-up": "1.0.1", - "require-directory": "2.1.1", - "require-main-filename": "1.0.1", - "set-blocking": "2.0.0", - "string-width": "1.0.2", - "which-module": "1.0.0", - "y18n": "3.2.1", - "yargs-parser": "4.2.1" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "yargs-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", - "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", - "dev": true, - "requires": { - "camelcase": "3.0.0" - } - } - } - }, - "yargs-parser": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz", - "integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=", - "requires": { - "camelcase": "3.0.0", - "lodash.assign": "4.2.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - } - } - }, - "yarn": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-0.21.3.tgz", - "integrity": "sha1-jdo6Y8eYs4PPpXdFLCs8s+Sqh+A=", - "requires": { - "babel-runtime": "6.23.0", - "bytes": "2.4.0", - "camelcase": "3.0.0", - "chalk": "1.1.3", - "cmd-shim": "2.0.2", - "commander": "2.11.0", - "death": "1.1.0", - "debug": "2.6.8", - "defaults": "1.0.3", - "detect-indent": "5.0.0", - "ini": "1.3.4", - "inquirer": "3.2.1", - "invariant": "2.2.2", - "is-builtin-module": "1.0.0", - "is-ci": "1.0.10", - "leven": "2.1.0", - "loud-rejection": "1.6.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "node-emoji": "1.8.1", - "node-gyp": "3.6.2", - "object-path": "0.11.4", - "proper-lockfile": "2.0.1", - "read": "1.0.7", - "request": "2.81.0", - "request-capture-har": "1.2.2", - "rimraf": "2.6.1", - "roadrunner": "1.1.0", - "semver": "5.4.1", - "strip-bom": "3.0.0", - "tar": "2.2.1", - "tar-stream": "1.5.4", - "validate-npm-package-license": "3.0.1" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" - }, - "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" - }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" - } - } - }, - "yauzl": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.8.0.tgz", - "integrity": "sha1-eUUK/yKyqcWkHvVOAtuQfM+/nuI=", - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } - }, - "zxcvbn": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.1.tgz", - "integrity": "sha1-I4Gq3X8HiiWoayFTJ1YmR7gKqKw=" - } - } -} diff --git a/js/package.json b/js/package.json deleted file mode 100644 index 1bb76b21c90ce185462eddf8b3d0e43e69e8da2e..0000000000000000000000000000000000000000 --- a/js/package.json +++ /dev/null @@ -1,240 +0,0 @@ -{ - "name": "parity.js", - "version": "1.8.17", - "main": "release/index.js", - "jsnext:main": "src/index.js", - "author": "Parity Team ", - "maintainers": [ - "Jaco Greeff", - "Nicolas Gotchac" - ], - "contributors": [ - "Jannis Redmann" - ], - "license": "GPL-3.0", - "repository": { - "type": "git", - "url": "git+https://github.com/paritytech/parity.git" - }, - "keywords": [ - "Ethereum", - "ABI", - "API", - "Web3", - "RPC", - "Parity", - "Promise" - ], - "scripts": { - "install": "napa", - "analize": "npm run analize:lib && npm run analize:dll && npm run analize:app", - "analize:app": "WPANALIZE=1 webpack --config webpack/app --json > .build/analize.app.json && cat .build/analize.app.json | webpack-bundle-size-analyzer", - "analize:lib": "WPANALIZE=1 webpack --config webpack/libraries --json > .build/analize.lib.json && cat .build/analize.lib.json | webpack-bundle-size-analyzer", - "analize:dll": "WPANALIZE=1 webpack --config webpack/vendor --json > .build/analize.dll.json && cat .build/analize.dll.json | webpack-bundle-size-analyzer", - "build": "npm run build:lib && npm run build:dll && npm run build:app && npm run build:embed", - "build:app": "webpack --config webpack/app", - "build:lib": "webpack --config webpack/libraries", - "build:dll": "webpack --config webpack/vendor", - "build:markdown": "babel-node ./scripts/build-rpc-markdown.js", - "build:json": "babel-node ./scripts/build-rpc-json.js", - "build:embed": "EMBED=1 node webpack/embed", - "build:i18n": "npm run clean && npm run build && babel-node ./scripts/build-i18n.js", - "ci:build": "npm run ci:build:lib && npm run ci:build:dll && npm run ci:build:app && npm run ci:build:embed", - "ci:build:app": "NODE_ENV=production webpack --config webpack/app", - "ci:build:lib": "NODE_ENV=production webpack --config webpack/libraries", - "ci:build:dll": "NODE_ENV=production webpack --config webpack/vendor", - "ci:build:npm": "NODE_ENV=production webpack --config webpack/npm", - "ci:build:jsonrpc": "babel-node ./scripts/build-rpc-json.js --output .npmjs/jsonrpc", - "ci:build:embed": "NODE_ENV=production EMBED=1 node webpack/embed", - "start": "npm run clean && npm install && npm run build:lib && npm run build:dll && npm run start:app", - "start:app": "node webpack/dev.server", - "clean": "rm -rf ./.build ./.coverage ./.happypack ./.npmjs ./build ./node_modules/.cache ./node_modules/@parity", - "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", - "lint:css": "stylelint ./src/**/*.css", - "lint:fix": "npm run lint:js:fix", - "lint:i18n": "babel-node ./scripts/lint-i18n.js", - "lint:js": "eslint --ignore-path .gitignore ./src/", - "lint:js:cached": "eslint --cache --ignore-path .gitignore ./src/", - "lint:js:fix": "eslint --fix --ignore-path .gitignore ./src/", - "test": "NODE_ENV=test mocha --compilers ejs:ejsify 'src/**/*.spec.js'", - "test:coverage": "NODE_ENV=test istanbul cover _mocha -- --compilers ejs:ejsify 'src/**/*.spec.js'", - "test:e2e": "NODE_ENV=test mocha 'src/**/*.e2e.js'", - "test:npm": "(cd .npmjs && npm i) && node test/npmParity && node test/npmJsonRpc && (rm -rf .npmjs/node_modules)", - "prepush": "npm run lint:cached" - }, - "napa": { - "qrcode-generator": "kazuhikoarase/qrcode-generator" - }, - "devDependencies": { - "babel-cli": "6.23.0", - "babel-core": "6.23.1", - "babel-eslint": "7.1.1", - "babel-loader": "6.3.2", - "babel-plugin-lodash": "3.2.11", - "babel-plugin-react-intl": "2.3.1", - "babel-plugin-recharts": "1.1.0", - "babel-plugin-transform-class-properties": "6.23.0", - "babel-plugin-transform-decorators-legacy": "1.3.4", - "babel-plugin-transform-es2015-modules-commonjs": "6.24.1", - "babel-plugin-transform-object-rest-spread": "6.23.0", - "babel-plugin-transform-react-remove-prop-types": "0.3.2", - "babel-plugin-transform-runtime": "6.23.0", - "babel-plugin-webpack-alias": "2.1.2", - "babel-preset-env": "1.1.9", - "babel-preset-es2015": "6.22.0", - "babel-preset-es2016": "6.22.0", - "babel-preset-es2017": "6.22.0", - "babel-preset-react": "6.23.0", - "babel-preset-stage-0": "6.22.0", - "babel-register": "6.23.0", - "babel-runtime": "6.23.0", - "chai": "3.5.0", - "chai-as-promised": "6.0.0", - "chai-enzyme": "0.6.1", - "chalk": "1.1.3", - "circular-dependency-plugin": "2.0.0", - "copy-webpack-plugin": "4.0.1", - "core-js": "2.4.1", - "coveralls": "2.11.16", - "css-loader": "0.26.1", - "ejs-loader": "0.3.0", - "ejsify": "1.0.0", - "empty-module": "0.0.2", - "enzyme": "2.7.1", - "eslint": "3.16.1", - "eslint-config-semistandard": "7.0.0", - "eslint-config-standard": "6.2.1", - "eslint-config-standard-react": "4.2.0", - "eslint-plugin-promise": "3.4.2", - "eslint-plugin-react": "6.10.0", - "eslint-plugin-standard": "2.0.1", - "express": "4.14.1", - "extract-loader": "0.1.0", - "extract-text-webpack-plugin": "2.0.0-beta.4", - "file-loader": "0.10.0", - "happypack": "3.0.3", - "html-loader": "0.4.4", - "html-webpack-plugin": "2.28.0", - "http-proxy-middleware": "0.17.3", - "husky": "0.13.1", - "ignore-styles": "5.0.1", - "image-webpack-loader": "3.2.0", - "istanbul": "1.0.0-alpha.2", - "jsdom": "9.11.0", - "json-loader": "0.5.4", - "markdown-loader": "2.0.0", - "mocha": "3.2.0", - "mock-local-storage": "1.0.2", - "mock-socket": "6.0.4", - "nock": "9.0.7", - "postcss-import": "9.1.0", - "postcss-loader": "1.3.2", - "postcss-nested": "1.0.0", - "postcss-simple-vars": "3.0.0", - "progress": "1.1.8", - "progress-bar-webpack-plugin": "1.9.3", - "raw-loader": "0.5.1", - "react-addons-perf": "15.4.2", - "react-addons-test-utils": "15.4.2", - "react-hot-loader": "3.0.0-beta.6", - "react-intl-aggregate-webpack-plugin": "0.0.1", - "rucksack-css": "0.9.1", - "script-ext-html-webpack-plugin": "1.7.1", - "serviceworker-webpack-plugin": "0.2.0", - "sinon": "1.17.7", - "sinon-as-promised": "4.0.2", - "sinon-chai": "2.8.0", - "style-loader": "0.13.1", - "stylelint": "7.9.0", - "stylelint-config-standard": "16.0.0", - "to-source": "2.0.3", - "url-loader": "0.5.7", - "webpack": "2.2.1", - "webpack-bundle-size-analyzer": "2.5.0", - "webpack-dev-middleware": "1.10.1", - "webpack-error-notification": "0.1.6", - "webpack-hot-middleware": "2.17.1", - "websocket": "1.0.24", - "yargs": "6.6.0" - }, - "dependencies": { - "@parity/wordlist": "1.0.1", - "arraybuffer-loader": "0.2.2", - "babel-runtime": "6.23.0", - "base32.js": "0.1.0", - "bignumber.js": "3.0.1", - "blockies": "0.0.2", - "brace": "0.9.0", - "bytes": "2.4.0", - "date-difference": "1.0.0", - "debounce": "1.0.0", - "es6-error": "4.0.0", - "es6-promise": "4.0.5", - "ethereumjs-tx": "1.2.5", - "eventemitter3": "2.0.2", - "file-saver": "1.3.3", - "flat": "2.0.1", - "format-json": "1.0.3", - "format-number": "2.0.1", - "geopattern": "1.2.3", - "isomorphic-fetch": "2.2.1", - "js-sha3": "0.5.5", - "keythereum": "0.4.6", - "lodash": "4.17.2", - "loglevel": "1.4.1", - "marked": "0.3.6", - "material-ui": "0.16.5", - "material-ui-chip-input": "0.11.1", - "mobx": "2.6.4", - "mobx-react": "4.0.3", - "mobx-react-devtools": "4.2.10", - "moment": "2.17.0", - "napa": "2.3.0", - "phoneformat.js": "1.0.3", - "promise-worker": "1.1.1", - "push.js": "0.0.11", - "qs": "6.3.0", - "react": "15.4.2", - "react-ace": "4.1.0", - "react-addons-css-transition-group": "15.4.2", - "react-codemirror": "^0.3.0", - "react-copy-to-clipboard": "4.2.3", - "react-dom": "15.4.2", - "react-dropzone": "3.7.3", - "react-element-to-jsx-string": "6.0.0", - "react-event-listener": "0.4.1", - "react-inspector": "paritytech/react-inspector", - "react-intl": "2.1.5", - "react-markdown": "2.4.4", - "react-portal": "3.0.0", - "react-qr-reader": "1.1.3", - "react-redux": "4.4.6", - "react-router": "3.0.0", - "react-router-redux": "4.0.7", - "react-tap-event-plugin": "2.0.1", - "react-tooltip": "3.2.2", - "recharts": "0.15.2", - "redux": "3.6.0", - "redux-actions": "1.1.0", - "redux-thunk": "2.1.0", - "rlp": "2.0.0", - "scryptsy": "2.0.0", - "solc": "ngotchac/solc-js", - "store": "1.3.20", - "sw-toolbox": "^3.6.0", - "u2f-api": "0.0.9", - "u2f-api-polyfill": "0.4.3", - "uglify-js": "2.8.16", - "useragent.js": "0.5.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", - "yarn": "^0.21.3", - "zxcvbn": "4.4.1" - } -} diff --git a/js/scripts/build-i18n.js b/js/scripts/build-i18n.js deleted file mode 100644 index 1acf2c852f50c4c369e81009d33f2516ccb9faff..0000000000000000000000000000000000000000 --- a/js/scripts/build-i18n.js +++ /dev/null @@ -1,154 +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 . - -const fs = require('fs'); -const _ = require('lodash'); -const path = require('path'); -const toSource = require('to-source'); - -const FILE_HEADER = `// 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 .\n\n`; -const SECTION_HEADER = 'export default '; -const SECTION_FOOTER = ';\n'; -const INDENT = ' '; -const DESTPATH = path.join(__dirname, '../src/i18n/_default'); -const ENPATH = path.join(__dirname, '../src/i18n/en'); -const SRCPATH = path.join(__dirname, '../.build/i18n/i18n/en.json'); - -// main entry point -(function main () { - const { sections, sectionNames } = createSectionMap(); - - sectionNames.forEach((name) => outputSection(name, sections[name])); - outputIndex(sectionNames); -})(); - -// sort an object based on its keys -function sortObject (object) { - return Object - .keys(object) - .sort() - .reduce((sorted, key) => { - if (typeof object[key] === 'object') { - sorted[key] = sortObject(object[key]); - } else { - sorted[key] = object[key]; - } - - return sorted; - }, {}); -} - -// create an object map of the actual inputs -function createSectionMap () { - console.log(`Reading strings from ${SRCPATH}`); - - const i18nstrings = require(SRCPATH); - const sections = sortObject( - Object - .keys(i18nstrings) - .reduce((sections, fullKey) => { - const defaultMessage = i18nstrings[fullKey].defaultMessage; - const keys = fullKey.split('.'); - let outputs = sections; - - keys.forEach((key, index) => { - if (index === keys.length - 1) { - outputs[key] = defaultMessage; - } else { - if (!outputs[key]) { - outputs[key] = {}; - } - - outputs = outputs[key]; - } - }); - - return sections; - }, {}) - ); - const sectionNames = Object.keys(sections); - - console.log(`Found ${sectionNames.length} sections`); - - return { - sections, - sectionNames - }; -} - -// load the available deafults (non-exported strings) for a section -function readDefaults (sectionName) { - let defaults = {}; - - try { - defaults = require(path.join(ENPATH, `${sectionName}.js`)).default; - } catch (error) { - defaults = {}; - } - - return defaults; -} - -// create the index.js file -function outputIndex (sectionNames) { - console.log(`Writing index.js to ${DESTPATH}`); - - const defaults = readDefaults('index'); - const dest = path.join(DESTPATH, 'index.js'); - const exports = _.uniq(Object.keys(defaults).concat(sectionNames)) - .sort() - .map((name) => `export ${name} from './${name}';`) - .join('\n'); - - fs.writeFileSync(dest, `${FILE_HEADER}${exports}\n`, 'utf8'); -} - -// export a section as a flatenned JS export string -function createJSSection (section) { - const source = toSource(section, { - enclose: true, - quoteChar: '`', - tabChar: INDENT, - tabDepth: 0 - }); - - return `${SECTION_HEADER}${source}${SECTION_FOOTER}`; -} - -// create the individual section files -function outputSection (sectionName, section) { - console.log(`Writing ${sectionName}.js to ${DESTPATH}`); - - const defaults = readDefaults(sectionName); - const dest = path.join(DESTPATH, `${sectionName}.js`); - const sectionText = createJSSection(_.defaultsDeep(section, defaults)); - - fs.writeFileSync(dest, `${FILE_HEADER}${sectionText}`, 'utf8'); -} diff --git a/js/scripts/build-rpc-json.js b/js/scripts/build-rpc-json.js deleted file mode 100644 index 740f96aa104365293fb59ab2f88bff87afe05b6a..0000000000000000000000000000000000000000 --- a/js/scripts/build-rpc-json.js +++ /dev/null @@ -1,70 +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 . - -import fs from 'fs'; -import path from 'path'; -import yargs from 'yargs'; - -import interfaces from '../src/jsonrpc'; - -const argv = yargs.default('output', 'release').argv; - -const INDEX_JSON = path.join(__dirname, `../${argv.output}/index.json`); -const methods = []; - -function formatDescription (obj) { - const optional = obj.optional ? '(optional) ' : ''; - const defaults = obj.default ? `(default: ${obj.default}) ` : ''; - - return `${obj.type.name} - ${optional}${defaults}${obj.desc}`; -} - -function formatType (obj) { - if (obj.type === Object && obj.details) { - const formatted = {}; - - Object.keys(obj.details).sort().forEach((key) => { - formatted[key] = formatType(obj.details[key]); - }); - - return { - desc: formatDescription(obj), - details: formatted - }; - } else if (obj.type && obj.type.name) { - return formatDescription(obj); - } - - return obj; -} - -Object.keys(interfaces).sort().forEach((group) => { - Object.keys(interfaces[group]).sort().forEach((name) => { - const method = interfaces[group][name]; - const deprecated = method.deprecated ? ' (Deprecated and not supported, to be removed in a future version)' : ''; - - methods.push({ - name: `${group}_${name}`, - desc: `${method.desc}${deprecated}`, - params: method.params.map(formatType), - returns: formatType(method.returns), - inputFormatters: method.params.map((param) => param.format || null), - outputFormatter: method.returns.format || null - }); - }); -}); - -fs.writeFileSync(INDEX_JSON, JSON.stringify({ methods: methods }, null, 2), 'utf8'); diff --git a/js/scripts/build-rpc-markdown.js b/js/scripts/build-rpc-markdown.js deleted file mode 100644 index 7a78e1ce96c3c52ae764a6b8899e8b700407811b..0000000000000000000000000000000000000000 --- a/js/scripts/build-rpc-markdown.js +++ /dev/null @@ -1,328 +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 . - -import fs from 'fs'; -import path from 'path'; -import { isPlainObject } from 'lodash'; - -import { info, warn, error } from './helpers/log'; -import { Dummy } from '../src/jsonrpc/helpers'; -import interfaces from '../src/jsonrpc'; -import rustMethods from './helpers/parsed-rpc-traits'; - -const ROOT_DIR = path.join(__dirname, '../docs'); - -if (!fs.existsSync(ROOT_DIR)) { - fs.mkdirSync(ROOT_DIR); -} - -Object.keys(rustMethods).forEach((group) => { - Object.keys(rustMethods[group]).forEach((method) => { - if (interfaces[group] == null || interfaces[group][method] == null) { - error(`${group}_${method} is defined in Rust traits, but not in js/src/jsonrpc/interfaces`); - } - }); -}); - -function printType (type, obj) { - if (!type) { - throw new Error(`Invalid type in ${JSON.stringify(obj)}`); - } - - return type.print || `\`${type.name}\``; -} - -function formatDescription (obj, prefix = '', indent = '') { - const optional = obj.optional ? '(optional) ' : ''; - const defaults = obj.default ? `(default: \`${obj.default}\`) ` : ''; - - return `${indent}${prefix}${printType(obj.type, obj)} - ${optional}${defaults}${obj.desc}`; -} - -function formatType (obj) { - if (obj == null || obj.type == null) { - return obj; - } - - const details = obj.details || obj.type.details; - - if (details) { - const sub = Object.keys(details).map((key) => { - return formatDescription(details[key], `\`${key}\`: `, ' - '); - }).join('\n'); - - return `${formatDescription(obj)}\n${sub}`; - } else if (obj.type && obj.type.name) { - return formatDescription(obj); - } - - return obj; -} - -const rpcReqTemplate = { - method: 'web3_clientVersion', - params: [], - id: 1, - jsonrpc: '2.0' -}; - -const { isDummy } = Dummy; -const { isArray } = Array; - -// Checks if a field definition has an example, -// or describes an object with fields that recursively have examples of their own, -// or is optional. -function hasExample ({ optional, example, details } = {}) { - if (optional || example !== undefined) { - return true; - } - - if (details !== undefined) { - const values = Object.keys(details).map((key) => details[key]); - - return values.every(hasExample); - } - - return false; -} - -// Remove all optional (trailing) params without examples from an array -function removeOptionalWithoutExamples (arr) { - return arr.filter(({ optional, example, details }) => { - return !optional || example !== undefined || details !== undefined; - }); -} - -// Grabs JSON compatible -function getExample (obj) { - if (isArray(obj)) { - return removeOptionalWithoutExamples(obj).map(getExample); - } - - const { example, details } = obj; - - if (example === undefined && details !== undefined) { - const nested = {}; - - Object.keys(details).forEach((key) => { - nested[key] = getExample(details[key]); - }); - - return nested; - } - - return example; -} - -function stringifyExample (example, dent = '') { - const indent = `${dent} `; - - if (isDummy(example)) { - return example.toString(); - } - - if (isArray(example)) { - const last = example.length - 1; - - // If all elements are dummies, print out a single line. - // Also covers empty arrays. - if (example.every(isDummy)) { - const dummies = example.map(d => d.toString()); - - return `[${dummies.join(', ')}]`; - } - - // For arrays containing just one object or string, don't unwind the array to multiline - if (last === 0 && (isPlainObject(example[0]) || typeof example[0] === 'string')) { - return `[${stringifyExample(example[0], dent)}]`; - } - - const elements = example.map((value, index) => { - const comma = index !== last ? ',' : ''; - const comment = value != null && value._comment ? ` // ${value._comment}` : ''; - - return `${stringifyExample(value, indent)}${comma}${comment}`; - }); - - return `[\n${indent}${elements.join(`\n${indent}`)}\n${dent}]`; - } - - if (isPlainObject(example)) { - const keys = Object.keys(example); - const last = keys.length - 1; - - // print out an empty object - if (last === -1) { - return '{}'; - } - - const elements = keys.map((key, index) => { - const value = example[key]; - const comma = index !== last ? ',' : ''; - const comment = value && value._comment ? ` // ${example[key]._comment}` : ''; - - return `${JSON.stringify(key)}: ${stringifyExample(value, indent)}${comma}${comment}`; - }); - - return `{\n${indent}${elements.join(`\n${indent}`)}\n${dent}}`; - } - - return JSON.stringify(example); -} - -function buildExample (name, method) { - // deprecated, don't care - if (method.deprecated) { - return ''; - } - - const logPostfix = method.subdoc ? ` (${method.subdoc})` : ''; - - const hasReqExample = method.params.every(hasExample); - const hasResExample = hasExample(method.returns); - - if (!hasReqExample && !hasResExample) { - error(`${name} has no examples${logPostfix}`); - - return ''; - } - - const examples = []; - - if (hasReqExample) { - const params = getExample(method.params); - const req = Dummy.stringifyJSON(Object.assign({}, rpcReqTemplate, { method: name, params })); - - examples.push(`Request\n\`\`\`bash\ncurl --data '${req}' -H "Content-Type: application/json" -X POST localhost:8545\n\`\`\``); - } else { - warn(`${name} has a response example but not a request example${logPostfix}`); - } - - if (hasResExample) { - const res = stringifyExample({ - id: 1, - jsonrpc: '2.0', - result: getExample(method.returns) - }); - - examples.push(`Response\n\`\`\`js\n${res}\n\`\`\``); - } else { - if (typeof method.returns === 'string') { - info(`${name} has a request example and only text description for response${logPostfix}`); - } else { - warn(`${name} has a request example but not a response example${logPostfix}`); - } - } - - return `\n\n#### Example\n\n${examples.join('\n\n')}`; -} - -function buildParameters (params) { - if (params.length === 0) { - return ''; - } - - let md = `0. ${params.map(formatType).join('\n0. ')}`; - - if (params.length > 0 && params.every(hasExample) && !isDummy(params[0].example)) { - const example = getExample(params); - - md = `${md}\n\n\`\`\`js\nparams: ${stringifyExample(example)}\n\`\`\``; - } - - return md; -} - -Object.keys(interfaces).sort().forEach((group) => { - const spec = interfaces[group]; - - for (const key in spec) { - const method = spec[key]; - - if (!method || !method.subdoc) { - continue; - } - - const subgroup = `${group}_${method.subdoc}`; - - interfaces[subgroup] = interfaces[subgroup] || {}; - - interfaces[subgroup][key] = method; - delete spec[key]; - } -}); - -Object.keys(interfaces).sort().forEach((group) => { - let preamble = `# The \`${group}\` Module`; - let markdown = `## JSON-RPC methods\n`; - - const spec = interfaces[group]; - - if (spec._preamble) { - preamble = `${preamble}\n\n${spec._preamble}`; - } - - const content = []; - const tocMain = []; - const tocSections = {}; - - // Comparator that will sort by sections first, names second - function methodComparator (a, b) { - const sectionA = spec[a].section || ''; - const sectionB = spec[b].section || ''; - - return sectionA.localeCompare(sectionB) || a.localeCompare(b); - } - - Object.keys(spec).sort(methodComparator).forEach((iname) => { - const method = spec[iname]; - const groupName = group.replace(/_.*$/, ''); - const name = `${groupName}_${iname}`; - - if (method.nodoc || method.deprecated) { - info(`Skipping ${name}: ${method.nodoc || 'Deprecated'}`); - - return; - } - - if (rustMethods[groupName] == null || rustMethods[groupName][iname] == null) { - error(`${name} is defined in js/src/jsonrpc/interfaces, but not in Rust traits`); - } - - const desc = method.desc; - const params = buildParameters(method.params); - const returns = `- ${formatType(method.returns)}`; - const example = buildExample(name, method); - - const { section } = method; - const toc = section ? tocSections[section] = tocSections[section] || [] : tocMain; - - toc.push(`- [${name}](#${name.toLowerCase()})`); - content.push(`### ${name}\n\n${desc}\n\n#### Parameters\n\n${params || 'None'}\n\n#### Returns\n\n${returns || 'None'}${example}`); - }); - - markdown = `${markdown}\n${tocMain.join('\n')}`; - - Object.keys(tocSections).sort().forEach((section) => { - markdown = `${markdown}\n\n#### ${section}\n${tocSections[section].join('\n')}`; - }); - - markdown = `${markdown}\n\n## JSON-RPC API Reference\n\n${content.join('\n\n***\n\n')}\n\n`; - - const mdFile = path.join(ROOT_DIR, `${group}.md`); - - fs.writeFileSync(mdFile, `${preamble}\n\n${markdown}`, 'utf8'); -}); diff --git a/js/scripts/build.sh b/js/scripts/build.sh deleted file mode 100755 index a6f4a913c02b488940066affd7009e10868f9697..0000000000000000000000000000000000000000 --- a/js/scripts/build.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# change into the js directory (one down from scripts) -pushd `dirname $0` -cd .. - -# run build (production) and store the exit code -EXITCODE=0 -BUILDDIR=./.dist -rm -rf $BUILDDIR -mkdir -p $BUILDDIR/src -BUILD_DEST=$BUILDDIR/build npm run ci:build || EXITCODE=1 - -# Copy rust files -cp Cargo.precompiled.toml $BUILDDIR/Cargo.toml -cp build.rs $BUILDDIR -cp src/lib.rs* $BUILDDIR/src - -# back to root -popd - -# exit with exit code -exit $EXITCODE diff --git a/js/scripts/dryrun-npm.sh b/js/scripts/dryrun-npm.sh deleted file mode 100755 index bf8a151a8b08d6bf8b8f9f87a3eca3a5499b1472..0000000000000000000000000000000000000000 --- a/js/scripts/dryrun-npm.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash -set -e - -# variables -PACKAGES=( "parity" "etherscan" "shapeshift" "jsonrpc" ) - -# change into the build directory -BASEDIR=`dirname $0` -cd $BASEDIR/.. - -# build jsonrpc -echo "*** Building JSONRPC .json" -mkdir -p .npmjs/jsonrpc -npm run ci:build:jsonrpc - -# build all packages -echo "*** Building packages for npmjs" -echo "$NPM_TOKEN" >> ~/.npmrc - -for PACKAGE in ${PACKAGES[@]} -do - echo "*** Building $PACKAGE" - LIBRARY=$PACKAGE npm run ci:build:npm - DIRECTORY=.npmjs/$PACKAGE - - cd $DIRECTORY - - echo "*** Publishing $PACKAGE from $DIRECTORY" - echo "npm publish --access public || true" - cd ../.. - -done -cd .. - -# exit with exit code -exit 0 diff --git a/js/scripts/helpers/log.js b/js/scripts/helpers/log.js deleted file mode 100644 index dc495564995c1e8198c06ea4937d846cb2e0a2ad..0000000000000000000000000000000000000000 --- a/js/scripts/helpers/log.js +++ /dev/null @@ -1,32 +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 . - -import chalk from 'chalk'; - -// INFO Logging helper -export function info (log) { - console.log(chalk.blue(`INFO:\t${log}`)); -} - -// WARN Logging helper -export function warn (log) { - console.warn(chalk.yellow(`WARN:\t${log}`)); -} - -// ERROR Logging helper -export function error (log) { - console.error(chalk.red(`ERROR:\t${log}`)); -} diff --git a/js/scripts/helpers/parsed-rpc-traits.js b/js/scripts/helpers/parsed-rpc-traits.js deleted file mode 100644 index 9f2d4ea8a47a07183f8979643d5ad5fda516651d..0000000000000000000000000000000000000000 --- a/js/scripts/helpers/parsed-rpc-traits.js +++ /dev/null @@ -1,81 +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 . - -import fs from 'fs'; -import path from 'path'; - -// ```js -// rustMethods['eth']['call'] === true -// ``` -const rustMethods = {}; - -export default rustMethods; - -// Get a list of JSON-RPC from Rust trait source code -function parseMethodsFromRust (source) { - // Matching the custom `rpc` attribute with it's doc comment - const attributePattern = /((?:\s*\/\/\/.*$)*)\s*#\[rpc\(([^)]+)\)]/gm; - const commentPattern = /\s*\/\/\/\s*/g; - const separatorPattern = /\s*,\s*/g; - const assignPattern = /([\S]+)\s*=\s*"([^"]*)"/; - const ignorePattern = /@(ignore|deprecated|unimplemented|alias)\b/i; - - const methods = []; - - source.toString().replace(attributePattern, (match, comment, props) => { - comment = comment.replace(commentPattern, '\n').trim(); - - // Skip deprecated methods - if (ignorePattern.test(comment)) { - return match; - } - - props.split(separatorPattern).forEach((prop) => { - const [, key, value] = prop.split(assignPattern) || []; - - if (key === 'name' && value != null) { - methods.push(value); - } - }); - - return match; - }); - - return methods; -} - -// Get a list of all JSON-RPC methods from all defined traits -function getMethodsFromRustTraits () { - const traitsDir = path.join(__dirname, '../../../rpc/src/v1/traits'); - - return fs.readdirSync(traitsDir) - .filter((name) => name !== 'mod.rs' && /\.rs$/.test(name)) - .map((name) => fs.readFileSync(path.join(traitsDir, name))) - .map(parseMethodsFromRust) - .reduce((a, b) => a.concat(b)); -} - -getMethodsFromRustTraits().sort().forEach((method) => { - const [group, name] = method.split('_'); - - // Skip methods with malformed names - if (group == null || name == null) { - return; - } - - rustMethods[group] = rustMethods[group] || {}; - rustMethods[group][name] = true; -}); diff --git a/js/scripts/install-deps.sh b/js/scripts/install-deps.sh deleted file mode 100755 index 96c2f36b11cef4e927f5f234d849b27bb983e4e4..0000000000000000000000000000000000000000 --- a/js/scripts/install-deps.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -# change into the js directory (one down from scripts) -pushd `dirname $0` -cd .. - -# install deps and store the exit code -EXITCODE=0 -node --version -npm --version -npm install --progress=false || EXITCODE=1 - -# back to root -popd - -# exit with exit code -exit $EXITCODE diff --git a/js/scripts/lint-i18n.js b/js/scripts/lint-i18n.js deleted file mode 100644 index d392353d0e0ee887f0f30dfe96855e7a57b5f434..0000000000000000000000000000000000000000 --- a/js/scripts/lint-i18n.js +++ /dev/null @@ -1,53 +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 . - -import flatten from 'flat'; - -import * as defaults from '../src/i18n/_default'; -import { LANGUAGES, MESSAGES } from '../src/i18n/store'; - -const SKIP_LANG = ['en']; -const defaultKeys = Object.keys(flatten(Object.assign({}, defaults, LANGUAGES))); - -Object - .keys(MESSAGES) - .filter((lang) => !SKIP_LANG.includes(lang)) - .forEach((lang) => { - const messageKeys = Object.keys(MESSAGES[lang]); - let extra = 0; - let found = 0; - let missing = 0; - - console.log(`*** Checking translations for ${lang}`); - - defaultKeys.forEach((key) => { - if (messageKeys.includes(key)) { - found++; - } else { - missing++; - console.log(` Missing ${key}`); - } - }); - - messageKeys.forEach((key) => { - if (!defaultKeys.includes(key)) { - extra++; - console.log(` Extra ${key}`); - } - }); - - console.log(`Found ${found} keys, missing ${missing} keys, ${extra} extraneous keys\n`); - }); diff --git a/js/scripts/lint.sh b/js/scripts/lint.sh deleted file mode 100755 index 147bb0a2d01fd36bc94cabba51e3eba947e42824..0000000000000000000000000000000000000000 --- a/js/scripts/lint.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# change into the js directory (one down from scripts) -pushd `dirname $0` -cd .. - -# run lint & tests and store the exit code -EXITCODE=0 -npm run lint || EXITCODE=1 - -# back to root -popd - -# exit with exit code -exit $EXITCODE diff --git a/js/scripts/release.sh b/js/scripts/release.sh deleted file mode 100755 index d1d9cfacb545cf94e6b46760851c41806215607f..0000000000000000000000000000000000000000 --- a/js/scripts/release.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash -set -e - -# variables -UTCDATE=`date -u "+%Y%m%d-%H%M%S"` -PACKAGES=( "parity" "etherscan" "shapeshift" "jsonrpc" ) -BRANCH=$CI_BUILD_REF_NAME -GIT_JS_PRECOMPILED="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/js-precompiled.git" -GIT_PARITY="https://${GITHUB_JS_PRECOMPILED}:@github.com/paritytech/parity.git" - -# setup the git user defaults for the current repo -function setup_git_user { - git config push.default simple - git config merge.ours.driver true - git config user.email "$GITHUB_EMAIL" - git config user.name "GitLab Build Bot" -} - -# change into the build directory -BASEDIR=`dirname $0` -GITLOG=./.git/gitcommand.log -pushd $BASEDIR -cd ../.dist - -# add local files and send it up -echo "*** Setting up GitHub config for js-precompiled" -rm -rf ./.git -git init -setup_git_user - -echo "*** Checking out $BRANCH branch" -git remote add origin $GIT_JS_PRECOMPILED -git fetch origin 2>$GITLOG -git checkout -b $BRANCH - -echo "*** Committing compiled files for $UTCDATE" -mv build ../build.new -git add . -git commit -m "$UTCDATE [update]" -git merge origin/$BRANCH -X ours --commit -m "$UTCDATE [merge]" -git rm -r build -rm -rf build -git commit -m "$UTCDATE [cleanup]" -mv ../build.new build -git add . -git commit -m "$UTCDATE [release]" - -echo "*** Merging remote" -git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG -PRECOMPILED_HASH=`git rev-parse HEAD` - -# move to root -cd ../.. - -echo "*** Setting up GitHub config for parity" -setup_git_user -git remote set-url origin $GIT_PARITY -git reset --hard origin/$BRANCH 2>$GITLOG - -if [ "$BRANCH" == "master" ]; then - cd js - - echo "*** Bumping package.json patch version" - npm --no-git-tag-version version - npm version patch - - echo "*** Building packages for npmjs" - echo "$NPM_TOKEN" >> ~/.npmrc - - # build jsonrpc - echo "*** Building JSONRPC .json" - mkdir -p .npmjs/jsonrpc - npm run ci:build:jsonrpc - - for PACKAGE in ${PACKAGES[@]} - do - echo "*** Building $PACKAGE" - LIBRARY=$PACKAGE npm run ci:build:npm - DIRECTORY=.npmjs/$PACKAGE - - echo "*** Publishing $PACKAGE from $DIRECTORY" - cd $DIRECTORY - npm publish --access public || true - cd ../.. - done - - cd .. -fi - -echo "*** Updating cargo parity-ui-precompiled#$PRECOMPILED_HASH" -git submodule update -sed -i "/^parity-ui-precompiled/ { s/branch = \".*\"/branch = \"$BRANCH\"/g; }" dapps/ui/Cargo.toml -cargo update -p parity-ui-precompiled -# --precise "$PRECOMPILED_HASH" - -echo "*** Committing updated files" -git add js -git add dapps/ui/Cargo.toml -git add Cargo.lock -git commit -m "[ci skip] js-precompiled $UTCDATE" -git push origin HEAD:refs/heads/$BRANCH 2>$GITLOG - -# back to root -echo "*** Release completed" -popd - -# exit with exit code -exit 0 diff --git a/js/scripts/test.js b/js/scripts/test.js deleted file mode 100644 index e426642db0b0e95332b63cbe52e72feddab150b7..0000000000000000000000000000000000000000 --- a/js/scripts/test.js +++ /dev/null @@ -1 +0,0 @@ -// test script 10 diff --git a/js/scripts/test.sh b/js/scripts/test.sh deleted file mode 100755 index 6827b243ca64bdacd03691100dafc65a68bc5e65..0000000000000000000000000000000000000000 --- a/js/scripts/test.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -# change into the js directory (one down from scripts) -pushd `dirname $0` -cd .. - -# run lint & tests and store the exit code -EXITCODE=0 -npm run test || EXITCODE=1 - -# back to root -popd - -# exit with exit code -exit $EXITCODE diff --git a/js/scripts/update-precompiled.sh b/js/scripts/update-precompiled.sh deleted file mode 100755 index 0b9461bf0b1f29ce20ac8cacc8ccea0e9d83b813..0000000000000000000000000000000000000000 --- a/js/scripts/update-precompiled.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -e - -# change into main dir -pushd `dirname $0` -cd ../../ - -cargo update -p parity-ui-precompiled - -popd -exit 0 diff --git a/js/src/3rdparty/email-verification/index.js b/js/src/3rdparty/email-verification/index.js deleted file mode 100644 index 9e79547ec66bb22d9c6f7e8c4eeba0da358945e9..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/email-verification/index.js +++ /dev/null @@ -1,68 +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 . - -import { stringify } from 'querystring'; - -export const isServerRunning = (isTestnet = false) => { - const port = isTestnet ? 28443 : 18443; - - return fetch(`https://email-verification.parity.io:${port}/health`, { - mode: 'cors', - cache: 'no-store' - }) - .then((res) => { - return res.ok; - }) - .catch(() => { - return false; - }); -}; - -export const hasReceivedCode = (email, address, isTestnet = false) => { - const port = isTestnet ? 28443 : 18443; - const query = stringify({ email, address }); - - return fetch(`https://email-verification.parity.io:${port}/?${query}`, { - mode: 'cors', - cache: 'no-store' - }) - .then((res) => { - return res.ok; - }) - .catch(() => { - return false; // todo: check for 404 - }); -}; - -export const postToServer = (query, isTestnet = false) => { - const port = isTestnet ? 28443 : 18443; - - query = stringify(query); - - return fetch(`https://email-verification.parity.io:${port}/?${query}`, { - method: 'POST', - mode: 'cors', - cache: 'no-store' - }) - .then((res) => { - return res.json().then((data) => { - if (res.ok) { - return data.message; - } - throw new Error(data.message || 'unknown error'); - }); - }); -}; diff --git a/js/src/3rdparty/email-verification/terms-of-service.js b/js/src/3rdparty/email-verification/terms-of-service.js deleted file mode 100644 index 8826be0329090acaca3dd1b63caaed221eb1e6f2..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/email-verification/terms-of-service.js +++ /dev/null @@ -1,27 +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 . - -import React from 'react'; - -export default ( -
    -
  • This privacy notice relates to your use of the Parity email verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.
  • -
  • We collect your email address when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the email address to prevent duplicated accounts. The cryptographic hash of your email address is also stored on the blockchain which is public by design. You consent to this use.
  • -
  • You pay a fee for the cost of this service using the account you want to verify.
  • -
  • Your email address is transmitted to a third party EU email verification service mailjet for the sole purpose of the email verification. You consent to this use. Mailjet's privacy policy is here: https://www.mailjet.com/privacy-policy.
  • -
  • Parity Technology Limited is registered in England and Wales under company number 09760015 and complies with the Data Protection Act 1998 (UK). You may contact us via email at admin@parity.io. Our general privacy policy can be found here: https://parity.io/legal.html.
  • -
-); diff --git a/js/src/3rdparty/etherscan/account.js b/js/src/3rdparty/etherscan/account.js deleted file mode 100644 index 7a6844759117bca1289bfbf5df4ee2b78411fb16..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/account.js +++ /dev/null @@ -1,75 +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 . - -import BigNumber from 'bignumber.js'; - -const PAGE_SIZE = 25; - -import util from '../../api/util'; -import { call } from './call'; - -function _call (method, params, test, netVersion) { - return call('account', method, params, test, netVersion); -} - -function balance (address, test, netVersion) { - return _call('balance', { - address: address, - tag: 'latest' - }, test, netVersion).then((balance) => { - // same format as balancemulti below - return { - account: address, - balance: balance - }; - }); -} - -function balances (addresses, test, netVersion) { - return _call('balancemulti', { - address: addresses.join(','), - tag: 'latest' - }, test, netVersion); -} - -function transactions (address, page, test, netVersion) { - // page offset from 0 - return _call('txlist', { - address: address, - offset: PAGE_SIZE, - page: (page || 0) + 1, - sort: 'desc' - }, test, netVersion).then((transactions) => { - return transactions.map((tx) => { - return { - blockNumber: new BigNumber(tx.blockNumber || 0), - from: util.toChecksumAddress(tx.from), - hash: tx.hash, - timeStamp: tx.timeStamp, - to: util.toChecksumAddress(tx.to), - value: tx.value - }; - }); - }); -} - -const account = { - balance, - balances, - transactions -}; - -export { account }; diff --git a/js/src/3rdparty/etherscan/account.spec.js b/js/src/3rdparty/etherscan/account.spec.js deleted file mode 100644 index 54eff9f9cd5ca0cda0ece385a820fa1dd8d4bf49..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/account.spec.js +++ /dev/null @@ -1,71 +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 . - -const etherscan = require('./'); - -const TESTADDR = '0xbf885e2b55c6bcc84556a3c5f07d3040833c8d00'; - -describe.skip('etherscan/account', function () { - this.timeout(60 * 1000); - - const checkBalance = function (balance, addr) { - expect(balance).to.be.ok; - expect(balance.account).to.equal(addr); - expect(balance.balance).to.be.ok; - }; - - it('retrieves an account balance', () => { - return etherscan.account - .balance(TESTADDR) - .then((balance) => { - checkBalance(balance, TESTADDR); - }); - }); - - it('retrieves multi account balances', () => { - const addresses = ['0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae', TESTADDR]; - - return etherscan.account - .balances(addresses) - .then((balances) => { - expect(balances).to.be.ok; - expect(balances.length).to.equal(2); - balances.forEach((balance, idx) => { - checkBalance(balance, addresses[idx]); - }); - }); - }); - - describe('transactions', () => { - it('retrieves a list of transactions (default)', () => { - return etherscan.account - .transactions(TESTADDR) - .then((transactions) => { - expect(transactions).to.be.ok; - expect(transactions.length).to.equal(25); - }); - }); - - it('retrieves a list of transactions (page 1)', () => { - return etherscan.account - .transactions(TESTADDR, 1) - .then((transactions) => { - expect(transactions).to.be.ok; - expect(transactions.length).to.equal(25); - }); - }); - }); -}); diff --git a/js/src/3rdparty/etherscan/call.js b/js/src/3rdparty/etherscan/call.js deleted file mode 100644 index 069627d78567fbbe1c001d1db777997a4a9e81be..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/call.js +++ /dev/null @@ -1,47 +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 . - -import { stringify } from 'qs'; -import { apiLink } from './links'; - -const options = { - method: 'GET', - headers: { - 'Accept': 'application/json' - } -}; - -export function call (module, action, _params, test, netVersion) { - const query = stringify(Object.assign({ - module, action - }, _params || {})); - - return fetch(apiLink(query, test, netVersion), options) - .then((response) => { - if (!response.ok) { - throw { code: response.status, message: response.statusText }; // eslint-disable-line - } - - return response.json(); - }) - .then((result) => { - if (result.message === 'NOTOK') { - throw { code: -1, message: result.result }; // eslint-disable-line - } - - return result.result; - }); -} diff --git a/js/src/3rdparty/etherscan/helpers.spec.js b/js/src/3rdparty/etherscan/helpers.spec.js deleted file mode 100644 index fa29c3d97715003893163b11bae6b13db043a2cb..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/helpers.spec.js +++ /dev/null @@ -1,38 +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 . - -import nock from 'nock'; -import { stringify } from 'qs'; - -import { url } from './links'; - -function mockget (requests, test, netVersion) { - let scope = nock(url(test, netVersion)); - - requests.forEach((request) => { - scope = scope - .get(`/api?${stringify(request.query)}`) - .reply(request.code || 200, () => { - return { result: request.reply }; - }); - }); - - return scope; -} - -export { - mockget -}; diff --git a/js/src/3rdparty/etherscan/index.js b/js/src/3rdparty/etherscan/index.js deleted file mode 100644 index 594e833a8f8de02c0046d79db8a1b1b66d3bfdc1..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/index.js +++ /dev/null @@ -1,28 +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 . - -import { account } from './account'; -import { stats } from './stats'; -import { txLink, addressLink } from './links'; - -const etherscan = { - account: account, - stats: stats, - txLink: txLink, - addressLink: addressLink -}; - -export default etherscan; diff --git a/js/src/3rdparty/etherscan/links.js b/js/src/3rdparty/etherscan/links.js deleted file mode 100644 index 3b08d60e835455fdd5dbea702c41deae02a324bd..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/links.js +++ /dev/null @@ -1,55 +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 . - -// NOTE: Keep 'isTestnet' for backwards library compatibility -const getUrlPrefix = (isTestnet = false, netVersion = '0', defaultPrefix = '') => { - if (isTestnet) { - return 'ropsten.'; - } - - switch (netVersion) { - case '1': - return defaultPrefix; - - case '3': - return 'ropsten.'; - - case '4': - return 'rinkeby.'; - - case '42': - return 'kovan.'; - - default: - return 'testnet.'; - } -}; - -export const url = (isTestnet = false, netVersion = '0', defaultPrefix = '') => { - return `https://${getUrlPrefix(isTestnet, netVersion, defaultPrefix)}etherscan.io`; -}; - -export const txLink = (hash, isTestnet = false, netVersion = '0') => { - return `${url(isTestnet, netVersion)}/tx/${hash}`; -}; - -export const addressLink = (address, isTestnet = false, netVersion = '0') => { - return `${url(isTestnet, netVersion)}/address/${address}`; -}; - -export const apiLink = (query, isTestnet = false, netVersion = '0') => { - return `${url(isTestnet, netVersion, 'api.')}/api?${query}`; -}; diff --git a/js/src/3rdparty/etherscan/links.spec.js b/js/src/3rdparty/etherscan/links.spec.js deleted file mode 100644 index c906940cbd9ca7fe2caedcf630a111a2795616a6..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/links.spec.js +++ /dev/null @@ -1,57 +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 . - -const { url, txLink, addressLink, apiLink } = require('./links'); - -describe('etherscan/links', function () { - it('builds link with a prefix', () => { - expect(url(false, '1', 'api.')).to.be.equal('https://api.etherscan.io'); - }); - - it('builds link to main network', () => { - expect(url(false, '1')).to.be.equal('https://etherscan.io'); - }); - - it('builds link to ropsten', () => { - expect(url(false, '3')).to.be.equal('https://ropsten.etherscan.io'); - expect(url(true)).to.be.equal('https://ropsten.etherscan.io'); - }); - - it('builds link to kovan', () => { - expect(url(false, '42')).to.be.equal('https://kovan.etherscan.io'); - }); - - it('builds link to rinkeby', () => { - expect(url(false, '4')).to.be.equal('https://rinkeby.etherscan.io'); - }); - - it('builds link to the testnet selector for unknown networks', () => { - expect(url(false, '10042')).to.be.equal('https://testnet.etherscan.io'); - expect(url(false, '51224')).to.be.equal('https://testnet.etherscan.io'); - }); - - it('builds transaction link', () => { - expect(txLink('aTxHash', false, '1')).to.be.equal('https://etherscan.io/tx/aTxHash'); - }); - - it('builds address link', () => { - expect(addressLink('anAddress', false, '1')).to.be.equal('https://etherscan.io/address/anAddress'); - }); - - it('builds api link', () => { - expect(apiLink('answer=42', false, '1')).to.be.equal('https://api.etherscan.io/api?answer=42'); - }); -}); diff --git a/js/src/3rdparty/etherscan/stats.js b/js/src/3rdparty/etherscan/stats.js deleted file mode 100644 index 282376c5ee1449aecd2621fd4f4c5f7120d8f073..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/stats.js +++ /dev/null @@ -1,36 +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 . - -import { call } from './call'; - -function _call (action, test) { - return call('stats', action, null, test); -} - -function price (test = false) { - return _call('ethprice', test); -} - -function supply (test = false) { - return _call('ethsupply', test); -} - -const stats = { - price: price, - supply: supply -}; - -export { stats }; diff --git a/js/src/3rdparty/etherscan/stats.spec.js b/js/src/3rdparty/etherscan/stats.spec.js deleted file mode 100644 index d837f17f768198cddad9a48c2fbde66da108295a..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/etherscan/stats.spec.js +++ /dev/null @@ -1,37 +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 . - -const etherscan = require('./'); - -describe.skip('etherscan/stats', function () { - this.timeout(60 * 1000); - - it('retrieves the latest price', () => { - return etherscan.stats - .price() - .then((price) => { - expect(price).to.be.ok; - }); - }); - - it('retrieves the ether total', () => { - return etherscan.stats - .supply() - .then((supply) => { - expect(supply).to.be.ok; - }); - }); -}); diff --git a/js/src/3rdparty/ledger/index.js b/js/src/3rdparty/ledger/index.js deleted file mode 100644 index a5b876dcac816e26d88312735ad58d1871c23480..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/ledger/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './ledger'; diff --git a/js/src/3rdparty/ledger/ledger.js b/js/src/3rdparty/ledger/ledger.js deleted file mode 100644 index 13a67199857c82ab10fd303665c4962478f7c9ed..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/ledger/ledger.js +++ /dev/null @@ -1,136 +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 . - -import 'u2f-api-polyfill'; - -import BigNumber from 'bignumber.js'; -import Transaction from 'ethereumjs-tx'; -import u2fapi from 'u2f-api'; - -import Ledger3 from './vendor/ledger3'; -import LedgerEth from './vendor/ledger-eth'; - -const LEDGER_PATH_ETC = "44’/60’/160720'/0'/0"; -const LEDGER_PATH_ETH = "44'/60'/0'/0"; -const SCRAMBLE_KEY = 'w0w'; - -function numberToHex (number) { - return `0x${new BigNumber(number).toString(16)}`; -} - -export default class Ledger { - constructor (api, ledger) { - this._api = api; - this._ledger = ledger; - - this._isSupported = false; - - this.checkJSSupport(); - } - - // FIXME: Until we have https support from Parity u2f will not work. Here we mark it completely - // as unsupported until a full end-to-end environment is available. - get isSupported () { - return false && this._isSupported; - } - - checkJSSupport () { - return u2fapi - .isSupported() - .then((isSupported) => { - console.log('Ledger:checkJSSupport', isSupported); - - this._isSupported = isSupported; - }); - } - - getAppConfiguration () { - return new Promise((resolve, reject) => { - this._ledger.getAppConfiguration((response, error) => { - if (error) { - reject(error); - return; - } - - resolve(response); - }); - }); - } - - scan () { - return new Promise((resolve, reject) => { - this._ledger.getAddress(LEDGER_PATH_ETH, (response, error) => { - if (error) { - reject(error); - return; - } - - resolve([response.address]); - }, true, false); - }); - } - - signTransaction (transaction) { - return this._api.net.version().then((_chainId) => { - return new Promise((resolve, reject) => { - const chainId = new BigNumber(_chainId).toNumber(); - const tx = new Transaction({ - data: transaction.data || transaction.input, - gasPrice: numberToHex(transaction.gasPrice), - gasLimit: numberToHex(transaction.gasLimit), - nonce: numberToHex(transaction.nonce), - to: transaction.to ? transaction.to.toLowerCase() : undefined, - value: numberToHex(transaction.value), - v: Buffer.from([chainId]), // pass the chainId to the ledger - r: Buffer.from([]), - s: Buffer.from([]) - }); - const rawTransaction = tx.serialize().toString('hex'); - - this._ledger.signTransaction(LEDGER_PATH_ETH, rawTransaction, (response, error) => { - if (error) { - reject(error); - return; - } - - tx.v = Buffer.from(response.v, 'hex'); - tx.r = Buffer.from(response.r, 'hex'); - tx.s = Buffer.from(response.s, 'hex'); - - if (chainId !== Math.floor((tx.v[0] - 35) / 2)) { - reject(new Error('Invalid EIP155 signature received from Ledger.')); - return; - } - - resolve(`0x${tx.serialize().toString('hex')}`); - }); - }); - }); - } - - static create (api, ledger) { - if (!ledger) { - ledger = new LedgerEth(new Ledger3(SCRAMBLE_KEY)); - } - - return new Ledger(api, ledger); - } -} - -export { - LEDGER_PATH_ETC, - LEDGER_PATH_ETH -}; diff --git a/js/src/3rdparty/ledger/ledger.spec.js b/js/src/3rdparty/ledger/ledger.spec.js deleted file mode 100644 index 406a4bfcd07e4f738e8d68e128ad0980bbabbe27..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/ledger/ledger.spec.js +++ /dev/null @@ -1,120 +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 . - -import sinon from 'sinon'; - -import Ledger from './'; - -const TEST_ADDRESS = '0x63Cf90D3f0410092FC0fca41846f596223979195'; - -let api; -let ledger; -let vendor; - -function createApi () { - api = { - net: { - version: sinon.stub().resolves('2') - } - }; - - return api; -} - -function createVendor (error = null) { - vendor = { - getAddress: (path, callback) => { - callback({ - address: TEST_ADDRESS - }, error); - }, - getAppConfiguration: (callback) => { - callback({}, error); - }, - signTransaction: (path, rawTransaction, callback) => { - callback({ - v: [39], - r: [0], - s: [0] - }, error); - } - }; - - return vendor; -} - -function create (error) { - ledger = new Ledger(createApi(), createVendor(error)); - - return ledger; -} - -describe('3rdparty/ledger', () => { - beforeEach(() => { - create(); - - sinon.spy(vendor, 'getAddress'); - sinon.spy(vendor, 'getAppConfiguration'); - sinon.spy(vendor, 'signTransaction'); - }); - - afterEach(() => { - vendor.getAddress.restore(); - vendor.getAppConfiguration.restore(); - vendor.signTransaction.restore(); - }); - - describe('getAppConfiguration', () => { - beforeEach(() => { - return ledger.getAppConfiguration(); - }); - - it('calls into getAppConfiguration', () => { - expect(vendor.getAppConfiguration).to.have.been.called; - }); - }); - - describe('scan', () => { - beforeEach(() => { - return ledger.scan(); - }); - - it('calls into getAddress', () => { - expect(vendor.getAddress).to.have.been.called; - }); - }); - - describe('signTransaction', () => { - beforeEach(() => { - return ledger.signTransaction({ - data: '0x0', - gasPrice: 20000000, - gasLimit: 1000000, - nonce: 2, - to: '0x63Cf90D3f0410092FC0fca41846f596223979195', - value: 1 - }); - }); - - it('retrieves chainId via API', () => { - expect(api.net.version).to.have.been.called; - }); - - it('calls into signTransaction', () => { - expect(vendor.signTransaction).to.have.been.called; - }); - }); -}); diff --git a/js/src/3rdparty/ledger/vendor/README.md b/js/src/3rdparty/ledger/vendor/README.md deleted file mode 100644 index a44c3521bdf91b539c8841425d02f463cc0972f2..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/ledger/vendor/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Description - -Vendor files (c) 2016 [Ledger](https://github.com/LedgerHQ) for [Ledger Nano-S](https://www.ledgerwallet.com/) integration - -# Origin - -Files originally created via [https://github.com/kvhnuke/etherwallet/pull/248/files](https://github.com/kvhnuke/etherwallet/pull/248/files) - -# License - -Files in this directory is licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) by their original author diff --git a/js/src/3rdparty/ledger/vendor/ledger-eth.js b/js/src/3rdparty/ledger/vendor/ledger-eth.js deleted file mode 100644 index 80ff0d0a6a62f2c4866fd7d71eb4658c111d636a..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/ledger/vendor/ledger-eth.js +++ /dev/null @@ -1,166 +0,0 @@ -/******************************************************************************** -* Ledger Communication toolkit -* (c) 2016 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ - -/* eslint-disable */ - -'use strict'; - -var LedgerEth = function(comm) { - this.comm = comm; -} - -LedgerEth.splitPath = function(path) { - var result = []; - var components = path.split('/'); - components.forEach(function (element, index) { - var number = parseInt(element, 10); - if (isNaN(number)) { - return; - } - if ((element.length > 1) && (element[element.length - 1] == "'")) { - number += 0x80000000; - } - result.push(number); - }); - return result; -} - -// callback is function(response, error) -LedgerEth.prototype.getAddress = function(path, callback, boolDisplay, boolChaincode) { - var splitPath = LedgerEth.splitPath(path); - var buffer = new Buffer(5 + 1 + splitPath.length * 4); - buffer[0] = 0xe0; - buffer[1] = 0x02; - buffer[2] = (boolDisplay ? 0x01 : 0x00); - buffer[3] = (boolChaincode ? 0x01 : 0x00); - buffer[4] = 1 + splitPath.length * 4; - buffer[5] = splitPath.length; - splitPath.forEach(function (element, index) { - buffer.writeUInt32BE(element, 6 + 4 * index); - }); - var self = this; - var localCallback = function(response, error) { - if (typeof error != "undefined") { - callback(undefined, error); - } - else { - var result = {}; - response = new Buffer(response, 'hex'); - var sw = response.readUInt16BE(response.length - 2); - if (sw != 0x9000) { - callback(undefined, "Invalid status " + sw.toString(16)); - return; - } - var publicKeyLength = response[0]; - var addressLength = response[1 + publicKeyLength]; - result['publicKey'] = response.slice(1, 1 + publicKeyLength).toString('hex'); - result['address'] = "0x" + response.slice(1 + publicKeyLength + 1, 1 + publicKeyLength + 1 + addressLength).toString('ascii'); - if (boolChaincode) { - result['chainCode'] = response.slice(1 + publicKeyLength + 1 + addressLength, 1 + publicKeyLength + 1 + addressLength + 32).toString('hex'); - } - callback(result); - } - }; - this.comm.exchange(buffer.toString('hex'), localCallback); -} - -// callback is function(response, error) -LedgerEth.prototype.signTransaction = function(path, rawTxHex, callback) { - var splitPath = LedgerEth.splitPath(path); - var offset = 0; - var rawTx = new Buffer(rawTxHex, 'hex'); - var apdus = []; - while (offset != rawTx.length) { - var maxChunkSize = (offset == 0 ? (150 - 1 - splitPath.length * 4) : 150) - var chunkSize = (offset + maxChunkSize > rawTx.length ? rawTx.length - offset : maxChunkSize); - var buffer = new Buffer(offset == 0 ? 5 + 1 + splitPath.length * 4 + chunkSize : 5 + chunkSize); - buffer[0] = 0xe0; - buffer[1] = 0x04; - buffer[2] = (offset == 0 ? 0x00 : 0x80); - buffer[3] = 0x00; - buffer[4] = (offset == 0 ? 1 + splitPath.length * 4 + chunkSize : chunkSize); - if (offset == 0) { - buffer[5] = splitPath.length; - splitPath.forEach(function (element, index) { - buffer.writeUInt32BE(element, 6 + 4 * index); - }); - rawTx.copy(buffer, 6 + 4 * splitPath.length, offset, offset + chunkSize); - } - else { - rawTx.copy(buffer, 5, offset, offset + chunkSize); - } - apdus.push(buffer.toString('hex')); - offset += chunkSize; - } - var self = this; - var localCallback = function(response, error) { - if (typeof error != "undefined") { - callback(undefined, error); - } - else { - response = new Buffer(response, 'hex'); - var sw = response.readUInt16BE(response.length - 2); - if (sw != 0x9000) { - callback(undefined, "Invalid status " + sw.toString(16)); - return; - } - if (apdus.length == 0) { - var result = {}; - result['v'] = response.slice(0, 1).toString('hex'); - result['r'] = response.slice(1, 1 + 32).toString('hex'); - result['s'] = response.slice(1 + 32, 1 + 32 + 32).toString('hex'); - callback(result); - } - else { - self.comm.exchange(apdus.shift(), localCallback); - } - } - }; - self.comm.exchange(apdus.shift(), localCallback); -} - -// callback is function(response, error) -LedgerEth.prototype.getAppConfiguration = function(callback) { - var buffer = new Buffer(5); - buffer[0] = 0xe0; - buffer[1] = 0x06; - buffer[2] = 0x00; - buffer[3] = 0x00; - buffer[4] = 0x00; - var localCallback = function(response, error) { - if (typeof error != "undefined") { - callback(undefined, error); - } - else { - response = new Buffer(response, 'hex'); - var result = {}; - var sw = response.readUInt16BE(response.length - 2); - if (sw != 0x9000) { - callback(undefined, "Invalid status " + sw.toString(16)); - return; - } - result['arbitraryDataEnabled'] = (response[0] & 0x01); - result['version'] = "" + response[1] + '.' + response[2] + '.' + response[3]; - callback(result); - } - }; - this.comm.exchange(buffer.toString('hex'), localCallback); -} - -module.exports = LedgerEth; - -/* eslint-enable */ diff --git a/js/src/3rdparty/ledger/vendor/ledger3.js b/js/src/3rdparty/ledger/vendor/ledger3.js deleted file mode 100644 index 9601279ad6b10cc39aac904e1ad9308a967b794b..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/ledger/vendor/ledger3.js +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************** -* Ledger Communication toolkit -* (c) 2016 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ - -/* eslint-disable */ - -'use strict'; - -var Ledger3 = function(scrambleKey, timeoutSeconds) { - this.scrambleKey = new Buffer(scrambleKey, 'ascii'); - this.timeoutSeconds = timeoutSeconds; -} - -Ledger3.wrapApdu = function(apdu, key) { - var result = new Buffer(apdu.length); - for (var i=0; i. - -const nock = require('nock'); - -const APIKEY = '0x123454321'; - -function mockget (shapeshift, requests) { - let scope = nock(shapeshift.getRpc().ENDPOINT); - - requests.forEach((request) => { - scope = scope - .get(`/${request.path}`) - .reply(request.code || 200, () => { - return request.reply; - }); - }); - - return scope; -} - -function mockpost (shapeshift, requests) { - let scope = nock(shapeshift.getRpc().ENDPOINT); - - requests.forEach((request) => { - scope = scope - .post(`/${request.path}`) - .reply(request.code || 200, (uri, body) => { - scope.body = scope.body || {}; - scope.body[request.path] = body; - - return request.reply; - }); - }); - - return scope; -} - -module.exports = { - APIKEY, - mockget, - mockpost -}; diff --git a/js/src/3rdparty/shapeshift/index.js b/js/src/3rdparty/shapeshift/index.js deleted file mode 100644 index aac05d3ebbb040b9df59f64c9480f1d3698e0845..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/shapeshift/index.js +++ /dev/null @@ -1,22 +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 . - -import initRpc from './rpc'; -import initShapeshift from './shapeshift'; - -export default function (apikey) { - return initShapeshift(initRpc(apikey)); -} diff --git a/js/src/3rdparty/shapeshift/rpc.js b/js/src/3rdparty/shapeshift/rpc.js deleted file mode 100644 index 711a41c51be3ea981400c08d889900ab6d52d429..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/shapeshift/rpc.js +++ /dev/null @@ -1,67 +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 . - -const ENDPOINT = 'https://cors.shapeshift.io'; - -function call (method, options) { - return fetch(`${ENDPOINT}/${method}`, options) - .then((response) => { - if (!response.ok) { - throw new Error(response.statusText); - } - - return response.json(); - }) - .then((result) => { - if (result.error) { - throw new Error(result.error); - } - - return result; - }); -} - -export default function (apiKey) { - function get (method) { - return call(method, { - method: 'GET', - headers: { - 'Accept': 'application/json' - } - }); - } - - function post (method, data) { - const params = Object.assign({}, { apiKey }, data); - const body = JSON.stringify(params); - - return call(method, { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - 'Content-Length': body.length - }, - body - }); - } - - return { - ENDPOINT, - get, - post - }; -} diff --git a/js/src/3rdparty/shapeshift/rpc.spec.js b/js/src/3rdparty/shapeshift/rpc.spec.js deleted file mode 100644 index d445fbb050833e32dc683c72c7ce95f15fefb6bd..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/shapeshift/rpc.spec.js +++ /dev/null @@ -1,91 +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 . - -const helpers = require('./helpers.spec.js'); - -const ShapeShift = require('./'); -const initShapeshift = (ShapeShift.default || ShapeShift); - -const mockget = helpers.mockget; -const mockpost = helpers.mockpost; - -describe('shapeshift/rpc', () => { - let rpc; - let shapeshift; - - beforeEach(() => { - shapeshift = initShapeshift(helpers.APIKEY); - rpc = shapeshift.getRpc(); - }); - - describe('GET', () => { - const REPLY = { test: 'this is some result' }; - - let scope; - let result; - - beforeEach(() => { - scope = mockget(shapeshift, [{ path: 'test', reply: REPLY }]); - - return rpc - .get('test') - .then((_result) => { - result = _result; - }); - }); - - it('does GET', () => { - expect(scope.isDone()).to.be.true; - }); - - it('retrieves the info', () => { - expect(result).to.deep.equal(REPLY); - }); - }); - - describe('POST', () => { - const REPLY = { test: 'this is some result' }; - - let scope; - let result; - - beforeEach(() => { - scope = mockpost(shapeshift, [{ path: 'test', reply: REPLY }]); - - return rpc - .post('test', { input: 'stuff' }) - .then((_result) => { - result = _result; - }); - }); - - it('does POST', () => { - expect(scope.isDone()).to.be.true; - }); - - it('retrieves the info', () => { - expect(result).to.deep.equal(REPLY); - }); - - it('passes the input object', () => { - expect(scope.body.test.input).to.equal('stuff'); - }); - - it('passes the apikey specified', () => { - expect(scope.body.test.apiKey).to.equal(helpers.APIKEY); - }); - }); -}); diff --git a/js/src/3rdparty/shapeshift/shapeshift.js b/js/src/3rdparty/shapeshift/shapeshift.js deleted file mode 100644 index 5ecf141daa8d7c76b171966452fc1985462a2e7e..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/shapeshift/shapeshift.js +++ /dev/null @@ -1,135 +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 . - -export default function (rpc) { - let _subscriptions = []; - let _pollStatusIntervalId = null; - let _subscriptionPromises = null; - - function getCoins () { - return rpc.get('getcoins'); - } - - function getMarketInfo (pair) { - return rpc.get(`marketinfo/${pair}`); - } - - function getRpc () { - return rpc; - } - - function getStatus (depositAddress) { - return rpc.get(`txStat/${depositAddress}`); - } - - function shift (toAddress, returnAddress, pair) { - return rpc.post('shift', { - pair, - returnAddress, - withdrawal: toAddress - }); - } - - function subscribe (depositAddress, callback) { - if (!depositAddress || !callback) { - return; - } - - const index = _subscriptions.length; - - _subscriptions.push({ - callback, - depositAddress, - index - }); - - if (_pollStatusIntervalId === null) { - _pollStatusIntervalId = setInterval(_pollStatus, 2000); - } - } - - function unsubscribe (depositAddress) { - _subscriptions = _subscriptions.filter((sub) => sub.depositAddress !== depositAddress); - - if (_subscriptions.length === 0) { - clearInterval(_pollStatusIntervalId); - _pollStatusIntervalId = null; - } - - return true; - } - - function _getSubscriptionStatus (subscription) { - if (!subscription) { - return Promise.resolve(); - } - - return getStatus(subscription.depositAddress) - .then((result) => { - switch (result.status) { - case 'no_deposits': - case 'received': - subscription.callback(null, result); - return true; - - case 'complete': - subscription.callback(null, result); - unsubscribe(subscription.depositAddress); - return true; - - case 'failed': - subscription.callback({ - message: status.error, - fatal: true - }); - unsubscribe(subscription.depositAddress); - return true; - } - }) - .catch(() => { - return true; - }); - } - - function _pollStatus () { - _subscriptionPromises = Promise.all(_subscriptions.map(_getSubscriptionStatus)); - } - - function _getSubscriptions () { - return _subscriptions; - } - - function _getSubscriptionPromises () { - return _subscriptionPromises; - } - - function _isPolling () { - return _pollStatusIntervalId !== null; - } - - return { - _getSubscriptions, - _getSubscriptionPromises, - _isPolling, - getCoins, - getMarketInfo, - getRpc, - getStatus, - shift, - subscribe, - unsubscribe - }; -} diff --git a/js/src/3rdparty/shapeshift/shapeshift.spec.js b/js/src/3rdparty/shapeshift/shapeshift.spec.js deleted file mode 100644 index 0fa6639d8e4f824cae2db5ee12c7fe33bb61e98e..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/shapeshift/shapeshift.spec.js +++ /dev/null @@ -1,220 +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 . - -const sinon = require('sinon'); - -const ShapeShift = require('./'); -const initShapeshift = (ShapeShift.default || ShapeShift); - -const helpers = require('./helpers.spec.js'); - -const mockget = helpers.mockget; -const mockpost = helpers.mockpost; - -describe('shapeshift/calls', () => { - let clock; - let shapeshift; - - beforeEach(() => { - clock = sinon.useFakeTimers(); - shapeshift = initShapeshift(helpers.APIKEY); - }); - - afterEach(() => { - clock.restore(); - }); - - describe('getCoins', () => { - const REPLY = { - BTC: { - name: 'Bitcoin', - symbol: 'BTC', - image: 'https://shapeshift.io/images/coins/bitcoin.png', - status: 'available' - }, - ETH: { - name: 'Ether', - symbol: 'ETH', - image: 'https://shapeshift.io/images/coins/ether.png', - status: 'available' - } - }; - - let scope; - - beforeEach(() => { - scope = mockget(shapeshift, [{ path: 'getcoins', reply: REPLY }]); - - return shapeshift.getCoins(); - }); - - it('makes the call', () => { - expect(scope.isDone()).to.be.ok; - }); - }); - - describe('getMarketInfo', () => { - const REPLY = { - pair: 'btc_ltc', - rate: 128.17959917, - minerFee: 0.003, - limit: 0, - minimum: 0.00004632 - }; - - let scope; - - beforeEach(() => { - scope = mockget(shapeshift, [{ path: 'marketinfo/btc_ltc', reply: REPLY }]); - - return shapeshift.getMarketInfo('btc_ltc'); - }); - - it('makes the call', () => { - expect(scope.isDone()).to.be.ok; - }); - }); - - describe('getStatus', () => { - const REPLY = { - status: '0x123', - address: '0x123' - }; - - let scope; - - beforeEach(() => { - scope = mockget(shapeshift, [{ path: 'txStat/0x123', reply: REPLY }]); - - return shapeshift.getStatus('0x123'); - }); - - it('makes the call', () => { - expect(scope.isDone()).to.be.ok; - }); - }); - - describe('shift', () => { - const REPLY = { - deposit: '1BTC', - depositType: 'btc', - withdrawal: '0x456', - withdrawalType: 'eth' - }; - - let scope; - - beforeEach(() => { - scope = mockpost(shapeshift, [{ path: 'shift', reply: REPLY }]); - - return shapeshift.shift('0x456', '1BTC', 'btc_eth'); - }); - - it('makes the call', () => { - expect(scope.isDone()).to.be.ok; - }); - - describe('body', () => { - it('has withdrawal set', () => { - expect(scope.body.shift.withdrawal).to.equal('0x456'); - }); - - it('has returnAddress set', () => { - expect(scope.body.shift.returnAddress).to.equal('1BTC'); - }); - - it('has pair set', () => { - expect(scope.body.shift.pair).to.equal('btc_eth'); - }); - }); - }); - - describe('subscriptions', () => { - const ADDRESS = '0123456789abcdef'; - const REPLY = { - status: 'complete', - address: ADDRESS - }; - - let callback; - - beforeEach(() => { - mockget(shapeshift, [{ path: `txStat/${ADDRESS}`, reply: REPLY }]); - callback = sinon.stub(); - shapeshift.subscribe(ADDRESS, callback); - }); - - describe('subscribe', () => { - it('adds the depositAddress to the list', () => { - const subscriptions = shapeshift._getSubscriptions(); - - expect(subscriptions.length).to.equal(1); - expect(subscriptions[0].depositAddress).to.equal(ADDRESS); - }); - - it('starts the polling timer', () => { - expect(shapeshift._isPolling()).to.be.true; - }); - - it('calls the callback once the timer has elapsed', () => { - clock.tick(2222); - - return shapeshift._getSubscriptionPromises().then(() => { - expect(callback).to.have.been.calledWith(null, REPLY); - }); - }); - - it('auto-unsubscribes on completed', () => { - clock.tick(2222); - - return shapeshift._getSubscriptionPromises().then(() => { - expect(shapeshift._getSubscriptions().length).to.equal(0); - }); - }); - }); - - describe('unsubscribe', () => { - it('unbsubscribes when requested', () => { - expect(shapeshift._getSubscriptions().length).to.equal(1); - shapeshift.unsubscribe(ADDRESS); - expect(shapeshift._getSubscriptions().length).to.equal(0); - }); - - it('clears the polling on no subscriptions', () => { - shapeshift.unsubscribe(ADDRESS); - expect(shapeshift._isPolling()).to.be.false; - }); - - it('handles unsubscribe of auto-unsubscribe', () => { - clock.tick(2222); - - return shapeshift._getSubscriptionPromises().then(() => { - expect(shapeshift.unsubscribe(ADDRESS)).to.be.true; - }); - }); - - it('handles unsubscribe when multiples listed', () => { - const ADDRESS2 = 'abcdef0123456789'; - - shapeshift.subscribe(ADDRESS2, sinon.stub()); - expect(shapeshift._getSubscriptions().length).to.equal(2); - expect(shapeshift._getSubscriptions()[0].depositAddress).to.equal(ADDRESS); - shapeshift.unsubscribe(ADDRESS); - expect(shapeshift._getSubscriptions()[0].depositAddress).to.equal(ADDRESS2); - }); - }); - }); -}); diff --git a/js/src/3rdparty/sms-verification/index.js b/js/src/3rdparty/sms-verification/index.js deleted file mode 100644 index 79cbf13d2fe7499401ffdd0baa20d253172cb6ed..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/sms-verification/index.js +++ /dev/null @@ -1,68 +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 . - -import { stringify } from 'querystring'; - -export const isServerRunning = (isTestnet = false) => { - const port = isTestnet ? 8443 : 443; - - return fetch(`https://sms-verification.parity.io:${port}/health`, { - mode: 'cors', - cache: 'no-store' - }) - .then((res) => { - return res.ok; - }) - .catch(() => { - return false; - }); -}; - -export const hasReceivedCode = (number, address, isTestnet = false) => { - const port = isTestnet ? 8443 : 443; - const query = stringify({ number, address }); - - return fetch(`https://sms-verification.parity.io:${port}/?${query}`, { - mode: 'cors', - cache: 'no-store' - }) - .then((res) => { - return res.ok; - }) - .catch(() => { - return false; // todo: check for 404 - }); -}; - -export const postToServer = (query, isTestnet = false) => { - const port = isTestnet ? 8443 : 443; - - query = stringify(query); - - return fetch(`https://sms-verification.parity.io:${port}/?${query}`, { - method: 'POST', - mode: 'cors', - cache: 'no-store' - }) - .then((res) => { - return res.json().then((data) => { - if (res.ok) { - return data.message; - } - throw new Error(data.message || 'unknown error'); - }); - }); -}; diff --git a/js/src/3rdparty/sms-verification/terms-of-service.js b/js/src/3rdparty/sms-verification/terms-of-service.js deleted file mode 100644 index 9451a382b7b1c3cbd3c860ca00e2df3ebd981547..0000000000000000000000000000000000000000 --- a/js/src/3rdparty/sms-verification/terms-of-service.js +++ /dev/null @@ -1,27 +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 . - -import React from 'react'; - -export default ( -
    -
  • This privacy notice relates to your use of the Parity SMS verification service. We take your privacy seriously and deal in an honest, direct and transparent way when it comes to your data.
  • -
  • We collect your phone number when you use this service. This is temporarily kept in memory, and then encrypted and stored in our EU servers. We only retain the cryptographic hash of the number to prevent duplicated accounts. You consent to this use.
  • -
  • You pay a fee for the cost of this service using the account you want to verify.
  • -
  • Your phone number is transmitted to a third party US SMS verification service Twilio for the sole purpose of the SMS verification. You consent to this use. Twilio’s privacy policy is here: https://www.twilio.com/legal/privacy/developer.
  • -
  • Parity Technology Limited is registered in England and Wales under company number 09760015 and complies with the Data Protection Act 1998 (UK). You may contact us via email at admin@parity.io. Our general privacy policy can be found here: https://parity.io/legal.html.
  • -
-); diff --git a/js/src/abi/README.md b/js/src/abi/README.md deleted file mode 100644 index 20bc094ded6d8e4d90e77847174add1914262e65..0000000000000000000000000000000000000000 --- a/js/src/abi/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# ethabi-js - -A very early, very POC-type port of [https://github.com/paritytech/ethabi](https://github.com/paritytech/ethabi) to JavaScript - -[![Build Status](https://travis-ci.org/jacogr/ethabi-js.svg?branch=master)](https://travis-ci.org/jacogr/ethabi-js) -[![Coverage Status](https://coveralls.io/repos/github/jacogr/ethabi-js/badge.svg?branch=master)](https://coveralls.io/github/jacogr/ethabi-js?branch=master) -[![Dependency Status](https://david-dm.org/jacogr/ethabi-js.svg)](https://david-dm.org/jacogr/ethabi-js) -[![devDependency Status](https://david-dm.org/jacogr/ethabi-js/dev-status.svg)](https://david-dm.org/jacogr/ethabi-js#info=devDependencies) - -## contributing - -Clone the repo and install dependencies via `npm install`. Tests can be executed via - -- `npm run testOnce` (100% covered unit tests) - -## installation - -Install the package with `npm install --save ethabi-js` from the [npm registry ethabi-js](https://www.npmjs.com/package/ethabi-js) - - -## implementation -### approach - -- this version tries to stay as close to the original Rust version in intent, function names & purpose -- it is a basic port of the Rust version, relying on effectively the same test-suite (expanded where deemed appropriate) -- it is meant as a library to be used in other projects, i.e. [ethapi-js](https://www.npmjs.com/package/ethapi-js) - -### differences to original Rust version - -- internally the library operates on string binary representations as opposed to Vector bytes, lengths are therefore 64 bytes as opposed to 32 bytes -- function names are adapted from the Rust standard snake_case to the JavaScript standard camelCase -- due to the initial library focus, the cli component (as implemented by the original) is not supported nor mplemented diff --git a/js/src/abi/abi.js b/js/src/abi/abi.js deleted file mode 100644 index 892f531fa0feabd36068e48d31bc4ce8a8733d12..0000000000000000000000000000000000000000 --- a/js/src/abi/abi.js +++ /dev/null @@ -1,20 +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 . - -import Interface from './spec/interface'; - -export default class Abi extends Interface { -} diff --git a/js/src/abi/decoder/bytesTaken.js b/js/src/abi/decoder/bytesTaken.js deleted file mode 100644 index dbf766f4bf136674168b38719bba0588293671c4..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/bytesTaken.js +++ /dev/null @@ -1,30 +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 . - -export default class BytesTaken { - constructor (bytes, newOffset) { - this._bytes = bytes; - this._newOffset = newOffset; - } - - get bytes () { - return this._bytes; - } - - get newOffset () { - return this._newOffset; - } -} diff --git a/js/src/abi/decoder/bytesTaken.spec.js b/js/src/abi/decoder/bytesTaken.spec.js deleted file mode 100644 index 9329657e48a62e23a2a20dfc6e14665a6773e394..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/bytesTaken.spec.js +++ /dev/null @@ -1,29 +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 . - -import BytesTaken from './bytesTaken'; - -describe('abi/decoder/BytesTaken', () => { - describe('constructor', () => { - it('sets the bytes of the object', () => { - expect((new BytesTaken(1, 2)).bytes).to.equal(1); - }); - - it('sets the newOffset of the object', () => { - expect((new BytesTaken(3, 4)).newOffset).to.equal(4); - }); - }); -}); diff --git a/js/src/abi/decoder/decodeResult.js b/js/src/abi/decoder/decodeResult.js deleted file mode 100644 index 5e41da4b60aa8595f8a1e451e4f3f02f54e5361f..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/decodeResult.js +++ /dev/null @@ -1,30 +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 . - -export default class DecodeResult { - constructor (token, newOffset) { - this._token = token; - this._newOffset = newOffset; - } - - get token () { - return this._token; - } - - get newOffset () { - return this._newOffset; - } -} diff --git a/js/src/abi/decoder/decodeResult.spec.js b/js/src/abi/decoder/decodeResult.spec.js deleted file mode 100644 index 0c4c81c5c4ffb46ec8fa6ce79f7b6e030ab9c466..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/decodeResult.spec.js +++ /dev/null @@ -1,29 +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 . - -import DecodeResult from './decodeResult'; - -describe('abi/decoder/DecodeResult', () => { - describe('constructor', () => { - it('sets the token of the object', () => { - expect((new DecodeResult('token', 2)).token).to.equal('token'); - }); - - it('sets the newOffset of the object', () => { - expect((new DecodeResult('baz', 4)).newOffset).to.equal(4); - }); - }); -}); diff --git a/js/src/abi/decoder/decoder.js b/js/src/abi/decoder/decoder.js deleted file mode 100644 index 6922c91e800924e0664ccc2fcb88484e3f9b1962..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/decoder.js +++ /dev/null @@ -1,156 +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 . - -import utf8 from 'utf8'; - -import Token from '../token/token'; -import BytesTaken from './bytesTaken'; -import DecodeResult from './decodeResult'; -import ParamType from '../spec/paramType/paramType'; -import { sliceData } from '../util/slice'; -import { asAddress, asBool, asI32, asU32 } from '../util/sliceAs'; -import { isArray, isInstanceOf } from '../util/types'; - -const NULL = '0000000000000000000000000000000000000000000000000000000000000000'; - -export default class Decoder { - static decode (params, data) { - if (!isArray(params)) { - throw new Error('Parameters should be array of ParamType'); - } - - const slices = sliceData(data); - let offset = 0; - - return params.map((param) => { - const result = Decoder.decodeParam(param, slices, offset); - - offset = result.newOffset; - return result.token; - }); - } - - static peek (slices, position) { - if (!slices || !slices[position]) { - return NULL; - } - - return slices[position]; - } - - static takeBytes (slices, position, length) { - const slicesLength = Math.floor((length + 31) / 32); - let bytesStr = ''; - - for (let idx = 0; idx < slicesLength; idx++) { - bytesStr = `${bytesStr}${Decoder.peek(slices, position + idx)}`; - } - - const bytes = (bytesStr.substr(0, length * 2).match(/.{1,2}/g) || []).map((code) => parseInt(code, 16)); - - return new BytesTaken(bytes, position + slicesLength); - } - - static decodeParam (param, slices, offset) { - if (!isInstanceOf(param, ParamType)) { - throw new Error('param should be instanceof ParamType'); - } - - const tokens = []; - let taken; - let lengthOffset; - let length; - let newOffset; - - switch (param.type) { - case 'address': - return new DecodeResult(new Token(param.type, asAddress(Decoder.peek(slices, offset))), offset + 1); - - case 'bool': - return new DecodeResult(new Token(param.type, asBool(Decoder.peek(slices, offset))), offset + 1); - - case 'int': - return new DecodeResult(new Token(param.type, asI32(Decoder.peek(slices, offset))), offset + 1); - - case 'uint': - return new DecodeResult(new Token(param.type, asU32(Decoder.peek(slices, offset))), offset + 1); - - case 'fixedBytes': - taken = Decoder.takeBytes(slices, offset, param.length); - - return new DecodeResult(new Token(param.type, taken.bytes), taken.newOffset); - - case 'bytes': - lengthOffset = asU32(Decoder.peek(slices, offset)).div(32).toNumber(); - length = asU32(Decoder.peek(slices, lengthOffset)).toNumber(); - taken = Decoder.takeBytes(slices, lengthOffset + 1, length); - - return new DecodeResult(new Token(param.type, taken.bytes), offset + 1); - - case 'string': - if (param.indexed) { - taken = Decoder.takeBytes(slices, offset, 32); - - return new DecodeResult(new Token('fixedBytes', taken.bytes), offset + 1); - } - - lengthOffset = asU32(Decoder.peek(slices, offset)).div(32).toNumber(); - length = asU32(Decoder.peek(slices, lengthOffset)).toNumber(); - taken = Decoder.takeBytes(slices, lengthOffset + 1, length); - - const str = taken.bytes.map((code) => String.fromCharCode(code)).join(''); - - let decoded; - - try { - decoded = utf8.decode(str); - } catch (error) { - decoded = str; - } - - return new DecodeResult(new Token(param.type, decoded), offset + 1); - - case 'array': - lengthOffset = asU32(Decoder.peek(slices, offset)).div(32).toNumber(); - length = asU32(Decoder.peek(slices, lengthOffset)).toNumber(); - newOffset = lengthOffset + 1; - - for (let idx = 0; idx < length; idx++) { - const result = Decoder.decodeParam(param.subtype, slices, newOffset); - - newOffset = result.newOffset; - tokens.push(result.token); - } - - return new DecodeResult(new Token(param.type, tokens), offset + 1); - - case 'fixedArray': - newOffset = offset; - - for (let idx = 0; idx < param.length; idx++) { - const result = Decoder.decodeParam(param.subtype, slices, newOffset); - - newOffset = result.newOffset; - tokens.push(result.token); - } - - return new DecodeResult(new Token(param.type, tokens), newOffset); - - default: - throw new Error(`Invalid param type ${param.type} in decodeParam`); - } - } -} diff --git a/js/src/abi/decoder/decoder.spec.js b/js/src/abi/decoder/decoder.spec.js deleted file mode 100644 index 5065be3a7ee603ca487e53aa5d72542e44b944fa..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/decoder.spec.js +++ /dev/null @@ -1,319 +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 . - -import BigNumber from 'bignumber.js'; - -import Decoder from './decoder'; -import ParamType from '../spec/paramType'; -import Token from '../token'; -import { padU32 } from '../util/pad'; - -describe('abi/decoder/Decoder', () => { - const stringToBytes = function (str) { - return str.match(/.{1,2}/g).map((code) => parseInt(code, 16)); - }; - - const address1 = '0000000000000000000000001111111111111111111111111111111111111111'; - const address2 = '0000000000000000000000002222222222222222222222222222222222222222'; - const address3 = '0000000000000000000000003333333333333333333333333333333333333333'; - const address4 = '0000000000000000000000004444444444444444444444444444444444444444'; - const bool1 = '0000000000000000000000000000000000000000000000000000000000000001'; - const bytes1 = '1234000000000000000000000000000000000000000000000000000000000000'; - const bytes2 = '1000000000000000000000000000000000000000000000000000000000000000'; - const bytes3 = '10000000000000000000000000000000000000000000000000000000000002'; - const bytes4 = '0010000000000000000000000000000000000000000000000000000000000002'; - const int1 = '0111111111111111111111111111111111111111111111111111111111111111'; - const intn = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85'; - const string1 = '6761766f66796f726b0000000000000000000000000000000000000000000000'; - const string2 = '4665726ee16e64657a0000000000000000000000000000000000000000000000'; - const tokenAddress1 = new Token('address', `0x${address1.slice(-40)}`); - const tokenAddress2 = new Token('address', `0x${address2.slice(-40)}`); - const tokenAddress3 = new Token('address', `0x${address3.slice(-40)}`); - const tokenAddress4 = new Token('address', `0x${address4.slice(-40)}`); - const tokenBool1 = new Token('bool', true); - const tokenFixedBytes1 = new Token('fixedBytes', [0x12, 0x34]); - const tokenBytes1 = new Token('bytes', [0x12, 0x34]); - const tokenBytes2 = new Token('bytes', stringToBytes(bytes2).concat(stringToBytes(bytes2))); - const tokenBytes3 = new Token('bytes', stringToBytes(bytes3)); - const tokenBytes4 = new Token('bytes', stringToBytes(bytes4)); - const tokenInt1 = new Token('int', new BigNumber(int1, 16)); - const tokenIntn = new Token('int', new BigNumber(-123)); - const tokenUint1 = new Token('uint', new BigNumber(int1, 16)); - const tokenUintn = new Token('uint', new BigNumber(intn, 16)); - const tokenString1 = new Token('string', 'gavofyork'); - const tokenString2 = new Token('string', 'Fernández'); - const slices = [ address1, address2, address3, address4 ]; - - describe('peek', () => { - it('returns the slice at the correct position', () => { - expect(Decoder.peek(slices, 1)).to.equal(slices[1]); - }); - - it('returns empty on invalid slices', () => { - expect(Decoder.peek(null, 4)).to.equal('0000000000000000000000000000000000000000000000000000000000000000'); - }); - }); - - describe('takeBytes', () => { - it('returns a single slice', () => { - expect(Decoder.takeBytes(slices, 0, 32).bytes).to.deep.equal(stringToBytes(slices[0])); - }); - - it('returns a single partial slice', () => { - expect(Decoder.takeBytes(slices, 0, 20).bytes).to.deep.equal(stringToBytes(slices[0].substr(0, 40))); - }); - - it('returns multiple slices', () => { - expect(Decoder.takeBytes(slices, 0, 64).bytes).to.deep.equal(stringToBytes(`${slices[0]}${slices[1]}`)); - }); - - it('returns a single offset slice', () => { - expect(Decoder.takeBytes(slices, 1, 32).bytes).to.deep.equal(stringToBytes(slices[1])); - }); - - it('returns multiple offset slices', () => { - expect(Decoder.takeBytes(slices, 1, 64).bytes).to.deep.equal(stringToBytes(`${slices[1]}${slices[2]}`)); - }); - - it('returns the requires length from slices', () => { - expect( - Decoder.takeBytes(slices, 1, 75).bytes - ).to.deep.equal(stringToBytes(`${slices[1]}${slices[2]}${slices[3]}`.substr(0, 150))); - }); - }); - - describe('decodeParam', () => { - it('throws an error on non ParamType param', () => { - expect(() => Decoder.decodeParam({})).to.throw(/ParamType/); - }); - - it('throws an error on invalid param type', () => { - const pt = new ParamType('address'); - - pt._type = 'noMatch'; - - expect(() => Decoder.decodeParam(pt)).to.throw(/noMatch/); - }); - - it('decodes an address', () => { - expect( - Decoder.decodeParam(new ParamType('address'), [address1], 0).token - ).to.deep.equal(tokenAddress1); - }); - - it('decodes a bool', () => { - expect( - Decoder.decodeParam(new ParamType('bool'), [bool1], 0).token - ).to.deep.equal(tokenBool1); - }); - - it('decodes an int', () => { - expect( - Decoder.decodeParam(new ParamType('int'), [int1], 0).token - ).to.deep.equal(tokenInt1); - }); - - it('decodes a negative int', () => { - expect( - Decoder.decodeParam(new ParamType('int'), [intn], 0).token - ).to.deep.equal(tokenIntn); - }); - - it('decodes an uint', () => { - expect( - Decoder.decodeParam(new ParamType('uint'), [int1], 0).token - ).to.deep.equal(tokenUint1); - }); - - it('decodes an uint (negative as int)', () => { - expect( - Decoder.decodeParam(new ParamType('uint'), [intn], 0).token - ).to.deep.equal(tokenUintn); - }); - - it('decodes fixedBytes', () => { - expect( - Decoder.decodeParam(new ParamType('fixedBytes', null, 2), [bytes1], 0).token - ).to.deep.equal(tokenFixedBytes1); - }); - - it('decodes bytes', () => { - expect( - Decoder.decodeParam(new ParamType('bytes'), [padU32(0x20), padU32(2), bytes1], 0).token - ).to.deep.equal(tokenBytes1); - }); - - it('decodes string', () => { - expect( - Decoder.decodeParam(new ParamType('string'), [padU32(0x20), padU32(9), string1], 0).token - ).to.deep.equal(tokenString1); - }); - - it('decodes utf8-invalid string', () => { - expect( - Decoder.decodeParam(new ParamType('string'), [padU32(0x20), padU32(9), string2], 0).token - ).to.deep.equal(tokenString2); - }); - - it('decodes string (indexed)', () => { - expect( - Decoder.decodeParam(new ParamType('string', null, 0, true), [bytes1], 0) - ).to.deep.equal(Decoder.decodeParam(new ParamType('fixedBytes', null, 32, true), [bytes1], 0)); - }); - }); - - describe('decode', () => { - it('throws an error on invalid params', () => { - expect(() => Decoder.decode(null, '123')).to.throw(/array/); - }); - - describe('address', () => { - it('decodes an address', () => { - expect( - Decoder.decode( - [new ParamType('address')], - `${address1}` - ) - ).to.deep.equal([tokenAddress1]); - }); - - it('decodes 2 addresses', () => { - expect( - Decoder.decode( - [new ParamType('address'), new ParamType('address')], - `${address1}${address2}` - ) - ).to.deep.equal([tokenAddress1, tokenAddress2]); - }); - - it('decodes a fixedArray of addresses', () => { - expect( - Decoder.decode( - [new ParamType('fixedArray', new ParamType('address'), 2)], - `${address1}${address2}` - ) - ).to.deep.equal([new Token('fixedArray', [tokenAddress1, tokenAddress2])]); - }); - - it('decodes a dynamic array of addresses', () => { - expect( - Decoder.decode( - [new ParamType('array', new ParamType('address'))], - `${padU32(0x20)}${padU32(2)}${address1}${address2}` - ) - ).to.deep.equal([new Token('array', [tokenAddress1, tokenAddress2])]); - }); - - it('decodes a dynamic array of fixed arrays', () => { - expect( - Decoder.decode( - [new ParamType('array', new ParamType('fixedArray', new ParamType('address'), 2))], - `${padU32(0x20)}${padU32(2)}${address1}${address2}${address3}${address4}` - ) - ).to.deep.equal([ - new Token('array', [ - new Token('fixedArray', [tokenAddress1, tokenAddress2]), - new Token('fixedArray', [tokenAddress3, tokenAddress4]) - ]) - ]); - }); - }); - - describe('int', () => { - it('decodes an int', () => { - expect( - Decoder.decode( - [new ParamType('int')], - `${int1}` - ) - ).to.deep.equal([tokenInt1]); - }); - }); - - describe('uint', () => { - it('decodes an uint', () => { - expect( - Decoder.decode( - [new ParamType('uint')], - `${int1}` - ) - ).to.deep.equal([tokenUint1]); - }); - }); - - describe('fixedBytes', () => { - it('decodes fixedBytes', () => { - expect( - Decoder.decode( - [new ParamType('fixedBytes', null, 2)], - `${bytes1}` - ) - ).to.deep.equal([tokenFixedBytes1]); - }); - }); - - describe('bytes', () => { - it('decodes bytes', () => { - expect( - Decoder.decode( - [new ParamType('bytes')], - `${padU32(0x20)}${padU32(2)}${bytes1}` - ) - ).to.deep.equal([tokenBytes1]); - }); - - it('decodes bytes sequence', () => { - expect( - Decoder.decode( - [new ParamType('bytes')], - `${padU32(0x20)}${padU32(0x40)}${bytes2}${bytes2}` - ) - ).to.deep.equal([tokenBytes2]); - }); - - it('decodes bytes seuence (2)', () => { - expect( - Decoder.decode( - [new ParamType('bytes'), new ParamType('bytes')], - `${padU32(0x40)}${padU32(0x80)}${padU32(0x1f)}${bytes3}00${padU32(0x20)}${bytes4}` - ) - ).to.deep.equal([tokenBytes3, tokenBytes4]); - }); - }); - - describe('bool', () => { - it('decodes a single bool', () => { - expect( - Decoder.decode( - [new ParamType('bool')], - bool1 - ) - ).to.deep.equal([tokenBool1]); - }); - }); - - describe('string', () => { - it('decodes a string', () => { - expect( - Decoder.decode( - [new ParamType('string')], - `${padU32(0x20)}${padU32(9)}${string1}` - ) - ).to.deep.equal([tokenString1]); - }); - }); - }); -}); diff --git a/js/src/abi/decoder/index.js b/js/src/abi/decoder/index.js deleted file mode 100644 index 2ead31504180855d0ee4e5e1192bf9135c2cbc7c..0000000000000000000000000000000000000000 --- a/js/src/abi/decoder/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './decoder'; diff --git a/js/src/abi/encoder/encoder.js b/js/src/abi/encoder/encoder.js deleted file mode 100644 index fa1aa04538a4164c2199591653aa1f668ede0cf6..0000000000000000000000000000000000000000 --- a/js/src/abi/encoder/encoder.js +++ /dev/null @@ -1,75 +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 . - -import { padAddress, padBool, padBytes, padFixedBytes, padU32, padString } from '../util/pad'; -import Mediate from './mediate'; -import Token from '../token/token'; -import { isArray, isInstanceOf } from '../util/types'; - -export default class Encoder { - static encode (tokens) { - if (!isArray(tokens)) { - throw new Error('tokens should be array of Token'); - } - - const mediates = tokens.map((token, index) => Encoder.encodeToken(token, index)); - const inits = mediates - .map((mediate, idx) => mediate.init(Mediate.offsetFor(mediates, idx))) - .join(''); - const closings = mediates - .map((mediate, idx) => mediate.closing(Mediate.offsetFor(mediates, idx))) - .join(''); - - return `${inits}${closings}`; - } - - static encodeToken (token, index = 0) { - if (!isInstanceOf(token, Token)) { - throw new Error('token should be instanceof Token'); - } - - try { - switch (token.type) { - case 'address': - return new Mediate('raw', padAddress(token.value)); - - case 'int': - case 'uint': - return new Mediate('raw', padU32(token.value)); - - case 'bool': - return new Mediate('raw', padBool(token.value)); - - case 'fixedBytes': - return new Mediate('raw', padFixedBytes(token.value)); - - case 'bytes': - return new Mediate('prefixed', padBytes(token.value)); - - case 'string': - return new Mediate('prefixed', padString(token.value)); - - case 'fixedArray': - case 'array': - return new Mediate(token.type, token.value.map((token) => Encoder.encodeToken(token))); - } - } catch (e) { - throw new Error(`Cannot encode token #${index} [${token.type}: ${token.value}]. ${e.message}`); - } - - throw new Error(`Invalid token type ${token.type} in encodeToken`); - } -} diff --git a/js/src/abi/encoder/encoder.spec.js b/js/src/abi/encoder/encoder.spec.js deleted file mode 100644 index 9a4a24361ffc226cde3c7cbaf2b79150bea0bba3..0000000000000000000000000000000000000000 --- a/js/src/abi/encoder/encoder.spec.js +++ /dev/null @@ -1,291 +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 . - -import Encoder from './encoder'; -import Token from '../token'; -import { padAddress, padFixedBytes, padU32 } from '../util/pad'; - -describe('abi/encoder/Encoder', () => { - describe('encodeToken', () => { - it('requires token as Token', () => { - expect(() => Encoder.encodeToken()).to.throw(/Token/); - }); - - it('encodes address tokens in Mediate(raw)', () => { - const mediate = Encoder.encodeToken(new Token('address', '123')); - - expect(mediate.type).to.equal('raw'); - expect(mediate.value).to.be.ok; - }); - - it('encodes bool tokens in Mediate(raw)', () => { - const mediatet = Encoder.encodeToken(new Token('bool', true)); - const mediatef = Encoder.encodeToken(new Token('bool', false)); - - expect(mediatet.type).to.equal('raw'); - expect(mediatet.value).to.be.ok; - - expect(mediatef.type).to.equal('raw'); - expect(mediatef.value).to.be.ok; - }); - - it('encodes int tokens in Mediate(raw)', () => { - const mediate = Encoder.encodeToken(new Token('int', '123')); - - expect(mediate.type).to.equal('raw'); - expect(mediate.value).to.be.ok; - }); - - it('encodes uint tokens in Mediate(raw)', () => { - const mediate = Encoder.encodeToken(new Token('uint', '123')); - - expect(mediate.type).to.equal('raw'); - expect(mediate.value).to.be.ok; - }); - - it('encodes fixedBytes tokens in Mediate(raw)', () => { - const mediate = Encoder.encodeToken(new Token('fixedBytes', '123')); - - expect(mediate.type).to.equal('raw'); - expect(mediate.value).to.be.ok; - }); - - it('encodes bytes tokens in Mediate(prefixed)', () => { - const mediate = Encoder.encodeToken(new Token('bytes', '123')); - - expect(mediate.type).to.equal('prefixed'); - expect(mediate.value).to.be.ok; - }); - - it('encodes string tokens in Mediate(prefixed)', () => { - const mediate = Encoder.encodeToken(new Token('string', '123')); - - expect(mediate.type).to.equal('prefixed'); - expect(mediate.value).to.be.ok; - }); - - it('encodes fixedArray tokens in Mediate(fixedArray)', () => { - const mediate = Encoder.encodeToken(new Token('fixedArray', [new Token('uint', '123')])); - - expect(mediate.type).to.equal('fixedArray'); - expect(mediate.value).to.be.ok; - }); - - it('encodes array tokens in Mediate(array)', () => { - const mediate = Encoder.encodeToken(new Token('array', [new Token('uint', '123')])); - - expect(mediate.type).to.equal('array'); - expect(mediate.value).to.be.ok; - }); - - it('throws an Error on invalid tokens', () => { - const token = new Token('address'); - - token._type = 'noMatch'; - - expect(() => Encoder.encodeToken(token)).to.throw(/noMatch/); - }); - }); - - describe('encode', () => { - it('requires tokens array', () => { - expect(() => Encoder.encode()).to.throw(/array/); - }); - - describe('addresses', () => { - const address1 = '1111111111111111111111111111111111111111'; - const address2 = '2222222222222222222222222222222222222222'; - const address3 = '3333333333333333333333333333333333333333'; - const address4 = '4444444444444444444444444444444444444444'; - const encAddress1 = padAddress(address1); - const encAddress2 = padAddress(address2); - const encAddress3 = padAddress(address3); - const encAddress4 = padAddress(address4); - const tokenAddress1 = new Token('address', address1); - const tokenAddress2 = new Token('address', address2); - const tokenAddress3 = new Token('address', address3); - const tokenAddress4 = new Token('address', address4); - - it('encodes an address', () => { - const token = tokenAddress1; - - expect(Encoder.encode([token])).to.equal(encAddress1); - }); - - it('encodes an array of addresses', () => { - const expected = `${padU32(0x20)}${padU32(2)}${encAddress1}${encAddress2}`; - const token = new Token('array', [tokenAddress1, tokenAddress2]); - - expect(Encoder.encode([token])).to.equal(expected); - }); - - it('encodes an fixedArray of addresses', () => { - const expected = `${encAddress1}${encAddress2}`; - const token = new Token('fixedArray', [tokenAddress1, tokenAddress2]); - - expect(Encoder.encode([token])).to.equal(expected); - }); - - it('encodes two addresses', () => { - const expected = `${encAddress1}${encAddress2}`; - const tokens = [tokenAddress1, tokenAddress2]; - - expect(Encoder.encode(tokens)).to.equal(expected); - }); - - it('encodes fixed array of dynamic array addresses', () => { - const tokens1 = new Token('array', [tokenAddress1, tokenAddress2]); - const tokens2 = new Token('array', [tokenAddress3, tokenAddress4]); - const fixed = new Token('fixedArray', [tokens1, tokens2]); - const expected = `${padU32(0x40)}${padU32(0xa0)}${padU32(2)}${encAddress1}${encAddress2}${padU32(2)}${encAddress3}${encAddress4}`; - - expect(Encoder.encode([fixed])).to.equal(expected); - }); - - it('encodes dynamic array of fixed array addresses', () => { - const tokens1 = new Token('fixedArray', [tokenAddress1, tokenAddress2]); - const tokens2 = new Token('fixedArray', [tokenAddress3, tokenAddress4]); - const dynamic = new Token('array', [tokens1, tokens2]); - const expected = `${padU32(0x20)}${padU32(2)}${encAddress1}${encAddress2}${encAddress3}${encAddress4}`; - - expect(Encoder.encode([dynamic])).to.equal(expected); - }); - - it('encodes dynamic array of dynamic array addresses', () => { - const tokens1 = new Token('array', [tokenAddress1]); - const tokens2 = new Token('array', [tokenAddress2]); - const dynamic = new Token('array', [tokens1, tokens2]); - const expected = `${padU32(0x20)}${padU32(2)}${padU32(0x80)}${padU32(0xc0)}${padU32(1)}${encAddress1}${padU32(1)}${encAddress2}`; - - expect(Encoder.encode([dynamic])).to.equal(expected); - }); - - it('encodes dynamic array of dynamic array addresses (2)', () => { - const tokens1 = new Token('array', [tokenAddress1, tokenAddress2]); - const tokens2 = new Token('array', [tokenAddress3, tokenAddress4]); - const dynamic = new Token('array', [tokens1, tokens2]); - const expected = `${padU32(0x20)}${padU32(2)}${padU32(0x80)}${padU32(0xe0)}${padU32(2)}${encAddress1}${encAddress2}${padU32(2)}${encAddress3}${encAddress4}`; - - expect(Encoder.encode([dynamic])).to.equal(expected); - }); - - it('encodes fixed array of fixed array addresses', () => { - const tokens1 = new Token('fixedArray', [tokenAddress1, tokenAddress2]); - const tokens2 = new Token('fixedArray', [tokenAddress3, tokenAddress4]); - const dynamic = new Token('fixedArray', [tokens1, tokens2]); - const expected = `${encAddress1}${encAddress2}${encAddress3}${encAddress4}`; - - expect(Encoder.encode([dynamic])).to.equal(expected); - }); - }); - - describe('bytes', () => { - const bytes1 = '0x1234'; - const bytes2 = '0x10000000000000000000000000000000000000000000000000000000000002'; - const bytes3 = '0x1000000000000000000000000000000000000000000000000000000000000000'; - - it('encodes fixed bytes', () => { - const token = new Token('fixedBytes', bytes1); - - expect(Encoder.encode([token])).to.equal(padFixedBytes(bytes1)); - }); - - it('encodes bytes', () => { - const token = new Token('bytes', bytes1); - - expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(2)}${padFixedBytes(bytes1)}`); - }); - - it('encodes bytes (short of boundary)', () => { - const token = new Token('bytes', bytes2); - - expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(0x1f)}${padFixedBytes(bytes2)}`); - }); - - it('encodes bytes (two blocks)', () => { - const input = `${bytes3}${bytes3.slice(-64)}`; - const token = new Token('bytes', input); - - expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(0x40)}${padFixedBytes(input)}`); - }); - - it('encodes two consecutive bytes', () => { - const in1 = '0x10000000000000000000000000000000000000000000000000000000000002'; - const in2 = '0x0010000000000000000000000000000000000000000000000000000000000002'; - const tokens = [new Token('bytes', in1), new Token('bytes', in2)]; - - expect(Encoder.encode(tokens)).to.equal(`${padU32(0x40)}${padU32(0x80)}${padU32(0x1f)}${padFixedBytes(in1)}${padU32(0x20)}${padFixedBytes(in2)}`); - }); - }); - - describe('string', () => { - it('encodes a string', () => { - const string = 'gavofyork'; - const stringEnc = padFixedBytes('0x6761766f66796f726b'); - const token = new Token('string', string); - - expect(Encoder.encode([token])).to.equal(`${padU32(0x20)}${padU32(string.length.toString(16))}${stringEnc}`); - }); - }); - - describe('uint', () => { - it('encodes a uint', () => { - const token = new Token('uint', 4); - - expect(Encoder.encode([token])).to.equal(padU32(4)); - }); - }); - - describe('int', () => { - it('encodes a int', () => { - const token = new Token('int', 4); - - expect(Encoder.encode([token])).to.equal(padU32(4)); - }); - }); - - describe('bool', () => { - it('encodes a bool (true)', () => { - const token = new Token('bool', true); - - expect(Encoder.encode([token])).to.equal(padU32(1)); - }); - - it('encodes a bool (false)', () => { - const token = new Token('bool', false); - - expect(Encoder.encode([token])).to.equal(padU32(0)); - }); - }); - - describe('comprehensive test', () => { - it('encodes a complex sequence', () => { - const bytes = '0x131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'; - const tokens = [new Token('int', 5), new Token('bytes', bytes), new Token('int', 3), new Token('bytes', bytes)]; - - expect(Encoder.encode(tokens)).to.equal(`${padU32(5)}${padU32(0x80)}${padU32(3)}${padU32(0xe0)}${padU32(0x40)}${bytes.substr(2)}${padU32(0x40)}${bytes.substr(2)}`); - }); - - it('encodes a complex sequence (nested)', () => { - const array = [new Token('int', 5), new Token('int', 6), new Token('int', 7)]; - const tokens = [new Token('int', 1), new Token('string', 'gavofyork'), new Token('int', 2), new Token('int', 3), new Token('int', 4), new Token('array', array)]; - const stringEnc = padFixedBytes('0x6761766f66796f726b'); - - expect(Encoder.encode(tokens)).to.equal(`${padU32(1)}${padU32(0xc0)}${padU32(2)}${padU32(3)}${padU32(4)}${padU32(0x100)}${padU32(9)}${stringEnc}${padU32(3)}${padU32(5)}${padU32(6)}${padU32(7)}`); - }); - }); - }); -}); diff --git a/js/src/abi/encoder/index.js b/js/src/abi/encoder/index.js deleted file mode 100644 index 5ac3c0a6b2150912c3f423c718e1923581004884..0000000000000000000000000000000000000000 --- a/js/src/abi/encoder/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './encoder'; diff --git a/js/src/abi/encoder/mediate.js b/js/src/abi/encoder/mediate.js deleted file mode 100644 index 90cc28881d793a36216143b5972d665aede6b724..0000000000000000000000000000000000000000 --- a/js/src/abi/encoder/mediate.js +++ /dev/null @@ -1,142 +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 . - -const TYPES = ['raw', 'prefixed', 'fixedArray', 'array']; - -import { padU32 } from '../util/pad'; - -export default class Mediate { - constructor (type, value) { - Mediate.validateType(type); - - this._type = type; - this._value = value; - } - - initLength () { - switch (this._type) { - case 'raw': - return this._value.length / 2; - - case 'array': - case 'prefixed': - return 32; - - case 'fixedArray': - return this._value - .reduce((total, mediate) => { - return total + mediate.initLength(); - }, 0); - } - } - - closingLength () { - switch (this._type) { - case 'raw': - return 0; - - case 'prefixed': - return this._value.length / 2; - - case 'array': - return this._value - .reduce((total, mediate) => { - return total + mediate.initLength(); - }, 32); - - case 'fixedArray': - return this._value - .reduce((total, mediate) => { - return total + mediate.initLength() + mediate.closingLength(); - }, 0); - } - } - - init (suffixOffset) { - switch (this._type) { - case 'raw': - return this._value; - - case 'fixedArray': - return this._value - .map((mediate, idx) => mediate.init(Mediate.offsetFor(this._value, idx)).toString(16)) - .join(''); - - case 'prefixed': - case 'array': - return padU32(suffixOffset); - } - } - - closing (offset) { - switch (this._type) { - case 'raw': - return ''; - - case 'prefixed': - return this._value; - - case 'fixedArray': - return this._value - .map((mediate, idx) => mediate.closing(Mediate.offsetFor(this._value, idx)).toString(16)) - .join(''); - - case 'array': - const prefix = padU32(this._value.length); - const inits = this._value - .map((mediate, idx) => mediate.init(offset + Mediate.offsetFor(this._value, idx) + 32).toString(16)) - .join(''); - const closings = this._value - .map((mediate, idx) => mediate.closing(offset + Mediate.offsetFor(this._value, idx)).toString(16)) - .join(''); - - return `${prefix}${inits}${closings}`; - } - } - - get type () { - return this._type; - } - - get value () { - return this._value; - } - - static offsetFor (mediates, position) { - if (position < 0 || position >= mediates.length) { - throw new Error(`Invalid position ${position} specified for Mediate.offsetFor`); - } - - const initLength = mediates - .reduce((total, mediate) => { - return total + mediate.initLength(); - }, 0); - - return mediates - .slice(0, position) - .reduce((total, mediate) => { - return total + mediate.closingLength(); - }, initLength); - } - - static validateType (type) { - if (TYPES.filter((_type) => type === _type).length) { - return true; - } - - throw new Error(`Invalid type ${type} received for Mediate.validateType`); - } -} diff --git a/js/src/abi/encoder/mediate.spec.js b/js/src/abi/encoder/mediate.spec.js deleted file mode 100644 index ab89909b1ed96fdfba04fa0f4f22f3f79e99a25b..0000000000000000000000000000000000000000 --- a/js/src/abi/encoder/mediate.spec.js +++ /dev/null @@ -1,105 +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 . - -import Mediate from './mediate'; - -describe('abi/encoder/Mediate', () => { - const LONG15 = '1234567890abcdef000000000000000000000000000000000000000000000000'; - const DOUBLE15 = `${LONG15}${LONG15}`; - const ARRAY = [new Mediate('raw', DOUBLE15), new Mediate('raw', LONG15)]; - - describe('validateType', () => { - it('validates raw', () => { - expect(Mediate.validateType('raw')).to.be.true; - }); - - it('validates prefixed', () => { - expect(Mediate.validateType('prefixed')).to.be.true; - }); - - it('validates fixedArray', () => { - expect(Mediate.validateType('fixedArray')).to.be.true; - }); - - it('validates array', () => { - expect(Mediate.validateType('array')).to.be.true; - }); - - it('throws an error on invalid types', () => { - expect(() => Mediate.validateType('noMatch')).to.throw(/noMatch/); - }); - }); - - describe('offsetFor', () => { - it('thows an error when offset < 0', () => { - expect(() => Mediate.offsetFor([1], -1)).to.throw(/Invalid position/); - }); - - it('throws an error when offset >= length', () => { - expect(() => Mediate.offsetFor([1], 1)).to.throw(/Invalid position/); - }); - }); - - describe('constructor', () => { - it('throws an error on invalid types', () => { - expect(() => new Mediate('noMatch', '1')).to.throw(/noMatch/); - }); - - it('sets the type of the object', () => { - expect((new Mediate('raw', '1')).type).to.equal('raw'); - }); - - it('sets the value of the object', () => { - expect((new Mediate('raw', '1')).value).to.equal('1'); - }); - }); - - describe('initLength', () => { - it('returns correct variable byte length for raw', () => { - expect(new Mediate('raw', DOUBLE15).initLength()).to.equal(64); - }); - - it('returns correct fixed byte length for array', () => { - expect(new Mediate('array', [1, 2, 3, 4]).initLength()).to.equal(32); - }); - - it('returns correct fixed byte length for prefixed', () => { - expect(new Mediate('prefixed', 0).initLength()).to.equal(32); - }); - - it('returns correct variable byte length for fixedArray', () => { - expect(new Mediate('fixedArray', ARRAY).initLength()).to.equal(96); - }); - }); - - describe('closingLength', () => { - it('returns 0 byte length for raw', () => { - expect(new Mediate('raw', DOUBLE15).closingLength()).to.equal(0); - }); - - it('returns prefix + size for prefixed', () => { - expect(new Mediate('prefixed', DOUBLE15).closingLength()).to.equal(64); - }); - - it('returns prefix + size for array', () => { - expect(new Mediate('array', ARRAY).closingLength()).to.equal(128); - }); - - it('returns total length for fixedArray', () => { - expect(new Mediate('fixedArray', ARRAY).closingLength()).to.equal(96); - }); - }); -}); diff --git a/js/src/abi/index.js b/js/src/abi/index.js deleted file mode 100644 index 703ed1c7884ecfbaf917f28799d1b75fb980df1d..0000000000000000000000000000000000000000 --- a/js/src/abi/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './abi'; diff --git a/js/src/abi/spec/constructor.js b/js/src/abi/spec/constructor.js deleted file mode 100644 index e9b23b593df2dfc38d3878ba7d5d49b6abefbadc..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/constructor.js +++ /dev/null @@ -1,36 +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 . - -import Encoder from '../encoder/encoder'; -import Param from './param'; - -export default class Constructor { - constructor (abi) { - this._inputs = Param.toParams(abi.inputs || []); - } - - get inputs () { - return this._inputs; - } - - inputParamTypes () { - return this._inputs.map((input) => input.kind); - } - - encodeCall (tokens) { - return Encoder.encode(tokens); - } -} diff --git a/js/src/abi/spec/constructor.spec.js b/js/src/abi/spec/constructor.spec.js deleted file mode 100644 index 7c7414bdc8a6422f1df35377e9cff25fcd90a2d2..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/constructor.spec.js +++ /dev/null @@ -1,52 +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 . - -import Constructor from './constructor'; -import Param from './param'; -import Token from '../token'; - -describe('abi/spec/Constructor', () => { - const inputsArr = [{ name: 'boolin', type: 'bool' }, { name: 'stringin', type: 'string' }]; - const bool = new Param('boolin', 'bool'); - const string = new Param('stringin', 'string'); - - const inputs = [bool, string]; - const cr = new Constructor({ inputs: inputsArr }); - - describe('constructor', () => { - it('stores the inputs as received', () => { - expect(cr.inputs).to.deep.equal(inputs); - }); - - it('matches empty inputs with []', () => { - expect(new Constructor({}).inputs).to.deep.equal([]); - }); - }); - - describe('inputParamTypes', () => { - it('retrieves the input types as received', () => { - expect(cr.inputParamTypes()).to.deep.equal([bool.kind, string.kind]); - }); - }); - - describe('encodeCall', () => { - it('encodes correctly', () => { - const result = cr.encodeCall([new Token('bool', true), new Token('string', 'jacogr')]); - - expect(result).to.equal('0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000066a61636f67720000000000000000000000000000000000000000000000000000'); - }); - }); -}); diff --git a/js/src/abi/spec/event/decodedLog.js b/js/src/abi/spec/event/decodedLog.js deleted file mode 100644 index e398c5a1bf552cee88cf7d6e33aa103a428da1ec..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/decodedLog.js +++ /dev/null @@ -1,30 +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 . - -export default class DecodedLog { - constructor (params, address) { - this._params = params; - this._address = address; - } - - get address () { - return this._address; - } - - get params () { - return this._params; - } -} diff --git a/js/src/abi/spec/event/decodedLog.spec.js b/js/src/abi/spec/event/decodedLog.spec.js deleted file mode 100644 index f448af011c0afbb42a8b5adde8f3e52ed5c0298c..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/decodedLog.spec.js +++ /dev/null @@ -1,28 +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 . - -import DecodedLog from './decodedLog'; - -const log = new DecodedLog('someParams', 'someAddress'); - -describe('abi/spec/event/DecodedLog', () => { - describe('constructor', () => { - it('sets internal state', () => { - expect(log.params).to.equal('someParams'); - expect(log.address).to.equal('someAddress'); - }); - }); -}); diff --git a/js/src/abi/spec/event/decodedLogParam.js b/js/src/abi/spec/event/decodedLogParam.js deleted file mode 100644 index 422fbaac84fa03facdfcfc82bc4a4070f9c2a7f3..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/decodedLogParam.js +++ /dev/null @@ -1,45 +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 . - -import ParamType from '../paramType/paramType'; -import Token from '../../token/token'; -import { isInstanceOf } from '../../util/types'; - -export default class DecodedLogParam { - constructor (name, kind, token) { - if (!isInstanceOf(kind, ParamType)) { - throw new Error('kind not instanceof ParamType'); - } else if (!isInstanceOf(token, Token)) { - throw new Error('token not instanceof Token'); - } - - this._name = name; - this._kind = kind; - this._token = token; - } - - get name () { - return this._name; - } - - get kind () { - return this._kind; - } - - get token () { - return this._token; - } -} diff --git a/js/src/abi/spec/event/decodedLogParam.spec.js b/js/src/abi/spec/event/decodedLogParam.spec.js deleted file mode 100644 index 6a7f5204495dfbdaec05d0f9d4f6c14c05379562..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/decodedLogParam.spec.js +++ /dev/null @@ -1,42 +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 . - -import DecodedLogParam from './decodedLogParam'; -import ParamType from '../paramType'; -import Token from '../../token'; - -describe('abi/spec/event/DecodedLogParam', () => { - describe('constructor', () => { - const pt = new ParamType('bool'); - const tk = new Token('bool'); - - it('disallows kind not instanceof ParamType', () => { - expect(() => new DecodedLogParam('test', 'param')).to.throw(/ParamType/); - }); - - it('disallows token not instanceof Token', () => { - expect(() => new DecodedLogParam('test', pt, 'token')).to.throw(/Token/); - }); - - it('stores all parameters received', () => { - const log = new DecodedLogParam('test', pt, tk); - - expect(log.name).to.equal('test'); - expect(log.kind).to.equal(pt); - expect(log.token).to.equal(tk); - }); - }); -}); diff --git a/js/src/abi/spec/event/event.js b/js/src/abi/spec/event/event.js deleted file mode 100644 index 604f58cb18b163b6bbe1da2ccda9f7196177a300..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/event.js +++ /dev/null @@ -1,114 +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 . - -import Decoder from '../../decoder/decoder'; -import DecodedLog from './decodedLog'; -import DecodedLogParam from './decodedLogParam'; -import EventParam from './eventParam'; -import { asAddress } from '../../util/sliceAs'; -import { eventSignature } from '../../util/signature'; - -export default class Event { - constructor (abi) { - this._inputs = EventParam.toEventParams(abi.inputs || []); - this._anonymous = !!abi.anonymous; - - const { id, name, signature } = eventSignature(abi.name, this.inputParamTypes()); - - this._id = id; - this._name = name; - this._signature = signature; - } - - get name () { - return this._name; - } - - get id () { - return this._id; - } - - get inputs () { - return this._inputs; - } - - get anonymous () { - return this._anonymous; - } - - get signature () { - return this._signature; - } - - inputParamTypes () { - return this._inputs.map((input) => input.kind); - } - - inputParamNames () { - return this._inputs.map((input) => input.name); - } - - indexedParams (indexed) { - return this._inputs.filter((input) => input.indexed === indexed); - } - - decodeLog (topics, data) { - const topicParams = this.indexedParams(true); - const dataParams = this.indexedParams(false); - - let address; - let toSkip; - - if (!this.anonymous) { - address = asAddress(topics[0]); - toSkip = 1; - } else { - toSkip = 0; - } - - const topicTypes = topicParams.map((param) => param.kind); - const flatTopics = topics - .filter((topic, idx) => idx >= toSkip) - .map((topic) => { - return (topic.substr(0, 2) === '0x') - ? topic.substr(2) - : topic; - }).join(''); - const topicTokens = Decoder.decode(topicTypes, flatTopics); - - if (topicTokens.length !== (topics.length - toSkip)) { - throw new Error('Invalid topic data'); - } - - const dataTypes = dataParams.map((param) => param.kind); - const dataTokens = Decoder.decode(dataTypes, data); - - const namedTokens = {}; - - topicParams.forEach((param, idx) => { - namedTokens[param.name || idx] = topicTokens[idx]; - }); - dataParams.forEach((param, idx) => { - namedTokens[param.name || idx] = dataTokens[idx]; - }); - - const inputParamTypes = this.inputParamTypes(); - const decodedParams = this.inputParamNames() - .map((name, idx) => new DecodedLogParam(name, inputParamTypes[idx], namedTokens[name || idx])); - - return new DecodedLog(decodedParams, address); - } -} diff --git a/js/src/abi/spec/event/event.spec.js b/js/src/abi/spec/event/event.spec.js deleted file mode 100644 index bf47980fc6441631ffc07a32ab885ac918abbde0..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/event.spec.js +++ /dev/null @@ -1,111 +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 . - -import BigNumber from 'bignumber.js'; - -import Event from './event'; -import EventParam from './eventParam'; -import DecodedLogParam from './decodedLogParam'; -import ParamType from '../paramType'; -import Token from '../../token'; - -describe('abi/spec/event/Event', () => { - const inputArr = [{ name: 'a', type: 'bool' }, { name: 'b', type: 'uint', indexed: true }]; - const inputs = [new EventParam('a', 'bool', false), new EventParam('b', 'uint', true)]; - const event = new Event({ name: 'test', inputs: inputArr, anonymous: true }); - - describe('constructor', () => { - it('stores the parameters as received', () => { - expect(event.name).to.equal('test'); - expect(event.inputs).to.deep.equal(inputs); - expect(event.anonymous).to.be.true; - }); - - it('matches empty inputs with []', () => { - expect(new Event({ name: 'test' }).inputs).to.deep.equal([]); - }); - - it('sets the event signature', () => { - expect(new Event({ name: 'baz' }).signature) - .to.equal('a7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf'); - }); - }); - - describe('inputParamTypes', () => { - it('returns all the types', () => { - expect(event.inputParamTypes()).to.deep.equal([new ParamType('bool'), new ParamType('uint', null, 256, true)]); - }); - }); - - describe('inputParamNames', () => { - it('returns all the names', () => { - expect(event.inputParamNames()).to.deep.equal(['a', 'b']); - }); - }); - - describe('indexedParams', () => { - it('returns all indexed parameters (indexed)', () => { - expect(event.indexedParams(true)).to.deep.equal([inputs[1]]); - }); - - it('returns all indexed parameters (non-indexed)', () => { - expect(event.indexedParams(false)).to.deep.equal([inputs[0]]); - }); - }); - - describe('decodeLog', () => { - it('decodes an event', () => { - const event = new Event({ - name: 'foo', - inputs: [ - { name: 'a', type: 'int' }, - { name: 'b', type: 'int', indexed: true }, - { name: 'c', type: 'address' }, - { name: 'd', type: 'address', indexed: true } - ] - }); - const decoded = event.decodeLog([ - '0000000000000000000000004444444444444444444444444444444444444444', - '0000000000000000000000000000000000000000000000000000000000000002', - '0000000000000000000000001111111111111111111111111111111111111111' ], - '00000000000000000000000000000000000000000000000000000000000000030000000000000000000000002222222222222222222222222222222222222222'); - - expect(decoded.address).to.equal('0x4444444444444444444444444444444444444444'); - expect(decoded.params).to.deep.equal([ - new DecodedLogParam('a', new ParamType('int', null, 256), new Token('int', new BigNumber(3))), - new DecodedLogParam('b', new ParamType('int', null, 256, true), new Token('int', new BigNumber(2))), - new DecodedLogParam('c', new ParamType('address'), new Token('address', '0x2222222222222222222222222222222222222222')), - new DecodedLogParam('d', new ParamType('address', null, 0, true), new Token('address', '0x1111111111111111111111111111111111111111')) - ]); - }); - - it('decodes an anonymous event', () => { - const event = new Event({ name: 'foo', inputs: [{ name: 'a', type: 'int' }], anonymous: true }); - const decoded = event.decodeLog([], '0000000000000000000000000000000000000000000000000000000000000003'); - - expect(decoded.address).to.not.be.ok; - expect(decoded.params).to.deep.equal([ - new DecodedLogParam('a', new ParamType('int', null, 256), new Token('int', new BigNumber(3))) - ]); - }); - - it('throws on invalid topics', () => { - const event = new Event({ name: 'foo', inputs: [{ name: 'a', type: 'int' }], anonymous: true }); - - expect(() => event.decodeLog(['0000000000000000000000004444444444444444444444444444444444444444'], '0000000000000000000000000000000000000000000000000000000000000003')).to.throw(/Invalid/); - }); - }); -}); diff --git a/js/src/abi/spec/event/eventParam.js b/js/src/abi/spec/event/eventParam.js deleted file mode 100644 index b49b778141183c8be180ae0a141f2975a3492a4c..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/eventParam.js +++ /dev/null @@ -1,41 +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 . - -import { toParamType } from '../paramType/format'; - -export default class EventParam { - constructor (name, type, indexed = false) { - this._name = name; - this._indexed = indexed; - this._kind = toParamType(type, indexed); - } - - get name () { - return this._name; - } - - get kind () { - return this._kind; - } - - get indexed () { - return this._indexed; - } - - static toEventParams (params) { - return params.map((param) => new EventParam(param.name, param.type, param.indexed)); - } -} diff --git a/js/src/abi/spec/event/eventParam.spec.js b/js/src/abi/spec/event/eventParam.spec.js deleted file mode 100644 index e35ebcebcce2f87d890670544c176a8fab3f75c7..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/eventParam.spec.js +++ /dev/null @@ -1,44 +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 . - -import EventParam from './eventParam'; - -describe('abi/spec/event/EventParam', () => { - describe('constructor', () => { - it('sets the properties', () => { - const param = new EventParam('foo', 'uint', true); - - expect(param.name).to.equal('foo'); - expect(param.kind.type).to.equal('uint'); - expect(param.indexed).to.be.true; - }); - - it('uses defaults for indexed', () => { - expect(new EventParam('foo', 'uint').indexed).to.be.false; - }); - }); - - describe('toEventParams', () => { - it('maps an array of params', () => { - const params = EventParam.toEventParams([{ name: 'foo', type: 'uint' }]); - - expect(params.length).to.equal(1); - expect(params[0].indexed).to.be.false; - expect(params[0].name).to.equal('foo'); - expect(params[0].kind.type).to.equal('uint'); - }); - }); -}); diff --git a/js/src/abi/spec/event/index.js b/js/src/abi/spec/event/index.js deleted file mode 100644 index 25441954b4837428bc895fc61c48f5f81cd24e58..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/event/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './event'; diff --git a/js/src/abi/spec/function.js b/js/src/abi/spec/function.js deleted file mode 100644 index 6010f4e598f898c980a389f810057c2c893e21af..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/function.js +++ /dev/null @@ -1,88 +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 . - -import Decoder from '../decoder/decoder'; -import Encoder from '../encoder/encoder'; -import Param from './param'; -import { methodSignature } from '../util/signature'; - -export default class Func { - constructor (abi) { - this._abi = abi; - this._constant = !!abi.constant; - this._payable = abi.payable; - this._inputs = Param.toParams(abi.inputs || []); - this._outputs = Param.toParams(abi.outputs || []); - - const { id, name, signature } = methodSignature(abi.name, this.inputParamTypes()); - - this._id = id; - this._name = name; - this._signature = signature; - } - - get abi () { - return this._abi; - } - - get constant () { - return this._constant; - } - - get name () { - return this._name; - } - - get id () { - return this._id; - } - - get payable () { - return this._payable; - } - - get inputs () { - return this._inputs; - } - - get outputs () { - return this._outputs; - } - - get signature () { - return this._signature; - } - - inputParamTypes () { - return this._inputs.map((input) => input.kind); - } - - outputParamTypes () { - return this._outputs.map((output) => output.kind); - } - - encodeCall (tokens) { - return `${this._signature}${Encoder.encode(tokens)}`; - } - - decodeInput (data) { - return Decoder.decode(this.inputParamTypes(), data); - } - - decodeOutput (data) { - return Decoder.decode(this.outputParamTypes(), data); - } -} diff --git a/js/src/abi/spec/function.spec.js b/js/src/abi/spec/function.spec.js deleted file mode 100644 index 436ca73650b1cf1014bbfb6d54f9a04001a8aa24..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/function.spec.js +++ /dev/null @@ -1,101 +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 . - -import Func from './function'; -import Param from './param'; -import Token from '../token'; - -describe('abi/spec/Function', () => { - const inputsArr = [{ name: 'boolin', type: 'bool' }, { name: 'stringin', type: 'string' }]; - const outputsArr = [{ name: 'output', type: 'uint' }]; - - const uint = new Param('output', 'uint'); - const bool = new Param('boolin', 'bool'); - const string = new Param('stringin', 'string'); - const inputs = [bool, string]; - const outputs = [uint]; - - const func = new Func({ - name: 'test', - inputs: inputsArr, - outputs: outputsArr - }); - - describe('constructor', () => { - it('returns signature correctly if name already contains it', () => { - const func = new Func({ - name: 'test(bool,string)', - inputs: inputsArr, - outputs: outputsArr - }); - - expect(func.name).to.equal('test'); - expect(func.id).to.equal('test(bool,string)'); - expect(func.signature).to.equal('02356205'); - }); - - it('stores the parameters as received', () => { - expect(func.name).to.equal('test'); - expect(func.constant).to.be.false; - expect(func.inputs).to.deep.equal(inputs); - expect(func.outputs).to.deep.equal(outputs); - }); - - it('matches empty inputs with []', () => { - expect(new Func({ name: 'test', outputs: outputsArr }).inputs).to.deep.equal([]); - }); - - it('matches empty outputs with []', () => { - expect(new Func({ name: 'test', inputs: inputsArr }).outputs).to.deep.equal([]); - }); - - it('sets the method signature', () => { - expect(new Func({ name: 'baz' }).signature).to.equal('a7916fac'); - }); - - it('allows constant functions', () => { - expect(new Func({ name: 'baz', constant: true }).constant).to.be.true; - }); - }); - - describe('inputParamTypes', () => { - it('retrieves the input types as received', () => { - expect(func.inputParamTypes()).to.deep.equal([bool.kind, string.kind]); - }); - }); - - describe('outputParamTypes', () => { - it('retrieves the output types as received', () => { - expect(func.outputParamTypes()).to.deep.equal([uint.kind]); - }); - }); - - describe('encodeCall', () => { - it('encodes the call correctly', () => { - const result = func.encodeCall([new Token('bool', true), new Token('string', 'jacogr')]); - - expect(result).to.equal('023562050000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000066a61636f67720000000000000000000000000000000000000000000000000000'); - }); - }); - - describe('decodeOutput', () => { - it('decodes the result correctly', () => { - const result = func.decodeOutput('1111111111111111111111111111111111111111111111111111111111111111'); - - expect(result[0].value.toString(16)).to.equal('1111111111111111111111111111111111111111111111111111111111111111'); - }); - }); -}); diff --git a/js/src/abi/spec/index.js b/js/src/abi/spec/index.js deleted file mode 100644 index 87852d4880307162ae8dd143843878be5c7077b8..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './interface'; diff --git a/js/src/abi/spec/interface.js b/js/src/abi/spec/interface.js deleted file mode 100644 index b24569525dbf4b8def78debea25fab04a56eaea1..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/interface.js +++ /dev/null @@ -1,77 +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 . - -import Constructor from './constructor'; -import Event from './event/event'; -import Func from './function'; -import Token from '../token'; - -export default class Interface { - constructor (abi) { - this._interface = Interface.parseABI(abi); - } - - get interface () { - return this._interface; - } - - get constructors () { - return this._interface.filter((item) => item instanceof Constructor); - } - - get events () { - return this._interface.filter((item) => item instanceof Event); - } - - get functions () { - return this._interface.filter((item) => item instanceof Func); - } - - encodeTokens (paramTypes, values) { - return Interface.encodeTokens(paramTypes, values); - } - - static encodeTokens (paramTypes, values) { - const createToken = function (paramType, value) { - if (paramType.subtype) { - return new Token(paramType.type, value.map((entry) => createToken(paramType.subtype, entry))); - } - - return new Token(paramType.type, value); - }; - - return paramTypes.map((paramType, idx) => createToken(paramType, values[idx])); - } - - static parseABI (abi) { - return abi.map((item) => { - switch (item.type) { - case 'constructor': - return new Constructor(item); - - case 'event': - return new Event(item); - - case 'function': - case 'fallback': - return new Func(item); - - default: - throw new Error(`Unknown ABI type ${item.type}`); - } - }); - } -} diff --git a/js/src/abi/spec/interface.spec.js b/js/src/abi/spec/interface.spec.js deleted file mode 100644 index ebaa323ed526644517e06eb55e696466f82f0019..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/interface.spec.js +++ /dev/null @@ -1,126 +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 . - -import Interface from './interface'; -import ParamType from './paramType'; -import Token from '../token'; - -describe('abi/spec/Interface', () => { - const construct = { - type: 'constructor', - inputs: [] - }; - const event = { - type: 'event', - name: 'Event2', - anonymous: false, - inputs: [{ name: 'a', type: 'uint256', indexed: true }, { name: 'b', type: 'bytes32', indexed: false }] - }; - const func = { - type: 'function', - name: 'foo', - inputs: [{ name: 'a', type: 'uint256' }], - outputs: [] - }; - - describe('parseABI', () => { - it('throws on invalid types', () => { - expect(() => Interface.parseABI([{ type: 'noMatch' }])).to.throw(/noMatch/); - }); - - it('creates constructors', () => { - expect(Interface.parseABI([ construct ])).to.deep.equal([{ _inputs: [] }]); - }); - - it('creates events', () => { - expect(Interface.parseABI([ event ])[0].name).to.equal('Event2'); - }); - - it('creates functions', () => { - expect(Interface.parseABI([ func ])[0].name).to.equal('foo'); - }); - - it('parse complex interfaces', () => { - expect(Interface.parseABI([ construct, event, func ]).length).to.equal(3); - }); - }); - - describe('constructor', () => { - const int = new Interface([ construct, event, func ]); - - it('contains the full interface', () => { - expect(int.interface.length).to.equal(3); - }); - - it('contains the constructors', () => { - expect(int.constructors.length).to.equal(1); - }); - - it('contains the events', () => { - expect(int.events.length).to.equal(1); - }); - - it('contains the functions', () => { - expect(int.functions.length).to.equal(1); - }); - }); - - describe('encodeTokens', () => { - const int = new Interface([ construct, event, func ]); - - it('encodes simple types', () => { - expect( - int.encodeTokens( - [new ParamType('bool'), new ParamType('string'), new ParamType('int'), new ParamType('uint')], - [true, 'gavofyork', -123, 123] - ) - ).to.deep.equal([ - new Token('bool', true), new Token('string', 'gavofyork'), new Token('int', -123), new Token('uint', 123) - ]); - }); - - it('encodes array', () => { - expect( - int.encodeTokens( - [new ParamType('array', new ParamType('bool'))], - [[true, false, true]] - ) - ).to.deep.equal([ - new Token('array', [ - new Token('bool', true), new Token('bool', false), new Token('bool', true) - ]) - ]); - }); - - it('encodes simple with array of array', () => { - expect( - int.encodeTokens( - [ - new ParamType('bool'), - new ParamType('fixedArray', new ParamType('array', new ParamType('uint')), 2) - ], - [true, [[0, 1], [2, 3]]] - ) - ).to.deep.equal([ - new Token('bool', true), - new Token('fixedArray', [ - new Token('array', [new Token('uint', 0), new Token('uint', 1)]), - new Token('array', [new Token('uint', 2), new Token('uint', 3)]) - ]) - ]); - }); - }); -}); diff --git a/js/src/abi/spec/param.js b/js/src/abi/spec/param.js deleted file mode 100644 index e02b99100389273b68f79835855bd2540ec2efa1..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/param.js +++ /dev/null @@ -1,42 +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 . - -import { toParamType } from './paramType/format'; - -export default class Param { - constructor (name, type) { - this._name = name; - this._kind = toParamType(type); - } - - get name () { - return this._name; - } - - get kind () { - return this._kind; - } - - static toParams (params) { - return params.map((param) => { - if (param instanceof Param) { - return param; - } - - return new Param(param.name, param.type); - }); - } -} diff --git a/js/src/abi/spec/param.spec.js b/js/src/abi/spec/param.spec.js deleted file mode 100644 index 0ecdb0319b19d08a766b55c9bdbf33a3f00b99fc..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/param.spec.js +++ /dev/null @@ -1,47 +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 . - -import Param from './param'; - -describe('abi/spec/Param', () => { - describe('constructor', () => { - const param = new Param('foo', 'uint'); - - it('sets the properties', () => { - expect(param.name).to.equal('foo'); - expect(param.kind.type).to.equal('uint'); - }); - }); - - describe('toParams', () => { - it('maps an array of params', () => { - const params = Param.toParams([{ name: 'foo', type: 'uint' }]); - - expect(params.length).to.equal(1); - expect(params[0].name).to.equal('foo'); - expect(params[0].kind.type).to.equal('uint'); - }); - - it('converts only if needed', () => { - const _params = Param.toParams([{ name: 'foo', type: 'uint' }]); - const params = Param.toParams(_params); - - expect(params.length).to.equal(1); - expect(params[0].name).to.equal('foo'); - expect(params[0].kind.type).to.equal('uint'); - }); - }); -}); diff --git a/js/src/abi/spec/paramType/format.js b/js/src/abi/spec/paramType/format.js deleted file mode 100644 index 5aafd5e3070cdc47eaa27ba9ef4ea2e62419aad4..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/paramType/format.js +++ /dev/null @@ -1,80 +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 . - -import ParamType from './paramType'; - -export function toParamType (type, indexed) { - if (type[type.length - 1] === ']') { - const last = type.lastIndexOf('['); - const length = type.substr(last + 1, type.length - last - 2); - const subtype = toParamType(type.substr(0, last)); - - if (length.length === 0) { - return new ParamType('array', subtype, 0, indexed); - } - - return new ParamType('fixedArray', subtype, parseInt(length, 10), indexed); - } - - switch (type) { - case 'address': - case 'bool': - case 'bytes': - case 'string': - return new ParamType(type, null, 0, indexed); - - case 'int': - case 'uint': - return new ParamType(type, null, 256, indexed); - - default: - if (type.indexOf('uint') === 0) { - return new ParamType('uint', null, parseInt(type.substr(4), 10), indexed); - } else if (type.indexOf('int') === 0) { - return new ParamType('int', null, parseInt(type.substr(3), 10), indexed); - } else if (type.indexOf('bytes') === 0) { - return new ParamType('fixedBytes', null, parseInt(type.substr(5), 10), indexed); - } - - throw new Error(`Cannot convert ${type} to valid ParamType`); - } -} - -export function fromParamType (paramType) { - switch (paramType.type) { - case 'address': - case 'bool': - case 'bytes': - case 'string': - return paramType.type; - - case 'int': - case 'uint': - return `${paramType.type}${paramType.length}`; - - case 'fixedBytes': - return `bytes${paramType.length}`; - - case 'fixedArray': - return `${fromParamType(paramType.subtype)}[${paramType.length}]`; - - case 'array': - return `${fromParamType(paramType.subtype)}[]`; - - default: - throw new Error(`Cannot convert from ParamType ${paramType.type}`); - } -} diff --git a/js/src/abi/spec/paramType/format.spec.js b/js/src/abi/spec/paramType/format.spec.js deleted file mode 100644 index cb000473380546c50f4289119f95e30d840085a8..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/paramType/format.spec.js +++ /dev/null @@ -1,228 +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 . - -import ParamType from './paramType'; -import { fromParamType, toParamType } from './format'; - -describe('abi/spec/paramType/format', () => { - describe('fromParamType', () => { - it('errors on invalid types', () => { - expect(() => fromParamType({ type: 'noMatch' })).to.throw(/noMatch/); - }); - - describe('simple types', () => { - it('converts address to address', () => { - const pt = new ParamType('address'); - - expect(fromParamType(pt)).to.equal('address'); - }); - - it('converts bool to bool', () => { - const pt = new ParamType('bool'); - - expect(fromParamType(pt)).to.equal('bool'); - }); - - it('converts bytes to bytes', () => { - const pt = new ParamType('bytes'); - - expect(fromParamType(pt)).to.equal('bytes'); - }); - - it('converts string to string', () => { - const pt = new ParamType('string'); - - expect(fromParamType(pt)).to.equal('string'); - }); - }); - - describe('length types', () => { - it('converts int32 to int32', () => { - const pt = new ParamType('int', null, 32); - - expect(fromParamType(pt)).to.equal('int32'); - }); - - it('converts uint64 to int64', () => { - const pt = new ParamType('uint', null, 64); - - expect(fromParamType(pt)).to.equal('uint64'); - }); - - it('converts fixedBytes8 to bytes8', () => { - const pt = new ParamType('fixedBytes', null, 8); - - expect(fromParamType(pt)).to.equal('bytes8'); - }); - }); - - describe('arrays', () => { - it('converts string[2] to string[2]', () => { - const pt = new ParamType('fixedArray', new ParamType('string'), 2); - - expect(fromParamType(pt)).to.equal('string[2]'); - }); - - it('converts bool[] to bool[]', () => { - const pt = new ParamType('array', new ParamType('bool')); - - expect(fromParamType(pt)).to.equal('bool[]'); - }); - - it('converts bool[][2] to bool[][2]', () => { - const pt = new ParamType('fixedArray', new ParamType('array', new ParamType('bool')), 2); - - expect(fromParamType(pt)).to.equal('bool[][2]'); - }); - - it('converts bool[2][] to bool[2][]', () => { - const pt = new ParamType('array', new ParamType('fixedArray', new ParamType('bool'), 2)); - - expect(fromParamType(pt)).to.equal('bool[2][]'); - }); - }); - }); - - describe('toParamType', () => { - it('errors on invalid types', () => { - expect(() => toParamType('noMatch')).to.throw(/noMatch/); - }); - - describe('simple mapping', () => { - it('converts address to address', () => { - const pt = toParamType('address'); - - expect(pt.type).to.equal('address'); - }); - - it('converts bool to bool', () => { - const pt = toParamType('bool'); - - expect(pt.type).to.equal('bool'); - }); - - it('converts bytes to bytes', () => { - const pt = toParamType('bytes'); - - expect(pt.type).to.equal('bytes'); - }); - - it('converts string to string', () => { - const pt = toParamType('string'); - - expect(pt.type).to.equal('string'); - }); - }); - - describe('number', () => { - it('converts int to int256', () => { - const pt = toParamType('int'); - - expect(pt.type).to.equal('int'); - expect(pt.length).to.equal(256); - }); - - it('converts uint to uint256', () => { - const pt = toParamType('uint'); - - expect(pt.type).to.equal('uint'); - expect(pt.length).to.equal(256); - }); - }); - - describe('sized types', () => { - it('converts int32 to int32', () => { - const pt = toParamType('int32'); - - expect(pt.type).to.equal('int'); - expect(pt.length).to.equal(32); - }); - - it('converts uint16 to uint16', () => { - const pt = toParamType('uint32'); - - expect(pt.type).to.equal('uint'); - expect(pt.length).to.equal(32); - }); - - it('converts bytes8 to fixedBytes8', () => { - const pt = toParamType('bytes8'); - - expect(pt.type).to.equal('fixedBytes'); - expect(pt.length).to.equal(8); - }); - }); - - describe('arrays', () => { - describe('fixed arrays', () => { - it('creates fixed array', () => { - const pt = toParamType('bytes[8]'); - - expect(pt.type).to.equal('fixedArray'); - expect(pt.subtype.type).to.equal('bytes'); - expect(pt.length).to.equal(8); - }); - - it('creates fixed arrays of fixed arrays', () => { - const pt = toParamType('bytes[45][3]'); - - expect(pt.type).to.equal('fixedArray'); - expect(pt.length).to.equal(3); - expect(pt.subtype.type).to.equal('fixedArray'); - expect(pt.subtype.length).to.equal(45); - expect(pt.subtype.subtype.type).to.equal('bytes'); - }); - }); - - describe('dynamic arrays', () => { - it('creates a dynamic array', () => { - const pt = toParamType('bytes[]'); - - expect(pt.type).to.equal('array'); - expect(pt.subtype.type).to.equal('bytes'); - }); - - it('creates a dynamic array of dynamic arrays', () => { - const pt = toParamType('bool[][]'); - - expect(pt.type).to.equal('array'); - expect(pt.subtype.type).to.equal('array'); - expect(pt.subtype.subtype.type).to.equal('bool'); - }); - }); - - describe('mixed arrays', () => { - it('creates a fixed dynamic array', () => { - const pt = toParamType('bool[][3]'); - - expect(pt.type).to.equal('fixedArray'); - expect(pt.length).to.equal(3); - expect(pt.subtype.type).to.equal('array'); - expect(pt.subtype.subtype.type).to.equal('bool'); - }); - - it('creates a dynamic fixed array', () => { - const pt = toParamType('bool[3][]'); - - expect(pt.type).to.equal('array'); - expect(pt.subtype.type).to.equal('fixedArray'); - expect(pt.subtype.length).to.equal(3); - expect(pt.subtype.subtype.type).to.equal('bool'); - }); - }); - }); - }); -}); diff --git a/js/src/abi/spec/paramType/index.js b/js/src/abi/spec/paramType/index.js deleted file mode 100644 index 123e198e8ea99cb0fe915794b3199dd135d2b2df..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/paramType/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './paramType'; diff --git a/js/src/abi/spec/paramType/paramType.js b/js/src/abi/spec/paramType/paramType.js deleted file mode 100644 index b65465d94edd8171c57a989bfc178797ea0aad5f..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/paramType/paramType.js +++ /dev/null @@ -1,52 +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 . - -import TYPES from './types'; - -export default class ParamType { - constructor (type, subtype = null, length = 0, indexed = false) { - ParamType.validateType(type); - - this._type = type; - this._subtype = subtype; - this._length = length; - this._indexed = indexed; - } - - get type () { - return this._type; - } - - get subtype () { - return this._subtype; - } - - get length () { - return this._length; - } - - get indexed () { - return this._indexed; - } - - static validateType (type) { - if (TYPES.filter((_type) => type === _type).length) { - return true; - } - - throw new Error(`Invalid type ${type} received for ParamType`); - } -} diff --git a/js/src/abi/spec/paramType/paramType.spec.js b/js/src/abi/spec/paramType/paramType.spec.js deleted file mode 100644 index dc71147211441a5991c9d3abe2cde6490bb72422..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/paramType/paramType.spec.js +++ /dev/null @@ -1,87 +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 . - -import ParamType from './paramType'; - -describe('abi/spec/paramType/ParamType', () => { - describe('validateType', () => { - it('validates address', () => { - expect(ParamType.validateType('address')).to.be.true; - }); - - it('validates fixedArray', () => { - expect(ParamType.validateType('fixedArray')).to.be.true; - }); - - it('validates array', () => { - expect(ParamType.validateType('array')).to.be.true; - }); - - it('validates fixedBytes', () => { - expect(ParamType.validateType('fixedBytes')).to.be.true; - }); - - it('validates bytes', () => { - expect(ParamType.validateType('bytes')).to.be.true; - }); - - it('validates bool', () => { - expect(ParamType.validateType('bool')).to.be.true; - }); - - it('validates int', () => { - expect(ParamType.validateType('int')).to.be.true; - }); - - it('validates uint', () => { - expect(ParamType.validateType('uint')).to.be.true; - }); - - it('validates string', () => { - expect(ParamType.validateType('string')).to.be.true; - }); - - it('throws an error on invalid types', () => { - expect(() => ParamType.validateType('noMatch')).to.throw(/noMatch/); - }); - }); - - describe('constructor', () => { - it('throws an error on invalid types', () => { - expect(() => new ParamType('noMatch')).to.throw(/noMatch/); - }); - - it('sets the type of the object', () => { - expect((new ParamType('bool', null, 1)).type).to.equal('bool'); - }); - - it('sets the subtype of the object', () => { - expect((new ParamType('array', 'bool', 1)).subtype).to.equal('bool'); - }); - - it('sets the length of the object', () => { - expect((new ParamType('array', 'bool', 1)).length).to.equal(1); - }); - - it('sets the index of the object', () => { - expect((new ParamType('array', 'bool', 1, true)).indexed).to.be.true; - }); - - it('sets default values where none supplied', () => { - expect(Object.values(new ParamType('string'))).to.deep.equal(['string', null, 0, false]); - }); - }); -}); diff --git a/js/src/abi/spec/paramType/types.js b/js/src/abi/spec/paramType/types.js deleted file mode 100644 index e9749c5886fbb6787774b12c2af09482ca065944..0000000000000000000000000000000000000000 --- a/js/src/abi/spec/paramType/types.js +++ /dev/null @@ -1,19 +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 . - -const TYPES = ['address', 'bytes', 'int', 'uint', 'bool', 'string', 'array', 'fixedBytes', 'fixedArray']; - -export default TYPES; diff --git a/js/src/abi/token/index.js b/js/src/abi/token/index.js deleted file mode 100644 index 6a636c3c89f4314c14616993035b021746b517c5..0000000000000000000000000000000000000000 --- a/js/src/abi/token/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './token'; diff --git a/js/src/abi/token/token.js b/js/src/abi/token/token.js deleted file mode 100644 index 7242248ab29272744cba03f25a812b8a67046875..0000000000000000000000000000000000000000 --- a/js/src/abi/token/token.js +++ /dev/null @@ -1,42 +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 . - -import TYPES from '../spec/paramType/types'; - -export default class Token { - constructor (type, value) { - Token.validateType(type); - - this._type = type; - this._value = value; - } - - get type () { - return this._type; - } - - get value () { - return this._value; - } - - static validateType (type) { - if (TYPES.filter((_type) => type === _type).length) { - return true; - } - - throw new Error(`Invalid type ${type} received for Token`); - } -} diff --git a/js/src/abi/token/token.spec.js b/js/src/abi/token/token.spec.js deleted file mode 100644 index cf5fc51bf798a82da16b27a2e7ccace52c809f7c..0000000000000000000000000000000000000000 --- a/js/src/abi/token/token.spec.js +++ /dev/null @@ -1,75 +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 . - -import Token from './token'; - -describe('abi/token/token', () => { - describe('validateType', () => { - it('validates address', () => { - expect(Token.validateType('address')).to.be.true; - }); - - it('validates fixedArray', () => { - expect(Token.validateType('fixedArray')).to.be.true; - }); - - it('validates array', () => { - expect(Token.validateType('array')).to.be.true; - }); - - it('validates fixedBytes', () => { - expect(Token.validateType('fixedBytes')).to.be.true; - }); - - it('validates bytes', () => { - expect(Token.validateType('bytes')).to.be.true; - }); - - it('validates bool', () => { - expect(Token.validateType('bool')).to.be.true; - }); - - it('validates int', () => { - expect(Token.validateType('int')).to.be.true; - }); - - it('validates uint', () => { - expect(Token.validateType('uint')).to.be.true; - }); - - it('validates string', () => { - expect(Token.validateType('string')).to.be.true; - }); - - it('throws an error on invalid types', () => { - expect(() => Token.validateType('noMatch')).to.throw(/noMatch/); - }); - }); - - describe('constructor', () => { - it('throws an error on invalid types', () => { - expect(() => new Token('noMatch', '1')).to.throw(/noMatch/); - }); - - it('sets the type of the object', () => { - expect((new Token('bool', '1')).type).to.equal('bool'); - }); - - it('sets the value of the object', () => { - expect((new Token('bool', '1')).value).to.equal('1'); - }); - }); -}); diff --git a/js/src/abi/util/address.js b/js/src/abi/util/address.js deleted file mode 100644 index c0153ee5daab229aadc18f0e21fe2e315b8ab33f..0000000000000000000000000000000000000000 --- a/js/src/abi/util/address.js +++ /dev/null @@ -1,66 +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 . - -import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase - -export function isChecksumValid (_address) { - const address = _address.replace('0x', ''); - const hash = keccak_256(address.toLowerCase()); - - for (let n = 0; n < 40; n++) { - const char = address[n]; - const isLower = char !== char.toUpperCase(); - const isUpper = char !== char.toLowerCase(); - const hashval = parseInt(hash[n], 16); - - if ((hashval > 7 && isLower) || (hashval <= 7 && isUpper)) { - return false; - } - } - - return true; -} - -export function isAddress (address) { - if (address && address.length === 42) { - if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) { - return false; - } else if (/^(0x)?[0-9a-f]{40}$/.test(address) || /^(0x)?[0-9A-F]{40}$/.test(address)) { - return true; - } - - return isChecksumValid(address); - } - - return false; -} - -export function toChecksumAddress (_address) { - const address = (_address || '').toLowerCase(); - - if (!isAddress(address)) { - return ''; - } - - const hash = keccak_256(address.slice(-40)); - let result = '0x'; - - for (let n = 0; n < 40; n++) { - result = `${result}${parseInt(hash[n], 16) > 7 ? address[n + 2].toUpperCase() : address[n + 2]}`; - } - - return result; -} diff --git a/js/src/abi/util/address.spec.js b/js/src/abi/util/address.spec.js deleted file mode 100644 index 324ba163da9aa4a6d51d4263e9d6969a8e5b2b00..0000000000000000000000000000000000000000 --- a/js/src/abi/util/address.spec.js +++ /dev/null @@ -1,100 +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 . - -import { isChecksumValid, isAddress, toChecksumAddress } from './address'; - -describe('abi/util/address', () => { - const value = '63Cf90D3f0410092FC0fca41846f596223979195'; - const address = `0x${value}`; - const lowercase = `0x${value.toLowerCase()}`; - const uppercase = `0x${value.toUpperCase()}`; - const invalid = '0x' + value.split('').map((char) => { - if (char >= 'a' && char <= 'f') { - return char.toUpperCase(); - } else if (char >= 'A' && char <= 'F') { - return char.toLowerCase(); - } - - return char; - }).join(''); - const invalidhex = '0x01234567890123456789012345678901234567gh'; - - describe('isChecksumValid', () => { - it('returns false when fully lowercase', () => { - expect(isChecksumValid(lowercase)).to.be.false; - }); - - it('returns false when fully uppercase', () => { - expect(isChecksumValid(uppercase)).to.be.false; - }); - - it('returns false on a mixed-case address', () => { - expect(isChecksumValid(invalid)).to.be.false; - }); - - it('returns true on a checksummed address', () => { - expect(isChecksumValid(address)).to.be.true; - }); - }); - - describe('isAddress', () => { - it('returns true when fully lowercase', () => { - expect(isAddress(lowercase)).to.be.true; - }); - - it('returns true when fully uppercase', () => { - expect(isAddress(uppercase)).to.be.true; - }); - - it('returns true when checksummed', () => { - expect(isAddress(address)).to.be.true; - }); - - it('returns false when invalid checksum', () => { - expect(isAddress(invalid)).to.be.false; - }); - - it('returns false on valid length, non-hex', () => { - expect(isAddress(invalidhex)).to.be.false; - }); - }); - - describe('toChecksumAddress', () => { - it('returns empty when no address specified', () => { - expect(toChecksumAddress()).to.equal(''); - }); - - it('returns empty on invalid address structure', () => { - expect(toChecksumAddress('0xnotaddress')).to.equal(''); - }); - - it('returns formatted address on checksum input', () => { - expect(toChecksumAddress(address)).to.equal(address); - }); - - it('returns formatted address on lowercase input', () => { - expect(toChecksumAddress(lowercase)).to.equal(address); - }); - - it('returns formatted address on uppercase input', () => { - expect(toChecksumAddress(uppercase)).to.equal(address); - }); - - it('returns formatted address on mixed input', () => { - expect(toChecksumAddress(invalid)).to.equal(address); - }); - }); -}); diff --git a/js/src/abi/util/pad.js b/js/src/abi/util/pad.js deleted file mode 100644 index 476a27445e2e3db3a1e0613e4c00a84470b9c2e6..0000000000000000000000000000000000000000 --- a/js/src/abi/util/pad.js +++ /dev/null @@ -1,77 +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 . - -import BigNumber from 'bignumber.js'; -import utf8 from 'utf8'; - -import { isArray } from './types'; - -const ZERO_64 = '0000000000000000000000000000000000000000000000000000000000000000'; - -export function padAddress (_input) { - const input = _input.substr(0, 2) === '0x' ? _input.substr(2) : _input; - - return `${ZERO_64}${input}`.slice(-64); -} - -export function padBool (input) { - return `${ZERO_64}${input ? '1' : '0'}`.slice(-64); -} - -export function padU32 (input) { - let bn = new BigNumber(input); - - if (bn.lessThan(0)) { - bn = new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16) - .plus(bn).plus(1); - } - - return `${ZERO_64}${bn.toString(16)}`.slice(-64); -} - -function stringToBytes (input) { - if (isArray(input)) { - return input; - } else if (input.substr(0, 2) === '0x') { - const matches = input.substr(2).toLowerCase().match(/.{1,2}/g) || []; - - return matches.map((value) => parseInt(value, 16)); - } else { - return input.split('').map((char) => char.charCodeAt(0)); - } -} - -export function padBytes (_input) { - const input = stringToBytes(_input); - - return `${padU32(input.length)}${padFixedBytes(input)}`; -} - -export function padFixedBytes (_input) { - const input = stringToBytes(_input); - const sinput = input.map((code) => `0${code.toString(16)}`.slice(-2)).join(''); - const max = Math.floor((sinput.length + 63) / 64) * 64; - - return `${sinput}${ZERO_64}`.substr(0, max); -} - -export function padString (input) { - const array = utf8.encode(input) - .split('') - .map((char) => char.charCodeAt(0)); - - return padBytes(array); -} diff --git a/js/src/abi/util/pad.spec.js b/js/src/abi/util/pad.spec.js deleted file mode 100644 index 74463b438c1ea0801bf42fe79aca2a44148ead6f..0000000000000000000000000000000000000000 --- a/js/src/abi/util/pad.spec.js +++ /dev/null @@ -1,124 +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 . - -import BigNumber from 'bignumber.js'; -import { padAddress, padBool, padBytes, padFixedBytes, padString, padU32 } from './pad'; - -describe('abi/util/pad', () => { - const SHORT15 = '1234567890abcdef'; - const BYTES15 = [0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef]; - const LONG15 = `${SHORT15}000000000000000000000000000000000000000000000000`; - const PAD123 = '0000000000000000000000000000000000000000000000000000000000000123'; - - describe('padAddress', () => { - it('pads to 64 characters', () => { - expect(padAddress('123')).to.equal(PAD123); - }); - - it('strips leading 0x when passed in', () => { - expect(padFixedBytes(`0x${PAD123}`)).to.equal(PAD123); - }); - }); - - describe('padBool', () => { - const TRUE = '0000000000000000000000000000000000000000000000000000000000000001'; - const FALSE = '0000000000000000000000000000000000000000000000000000000000000000'; - - it('pads true to 64 characters', () => { - expect(padBool(true)).to.equal(TRUE); - }); - - it('pads false to 64 characters', () => { - expect(padBool(false)).to.equal(FALSE); - }); - }); - - describe('padU32', () => { - it('left pads length < 64 bytes to 64 bytes', () => { - expect(padU32(1)).to.equal('0000000000000000000000000000000000000000000000000000000000000001'); - }); - - it('pads hex representation', () => { - expect(padU32(0x123)).to.equal(PAD123); - }); - - it('pads decimal representation', () => { - expect(padU32(291)).to.equal(PAD123); - }); - - it('pads string representation', () => { - expect(padU32('0x123')).to.equal(PAD123); - }); - - it('pads BigNumber representation', () => { - expect(padU32(new BigNumber(0x123))).to.equal(PAD123); - }); - - it('converts negative numbers to 2s complement', () => { - expect(padU32(-123)).to.equal('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85'); - }); - }); - - describe('padFixedBytes', () => { - it('right pads length < 64 bytes to 64 bytes (string)', () => { - expect(padFixedBytes(`0x${SHORT15}`)).to.equal(LONG15); - }); - - it('right pads length < 64 bytes to 64 bytes (array)', () => { - expect(padFixedBytes(BYTES15)).to.equal(LONG15); - }); - - it('right pads length > 64 bytes (64 byte multiples)', () => { - expect(padFixedBytes(`0x${LONG15}${SHORT15}`)).to.equal(`${LONG15}${LONG15}`); - }); - - it('strips leading 0x when passed in', () => { - expect(padFixedBytes(`0x${SHORT15}`)).to.equal(LONG15); - }); - }); - - describe('padBytes', () => { - it('right pads length < 64, adding the length (string)', () => { - const result = padBytes(`0x${SHORT15}`); - - expect(result.length).to.equal(128); - expect(result).to.equal(`${padU32(8)}${LONG15}`); - }); - - it('right pads length < 64, adding the length (array)', () => { - const result = padBytes(BYTES15); - - expect(result.length).to.equal(128); - expect(result).to.equal(`${padU32(8)}${LONG15}`); - }); - - it('right pads length > 64, adding the length', () => { - const result = padBytes(`0x${LONG15}${SHORT15}`); - - expect(result.length).to.equal(192); - expect(result).to.equal(`${padU32(0x28)}${LONG15}${LONG15}`); - }); - }); - - describe('padString', () => { - it('correctly converts & pads strings', () => { - const result = padString('gavofyork'); - - expect(result.length).to.equal(128); - expect(result).to.equal(padBytes('0x6761766f66796f726b')); - }); - }); -}); diff --git a/js/src/abi/util/signature.js b/js/src/abi/util/signature.js deleted file mode 100644 index 86ed6f2657fe4adbaae471099ba53db97408e946..0000000000000000000000000000000000000000 --- a/js/src/abi/util/signature.js +++ /dev/null @@ -1,49 +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 . - -import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase -import { fromParamType } from '../spec/paramType/format'; - -export function eventSignature (eventName, params) { - const { strName, name } = parseName(eventName); - const types = (params || []).map(fromParamType).join(','); - const id = `${strName}(${types})`; - const signature = strName ? keccak_256(id) : ''; - - return { id, name, signature }; -} - -export function methodSignature (methodName, params) { - const { id, name, signature } = eventSignature(methodName, params); - - return { id, name, signature: signature.substr(0, 8) }; -} - -function parseName (name) { - const strName = `${name || ''}`; - const idx = strName.indexOf('('); - - if (idx === -1) { - return { strName, name }; - } - - const trimmedName = strName.slice(0, idx); - - return { - strName: trimmedName, - name: trimmedName - }; -} diff --git a/js/src/abi/util/signature.spec.js b/js/src/abi/util/signature.spec.js deleted file mode 100644 index 118ebf4e510faf77b7a2a30a99b8cba8f524c9fb..0000000000000000000000000000000000000000 --- a/js/src/abi/util/signature.spec.js +++ /dev/null @@ -1,111 +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 . - -import { eventSignature, methodSignature } from './signature'; - -describe('abi/util/signature', () => { - describe('eventSignature', () => { - it('encodes signature baz() correctly', () => { - expect(eventSignature('baz', [])).to.deep.equal({ - id: 'baz()', - name: 'baz', - signature: 'a7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf' - }); - }); - - it('encodes signature baz(uint32) correctly', () => { - expect(eventSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({ - id: 'baz(uint32)', - name: 'baz', - signature: '7d68785e8fc871be024b75964bd86d093511d4bc2dc7cf7bea32c48a0efaecb1' - }); - }); - - it('encodes signature baz(uint32, bool) correctly', () => { - expect(eventSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ - id: 'baz(uint32,bool)', - name: 'baz', - signature: 'cdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2' - }); - }); - - it('encodes no-name signature correctly as ()', () => { - expect(eventSignature(undefined, [])).to.deep.equal({ - id: '()', - name: undefined, - signature: '' - }); - }); - - it('encodes no-params signature correctly as ()', () => { - expect(eventSignature(undefined, undefined)).to.deep.equal({ - id: '()', - name: undefined, - signature: '' - }); - }); - }); - - describe('methodSignature', () => { - it('encodes signature baz() correctly', () => { - expect(methodSignature('baz', [])).to.deep.equal({ - id: 'baz()', - name: 'baz', - signature: 'a7916fac' - }); - }); - - it('encodes signature baz(uint32) correctly', () => { - expect(methodSignature('baz', [{ type: 'uint', length: 32 }])).to.deep.equal({ - id: 'baz(uint32)', - name: 'baz', - signature: '7d68785e' - }); - }); - - it('encodes signature baz(uint32, bool) correctly', () => { - expect(methodSignature('baz', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ - id: 'baz(uint32,bool)', - name: 'baz', - signature: 'cdcd77c0' - }); - }); - - it('encodes signature in name correctly', () => { - expect(methodSignature('baz(uint32,bool)', [{ type: 'uint', length: 32 }, { type: 'bool' }])).to.deep.equal({ - id: 'baz(uint32,bool)', - name: 'baz', - signature: 'cdcd77c0' - }); - }); - - it('encodes no-name signature correctly as ()', () => { - expect(methodSignature(undefined, [])).to.deep.equal({ - id: '()', - name: undefined, - signature: '' - }); - }); - - it('encodes no-params signature correctly as ()', () => { - expect(methodSignature(undefined, undefined)).to.deep.equal({ - id: '()', - name: undefined, - signature: '' - }); - }); - }); -}); diff --git a/js/src/abi/util/slice.js b/js/src/abi/util/slice.js deleted file mode 100644 index daab54f1ce2d569bef6a60cdcbfb9fd1659172d6..0000000000000000000000000000000000000000 --- a/js/src/abi/util/slice.js +++ /dev/null @@ -1,31 +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 . - -import { padAddress } from './pad'; - -export function sliceData (_data) { - if (!_data || !_data.length) { - return []; - } - - let data = (_data.substr(0, 2) === '0x') ? _data.substr(2) : _data; - - if (!data.length) { - data = padAddress(''); - } - - return data.match(/.{1,64}/g); -} diff --git a/js/src/abi/util/slice.spec.js b/js/src/abi/util/slice.spec.js deleted file mode 100644 index 1b754ccbb22fd88f7c244efd1bd4dcb7273c017d..0000000000000000000000000000000000000000 --- a/js/src/abi/util/slice.spec.js +++ /dev/null @@ -1,44 +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 . - -import { sliceData } from './slice'; - -describe('abi/util/slice', () => { - describe('sliceData', () => { - const slice1 = '131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b'; - const slice2 = '2124768576358735263578356373526387638357635873563586353756358763'; - - it('returns an empty array when length === 0', () => { - expect(sliceData('')).to.deep.equal([]); - }); - - it('returns an array with the slices otherwise', () => { - const sliced = sliceData(`${slice1}${slice2}`); - - expect(sliced.length).to.equal(2); - expect(sliced[0]).to.equal(slice1); - expect(sliced[1]).to.equal(slice2); - }); - - it('removes leading 0x when passed in', () => { - const sliced = sliceData(`0x${slice1}${slice2}`); - - expect(sliced.length).to.equal(2); - expect(sliced[0]).to.equal(slice1); - expect(sliced[1]).to.equal(slice2); - }); - }); -}); diff --git a/js/src/abi/util/sliceAs.js b/js/src/abi/util/sliceAs.js deleted file mode 100644 index e177897a197f34f31dcc9c74e36a0f4e9254a335..0000000000000000000000000000000000000000 --- a/js/src/abi/util/sliceAs.js +++ /dev/null @@ -1,47 +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 . - -import BigNumber from 'bignumber.js'; - -import { toChecksumAddress } from './address'; - -export function asU32 (slice) { - // TODO: validation - - return new BigNumber(slice, 16); -} - -export function asI32 (slice) { - if (new BigNumber(slice.substr(0, 1), 16).toString(2)[0] === '1') { - return new BigNumber(slice, 16) - .minus(new BigNumber('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', 16)) - .minus(1); - } - - return new BigNumber(slice, 16); -} - -export function asAddress (slice) { - // TODO: address validation? - - return toChecksumAddress(`0x${slice.slice(-40)}`); -} - -export function asBool (slice) { - // TODO: everything else should be 0 - - return new BigNumber(slice[63]).eq(1); -} diff --git a/js/src/abi/util/sliceAs.spec.js b/js/src/abi/util/sliceAs.spec.js deleted file mode 100644 index c29e345547bbc1684ae7e38eb37616352e1b0316..0000000000000000000000000000000000000000 --- a/js/src/abi/util/sliceAs.spec.js +++ /dev/null @@ -1,55 +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 . - -import { asAddress, asBool, asI32, asU32 } from './sliceAs'; - -describe('abi/util/sliceAs', () => { - const MAX_INT = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; - - describe('asAddress', () => { - it('correctly returns the last 0x40 characters', () => { - const address = '1111111111222222222233333333334444444444'; - - expect(asAddress(`000000000000000000000000${address}`)).to.equal(`0x${address}`); - }); - }); - - describe('asBool', () => { - it('correctly returns true', () => { - expect(asBool('0000000000000000000000000000000000000000000000000000000000000001')).to.be.true; - }); - - it('correctly returns false', () => { - expect(asBool('0000000000000000000000000000000000000000000000000000000000000000')).to.be.false; - }); - }); - - describe('asI32', () => { - it('correctly decodes positive numbers', () => { - expect(asI32('000000000000000000000000000000000000000000000000000000000000007b').toString()).to.equal('123'); - }); - - it('correctly decodes negative numbers', () => { - expect(asI32('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85').toString()).to.equal('-123'); - }); - }); - - describe('asU32', () => { - it('returns a maxium U32', () => { - expect(asU32(MAX_INT).toString(16)).to.equal(MAX_INT); - }); - }); -}); diff --git a/js/src/abi/util/types.js b/js/src/abi/util/types.js deleted file mode 100644 index dd408f3716fbc2e5bd065c2afcdbe94d07a6ae85..0000000000000000000000000000000000000000 --- a/js/src/abi/util/types.js +++ /dev/null @@ -1,27 +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 . - -export function isArray (test) { - return Object.prototype.toString.call(test) === '[object Array]'; -} - -export function isString (test) { - return Object.prototype.toString.call(test) === '[object String]'; -} - -export function isInstanceOf (test, clazz) { - return test instanceof clazz; -} diff --git a/js/src/abi/util/types.spec.js b/js/src/abi/util/types.spec.js deleted file mode 100644 index 177662ae271479390e5309ed5a9dbd542c6399a8..0000000000000000000000000000000000000000 --- a/js/src/abi/util/types.spec.js +++ /dev/null @@ -1,62 +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 . - -import { isArray, isString, isInstanceOf } from './types'; -import Token from '../token'; - -describe('abi/util/types', () => { - describe('isArray', () => { - it('correctly identifies empty arrays as Array', () => { - expect(isArray([])).to.be.true; - }); - - it('correctly identifies non-empty arrays as Array', () => { - expect(isArray([1, 2, 3])).to.be.true; - }); - - it('correctly identifies strings as non-Array', () => { - expect(isArray('not an array')).to.be.false; - }); - - it('correctly identifies objects as non-Array', () => { - expect(isArray({})).to.be.false; - }); - }); - - describe('isString', () => { - it('correctly identifies empty string as string', () => { - expect(isString('')).to.be.true; - }); - - it('correctly identifies string as string', () => { - expect(isString('123')).to.be.true; - }); - }); - - describe('isInstanceOf', () => { - it('correctly identifies build-in instanceof', () => { - expect(isInstanceOf(new String('123'), String)).to.be.true; // eslint-disable-line no-new-wrappers - }); - - it('correctly identifies own instanceof', () => { - expect(isInstanceOf(new Token('int', 123), Token)).to.be.true; - }); - - it('correctly reports false for own', () => { - expect(isInstanceOf({ type: 'int' }, Token)).to.be.false; - }); - }); -}); diff --git a/js/src/api/README.md b/js/src/api/README.md deleted file mode 100644 index 1a2051eaf499ace119526ca218df7266d2e6f9c2..0000000000000000000000000000000000000000 --- a/js/src/api/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# ethapi-js - -A thin, fast, low-level Promise-based wrapper around the Ethereum APIs. - -[![Build Status](https://travis-ci.org/jacogr/ethapi-js.svg?branch=master)](https://travis-ci.org/jacogr/ethapi-js) -[![Coverage Status](https://coveralls.io/repos/github/jacogr/ethapi-js/badge.svg?branch=master)](https://coveralls.io/github/jacogr/ethapi-js?branch=master) -[![Dependency Status](https://david-dm.org/jacogr/ethapi-js.svg)](https://david-dm.org/jacogr/ethapi-js) -[![devDependency Status](https://david-dm.org/jacogr/ethapi-js/dev-status.svg)](https://david-dm.org/jacogr/ethapi-js#info=devDependencies) - -## contributing - -Clone the repo and install dependencies via `npm install`. Tests can be executed via - -- `npm run testOnce` (100% covered unit tests) -- `npm run testE2E` (E2E against a running RPC-enabled testnet Parity/Geth instance, `parity --testnet` and for WebScokets, `geth --testnet --ws --wsorigins '*' --rpc`) -- setting the environment `DEBUG=true` will display the RPC POST bodies and responses on E2E tests - -## installation - -Install the package with `npm install --save ethapi-js` from the [npm registry ethapi-js](https://www.npmjs.com/package/ethapi-js) - -## usage - -### initialisation - -```javascript -// import the actual EthApi class -import EthApi from 'ethapi-js'; - -// do the setup -const transport = new EthApi.Transport.Http('http://localhost:8545'); // or .Ws('ws://localhost:8546') -const ethapi = new EthApi(transport); -``` - -You will require native Promises and fetch support (latest browsers only), they can be utilised by - -```javascript -import 'isomorphic-fetch'; - -import es6Promise from 'es6-promise'; -es6Promise.polyfill(); -``` - -### making calls - -perform a call - -```javascript -ethapi.eth - .coinbase() - .then((coinbase) => { - console.log(`The coinbase is ${coinbase}`); - }); -``` - -multiple promises - -```javascript -Promise - .all([ - ethapi.eth.coinbase(), - ethapi.net.listening() - ]) - .then(([coinbase, listening]) => { - // do stuff here - }); -``` - -chaining promises - -```javascript -ethapi.eth - .newFilter({...}) - .then((filterId) => ethapi.eth.getFilterChanges(filterId)) - .then((changes) => { - console.log(changes); - }); -``` - -### contracts - -attach contract - -```javascript -const abi = [{ name: 'callMe', inputs: [{ type: 'bool', ...}, { type: 'string', ...}]}, ...abi...]; -const contract = new ethapi.newContract(abi); -``` - -deploy - -```javascript -contract - .deploy('0xc0de', [params], 'superPassword') - .then((address) => { - console.log(`the contract was deployed at ${address}`); - }); -``` - -attach a contract at address - -```javascript -// via the constructor & .at function -const contract = api.newContract(abi).at('0xa9280...7347b'); -// or on an already initialised contract -contract.at('0xa9280...7347b'); -// perform calls here -``` - -find & call a function - -```javascript -contract.instance - .myContractMethodName - .call({}, [myContractMethodParameter]) // or estimateGas or sendTransaction - .then((result) => { - console.log(`the result was ${result}`); - }); -``` - -parse events from transaction receipt - -```javascript -contract - .parseTransactionEvents(txReceipt) - .then((receipt) => { - receipt.logs.forEach((log) => { - console.log('log parameters', log.params); - }); - }); -``` - -## apis - -APIs implement the calls as exposed in the [Ethcore JSON Ethereum RPC](https://github.com/paritytech/ethereum-rpc-json/) definitions. Mapping follows the naming conventions of the originals, i.e. `eth_call` becomes `eth.call`, `personal_accounts` becomes `personal.accounts`, etc. - -- [ethapi.db](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#db) -- [ethapi.eth](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#eth) -- [ethapi.parity](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#parity) -- [ethapi.net](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#net) -- [ethapi.personal](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#personal) -- [ethapi.shh](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#shh) -- [ethapi.signer](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#signer) -- [ethapi.trace](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#trace) -- [ethapi.web3](https://github.com/paritytech/ethereum-rpc-json/blob/master/interfaces.md#web3) - -As a verification step, all exposed interfaces are tested for existing and pointing to the correct endpoints by using the generated interfaces from the above repo. diff --git a/js/src/api/api.js b/js/src/api/api.js deleted file mode 100644 index 220c3be294158d1ba2fcd93c60ab1382a1cece02..0000000000000000000000000000000000000000 --- a/js/src/api/api.js +++ /dev/null @@ -1,179 +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 . - -import EventEmitter from 'eventemitter3'; - -import { Http, Ws } from './transport'; -import Contract from './contract'; - -import { Db, Eth, Parity, Net, Personal, Shh, Signer, Trace, Web3 } from './rpc'; -import Subscriptions from './subscriptions'; -import Pubsub from './pubsub'; -import util from './util'; -import { isFunction } from './util/types'; - -import LocalAccountsMiddleware from '~/api/local'; - -export default class Api extends EventEmitter { - constructor (transport, allowSubscriptions = true) { - super(); - - if (!transport || !isFunction(transport.execute)) { - throw new Error('EthApi needs transport with execute() function defined'); - } - - this._transport = transport; - - this._db = new Db(transport); - this._eth = new Eth(transport); - this._net = new Net(transport); - this._parity = new Parity(transport); - this._personal = new Personal(transport); - this._shh = new Shh(transport); - this._signer = new Signer(transport); - this._trace = new Trace(transport); - this._web3 = new Web3(transport); - - if (isFunction(transport.subscribe)) { - this._pubsub = new Pubsub(transport); - } - - if (allowSubscriptions) { - this._subscriptions = new Subscriptions(this); - } - // Doing a request here in test env would cause an error - if (LocalAccountsMiddleware && process.env.NODE_ENV !== 'test') { - const middleware = this.parity - .nodeKind() - .then((nodeKind) => { - if (nodeKind.availability === 'public') { - return LocalAccountsMiddleware; - } - - return null; - }) - .catch(() => null); - - transport.addMiddleware(middleware); - } - } - - get pubsub () { - if (!this._pubsub) { - throw Error('Pubsub is only available with a subscribing-supported transport injected!'); - } - return this._pubsub; - } - - get db () { - return this._db; - } - - get eth () { - return this._eth; - } - - get parity () { - return this._parity; - } - - get net () { - return this._net; - } - - get personal () { - return this._personal; - } - - get shh () { - return this._shh; - } - - get signer () { - return this._signer; - } - - get trace () { - return this._trace; - } - - get transport () { - return this._transport; - } - - get web3 () { - return this._web3; - } - - get util () { - return util; - } - - newContract (abi, address) { - return new Contract(this, abi).at(address); - } - - subscribe (subscriptionName, callback) { - if (!this._subscriptions) { - return Promise.resolve(1); - } - - return this._subscriptions.subscribe(subscriptionName, callback); - } - - unsubscribe (subscriptionId) { - if (!this._subscriptions) { - return Promise.resolve(true); - } - - return this._subscriptions.unsubscribe(subscriptionId); - } - - pollMethod (method, input, validate) { - const [_group, endpoint] = method.split('_'); - const group = `_${_group}`; - - return new Promise((resolve, reject) => { - const timeout = () => { - this[group][endpoint](input) - .then((result) => { - if (validate ? validate(result) : result) { - resolve(result); - } else { - setTimeout(timeout, 500); - } - }) - .catch((error) => { - // Don't print if the request is rejected: that's ok - if (error.type !== 'REQUEST_REJECTED') { - console.error('pollMethod', error); - } - - reject(error); - }); - }; - - timeout(); - }); - } - - static util = util - - static Transport = { - Http: Http, - Ws: Ws - } -} diff --git a/js/src/api/api.spec.js b/js/src/api/api.spec.js deleted file mode 100644 index c72b2284922cc5e0d069755bdbbd5847fd7328b9..0000000000000000000000000000000000000000 --- a/js/src/api/api.spec.js +++ /dev/null @@ -1,59 +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 . - -import { TEST_HTTP_URL, endpointTest } from '../../test/mockRpc'; - -import util from './util'; -import Api from './api'; - -import ethereumRpc from '../jsonrpc/'; - -describe('api/Api', () => { - describe('constructor', () => { - it('requires defined/non-null transport object', () => { - expect(() => new Api()).to.throw(/Api needs transport/); - expect(() => new Api(null)).to.throw(/Api needs transport/); - }); - - it('requires an execute function on the transport object', () => { - expect(() => new Api({})).to.throw(/Api needs transport/); - expect(() => new Api({ execute: true })).to.throw(/Api needs transport/); - }); - }); - - describe('interface', () => { - const api = new Api(new Api.Transport.Http(TEST_HTTP_URL, -1)); - const ignored = [ - 'eth_subscribe', 'eth_unsubscribe', - 'parity_subscribe', 'parity_unsubscribe', - 'signer_subscribePending', 'signer_unsubscribePending' - ]; - - Object.keys(ethereumRpc).sort().forEach((endpoint) => { - describe(endpoint, () => { - Object.keys(ethereumRpc[endpoint]).sort() - .filter(method => ignored.indexOf(method) !== -1) - .forEach((method) => { - endpointTest(api, endpoint, method); - }); - }); - }); - }); - - it('exposes util as static property', () => { - expect(Api.util).to.equal(util); - }); -}); diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js deleted file mode 100644 index dee4d6d777b6405ead63261d3db8a24bf8368c14..0000000000000000000000000000000000000000 --- a/js/src/api/contract/contract.js +++ /dev/null @@ -1,561 +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 . - -import Abi from '~/abi'; - -let nextSubscriptionId = 0; - -export default class Contract { - constructor (api, abi) { - if (!api) { - throw new Error('API instance needs to be provided to Contract'); - } - - if (!abi) { - throw new Error('ABI needs to be provided to Contract instance'); - } - - this._api = api; - this._abi = new Abi(abi); - - this._subscriptions = {}; - this._constructors = this._abi.constructors.map(this._bindFunction); - this._functions = this._abi.functions.map(this._bindFunction); - this._events = this._abi.events.map(this._bindEvent); - - this._instance = {}; - - this._events.forEach((evt) => { - this._instance[evt.name] = evt; - this._instance[evt.signature] = evt; - }); - - this._functions.forEach((fn) => { - this._instance[fn.name] = fn; - this._instance[fn.signature] = fn; - }); - - this._subscribedToPendings = false; - this._pendingsSubscriptionId = null; - - this._subscribedToBlock = false; - this._blockSubscriptionId = null; - - if (api && api.patch && api.patch.contract) { - api.patch.contract(this); - } - } - - get address () { - return this._address; - } - - get constructors () { - return this._constructors; - } - - get events () { - return this._events; - } - - get functions () { - return this._functions; - } - - get receipt () { - return this._receipt; - } - - get instance () { - this._instance.address = this._address; - return this._instance; - } - - get api () { - return this._api; - } - - get abi () { - return this._abi; - } - - at (address) { - this._address = address; - return this; - } - - deployEstimateGas (options, values) { - const _options = this._encodeOptions(this.constructors[0], options, values); - - return this._api.eth - .estimateGas(_options) - .then((gasEst) => { - return [gasEst, gasEst.mul(1.2)]; - }); - } - - deploy (options, values, statecb = () => {}, skipGasEstimate = false) { - let gasEstPromise; - - if (skipGasEstimate) { - gasEstPromise = Promise.resolve(null); - } else { - statecb(null, { state: 'estimateGas' }); - - gasEstPromise = this.deployEstimateGas(options, values) - .then(([gasEst, gas]) => gas); - } - - return gasEstPromise - .then((_gas) => { - if (_gas) { - options.gas = _gas.toFixed(0); - } - - const gas = _gas || options.gas; - - statecb(null, { state: 'postTransaction', gas }); - - const encodedOptions = this._encodeOptions(this.constructors[0], options, values); - - return this._api.parity - .postTransaction(encodedOptions) - .then((requestId) => { - statecb(null, { state: 'checkRequest', requestId }); - return this._pollCheckRequest(requestId); - }) - .then((txhash) => { - statecb(null, { state: 'getTransactionReceipt', txhash }); - return this._pollTransactionReceipt(txhash, gas); - }) - .then((receipt) => { - if (receipt.gasUsed.eq(gas)) { - throw new Error(`Contract not deployed, gasUsed == ${gas.toFixed(0)}`); - } - - statecb(null, { state: 'hasReceipt', receipt }); - this._receipt = receipt; - this._address = receipt.contractAddress; - return this._address; - }) - .then((address) => { - statecb(null, { state: 'getCode' }); - return this._api.eth.getCode(this._address); - }) - .then((code) => { - if (code === '0x') { - throw new Error('Contract not deployed, getCode returned 0x'); - } - - statecb(null, { state: 'completed' }); - return this._address; - }); - }); - } - - parseEventLogs (logs) { - return logs - .map((log) => { - const signature = log.topics[0].substr(2); - const event = this.events.find((evt) => evt.signature === signature); - - if (!event) { - console.warn(`Unable to find event matching signature ${signature}`); - return null; - } - - try { - const decoded = event.decodeLog(log.topics, log.data); - - log.params = {}; - log.event = event.name; - - decoded.params.forEach((param, index) => { - const { type, value } = param.token; - const key = param.name || index; - - log.params[key] = { type, value }; - }); - - return log; - } catch (error) { - console.warn('Error decoding log', log); - console.warn(error); - - return null; - } - }) - .filter((log) => log); - } - - parseTransactionEvents (receipt) { - receipt.logs = this.parseEventLogs(receipt.logs); - - return receipt; - } - - _pollCheckRequest = (requestId) => { - return this._api.pollMethod('parity_checkRequest', requestId); - } - - _pollTransactionReceipt = (txhash, gas) => { - return this.api.pollMethod('eth_getTransactionReceipt', txhash, (receipt) => { - if (!receipt || !receipt.blockNumber || receipt.blockNumber.eq(0)) { - return false; - } - - return true; - }); - } - - getCallData = (func, options, values) => { - let data = options.data; - - const tokens = func ? Abi.encodeTokens(func.inputParamTypes(), values) : null; - const call = tokens ? func.encodeCall(tokens) : null; - - if (data && data.substr(0, 2) === '0x') { - data = data.substr(2); - } - - return `0x${data || ''}${call || ''}`; - } - - _encodeOptions (func, options, values) { - const data = this.getCallData(func, options, values); - - return { - ...options, - data - }; - } - - _addOptionsTo (options = {}) { - return { - to: this._address, - ...options - }; - } - - _bindFunction = (func) => { - func.contract = this; - - func.call = (_options = {}, values = []) => { - const rawTokens = !!_options.rawTokens; - const options = { - ..._options - }; - - delete options.rawTokens; - - let callParams; - - try { - callParams = this._encodeOptions(func, this._addOptionsTo(options), values); - } catch (error) { - return Promise.reject(error); - } - - return this._api.eth - .call(callParams) - .then((encoded) => func.decodeOutput(encoded)) - .then((tokens) => { - if (rawTokens) { - return tokens; - } - - return tokens.map((token) => token.value); - }) - .then((returns) => returns.length === 1 ? returns[0] : returns) - .catch((error) => { - console.warn(`${func.name}.call`, values, error); - throw error; - }); - }; - - if (!func.constant) { - func.postTransaction = (options, values = []) => { - let _options; - - try { - _options = this._encodeOptions(func, this._addOptionsTo(options), values); - } catch (error) { - return Promise.reject(error); - } - - return this._api.parity - .postTransaction(_options) - .catch((error) => { - console.warn(`${func.name}.postTransaction`, values, error); - throw error; - }); - }; - - func.estimateGas = (options, values = []) => { - const _options = this._encodeOptions(func, this._addOptionsTo(options), values); - - return this._api.eth - .estimateGas(_options) - .catch((error) => { - console.warn(`${func.name}.estimateGas`, values, error); - throw error; - }); - }; - } - - return func; - } - - _bindEvent = (event) => { - event.subscribe = (options = {}, callback, autoRemove) => { - return this._subscribe(event, options, callback, autoRemove); - }; - - event.unsubscribe = (subscriptionId) => { - return this.unsubscribe(subscriptionId); - }; - - event.getAllLogs = (options = {}) => { - return this.getAllLogs(event); - }; - - return event; - } - - getAllLogs (event, _options) { - // Options as first parameter - if (!_options && event && event.topics) { - return this.getAllLogs(null, event); - } - - const options = this._getFilterOptions(event, _options); - - options.fromBlock = 0; - options.toBlock = 'latest'; - - return this._api.eth - .getLogs(options) - .then((logs) => this.parseEventLogs(logs)); - } - - _findEvent (eventName = null) { - const event = eventName - ? this._events.find((evt) => evt.name === eventName) - : null; - - if (eventName && !event) { - const events = this._events.map((evt) => evt.name).join(', '); - - throw new Error(`${eventName} is not a valid eventName, subscribe using one of ${events} (or null to include all)`); - } - - return event; - } - - _getFilterOptions (event = null, _options = {}) { - const optionTopics = _options.topics || []; - const signature = event && event.signature || null; - - // If event provided, remove the potential event signature - // as the first element of the topics - const topics = signature - ? [ signature ].concat(optionTopics.filter((t, idx) => idx > 0 || t !== signature)) - : optionTopics; - - const options = Object.assign({}, _options, { - address: this._address, - topics - }); - - return options; - } - - _createEthFilter (event = null, _options) { - const options = this._getFilterOptions(event, _options); - - return this._api.eth.newFilter(options); - } - - subscribe (eventName = null, options = {}, callback, autoRemove) { - try { - const event = this._findEvent(eventName); - - return this._subscribe(event, options, callback, autoRemove); - } catch (e) { - return Promise.reject(e); - } - } - - _sendData (subscriptionId, error, logs) { - const { autoRemove, callback } = this._subscriptions[subscriptionId]; - let result = true; - - try { - result = callback(error, logs); - } catch (error) { - console.warn('_sendData', subscriptionId, error); - } - - if (autoRemove && result && typeof result === 'boolean') { - this.unsubscribe(subscriptionId); - } - } - - _subscribe (event = null, _options, callback, autoRemove = false) { - const subscriptionId = nextSubscriptionId++; - const { skipInitFetch } = _options; - - delete _options['skipInitFetch']; - - return this - ._createEthFilter(event, _options) - .then((filterId) => { - this._subscriptions[subscriptionId] = { - options: _options, - autoRemove, - callback, - filterId, - id: subscriptionId - }; - - if (skipInitFetch) { - this._subscribeToChanges(); - return subscriptionId; - } - - return this._api.eth - .getFilterLogs(filterId) - .then((logs) => { - this._sendData(subscriptionId, null, this.parseEventLogs(logs)); - this._subscribeToChanges(); - return subscriptionId; - }); - }) - .catch((error) => { - console.warn('subscribe', event, _options, error); - throw error; - }); - } - - unsubscribe (subscriptionId) { - return this._api.eth - .uninstallFilter(this._subscriptions[subscriptionId].filterId) - .catch((error) => { - console.error('unsubscribe', error); - }) - .then(() => { - delete this._subscriptions[subscriptionId]; - this._unsubscribeFromChanges(); - }); - } - - _subscribeToChanges = () => { - const subscriptions = Object.values(this._subscriptions); - - const pendingSubscriptions = subscriptions - .filter((s) => s.options.toBlock && s.options.toBlock === 'pending'); - - const otherSubscriptions = subscriptions - .filter((s) => !(s.options.toBlock && s.options.toBlock === 'pending')); - - if (pendingSubscriptions.length > 0 && !this._subscribedToPendings) { - this._subscribedToPendings = true; - this._subscribeToPendings(); - } - - if (otherSubscriptions.length > 0 && !this._subscribedToBlock) { - this._subscribedToBlock = true; - this._subscribeToBlock(); - } - } - - _unsubscribeFromChanges = () => { - const subscriptions = Object.values(this._subscriptions); - - const pendingSubscriptions = subscriptions - .filter((s) => s.options.toBlock && s.options.toBlock === 'pending'); - - const otherSubscriptions = subscriptions - .filter((s) => !(s.options.toBlock && s.options.toBlock === 'pending')); - - if (pendingSubscriptions.length === 0 && this._subscribedToPendings) { - this._subscribedToPendings = false; - clearTimeout(this._pendingsSubscriptionId); - } - - if (otherSubscriptions.length === 0 && this._subscribedToBlock) { - this._subscribedToBlock = false; - this._api.unsubscribe(this._blockSubscriptionId); - } - } - - _subscribeToBlock = () => { - this._api - .subscribe('eth_blockNumber', (error) => { - if (error) { - console.error('::_subscribeToBlock', error, error && error.stack); - } - - const subscriptions = Object.values(this._subscriptions) - .filter((s) => !(s.options.toBlock && s.options.toBlock === 'pending')); - - this._sendSubscriptionChanges(subscriptions); - }) - .then((blockSubId) => { - this._blockSubscriptionId = blockSubId; - }) - .catch((e) => { - console.error('::_subscribeToBlock', e, e && e.stack); - }); - } - - _subscribeToPendings = () => { - const subscriptions = Object.values(this._subscriptions) - .filter((s) => s.options.toBlock && s.options.toBlock === 'pending'); - - const timeout = () => setTimeout(() => this._subscribeToPendings(), 1000); - - this._sendSubscriptionChanges(subscriptions) - .then(() => { - this._pendingsSubscriptionId = timeout(); - }); - } - - _sendSubscriptionChanges = (subscriptions) => { - return Promise - .all( - subscriptions.map((subscription) => { - return this._api.eth.getFilterChanges(subscription.filterId); - }) - ) - .then((logsArray) => { - logsArray.forEach((logs, index) => { - if (!logs || !logs.length) { - return; - } - - try { - this._sendData(subscriptions[index].id, null, this.parseEventLogs(logs)); - } catch (error) { - console.error('_sendSubscriptionChanges', error); - } - }); - }) - .catch((error) => { - console.error('_sendSubscriptionChanges', error); - }); - } -} diff --git a/js/src/api/contract/contract.spec.js b/js/src/api/contract/contract.spec.js deleted file mode 100644 index bd8b0fbdae711a384b37bc1f3e4ae81d8e824ccc..0000000000000000000000000000000000000000 --- a/js/src/api/contract/contract.spec.js +++ /dev/null @@ -1,597 +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 . - -import BigNumber from 'bignumber.js'; -import sinon from 'sinon'; - -import { TEST_HTTP_URL, mockHttp } from '../../../test/mockRpc'; - -import Abi from '../../abi'; -import { sha3 } from '../util/sha3'; - -import Api from '../api'; -import Contract from './contract'; -import { isInstanceOf, isFunction } from '../util/types'; - -const transport = new Api.Transport.Http(TEST_HTTP_URL, -1); -const eth = new Api(transport); - -describe('api/contract/Contract', () => { - const ADDR = '0x0123456789'; - - const ABI = [ - { - type: 'function', name: 'test', - inputs: [{ name: 'boolin', type: 'bool' }, { name: 'stringin', type: 'string' }], - outputs: [{ type: 'uint' }] - }, - { - type: 'function', name: 'test2', - outputs: [{ type: 'uint' }, { type: 'uint' }] - }, - { - type: 'constructor', - inputs: [{ name: 'boolin', type: 'bool' }, { name: 'stringin', type: 'string' }] - }, - { type: 'event', name: 'baz' }, - { type: 'event', name: 'foo' } - ]; - - const ABI_NO_PARAMS = [ - { - type: 'function', name: 'test', - inputs: [{ name: 'boolin', type: 'bool' }, { name: 'stringin', type: 'string' }], - outputs: [{ type: 'uint' }] - }, - { - type: 'function', name: 'test2', - outputs: [{ type: 'uint' }, { type: 'uint' }] - }, - { - type: 'constructor' - }, - { type: 'event', name: 'baz' }, - { type: 'event', name: 'foo' } - ]; - - const VALUES = [ true, 'jacogr' ]; - const CALLDATA = ` - 0000000000000000000000000000000000000000000000000000000000000001 - 0000000000000000000000000000000000000000000000000000000000000040 - 0000000000000000000000000000000000000000000000000000000000000006 - 6a61636f67720000000000000000000000000000000000000000000000000000 - `.replace(/\s/g, ''); - const SIGNATURE = '02356205'; - - const ENCODED = `0x${SIGNATURE}${CALLDATA}`; - - const RETURN1 = '0000000000000000000000000000000000000000000000000000000000123456'; - const RETURN2 = '0000000000000000000000000000000000000000000000000000000000456789'; - let scope; - - describe('constructor', () => { - it('needs an EthAbi instance', () => { - expect(() => new Contract()).to.throw(/API instance needs to be provided to Contract/); - }); - - it('needs an ABI', () => { - expect(() => new Contract(eth)).to.throw(/ABI needs to be provided to Contract instance/); - }); - - describe('internal setup', () => { - const contract = new Contract(eth, ABI); - - it('sets EthApi & parsed interface', () => { - expect(contract.address).to.not.be.ok; - expect(contract.api).to.deep.equal(eth); - expect(isInstanceOf(contract.abi, Abi)).to.be.ok; - }); - - it('attaches functions', () => { - expect(contract.functions.length).to.equal(2); - expect(contract.functions[0].name).to.equal('test'); - }); - - it('attaches constructors', () => { - expect(contract.constructors.length).to.equal(1); - }); - - it('attaches events', () => { - expect(contract.events.length).to.equal(2); - expect(contract.events[0].name).to.equal('baz'); - }); - }); - }); - - describe('at', () => { - it('sets returns the functions, events & sets the address', () => { - const contract = new Contract(eth, [ - { - constant: true, - inputs: [{ - name: '_who', - type: 'address' - }], - name: 'balanceOf', - outputs: [{ - name: '', - type: 'uint256' - }], - type: 'function' - }, - { - anonymous: false, - inputs: [{ - indexed: false, - name: 'amount', - type: 'uint256' - }], - name: 'Drained', - type: 'event' - } - ]); - - contract.at('6789'); - - expect(Object.keys(contract.instance)).to.deep.equal([ - 'Drained', - /^(?:0x)(.+)$/.exec(sha3('Drained(uint256)'))[1], - 'balanceOf', - /^(?:0x)(.+)$/.exec(sha3('balanceOf(address)'))[1].substr(0, 8), - 'address' - ]); - expect(contract.address).to.equal('6789'); - }); - }); - - describe('parseTransactionEvents', () => { - it('parses a transaction log into the data', () => { - const contract = new Contract(eth, [ - { - anonymous: false, name: 'Message', type: 'event', - inputs: [ - { indexed: true, name: 'postId', type: 'uint256' }, - { indexed: false, name: 'parentId', type: 'uint256' }, - { indexed: false, name: 'sender', type: 'address' }, - { indexed: false, name: 'at', type: 'uint256' }, - { indexed: false, name: 'messageId', type: 'uint256' }, - { indexed: false, name: 'message', type: 'string' } - ] - } - ]); - const decoded = contract.parseTransactionEvents({ - blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b', - blockNumber: '0x4fcd', - cumulativeGasUsed: '0xb57f', - gasUsed: '0xb57f', - logs: [{ - address: '0x22bff18ec62281850546a664bb63a5c06ac5f76c', - blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b', - blockNumber: '0x4fcd', - data: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063cf90d3f0410092fc0fca41846f5962239791950000000000000000000000000000000000000000000000000000000056e6c85f0000000000000000000000000000000000000000000000000001000000004fcd00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d706f7374286d6573736167652900000000000000000000000000000000000000', - logIndex: '0x0', - topics: [ - '0x954ba6c157daf8a26539574ffa64203c044691aa57251af95f4b48d85ec00dd5', - '0x0000000000000000000000000000000000000000000000000001000000004fe0' - ], - transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917', - transactionIndex: '0x0' - }], - to: '0x22bff18ec62281850546a664bb63a5c06ac5f76c', - transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917', - transactionIndex: '0x0' - }); - const log = decoded.logs[0]; - - expect(log.event).to.equal('Message'); - expect(log.address).to.equal('0x22bff18ec62281850546a664bb63a5c06ac5f76c'); - expect(log.params).to.deep.equal({ - at: { type: 'uint', value: new BigNumber('1457965151') }, - message: { type: 'string', value: 'post(message)' }, - messageId: { type: 'uint', value: new BigNumber('281474976731085') }, - parentId: { type: 'uint', value: new BigNumber(0) }, - postId: { type: 'uint', value: new BigNumber('281474976731104') }, - sender: { type: 'address', value: '0x63Cf90D3f0410092FC0fca41846f596223979195' } - }); - }); - }); - - describe('_pollTransactionReceipt', () => { - const contract = new Contract(eth, ABI); - const ADDRESS = '0xD337e80eEdBdf86eDBba021797d7e4e00Bb78351'; - const BLOCKNUMBER = '555000'; - const RECEIPT = { contractAddress: ADDRESS.toLowerCase(), blockNumber: BLOCKNUMBER }; - const EXPECT = { contractAddress: ADDRESS, blockNumber: new BigNumber(BLOCKNUMBER) }; - - let scope; - let receipt; - - describe('success', () => { - before(() => { - scope = mockHttp([ - { method: 'eth_getTransactionReceipt', reply: { result: null } }, - { method: 'eth_getTransactionReceipt', reply: { result: null } }, - { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT } } - ]); - - return contract - ._pollTransactionReceipt('0x123') - .then((_receipt) => { - receipt = _receipt; - }); - }); - - it('sends multiple getTransactionReceipt calls', () => { - expect(scope.isDone()).to.be.true; - }); - - it('passes the txhash through', () => { - expect(scope.body.eth_getTransactionReceipt.params[0]).to.equal('0x123'); - }); - - it('receives the final receipt', () => { - expect(receipt).to.deep.equal(EXPECT); - }); - }); - - describe('error', () => { - before(() => { - scope = mockHttp([{ method: 'eth_getTransactionReceipt', reply: { error: { code: -1, message: 'failure' } } }]); - }); - - it('returns the errors', () => { - return contract - ._pollTransactionReceipt('0x123') - .catch((error) => { - expect(error.message).to.match(/failure/); - }); - }); - }); - }); - - describe('deploy without parameters', () => { - const contract = new Contract(eth, ABI_NO_PARAMS); - const CODE = '0x123'; - const ADDRESS = '0xD337e80eEdBdf86eDBba021797d7e4e00Bb78351'; - const RECEIPT_DONE = { contractAddress: ADDRESS.toLowerCase(), gasUsed: 50, blockNumber: 2500 }; - - let scope; - - describe('success', () => { - before(() => { - scope = mockHttp([ - { method: 'eth_estimateGas', reply: { result: 1000 } }, - { method: 'parity_postTransaction', reply: { result: '0x678' } }, - { method: 'parity_checkRequest', reply: { result: '0x890' } }, - { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } }, - { method: 'eth_getCode', reply: { result: CODE } } - ]); - - return contract.deploy({ data: CODE }, []); - }); - - it('passes the options through to postTransaction (incl. gas calculation)', () => { - expect(scope.body.parity_postTransaction.params[0].data).to.equal(CODE); - }); - }); - }); - - describe('deploy', () => { - const contract = new Contract(eth, ABI); - const ADDRESS = '0xD337e80eEdBdf86eDBba021797d7e4e00Bb78351'; - const RECEIPT_PEND = { contractAddress: ADDRESS.toLowerCase(), gasUsed: 50, blockNumber: 0 }; - const RECEIPT_DONE = { contractAddress: ADDRESS.toLowerCase(), gasUsed: 50, blockNumber: 2500 }; - const RECEIPT_EXCP = { contractAddress: ADDRESS.toLowerCase(), gasUsed: 1200, blockNumber: 2500 }; - - let scope; - - describe('success', () => { - before(() => { - scope = mockHttp([ - { method: 'eth_estimateGas', reply: { result: 1000 } }, - { method: 'parity_postTransaction', reply: { result: '0x678' } }, - { method: 'parity_checkRequest', reply: { result: null } }, - { method: 'parity_checkRequest', reply: { result: '0x890' } }, - { method: 'eth_getTransactionReceipt', reply: { result: null } }, - { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_PEND } }, - { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } }, - { method: 'eth_getCode', reply: { result: '0x456' } } - ]); - - return contract.deploy({ data: '0x123' }, VALUES); - }); - - it('calls estimateGas, postTransaction, checkRequest, getTransactionReceipt & getCode in order', () => { - expect(scope.isDone()).to.be.true; - }); - - it('passes the options through to postTransaction (incl. gas calculation)', () => { - expect(scope.body.parity_postTransaction.params).to.deep.equal([ - { data: `0x123${CALLDATA}`, gas: '0x4b0' } - ]); - }); - - it('sets the address of the contract', () => { - expect(contract.address).to.equal(ADDRESS); - }); - }); - - describe('error', () => { - it('fails when gasUsed == gas', () => { - mockHttp([ - { method: 'eth_estimateGas', reply: { result: 1000 } }, - { method: 'parity_postTransaction', reply: { result: '0x678' } }, - { method: 'parity_checkRequest', reply: { result: '0x789' } }, - { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_EXCP } } - ]); - - return contract - .deploy({ data: '0x123' }, VALUES) - .catch((error) => { - expect(error.message).to.match(/not deployed, gasUsed/); - }); - }); - - it('fails when no code was deployed', () => { - mockHttp([ - { method: 'eth_estimateGas', reply: { result: 1000 } }, - { method: 'parity_postTransaction', reply: { result: '0x678' } }, - { method: 'parity_checkRequest', reply: { result: '0x789' } }, - { method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } }, - { method: 'eth_getCode', reply: { result: '0x' } } - ]); - - return contract - .deploy({ data: '0x123' }, VALUES) - .catch((error) => { - expect(error.message).to.match(/not deployed, getCode/); - }); - }); - }); - }); - - describe('bindings', () => { - let contract; - let cons; - let func; - - beforeEach(() => { - contract = new Contract(eth, ABI); - contract.at(ADDR); - cons = contract.constructors[0]; - func = contract.functions.find((fn) => fn.name === 'test'); - }); - - describe('_addOptionsTo', () => { - it('works on no object specified', () => { - expect(contract._addOptionsTo()).to.deep.equal({ to: ADDR }); - }); - - it('uses the contract address when none specified', () => { - expect(contract._addOptionsTo({ from: 'me' })).to.deep.equal({ to: ADDR, from: 'me' }); - }); - - it('overrides the contract address when specified', () => { - expect(contract._addOptionsTo({ to: 'you', from: 'me' })).to.deep.equal({ to: 'you', from: 'me' }); - }); - }); - - describe('attachments', () => { - it('attaches .call, .postTransaction & .estimateGas to constructors', () => { - expect(isFunction(cons.call)).to.be.true; - expect(isFunction(cons.postTransaction)).to.be.true; - expect(isFunction(cons.estimateGas)).to.be.true; - }); - - it('attaches .call, .postTransaction & .estimateGas to functions', () => { - expect(isFunction(func.call)).to.be.true; - expect(isFunction(func.postTransaction)).to.be.true; - expect(isFunction(func.estimateGas)).to.be.true; - }); - - it('attaches .call only to constant functions', () => { - func = (new Contract(eth, [{ type: 'function', name: 'test', constant: true }])).functions[0]; - - expect(isFunction(func.call)).to.be.true; - expect(isFunction(func.postTransaction)).to.be.false; - expect(isFunction(func.estimateGas)).to.be.false; - }); - }); - - describe('postTransaction', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'parity_postTransaction', reply: { result: ['hashId'] } }]); - }); - - it('encodes options and mades an parity_postTransaction call', () => { - return func - .postTransaction({ someExtras: 'foo' }, VALUES) - .then(() => { - expect(scope.isDone()).to.be.true; - expect(scope.body.parity_postTransaction.params[0]).to.deep.equal({ - someExtras: 'foo', - to: ADDR, - data: ENCODED - }); - }); - }); - }); - - describe('estimateGas', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_estimateGas', reply: { result: ['0x123'] } }]); - }); - - it('encodes options and mades an eth_estimateGas call', () => { - return func - .estimateGas({ someExtras: 'foo' }, VALUES) - .then((amount) => { - expect(scope.isDone()).to.be.true; - expect(amount.toString(16)).to.equal('123'); - expect(scope.body.eth_estimateGas.params).to.deep.equal([{ - someExtras: 'foo', - to: ADDR, - data: ENCODED - }]); - }); - }); - }); - - describe('call', () => { - it('encodes options and mades an eth_call call', () => { - scope = mockHttp([{ method: 'eth_call', reply: { result: RETURN1 } }]); - - return func - .call({ someExtras: 'foo' }, VALUES) - .then((result) => { - expect(scope.isDone()).to.be.true; - expect(scope.body.eth_call.params).to.deep.equal([{ - someExtras: 'foo', - to: ADDR, - data: ENCODED - }, 'latest']); - expect(result.toString(16)).to.equal('123456'); - }); - }); - - it('encodes options and mades an eth_call call (multiple returns)', () => { - scope = mockHttp([{ method: 'eth_call', reply: { result: `${RETURN1}${RETURN2}` } }]); - - return contract.functions[1] - .call({}, []) - .then((result) => { - expect(scope.isDone()).to.be.true; - expect(result.length).to.equal(2); - expect(result[0].toString(16)).to.equal('123456'); - expect(result[1].toString(16)).to.equal('456789'); - }); - }); - }); - }); - - describe('subscribe', () => { - const abi = [ - { - anonymous: false, name: 'Message', type: 'event', - inputs: [ - { indexed: true, name: 'postId', type: 'uint256' }, - { indexed: false, name: 'parentId', type: 'uint256' }, - { indexed: false, name: 'sender', type: 'address' }, - { indexed: false, name: 'at', type: 'uint256' }, - { indexed: false, name: 'messageId', type: 'uint256' }, - { indexed: false, name: 'message', type: 'string' } - ] - } - ]; - - const logs = [{ - address: '0x22bff18ec62281850546a664bb63a5c06ac5f76c', - blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b', - blockNumber: '0x4fcd', - data: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063cf90d3f0410092fc0fca41846f5962239791950000000000000000000000000000000000000000000000000000000056e6c85f0000000000000000000000000000000000000000000000000001000000004fcd00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d706f7374286d6573736167652900000000000000000000000000000000000000', - logIndex: '0x0', - topics: [ - '0x954ba6c157daf8a26539574ffa64203c044691aa57251af95f4b48d85ec00dd5', - '0x0000000000000000000000000000000000000000000000000001000000004fe0' - ], - transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917', - transactionIndex: '0x0' - }]; - - const parsed = [{ - address: '0x22bfF18ec62281850546a664bb63a5C06AC5F76C', - blockHash: '0xa9280530a3b47bee2fc80f2862fd56502ae075350571d724d6442ea4c597347b', - blockNumber: new BigNumber(20429), - data: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063cf90d3f0410092fc0fca41846f5962239791950000000000000000000000000000000000000000000000000000000056e6c85f0000000000000000000000000000000000000000000000000001000000004fcd00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000d706f7374286d6573736167652900000000000000000000000000000000000000', - event: 'Message', - logIndex: new BigNumber(0), - params: { - at: { type: 'uint', value: new BigNumber(1457965151) }, - message: { type: 'string', value: 'post(message)' }, - messageId: { type: 'uint', value: new BigNumber(281474976731085) }, - parentId: { type: 'uint', value: new BigNumber(0) }, - postId: { type: 'uint', value: new BigNumber(281474976731104) }, - sender: { type: 'address', value: '0x63Cf90D3f0410092FC0fca41846f596223979195' } - }, - topics: [ - '0x954ba6c157daf8a26539574ffa64203c044691aa57251af95f4b48d85ec00dd5', - '0x0000000000000000000000000000000000000000000000000001000000004fe0' - ], - transactionHash: '0xca16f537d761d13e4e80953b754e2b15541f267d6cad9381f750af1bae1e4917', - transactionIndex: new BigNumber(0) - }]; - - let contract; - - beforeEach(() => { - contract = new Contract(eth, abi); - contract.at(ADDR); - }); - - describe('invalid events', () => { - it('fails to subscribe to an invalid names', () => { - return contract - .subscribe('invalid') - .catch((error) => { - expect(error.message).to.match(/invalid is not a valid eventName/); - }); - }); - }); - - describe('valid events', () => { - let cbb; - let cbe; - - beforeEach(() => { - scope = mockHttp([ - { method: 'eth_newFilter', reply: { result: '0x123' } }, - { method: 'eth_getFilterLogs', reply: { result: logs } }, - { method: 'eth_getFilterChanges', reply: { result: logs } }, - { method: 'eth_newFilter', reply: { result: '0x123' } }, - { method: 'eth_getFilterLogs', reply: { result: logs } } - ]); - cbb = sinon.stub(); - cbe = sinon.stub(); - - return contract.subscribe('Message', { toBlock: 'pending' }, cbb); - }); - - it('sets the subscriptionId returned', () => { - return contract - .subscribe('Message', { toBlock: 'pending' }, cbe) - .then((subscriptionId) => { - expect(subscriptionId).to.equal(1); - }); - }); - - it('creates a new filter and retrieves the logs on it', () => { - return contract - .subscribe('Message', { toBlock: 'pending' }, cbe) - .then((subscriptionId) => { - expect(scope.isDone()).to.be.true; - }); - }); - - it('returns the logs to the callback', () => { - return contract - .subscribe('Message', { toBlock: 'pending' }, cbe) - .then((subscriptionId) => { - expect(cbe).to.have.been.calledWith(null, parsed); - }); - }); - }); - }); -}); diff --git a/js/src/api/contract/index.js b/js/src/api/contract/index.js deleted file mode 100644 index 74c58e942d4f23ba7637a544b403a1e1f88ffb37..0000000000000000000000000000000000000000 --- a/js/src/api/contract/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './contract'; diff --git a/js/src/api/format/input.js b/js/src/api/format/input.js deleted file mode 100644 index 0ccd10604bfe3d218553d006b9caf89b7e10b001..0000000000000000000000000000000000000000 --- a/js/src/api/format/input.js +++ /dev/null @@ -1,242 +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 . - -import BigNumber from 'bignumber.js'; - -import { isArray, isHex, isInstanceOf, isString } from '../util/types'; -import { padLeft, toHex } from '../util/format'; - -export function inAddress (address) { - // TODO: address validation if we have upper-lower addresses - return inHex(address); -} - -export function inAddresses (addresses) { - return (addresses || []).map(inAddress); -} - -export function inBlockNumber (blockNumber) { - if (isString(blockNumber)) { - switch (blockNumber) { - case 'earliest': - case 'latest': - case 'pending': - return blockNumber; - } - } - - return inNumber16(blockNumber); -} - -export function inData (data) { - if (data && data.length && !isHex(data)) { - data = data.split('').map((chr) => { - return `0${chr.charCodeAt(0).toString(16)}`.slice(-2); - }).join(''); - } - - return inHex(data); -} - -export function inHash (hash) { - return inHex(hash); -} - -export function inTopics (_topics) { - let topics = (_topics || []) - .filter((topic) => topic === null || topic) - .map((topic) => { - if (topic === null) { - return null; - } - - if (Array.isArray(topic)) { - return inTopics(topic); - } - - return padLeft(topic, 32); - }); - - return topics; -} - -export function inFilter (options) { - if (options) { - Object.keys(options).forEach((key) => { - switch (key) { - case 'address': - if (isArray(options[key])) { - options[key] = options[key].map(inAddress); - } else { - options[key] = inAddress(options[key]); - } - break; - - case 'fromBlock': - case 'toBlock': - options[key] = inBlockNumber(options[key]); - break; - - case 'limit': - options[key] = inNumber10(options[key]); - break; - - case 'topics': - options[key] = inTopics(options[key]); - } - }); - } - - return options; -} - -export function inHex (str) { - return toHex(str); -} - -export function inNumber10 (number) { - if (isInstanceOf(number, BigNumber)) { - return number.toNumber(); - } - - return (new BigNumber(number || 0)).toNumber(); -} - -export function inNumber16 (number) { - const bn = isInstanceOf(number, BigNumber) - ? number - : (new BigNumber(number || 0)); - - if (!bn.isInteger()) { - throw new Error(`[format/input::inNumber16] the given number is not an integer: ${bn.toFormat()}`); - } - - return inHex(bn.toString(16)); -} - -export function inOptionsCondition (condition) { - if (condition) { - if (condition.block) { - condition.block = condition.block ? inNumber10(condition.block) : null; - } else if (condition.time) { - condition.time = inNumber10(Math.floor(condition.time.getTime() / 1000)); - } - } - - return condition; -} - -export function inOptions (_options = {}) { - const options = { ..._options }; - - Object.keys(options).forEach((key) => { - switch (key) { - case 'to': - // Don't encode the `to` option if it's empty - // (eg. contract deployments) - if (options[key]) { - options.to = inAddress(options[key]); - } - break; - - case 'from': - options[key] = inAddress(options[key]); - break; - - case 'condition': - options[key] = inOptionsCondition(options[key]); - break; - - case 'gas': - case 'gasPrice': - options[key] = inNumber16((new BigNumber(options[key])).round()); - break; - - case 'value': - case 'nonce': - options[key] = inNumber16(options[key]); - break; - - case 'data': - options[key] = inData(options[key]); - break; - } - }); - - return options; -} - -export function inTraceFilter (filterObject) { - if (filterObject) { - Object.keys(filterObject).forEach((key) => { - switch (key) { - case 'fromAddress': - case 'toAddress': - filterObject[key] = [].concat(filterObject[key]) - .map(address => inAddress(address)); - break; - - case 'toBlock': - case 'fromBlock': - filterObject[key] = inBlockNumber(filterObject[key]); - break; - } - }); - } - - return filterObject; -} - -export function inTraceType (whatTrace) { - if (isString(whatTrace)) { - return [whatTrace]; - } - - return whatTrace; -} - -function inDeriveType (derive) { - return derive && derive.type === 'hard' ? 'hard' : 'soft'; -} - -export function inDeriveHash (derive) { - const hash = derive && derive.hash ? derive.hash : derive; - const type = inDeriveType(derive); - - return { - hash: inHex(hash), - type - }; -} - -export function inDeriveIndex (derive) { - if (!derive) { - return []; - } - - if (!isArray(derive)) { - derive = [derive]; - } - - return derive.map(item => { - const index = inNumber10(item && item.index ? item.index : item); - - return { - index, - type: inDeriveType(item) - }; - }); -} diff --git a/js/src/api/format/input.spec.js b/js/src/api/format/input.spec.js deleted file mode 100644 index eb74b7bd67cef4c96f0d35273107076e0c5cb478..0000000000000000000000000000000000000000 --- a/js/src/api/format/input.spec.js +++ /dev/null @@ -1,341 +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 . - -import BigNumber from 'bignumber.js'; - -import { - inAddress, inBlockNumber, inData, inFilter, inHex, - inNumber10, inNumber16, inOptions, inTraceType, - inDeriveHash, inDeriveIndex -} from './input'; -import { isAddress } from '../../../test/types'; - -describe('api/format/input', () => { - const address = '0x63cf90d3f0410092fc0fca41846f596223979195'; - - describe('inAddress', () => { - const address = '63cf90d3f0410092fc0fca41846f596223979195'; - - it('adds the leading 0x as required', () => { - expect(inAddress(address)).to.equal(`0x${address}`); - }); - - it('returns verified addresses as-is', () => { - expect(inAddress(`0x${address}`)).to.equal(`0x${address}`); - }); - - it('returns lowercase equivalents', () => { - expect(inAddress(address.toUpperCase())).to.equal(`0x${address}`); - }); - - it('returns 0x on null addresses', () => { - expect(inAddress()).to.equal('0x'); - }); - }); - - describe('inBlockNumber()', () => { - it('returns earliest as-is', () => { - expect(inBlockNumber('earliest')).to.equal('earliest'); - }); - - it('returns latest as-is', () => { - expect(inBlockNumber('latest')).to.equal('latest'); - }); - - it('returns pending as-is', () => { - expect(inBlockNumber('pending')).to.equal('pending'); - }); - - it('formats existing BigNumber into hex', () => { - expect(inBlockNumber(new BigNumber(0x123456))).to.equal('0x123456'); - }); - - it('formats hex strings into hex', () => { - expect(inBlockNumber('0x123456')).to.equal('0x123456'); - }); - - it('formats numbers into hex', () => { - expect(inBlockNumber(0x123456)).to.equal('0x123456'); - }); - }); - - describe('inData', () => { - it('formats to hex', () => { - expect(inData('123456')).to.equal('0x123456'); - }); - - it('converts a string to a hex representation', () => { - expect(inData('jaco')).to.equal('0x6a61636f'); - }); - }); - - describe('inHex', () => { - it('leaves leading 0x as-is', () => { - expect(inHex('0x123456')).to.equal('0x123456'); - }); - - it('adds a leading 0x', () => { - expect(inHex('123456')).to.equal('0x123456'); - }); - - it('returns uppercase as lowercase (leading 0x)', () => { - expect(inHex('0xABCDEF')).to.equal('0xabcdef'); - }); - - it('returns uppercase as lowercase (no leading 0x)', () => { - expect(inHex('ABCDEF')).to.equal('0xabcdef'); - }); - - it('handles empty & null', () => { - expect(inHex()).to.equal('0x'); - expect(inHex('')).to.equal('0x'); - }); - }); - - describe('inFilter', () => { - ['address'].forEach((input) => { - it(`formats ${input} address as address`, () => { - const block = {}; - - block[input] = address; - const formatted = inFilter(block)[input]; - - expect(isAddress(formatted)).to.be.true; - expect(formatted).to.equal(address); - }); - }); - - ['fromBlock', 'toBlock'].forEach((input) => { - it(`formats ${input} number as blockNumber`, () => { - const block = {}; - - block[input] = 0x123; - const formatted = inFilter(block)[input]; - - expect(formatted).to.equal('0x123'); - }); - }); - - it('ignores and passes through unknown keys', () => { - expect(inFilter({ someRandom: 'someRandom' })).to.deep.equal({ someRandom: 'someRandom' }); - }); - - it('formats an filter options object with relevant entries converted', () => { - expect( - inFilter({ - address: address, - fromBlock: 'latest', - toBlock: 0x101, - extraData: 'someExtraStuffInHere', - limit: 0x32 - }) - ).to.deep.equal({ - address: address, - fromBlock: 'latest', - toBlock: '0x101', - extraData: 'someExtraStuffInHere', - limit: 50 - }); - }); - }); - - describe('inNumber10()', () => { - it('formats existing BigNumber into number', () => { - expect(inNumber10(new BigNumber(123))).to.equal(123); - }); - - it('formats hex strings into decimal', () => { - expect(inNumber10('0x0a')).to.equal(10); - }); - - it('formats numbers into number', () => { - expect(inNumber10(123)).to.equal(123); - }); - - it('formats undefined into 0', () => { - expect(inNumber10()).to.equal(0); - }); - }); - - describe('inNumber16()', () => { - it('formats existing BigNumber into hex', () => { - expect(inNumber16(new BigNumber(0x123456))).to.equal('0x123456'); - }); - - it('formats hex strings into hex', () => { - expect(inNumber16('0x123456')).to.equal('0x123456'); - }); - - it('formats numbers into hex', () => { - expect(inNumber16(0x123456)).to.equal('0x123456'); - }); - - it('formats undefined into 0', () => { - expect(inNumber16()).to.equal('0x0'); - }); - }); - - describe('inOptions', () => { - ['data'].forEach((input) => { - it(`converts ${input} to hex data`, () => { - const block = {}; - - block[input] = '1234'; - const formatted = inData(block[input]); - - expect(formatted).to.equal('0x1234'); - }); - }); - - ['from', 'to'].forEach((input) => { - it(`formats ${input} address as address`, () => { - const block = {}; - - block[input] = address; - const formatted = inOptions(block)[input]; - - expect(isAddress(formatted)).to.be.true; - expect(formatted).to.equal(address); - }); - }); - - it('does not encode an empty `to` value', () => { - const options = { to: '' }; - const formatted = inOptions(options); - - expect(formatted.to).to.equal(''); - }); - - ['gas', 'gasPrice', 'value', 'nonce'].forEach((input) => { - it(`formats ${input} number as hexnumber`, () => { - const block = {}; - - block[input] = 0x123; - const formatted = inOptions(block)[input]; - - expect(formatted).to.equal('0x123'); - }); - }); - - it('passes condition as null when specified as such', () => { - expect(inOptions({ condition: null })).to.deep.equal({ condition: null }); - }); - - it('ignores and passes through unknown keys', () => { - expect(inOptions({ someRandom: 'someRandom' })).to.deep.equal({ someRandom: 'someRandom' }); - }); - - it('formats an options object with relevant entries converted', () => { - expect( - inOptions({ - from: address, - to: address, - gas: new BigNumber('0x100'), - gasPrice: 0x101, - value: 258, - nonce: '0x104', - data: '0123456789', - extraData: 'someExtraStuffInHere' - }) - ).to.deep.equal({ - from: address, - to: address, - gas: '0x100', - gasPrice: '0x101', - value: '0x102', - nonce: '0x104', - data: '0x0123456789', - extraData: 'someExtraStuffInHere' - }); - }); - }); - - describe('inTraceType', () => { - it('returns array of types as is', () => { - const types = ['vmTrace', 'trace', 'stateDiff']; - - expect(inTraceType(types)).to.deep.equal(types); - }); - - it('formats single string type into array', () => { - const type = 'vmTrace'; - - expect(inTraceType(type)).to.deep.equal([type]); - }); - }); - - describe('inDeriveHash', () => { - it('returns derive hash', () => { - expect(inDeriveHash(1)).to.deep.equal({ - hash: '0x1', - type: 'soft' - }); - - expect(inDeriveHash(null)).to.deep.equal({ - hash: '0x', - type: 'soft' - }); - - expect(inDeriveHash({ - hash: 5 - })).to.deep.equal({ - hash: '0x5', - type: 'soft' - }); - - expect(inDeriveHash({ - hash: 5, - type: 'hard' - })).to.deep.equal({ - hash: '0x5', - type: 'hard' - }); - }); - }); - - describe('inDeriveIndex', () => { - it('returns derive hash', () => { - expect(inDeriveIndex(null)).to.deep.equal([]); - expect(inDeriveIndex([])).to.deep.equal([]); - - expect(inDeriveIndex([1])).to.deep.equal([{ - index: 1, - type: 'soft' - }]); - - expect(inDeriveIndex({ - index: 1 - })).to.deep.equal([{ - index: 1, - type: 'soft' - }]); - - expect(inDeriveIndex([{ - index: 1, - type: 'hard' - }, 5])).to.deep.equal([ - { - index: 1, - type: 'hard' - }, - { - index: 5, - type: 'soft' - } - ]); - }); - }); -}); diff --git a/js/src/api/format/output.js b/js/src/api/format/output.js deleted file mode 100644 index 7bf39d17c675b8292c7428776067915d54a0c255..0000000000000000000000000000000000000000 --- a/js/src/api/format/output.js +++ /dev/null @@ -1,414 +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 . - -import BigNumber from 'bignumber.js'; - -import { toChecksumAddress } from '../../abi/util/address'; -import { isString } from '../util/types'; - -export function outAccountInfo (infos) { - return Object - .keys(infos) - .reduce((ret, _address) => { - const info = infos[_address]; - const address = outAddress(_address); - - ret[address] = { - name: info.name - }; - - if (info.meta) { - ret[address].uuid = info.uuid; - ret[address].meta = JSON.parse(info.meta); - } - - return ret; - }, {}); -} - -export function outAddress (address) { - return toChecksumAddress(address); -} - -export function outAddresses (addresses) { - return (addresses || []).map(outAddress); -} - -export function outBlock (block) { - if (block) { - Object.keys(block).forEach((key) => { - switch (key) { - case 'author': - case 'miner': - block[key] = outAddress(block[key]); - break; - - case 'difficulty': - case 'gasLimit': - case 'gasUsed': - case 'nonce': - case 'number': - case 'totalDifficulty': - block[key] = outNumber(block[key]); - break; - - case 'timestamp': - block[key] = outDate(block[key]); - break; - } - }); - } - - return block; -} - -export function outChainStatus (status) { - if (status) { - Object.keys(status).forEach((key) => { - switch (key) { - case 'blockGap': - status[key] = status[key] - ? status[key].map(outNumber) - : status[key]; - break; - } - }); - } - - return status; -} - -export function outDate (date) { - if (typeof date.toISOString === 'function') { - return date; - } - - try { - if (typeof date === 'string' && (new Date(date)).toISOString() === date) { - return new Date(date); - } - } catch (error) {} - - return new Date(outNumber(date).toNumber() * 1000); -} - -export function outHistogram (histogram) { - if (histogram) { - Object.keys(histogram).forEach((key) => { - switch (key) { - case 'bucketBounds': - case 'counts': - histogram[key] = histogram[key].map(outNumber); - break; - } - }); - } - - return histogram; -} - -export function outLog (log) { - Object.keys(log).forEach((key) => { - switch (key) { - case 'blockNumber': - case 'logIndex': - case 'transactionIndex': - log[key] = outNumber(log[key]); - break; - - case 'address': - log[key] = outAddress(log[key]); - break; - } - }); - - return log; -} - -export function outHwAccountInfo (infos) { - return Object - .keys(infos) - .reduce((ret, _address) => { - const address = outAddress(_address); - - ret[address] = infos[_address]; - - return ret; - }, {}); -} - -export function outNodeKind (info) { - return info; -} - -export function outNumber (number) { - return new BigNumber(number || 0); -} - -export function outPeer (peer) { - const protocols = Object.keys(peer.protocols) - .reduce((obj, key) => { - if (peer.protocols[key]) { - obj[key] = { - ...peer.protocols[key], - difficulty: outNumber(peer.protocols[key].difficulty) - }; - } - - return obj; - }, {}); - - return { - ...peer, - protocols - }; -} - -export function outPeers (peers) { - return { - active: outNumber(peers.active), - connected: outNumber(peers.connected), - max: outNumber(peers.max), - peers: peers.peers.map((peer) => outPeer(peer)) - }; -} - -export function outReceipt (receipt) { - if (receipt) { - Object.keys(receipt).forEach((key) => { - switch (key) { - case 'blockNumber': - case 'cumulativeGasUsed': - case 'gasUsed': - case 'transactionIndex': - receipt[key] = outNumber(receipt[key]); - break; - - case 'contractAddress': - receipt[key] = outAddress(receipt[key]); - break; - } - }); - } - - return receipt; -} - -export function outRecentDapps (recentDapps) { - if (recentDapps) { - Object.keys(recentDapps).forEach((url) => { - recentDapps[url] = outDate(recentDapps[url]); - }); - } - - return recentDapps; -} - -export function outSignerRequest (request) { - if (request) { - Object.keys(request).forEach((key) => { - switch (key) { - case 'id': - request[key] = outNumber(request[key]); - break; - - case 'payload': - request[key].decrypt = outSigningPayload(request[key].decrypt); - request[key].sign = outSigningPayload(request[key].sign); - request[key].signTransaction = outTransaction(request[key].signTransaction); - request[key].sendTransaction = outTransaction(request[key].sendTransaction); - break; - - case 'origin': - const type = Object.keys(request[key])[0]; - const details = request[key][type]; - - request[key] = { type, details }; - break; - } - }); - } - - return request; -} - -export function outSyncing (syncing) { - if (syncing && syncing !== 'false') { - Object.keys(syncing).forEach((key) => { - switch (key) { - case 'currentBlock': - case 'highestBlock': - case 'startingBlock': - case 'warpChunksAmount': - case 'warpChunksProcessed': - syncing[key] = outNumber(syncing[key]); - break; - - case 'blockGap': - syncing[key] = syncing[key] ? syncing[key].map(outNumber) : syncing[key]; - break; - } - }); - } - - return syncing; -} - -export function outTransactionCondition (condition) { - if (condition) { - if (condition.block) { - condition.block = outNumber(condition.block); - } else if (condition.time) { - condition.time = outDate(condition.time); - } - } - - return condition; -} - -export function outTransaction (tx) { - if (tx) { - Object.keys(tx).forEach((key) => { - switch (key) { - case 'blockNumber': - case 'gasPrice': - case 'gas': - case 'nonce': - case 'transactionIndex': - case 'value': - tx[key] = outNumber(tx[key]); - break; - - case 'condition': - tx[key] = outTransactionCondition(tx[key]); - break; - - case 'creates': - case 'from': - case 'to': - tx[key] = outAddress(tx[key]); - break; - } - }); - } - - return tx; -} - -export function outSigningPayload (payload) { - if (payload) { - Object.keys(payload).forEach((key) => { - switch (key) { - case 'address': - payload[key] = outAddress(payload[key]); - break; - } - }); - } - - return payload; -} - -export function outTrace (trace) { - if (trace) { - if (trace.action) { - Object.keys(trace.action).forEach(key => { - switch (key) { - case 'gas': - case 'value': - case 'balance': - trace.action[key] = outNumber(trace.action[key]); - break; - - case 'from': - case 'to': - case 'address': - case 'refundAddress': - trace.action[key] = outAddress(trace.action[key]); - break; - } - }); - } - - if (trace.result) { - Object.keys(trace.result).forEach(key => { - switch (key) { - case 'gasUsed': - trace.result[key] = outNumber(trace.result[key]); - break; - - case 'address': - trace.action[key] = outAddress(trace.action[key]); - break; - } - }); - } - - if (trace.traceAddress) { - trace.traceAddress.forEach((address, index) => { - trace.traceAddress[index] = outNumber(address); - }); - } - - Object.keys(trace).forEach((key) => { - switch (key) { - case 'subtraces': - case 'transactionPosition': - case 'blockNumber': - trace[key] = outNumber(trace[key]); - break; - } - }); - } - - return trace; -} - -export function outTraces (traces) { - if (traces) { - return traces.map(outTrace); - } - - return traces; -} - -export function outTraceReplay (trace) { - if (trace) { - Object.keys(trace).forEach((key) => { - switch (key) { - case 'trace': - trace[key] = outTraces(trace[key]); - break; - } - }); - } - - return trace; -} - -export function outVaultMeta (meta) { - if (isString(meta)) { - try { - const obj = JSON.parse(meta); - - return obj; - } catch (error) { - return {}; - } - } - - return meta || {}; -} diff --git a/js/src/api/format/output.spec.js b/js/src/api/format/output.spec.js deleted file mode 100644 index 6ffefaedcc7e5a646546962defab3f1681ea0ce9..0000000000000000000000000000000000000000 --- a/js/src/api/format/output.spec.js +++ /dev/null @@ -1,502 +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 . - -import BigNumber from 'bignumber.js'; - -import { outBlock, outAccountInfo, outAddress, outChainStatus, outDate, outHistogram, outHwAccountInfo, outNodeKind, outNumber, outPeer, outPeers, outReceipt, outRecentDapps, outSyncing, outTransaction, outTrace, outVaultMeta } from './output'; -import { isAddress, isBigNumber, isInstanceOf } from '../../../test/types'; - -describe('api/format/output', () => { - const address = '0x63cf90d3f0410092fc0fca41846f596223979195'; - const checksum = '0x63Cf90D3f0410092FC0fca41846f596223979195'; - - describe('outAccountInfo', () => { - it('returns meta objects parsed', () => { - expect(outAccountInfo( - { '0x63cf90d3f0410092fc0fca41846f596223979195': { - name: 'name', uuid: 'uuid', meta: '{"name":"456"}' } - } - )).to.deep.equal({ - '0x63Cf90D3f0410092FC0fca41846f596223979195': { - name: 'name', uuid: 'uuid', meta: { name: '456' } - } - }); - }); - - it('returns objects without meta & uuid as required', () => { - expect(outAccountInfo( - { '0x63cf90d3f0410092fc0fca41846f596223979195': { name: 'name' } } - )).to.deep.equal({ - '0x63Cf90D3f0410092FC0fca41846f596223979195': { name: 'name' } - }); - }); - }); - - describe('outAddress', () => { - it('retuns the address as checksummed', () => { - expect(outAddress(address)).to.equal(checksum); - }); - - it('retuns the checksum as checksummed', () => { - expect(outAddress(checksum)).to.equal(checksum); - }); - }); - - describe('outBlock', () => { - ['author', 'miner'].forEach((input) => { - it(`formats ${input} address as address`, () => { - const block = {}; - - block[input] = address; - const formatted = outBlock(block)[input]; - - expect(isAddress(formatted)).to.be.true; - expect(formatted).to.equal(checksum); - }); - }); - - ['difficulty', 'gasLimit', 'gasUsed', 'number', 'nonce', 'totalDifficulty'].forEach((input) => { - it(`formats ${input} number as hexnumber`, () => { - const block = {}; - - block[input] = 0x123; - const formatted = outBlock(block)[input]; - - expect(isInstanceOf(formatted, BigNumber)).to.be.true; - expect(formatted.toString(16)).to.equal('123'); - }); - }); - - ['timestamp'].forEach((input) => { - it(`formats ${input} number as Date`, () => { - const block = {}; - - block[input] = 0x57513668; - const formatted = outBlock(block)[input]; - - expect(isInstanceOf(formatted, Date)).to.be.true; - expect(formatted.getTime()).to.equal(1464940136000); - }); - }); - - it('ignores and passes through unknown keys', () => { - expect(outBlock({ someRandom: 'someRandom' })).to.deep.equal({ someRandom: 'someRandom' }); - }); - - it('formats a block with all the info converted', () => { - expect( - outBlock({ - author: address, - miner: address, - difficulty: '0x100', - gasLimit: '0x101', - gasUsed: '0x102', - number: '0x103', - nonce: '0x104', - totalDifficulty: '0x105', - timestamp: '0x57513668', - extraData: 'someExtraStuffInHere' - }) - ).to.deep.equal({ - author: checksum, - miner: checksum, - difficulty: new BigNumber('0x100'), - gasLimit: new BigNumber('0x101'), - gasUsed: new BigNumber('0x102'), - number: new BigNumber('0x103'), - nonce: new BigNumber('0x104'), - totalDifficulty: new BigNumber('0x105'), - timestamp: new Date('2016-06-03T07:48:56.000Z'), - extraData: 'someExtraStuffInHere' - }); - }); - }); - - describe('outChainStatus', () => { - it('formats blockGap values', () => { - const status = { - blockGap: [0x1234, '0x5678'] - }; - - expect(outChainStatus(status)).to.deep.equal({ - blockGap: [new BigNumber(0x1234), new BigNumber(0x5678)] - }); - }); - - it('handles null blockGap values', () => { - const status = { - blockGap: null - }; - - expect(outChainStatus(status)).to.deep.equal(status); - }); - }); - - describe('outDate', () => { - it('converts a second date in unix timestamp', () => { - expect(outDate(0x57513668)).to.deep.equal(new Date('2016-06-03T07:48:56.000Z')); - }); - }); - - describe('outHistogram', () => { - ['bucketBounds', 'counts'].forEach((type) => { - it(`formats ${type} as number arrays`, () => { - expect( - outHistogram({ [type]: [0x123, 0x456, 0x789] }) - ).to.deep.equal({ - [type]: [new BigNumber(0x123), new BigNumber(0x456), new BigNumber(0x789)] - }); - }); - }); - }); - - describe('outHwAccountInfo', () => { - it('returns objects with formatted addresses', () => { - expect(outHwAccountInfo( - { '0x63cf90d3f0410092fc0fca41846f596223979195': { manufacturer: 'mfg', name: 'type' } } - )).to.deep.equal({ - '0x63Cf90D3f0410092FC0fca41846f596223979195': { manufacturer: 'mfg', name: 'type' } - }); - }); - }); - - describe('outNodeKind', () => { - it('formats the input as received', () => { - const kind = { availability: 'personal', capability: 'full' }; - - expect(outNodeKind(kind)).to.deep.equal(kind); - }); - }); - - describe('outNumber', () => { - it('returns a BigNumber equalling the value', () => { - const bn = outNumber('0x123456'); - - expect(isBigNumber(bn)).to.be.true; - expect(bn.eq(0x123456)).to.be.true; - }); - - it('assumes 0 when ivalid input', () => { - expect(outNumber().eq(0)).to.be.true; - }); - }); - - describe('outPeer', () => { - it('converts all internal numbers to BigNumbers', () => { - expect(outPeer({ - caps: ['par/1'], - id: '0x01', - name: 'Parity', - network: { - localAddress: '10.0.0.1', - remoteAddress: '10.0.0.1' - }, - protocols: { - par: { - difficulty: '0x0f', - head: '0x02', - version: 63 - } - } - })).to.deep.equal({ - caps: ['par/1'], - id: '0x01', - name: 'Parity', - network: { - localAddress: '10.0.0.1', - remoteAddress: '10.0.0.1' - }, - protocols: { - par: { - difficulty: new BigNumber(15), - head: '0x02', - version: 63 - } - } - }); - }); - - it('does not output null protocols', () => { - expect(outPeer({ - caps: ['par/1'], - id: '0x01', - name: 'Parity', - network: { - localAddress: '10.0.0.1', - remoteAddress: '10.0.0.1' - }, - protocols: { - les: null - } - })).to.deep.equal({ - caps: ['par/1'], - id: '0x01', - name: 'Parity', - network: { - localAddress: '10.0.0.1', - remoteAddress: '10.0.0.1' - }, - protocols: {} - }); - }); - }); - - describe('outPeers', () => { - it('converts all internal numbers to BigNumbers', () => { - expect(outPeers({ - active: 789, - connected: '456', - max: 0x7b, - peers: [ - { - caps: ['par/1'], - id: '0x01', - name: 'Parity', - network: { - localAddress: '10.0.0.1', - remoteAddress: '10.0.0.1' - }, - protocols: { - par: { - difficulty: '0x0f', - head: '0x02', - version: 63 - }, - les: null - } - } - ] - })).to.deep.equal({ - active: new BigNumber(789), - connected: new BigNumber(456), - max: new BigNumber(123), - peers: [ - { - caps: ['par/1'], - id: '0x01', - name: 'Parity', - network: { - localAddress: '10.0.0.1', - remoteAddress: '10.0.0.1' - }, - protocols: { - par: { - difficulty: new BigNumber(15), - head: '0x02', - version: 63 - } - } - } - ] - }); - }); - }); - - describe('outReceipt', () => { - ['contractAddress'].forEach((input) => { - it(`formats ${input} address as address`, () => { - const block = {}; - - block[input] = address; - const formatted = outReceipt(block)[input]; - - expect(isAddress(formatted)).to.be.true; - expect(formatted).to.equal(checksum); - }); - }); - - ['blockNumber', 'cumulativeGasUsed', 'cumulativeGasUsed', 'gasUsed', 'transactionIndex'].forEach((input) => { - it(`formats ${input} number as hexnumber`, () => { - const block = {}; - - block[input] = 0x123; - const formatted = outReceipt(block)[input]; - - expect(isInstanceOf(formatted, BigNumber)).to.be.true; - expect(formatted.toString(16)).to.equal('123'); - }); - }); - - it('ignores and passes through unknown keys', () => { - expect(outReceipt({ someRandom: 'someRandom' })).to.deep.equal({ someRandom: 'someRandom' }); - }); - - it('formats a receipt with all the info converted', () => { - expect( - outReceipt({ - contractAddress: address, - blockNumber: '0x100', - cumulativeGasUsed: '0x101', - gasUsed: '0x102', - transactionIndex: '0x103', - extraData: 'someExtraStuffInHere' - }) - ).to.deep.equal({ - contractAddress: checksum, - blockNumber: new BigNumber('0x100'), - cumulativeGasUsed: new BigNumber('0x101'), - gasUsed: new BigNumber('0x102'), - transactionIndex: new BigNumber('0x103'), - extraData: 'someExtraStuffInHere' - }); - }); - }); - - describe('outRecentDapps', () => { - it('formats the URLs with timestamps', () => { - expect(outRecentDapps({ testing: 0x57513668 })).to.deep.equal({ - testing: new Date('2016-06-03T07:48:56.000Z') - }); - }); - }); - - describe('outSyncing', () => { - ['currentBlock', 'highestBlock', 'startingBlock', 'warpChunksAmount', 'warpChunksProcessed'].forEach((input) => { - it(`formats ${input} numbers as a number`, () => { - expect(outSyncing({ [input]: '0x123' })).to.deep.equal({ - [input]: new BigNumber('0x123') - }); - }); - }); - - it('formats blockGap properly', () => { - expect(outSyncing({ blockGap: [0x123, 0x456] })).to.deep.equal({ - blockGap: [new BigNumber(0x123), new BigNumber(0x456)] - }); - }); - }); - - describe('outTransaction', () => { - ['from', 'to'].forEach((input) => { - it(`formats ${input} address as address`, () => { - const block = {}; - - block[input] = address; - const formatted = outTransaction(block)[input]; - - expect(isAddress(formatted)).to.be.true; - expect(formatted).to.equal(checksum); - }); - }); - - ['blockNumber', 'gasPrice', 'gas', 'nonce', 'transactionIndex', 'value'].forEach((input) => { - it(`formats ${input} number as hexnumber`, () => { - const block = {}; - - block[input] = 0x123; - const formatted = outTransaction(block)[input]; - - expect(isInstanceOf(formatted, BigNumber)).to.be.true; - expect(formatted.toString(16)).to.equal('123'); - }); - }); - - it('passes condition as null when null', () => { - expect(outTransaction({ condition: null })).to.deep.equal({ condition: null }); - }); - - it('ignores and passes through unknown keys', () => { - expect(outTransaction({ someRandom: 'someRandom' })).to.deep.equal({ someRandom: 'someRandom' }); - }); - - it('formats a transaction with all the info converted', () => { - expect( - outTransaction({ - from: address, - to: address, - blockNumber: '0x100', - gasPrice: '0x101', - gas: '0x102', - nonce: '0x103', - transactionIndex: '0x104', - value: '0x105', - extraData: 'someExtraStuffInHere' - }) - ).to.deep.equal({ - from: checksum, - to: checksum, - blockNumber: new BigNumber('0x100'), - gasPrice: new BigNumber('0x101'), - gas: new BigNumber('0x102'), - nonce: new BigNumber('0x103'), - transactionIndex: new BigNumber('0x104'), - value: new BigNumber('0x105'), - extraData: 'someExtraStuffInHere' - }); - }); - }); - - describe('outTrace', () => { - it('ignores and passes through unknown keys', () => { - expect(outTrace({ someRandom: 'someRandom' })).to.deep.equal({ someRandom: 'someRandom' }); - }); - - it('formats a trace with all the info converted', () => { - const formatted = outTrace({ - type: 'call', - action: { - from: address, - to: address, - value: '0x06', - gas: '0x07', - input: '0x1234', - callType: 'call' - }, - result: { - gasUsed: '0x08', - output: '0x5678' - }, - traceAddress: [ '0x2' ], - subtraces: 3, - transactionPosition: '0xb', - transactionHash: '0x000000000000000000000000000000000000000000000000000000000000000c', - blockNumber: '0x0d', - blockHash: '0x000000000000000000000000000000000000000000000000000000000000000e' - }); - - expect(isBigNumber(formatted.action.gas)).to.be.true; - expect(formatted.action.gas.toNumber()).to.equal(7); - expect(isBigNumber(formatted.action.value)).to.be.true; - expect(formatted.action.value.toNumber()).to.equal(6); - - expect(formatted.action.from).to.equal(checksum); - expect(formatted.action.to).to.equal(checksum); - - expect(isBigNumber(formatted.blockNumber)).to.be.true; - expect(formatted.blockNumber.toNumber()).to.equal(13); - expect(isBigNumber(formatted.transactionPosition)).to.be.true; - expect(formatted.transactionPosition.toNumber()).to.equal(11); - }); - }); - - describe('outVaultMeta', () => { - it('returns an exmpt object on null', () => { - expect(outVaultMeta(null)).to.deep.equal({}); - }); - - it('returns the original value if not string', () => { - expect(outVaultMeta({ test: 123 })).to.deep.equal({ test: 123 }); - }); - - it('returns an object from JSON string', () => { - expect(outVaultMeta('{"test":123}')).to.deep.equal({ test: 123 }); - }); - - it('returns an empty object on invalid JSON', () => { - expect(outVaultMeta('{"test"}')).to.deep.equal({}); - }); - }); -}); diff --git a/js/src/api/index.js b/js/src/api/index.js deleted file mode 100644 index 978d98fecaf151b8755a8d9869287774f7a63200..0000000000000000000000000000000000000000 --- a/js/src/api/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './api'; diff --git a/js/src/api/local/accounts/account.js b/js/src/api/local/accounts/account.js deleted file mode 100644 index 224a05cd9f81f1e399d727615298f4840c68e822..0000000000000000000000000000000000000000 --- a/js/src/api/local/accounts/account.js +++ /dev/null @@ -1,116 +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 . - -import { createKeyObject, decryptPrivateKey } from '../ethkey'; - -export default class Account { - constructor (persist, data = {}) { - const { - keyObject = null, - meta = {}, - name = '' - } = data; - - this._persist = persist; - this._keyObject = keyObject; - this._name = name; - this._meta = meta; - } - - isValidPassword (password) { - if (!this._keyObject) { - return false; - } - - return decryptPrivateKey(this._keyObject, password) - .then((privateKey) => { - if (!privateKey) { - return false; - } - - return true; - }); - } - - export () { - const exported = Object.assign({}, this._keyObject); - - exported.meta = JSON.stringify(this._meta); - exported.name = this._name; - - return exported; - } - - get address () { - return `0x${this._keyObject.address.toLowerCase()}`; - } - - get name () { - return this._name; - } - - set name (name) { - this._name = name; - - this._persist(); - } - - get meta () { - return JSON.stringify(this._meta); - } - - set meta (meta) { - this._meta = JSON.parse(meta); - - this._persist(); - } - - get uuid () { - if (!this._keyObject) { - return null; - } - - return this._keyObject.id; - } - - decryptPrivateKey (password) { - return decryptPrivateKey(this._keyObject, password); - } - - changePassword (key, password) { - return createKeyObject(key, password).then((keyObject) => { - this._keyObject = keyObject; - - this._persist(); - }); - } - - static fromPrivateKey (persist, key, password) { - return createKeyObject(key, password).then((keyObject) => { - const account = new Account(persist, { keyObject }); - - return account; - }); - } - - toJSON () { - return { - keyObject: this._keyObject, - name: this._name, - meta: this._meta - }; - } -} diff --git a/js/src/api/local/accounts/accounts.js b/js/src/api/local/accounts/accounts.js deleted file mode 100644 index d11ea2badb65c571dea36bb45bda8b4196b5c787..0000000000000000000000000000000000000000 --- a/js/src/api/local/accounts/accounts.js +++ /dev/null @@ -1,229 +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 . - -import Account from './account'; -import localStore from 'store'; -import { debounce } from 'lodash'; -import { decryptPrivateKey } from '../ethkey'; - -const NULL_ADDRESS = '0x0000000000000000000000000000000000000000'; -const LS_STORE_KEY = '_parity::localAccounts'; - -export default class Accounts { - persist = debounce(() => { - this._lastState = JSON.stringify(this); - - localStore.set(LS_STORE_KEY, this); - }, 100); - - constructor (data = localStore.get(LS_STORE_KEY) || {}) { - this._lastState = JSON.stringify(data); - - window.addEventListener('storage', ({ key, newValue }) => { - if (key !== LS_STORE_KEY) { - return; - } - - if (newValue !== this._lastState) { - console.log('Data changed in a second tab, syncing state'); - - this.restore(JSON.parse(newValue)); - } - }); - - this.restore(data); - } - - restore (data) { - const { - last = NULL_ADDRESS, - dappsDefault = NULL_ADDRESS, - store = {} - } = data; - - this._last = last; - this._dappsDefaultAddress = dappsDefault; - this._store = {}; - - if (Array.isArray(store)) { - // Recover older version that stored accounts as an array - store.forEach((data) => { - const account = new Account(this.persist, data); - - this._store[account.address] = account; - }); - } else { - Object.keys(store).forEach((key) => { - this._store[key] = new Account(this.persist, store[key]); - }); - } - } - - _addAccount = (account) => { - const { address } = account; - - if (address in this._store && this._store[address].uuid) { - throw new Error(`Account ${address} already exists!`); - } - - this._store[address] = account; - this.lastAddress = address; - - this.persist(); - - return account.address; - } - - create (secret, password) { - const privateKey = Buffer.from(secret.slice(2), 'hex'); - - return Account - .fromPrivateKey(this.persist, privateKey, password) - .then(this._addAccount); - } - - restoreFromWallet (wallet, password) { - return decryptPrivateKey(wallet, password) - .then((privateKey) => { - if (!privateKey) { - throw new Error('Invalid password'); - } - - return Account.fromPrivateKey(this.persist, privateKey, password); - }) - .then(this._addAccount); - } - - set lastAddress (value) { - this._last = value.toLowerCase(); - } - - get lastAddress () { - return this._last; - } - - get dappsDefaultAddress () { - if (this._dappsDefaultAddress === NULL_ADDRESS) { - return this._last; - } - - if (this._dappsDefaultAddress in this._store) { - return this._dappsDefaultAddress; - } - - return NULL_ADDRESS; - } - - set dappsDefaultAddress (value) { - this._dappsDefaultAddress = value.toLowerCase(); - - this.persist(); - } - - get (address) { - address = address.toLowerCase(); - - const account = this._store[address]; - - if (!account) { - throw new Error(`Account not found: ${address}`); - } - - this.lastAddress = address; - - return account; - } - - getLazyCreate (address) { - address = address.toLowerCase(); - - this.lastAddress = address; - - if (!(address in this._store)) { - this._store[address] = new Account(this.persist); - } - - return this._store[address]; - } - - remove (address, password) { - address = address.toLowerCase(); - - const account = this.get(address); - - if (!account) { - return false; - } - - if (!account.uuid) { - this.removeUnsafe(address); - - return true; - } - - return account - .isValidPassword(password) - .then((isValid) => { - if (!isValid) { - return false; - } - - if (address === this.lastAddress) { - this.lastAddress = NULL_ADDRESS; - } - - this.removeUnsafe(address); - - return true; - }); - } - - removeUnsafe (address) { - address = address.toLowerCase(); - - delete this._store[address]; - - this.persist(); - } - - allAddresses () { - return Object.keys(this._store); - } - - accountAddresses () { - return Object - .keys(this._store) - .filter((address) => this._store[address].uuid); - } - - map (mapper) { - const result = {}; - - Object.keys(this._store).forEach((key) => { - result[key] = mapper(this._store[key]); - }); - - return result; - } - - toJSON () { - return { - last: this._last, - dappsDefault: this._dappsDefaultAddress, - store: this._store - }; - } -} diff --git a/js/src/api/local/accounts/index.js b/js/src/api/local/accounts/index.js deleted file mode 100644 index 800cf95f6a02f7c5eb978fadf7cdc2932d40ec37..0000000000000000000000000000000000000000 --- a/js/src/api/local/accounts/index.js +++ /dev/null @@ -1,21 +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 . - -import Accounts from './accounts'; - -const accounts = new Accounts(); - -export default accounts; diff --git a/js/src/api/local/ethkey/ethkey.js b/js/src/api/local/ethkey/ethkey.js deleted file mode 100644 index f8395b007abc3e0be2daccfff388baf07c6c1218..0000000000000000000000000000000000000000 --- a/js/src/api/local/ethkey/ethkey.js +++ /dev/null @@ -1,147 +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 . - -/* global WebAssembly */ - -import wasmBuffer from './ethkey.wasm.js'; - -const NOOP = () => {}; - -// WASM memory setup -const WASM_PAGE_SIZE = 65536; -const STATIC_BASE = 1024; -const STATICTOP = STATIC_BASE + WASM_PAGE_SIZE * 2; -const STACK_BASE = align(STATICTOP + 16); -const STACKTOP = STACK_BASE; -const TOTAL_STACK = 5 * 1024 * 1024; -const TOTAL_MEMORY = 16777216; -const STACK_MAX = STACK_BASE + TOTAL_STACK; -const DYNAMIC_BASE = STACK_MAX + 64; -const DYNAMICTOP_PTR = STACK_MAX; - -function mockWebAssembly () { - function throwWasmError () { - throw new Error('Missing WebAssembly support'); - } - - // Simple mock replacement - return { - Memory: class { buffer = new ArrayBuffer(2048) }, - Table: class {}, - Module: class {}, - Instance: class { - exports = { - '_input_ptr': () => 0, - '_secret_ptr': () => 0, - '_public_ptr': () => 0, - '_address_ptr': () => 0, - '_ecpointg': NOOP, - '_brain': throwWasmError, - '_verify_secret': throwWasmError - } - } - }; -} - -const { Memory, Table, Module, Instance } = typeof WebAssembly !== 'undefined' ? WebAssembly : mockWebAssembly(); - -const wasmMemory = new Memory({ - initial: TOTAL_MEMORY / WASM_PAGE_SIZE, - maximum: TOTAL_MEMORY / WASM_PAGE_SIZE -}); - -const wasmTable = new Table({ - initial: 8, - maximum: 8, - element: 'anyfunc' -}); - -// TypedArray views into the memory -const wasmMemoryU8 = new Uint8Array(wasmMemory.buffer); -const wasmMemoryU32 = new Uint32Array(wasmMemory.buffer); - -// Keep DYNAMIC_BASE in memory -wasmMemoryU32[DYNAMICTOP_PTR >> 2] = align(DYNAMIC_BASE); - -function align (mem) { - const ALIGN_SIZE = 16; - - return (Math.ceil(mem / ALIGN_SIZE) * ALIGN_SIZE) | 0; -} - -export function slice (ptr, len) { - return wasmMemoryU8.subarray(ptr, ptr + len); -} - -// Required by emscripten -function abort (what) { - throw new Error(what || 'WASM abort'); -} - -// Required by emscripten -function abortOnCannotGrowMemory () { - abort(`Cannot enlarge memory arrays.`); -} - -// Required by emscripten -function enlargeMemory () { - abortOnCannotGrowMemory(); -} - -// Required by emscripten -function getTotalMemory () { - return TOTAL_MEMORY; -} - -// Required by emscripten - used to perform memcpy on large data -function memcpy (dest, src, len) { - wasmMemoryU8.set(wasmMemoryU8.subarray(src, src + len), dest); - - return dest; -} - -// Synchronously compile WASM from the buffer -const module = new Module(wasmBuffer); - -// Instantiated WASM module -const instance = new Instance(module, { - global: {}, - env: { - DYNAMICTOP_PTR, - STACKTOP, - STACK_MAX, - abort, - enlargeMemory, - getTotalMemory, - abortOnCannotGrowMemory, - ___lock: NOOP, - ___syscall6: () => 0, - ___setErrNo: (no) => no, - _abort: abort, - ___syscall140: () => 0, - _emscripten_memcpy_big: memcpy, - ___syscall54: () => 0, - ___unlock: NOOP, - _llvm_trap: abort, - ___syscall146: () => 0, - 'memory': wasmMemory, - 'table': wasmTable, - tableBase: 0, - memoryBase: STATIC_BASE - } -}); - -export const extern = instance.exports; diff --git a/js/src/api/local/ethkey/ethkey.wasm.js b/js/src/api/local/ethkey/ethkey.wasm.js deleted file mode 100644 index d426f0e0c46e5a947183538170fb44a56e01fb1b..0000000000000000000000000000000000000000 --- a/js/src/api/local/ethkey/ethkey.wasm.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = new Buffer('AGFzbQEAAAABOgpgA39/fwF/YAF/AX9gAn9/AX9gAX8AYAABf2AAAGACf38AYAR/f39/AGADf39/AGAGf39/f39/AX8CyQELA2VudghTVEFDS1RPUAN/AANlbnYFYWJvcnQAAwNlbnYLX19fc3lzY2FsbDYAAgNlbnYNX19fc3lzY2FsbDE0MAACA2VudhZfZW1zY3JpcHRlbl9tZW1jcHlfYmlnAAADZW52DF9fX3N5c2NhbGw1NAACA2VudgpfbGx2bV90cmFwAAUDZW52DV9fX3N5c2NhbGwxNDYAAgNlbnYGbWVtb3J5AgGAAoACA2VudgV0YWJsZQFwAQgIA2Vudgl0YWJsZUJhc2UDfwADOjkEBAQEBAQDBwMICAgIAwYGBgIIAwMDBgMDCAYGBgMCBwYIAgICBgkDBgEAAAEEBAQAAQAAAQABAAIGBgF/ASMACwdfBw5fdmVyaWZ5X3NlY3JldAAMC19wdWJsaWNfcHRyAAoLX3NlY3JldF9wdHIACQpfaW5wdXRfcHRyAAgJX2VjcG9pbnRnAAcGX2JyYWluAA0MX2FkZHJlc3NfcHRyAAsJDgEAIwELCD0wPjEyNz8rCpClAzlJAQJ/An8jAiEAIwJB0JgBaiQCQagZKAIAQQFGBEAgACQCQawZDwsgACIBEB9BqBlBATYCAEGsGSABQdCYARA8GiAAJAJBrBkLCwYAQbi2AQsGAEG4vgELBgBB2L4BCwYAQZi/AQsKAEG4vgFBIBAlC74HAQt/AkAjAiEIIwJBoJwBaiQCIABBgAhLBEAgAEGACBAnCyAIQaACaiEFQagZKAIAQQFHBEAgBRAfQagZQQE2AgBBrBkgBUHQmAEQPBoLIAghCSAIQcgAaiIEEBQgCEH4mwFqIgFCADcAACABQgA3AAggAUIANwAQIAFCADcAGCAEQbi2ASAAEBAgBSAEQdgBEDwaIAUgAUEgEBIgCEHwmgFqIgMgASkAADcAACADIAEpAAg3AAggAyABKQAQNwAQIAMgASkAGDcAGCAIQZCbAWoiBkEBaiEHIAhB2JsBaiICQQxqIQpBACEAA0AgBBAUIAFCADcAACABQgA3AAggAUIANwAQIAFCADcAGCAEIANBIBAQIAUgBEHYARA8GiAFIAFBIBASIAIgASkAADcAACACIAEpAAg3AAggAiABKQAQNwAQIAIgASkAGDcAGCADIAIpAAA3AAAgAyACKQAINwAIIAMgAikAEDcAECADIAIpABg3ABggAEEBaiELIABBgYABRwRAIAshAAwBCwsgCUEBaiEAA0ACQCAJQawZIANBIBAmIAksAABBAUYEQCAGIAApAAA3AAAgBiAAKQAINwAIIAYgACkAEDcAECAGIAApABg3ABggBiAAKQAgNwAgIAYgACkAKDcAKCAGIAApADA3ADAgBiAAKQA4NwA4IAYgACwAQDoAQCAEEBQgAUIANwAAIAFCADcACCABQgA3ABAgAUIANwAYIAQgB0HAABAQIAUgBEHYARA8GiAFIAFBIBASIAIgASkAADcAACACIAEpAAg3AAggAiABKQAQNwAQIAIgASkAGDcAGEGYvwEgCikAADcAAEGgvwEgCikACDcAAEGovwEgCigAEDYAAEGYvwEsAABFDQELIAQQFCABQgA3AAAgAUIANwAIIAFCADcAECABQgA3ABggBCADQSAQECAFIARB2AEQPBogBSABQSAQEiACIAEpAAA3AAAgAiABKQAINwAIIAIgASkAEDcAECACIAEpABg3ABggAyACKQAANwAAIAMgAikACDcACCADIAIpABA3ABAgAyACKQAYNwAYDAELC0HYvgEgBykAADcAAEHgvgEgBykACDcAAEHovgEgBykAEDcAAEHwvgEgBykAGDcAAEH4vgEgBykAIDcAAEGAvwEgBykAKDcAAEGIvwEgBykAMDcAAEGQvwEgBykAODcAAEG4vgEgAykAADcAAEHAvgEgAykACDcAAEHIvgEgAykAEDcAAEHQvgEgAykAGDcAACAIJAILCwQAEAUL1wsCGX8tfgJAIAApAwAhJCAAQShqIgIpAwAhJSAAQdAAaiIDKQMAITAgAEH4AGoiBCkDACE+IABBoAFqIgUpAwAhJiAAQQhqIgYpAwAhMSAAQTBqIgcpAwAhMiAAQdgAaiIIKQMAIScgAEGAAWoiCSkDACEgIABBqAFqIgopAwAhPyAAQRBqIgspAwAhMyAAQThqIgwpAwAhHSAAQeAAaiINKQMAISEgAEGIAWoiDikDACE0IABBsAFqIg8pAwAhHiAAQRhqIhApAwAhNSAAQcAAaiIRKQMAISggAEHoAGoiEikDACE2IABBkAFqIhMpAwAhGyAAQbgBaiIUKQMAISIgAEEgaiIVKQMAITcgAEHIAGoiFikDACE4IABB8ABqIhcpAwAhHCAAQZgBaiIYKQMAISMgAEHAAWoiGSkDACEaQQAhAQNAICQgGiAjIBwgOCA3hYWFhSIphSA/ICAgJyAyIDGFhYWFIipCAYYgKkI/iIQiOYUhQCAxICYgPiAwICUgJIWFhYUiK4UgHiA0ICEgHSAzhYWFhSIsQgGGICxCP4iEIjqFIUEgMyAqhSAiIBsgNiAoIDWFhYWFIi1CAYYgLUI/iIQiO4UhQiA1ICyFIClCAYYgKUI/iIQiPIUhLiA3IC2FICtCAYYgK0I/iIQiPYUhQyAbICyFIDyFIhtCFYYgG0IriIQiHyAhICqFIDuFIhtCK4YgG0IViIQiREJ/hYMgMiArhSA6hSIbQiyGIBtCFIiEIiSFITEgGiAthSA9hSIaQg6GIBpCMoiEIhogH0J/hYMgRIUhMyBAIBpCf4WDIB+FITUgJCBAQn+FgyAahSE3IDAgKYUgOYUiGkIDhiAaQj2IhCIvIDggLYUgPYUiGkIUhiAaQiyIhCIhQn+FgyAuQhyGIC5CJIiEIh+FIUUgICArhSA6hSIaQi2GIBpCE4iEIhsgL0J/hYMgIYUhMiAeICqFIDuFIhpCPYYgGkIDiIQiGiAbQn+FgyAvhSFGIB8gGkJ/hYMgG4UhLiAhIB9Cf4WDIBqFITggNiAshSA8hSIaQhmGIBpCJ4iEIiAgHSAqhSA7hSIaQgaGIBpCOoiEIhtCf4WDIEFCAYYgQUI/iIQiHYUhMCAjIC2FID2FIhpCCIYgGkI4iIQiHiAgQn+FgyAbhSEvICYgKYUgOYUiGkIShiAaQi6IhCIaIB5Cf4WDICCFISEgHSAaQn+FgyAehSE2IBsgHUJ/hYMgGoUhHyAnICuFIDqFIhpCCoYgGkI2iIQiGyAlICmFIDmFIhpCJIYgGkIciIQiI0J/hYMgQ0IbhiBDQiWIhCIdhSEnIDQgKoUgO4UiGkIPhiAaQjGIhCIeIBtCf4WDICOFISAgIiAshSA8hSIaQjiGIBpCCIiEIhogHkJ/hYMgG4UhNCAdIBpCf4WDIB6FIRsgIyAdQn+FgyAahSEjIBwgLYUgPYUiHEInhiAcQhmIhCIiICggLIUgPIUiHEI3hiAcQgmIhCIlQn+FgyBCQj6GIEJCAoiEIiaFIR0gPiAphSA5hSIcQimGIBxCF4iEIhogIkJ/hYMgJYUhHiA/ICuFIDqFIhxCAoYgHEI+iIQiHCAaQn+FgyAihSEoICYgHEJ/hYMgGoUhIiAlICZCf4WDIByFIRogRCAkQn+FgyBAhSABQQN0QYAIaikDAIUhHCABQQFqIgFBGEcEQCAcISQgRSElICchPiAdISYgLyEnIB4hPyBGIR0gKCEeIC4hKCAfIRwMAQsLIAAgHDcDACACIEU3AwAgAyAwNwMAIAQgJzcDACAFIB03AwAgBiAxNwMAIAcgMjcDACAIIC83AwAgCSAgNwMAIAogHjcDACALIDM3AwAgDCBGNwMAIA0gITcDACAOIDQ3AwAgDyAoNwMAIBAgNTcDACARIC43AwAgEiA2NwMAIBMgGzcDACAUICI3AwAgFSA3NwMAIBYgODcDACAXIB83AwAgGCAjNwMAIBkgGjcDAAsLCgAgACABIAIQEQu9AwEPfwJAIABByAFqIgooAgAiA0HIAUsEQCADQcgBEC8LIAAgA2ohC0HIASADayEEAkAgAEHMAWoiECgCACADayIFIAJLBEAgBCEMIAshDSADIQ9BACEIIAIhBgUgBCEJQQAhByACIQ4gBSEEAkACQAJAA0AgBCAJSw0BIAcgAksNAiABIAdqIREgBCACIAdrIgNNBH8gBAUgAwsiCQRAIAshA0EAIQUDQCADIAMsAAAgESAFaiwAAHM6AAAgCyAFQQFqIgVqIQMgBSAJSQ0ACwsgABAPIAQgB2ohAyAQKAIAIQUgCkEANgIAIA4gBGsiDiAFSQRAQcgBIQwgACENQQAhDyADIQggDiEGDAYFQcgBIQkgACELIAMhByAFIQQMAQsACwALIAQgCRAnDAELIAcgAhAvCwsLIAYgDEsEQCAGIAwQJwsgCCACSwRAIAggAhAvCyAGIAIgCGsiAE0EfyAGBSAACyIEBEAgDSEAQQAhAgUgCiAPIAZqNgIADwsgASAIaiEBA0AgACAALAAAIAEgAmosAABzOgAAIA0gAkEBaiICaiEAIAIgBEkNAAsgCiAKKAIAIAZqNgIACwuSAQEDfwJAIwIhBCMCQeABaiQCIAQiAyAAQdgBEDwaIAMoAsgBIgBByAFPBEBB3AogAEHIARAoCyADKALMASEFIAMgAGoiACAALAAAIAMsANABczoAACAFQX9qIgBByAFJBEAgAyAAaiIAIAAsAABBgH9zOgAAIAMQDyADIAEgAhATIAQkAgVB0AogAEHIARAoCwsLygEBB38CQAJAIAAoAswBIgNByAFLBEAgAyACSwRAIAEhCCACIQYFIANByAEQJwsFIAIhBEEAIQUCQAJAAkACQANAIAEgBWohCSACIAVrIQcgBCADSQ0DIAMgB0sNAiAJIAAgAxA8GiAAEA8gBCADayEEIAUgA2oiBSACTQ0ADAELAAsgBSACEC8MAgsgAyAHECcMAQsgBCAHTQRAIAkhCCAEIQYMAwsgBCAHECcLCwsgBkHIAUsEQCAGQcgBECcFIAggACAGEDwaCwsLIAACQCAAQQBBzAEQOhogAEGIATYCzAEgAEEBOgDQAQsLgQUCCH8DfgJAIwIhBSMCQdAAaiQCIAUhAiAAQcQAaiIDLAAAIgcgASwAREcEQCAHBEAgA0EAOgAAIAAgARAWIAMgAywAAEEBczoAAAUgAiABKQIANwIAIAIgASkCCDcCCCACIAEpAhA3AhAgAiABKQIYNwIYIAIgASkCIDcCICACIAEpAig3AiggAiABKQIwNwIwIAIgASkCODcCOCACIAEpAkA3AkAgAkEAOgBEIAAgAhAWCyAAKAIABEAgBSQCDwsgACgCBARAIAUkAg8LIANBADoAACAFJAIPCwJAIAEoAgAiAyAAKAIAIgJLBEACQAJAA0AgAkEQTw0CIABBBGogAkECdGpBADYCACACQQFqIgIgA0kNAAwBCwALIAAgAzYCAEIAIQtBACEEDAILQcgLIAJBEBAoBSADBEBCACELQQAhBAUgBSQCDwsLCwJAAkADQCAEQRBPDQEgAEEEaiAEQQJ0aiICKAIArSALfCABQQRqIARBAnRqKAIArXwhCiACIAo+AgAgCkIgiCEKIARBAWoiBiADSQRAIAohCyAGIQQMAQsLDAELQdQLIARBEBAoCyAKQgBSIgQgBiAAKAIAIgFJcQRAIAYhAQJAAkADQCABQRBPDQEgAEEEaiABQQJ0aiICKAIArSAKfCEKIAIgCj4CACAKQiCIIgxCAFIiCCABQQFqIgEgACgCACIJSXEEQCAMIQoMAQsLDAELQeALIAFBEBAoCyAMpyECIAgEQCAJIQEFIAUkAg8LBSAKpyECIARFBEAgBSQCDwsLIAFBEE8EQEHsCyABQRAQKAsgAEEEaiABQQJ0aiACNgIAIAAgACgCAEEBajYCACAFJAILC+YHAg1/An4CQCMCIQUjAkHQAGokAiAFIQIgAEHEAGoiBiwAACIDIAEsAERHBEAgAwRAIAZBADoAACAAIAEQFSAGQQE6AAAFIAIgASkCADcCACACIAEpAgg3AgggAiABKQIQNwIQIAIgASkCGDcCGCACIAEpAiA3AiAgAiABKQIoNwIoIAIgASkCMDcCMCACIAEpAjg3AjggAiABKQJANwJAIAJBADoARCAAIAIQFQsgACgCAARAIAUkAg8LIAAoAgQEQCAFJAIPCyAGQQA6AAAgBSQCDwsgACgCACIHQRBLBEAgB0EQECcLIAEoAgAiCEEQSwRAIAhBEBAnCyAAQQRqIQsCQAJAIAcgCEYEQCAAIAFHBEAgCyABQQRqIAdBAnQQOQRAIAchAwJAAkACQANAIANBf2ohCSADRQ0IIAlBEE8NASABQQRqIAlBAnRqKAIAIgMgAEEEaiAJQQJ0aigCACIORw0CIAkhAwwACwALQbwLIAlBEBAoDAELIAMgDkkNBQwECwsLIABBATYCACAGQQA6AAAgC0EANgIAIAUkAg8FIAggB08NAQsMAQsgAiAAKQIANwIAIAIgACkCCDcCCCACIAApAhA3AhAgAiAAKQIYNwIYIAIgACkCIDcCICACIAApAig3AiggAiAAKQIwNwIwIAIgACkCODcCOCACIAApAkA3AkAgACABKQIANwIAIAAgASkCCDcCCCAAIAEpAhA3AhAgACABKQIYNwIYIAAgASkCIDcCICAAIAEpAig3AiggACABKQIwNwIwIAAgASkCODcCOCAAIAEpAkA3AkAgACACEBYgBkEBOgAAIAUkAg8LAkAgCAR/QgAhD0EAIQMCQAJAA0AgA0EQTw0BIABBBGogA0ECdGoiBCgCAK0gAUEEaiADQQJ0aigCAK19IA98Ig9CIIchECAEIA8+AgAgA0EBaiIEIAhJBEAgECEPIAQhAwwBCwsMAQtB+AsgA0EQECgLAkAgEEIAUiAEIAAoAgAiAUlxBEADQCAEQRBJBEAgAEEEaiAEQQJ0aiIBKAIArSAQfCIPQiCHIRAgASAPPgIAIBBCAFIgBEEBaiIEIAAoAgAiAUlxDQEgASEMIAQhCgwDCwtBhAwgBEEQECgFIAEhDCAEIQoLCyAKIAxLBH8gACAKNgIAIAoFIAwLBSAHCyIBQQFLBEACQAJAA0AgAUF/aiIBQRBPDQIgAEEEaiABQQJ0aigCAA0BIAAgATYCACABQQFLDQAgASENDAQLAAsgBSQCDwtBsAsgAUEQECgFIAEhDQsLIA0gCygCAHIEQCAFJAIPCyAGQQA6AAAgBSQCCwv1GwIofwN+AkAjAiEgIwJB0ABqJAIgACgCACIKQQhGIAEoAgAiA0EIRnEEQCAAQQRqIg0oAgAiDkH//wNxIQQgAEEIaiIPKAIAIhBB//8DcSEIIABBDGoiESgCACISQf//A3EhBSAAQRBqIhMoAgAiFEH//wNxIQkgAEEUaiIVKAIAIhZB//8DcSEGIABBGGoiFygCACIYQf//A3EhAiAAQRxqIhkoAgAiGkH//wNxIQcgAEEgaiIbKAIAIiFB//8DcSELIAEoAgQiIkH//wNxIQMgASgCCCIjQf//A3EhCiABKAIMIiRB//8DcSEMIAEoAhAiJUH//wNxIRwgASgCFCImQf//A3EhHSABKAIYIidB//8DcSEeIAEoAhwiKEH//wNxIR8gASgCICIpQf//A3EhASANICJBEHYiDSAEbK0gAyAOQRB2Ig5srXwiKkIQhkKAgPz/D4MgAyAEbK18Iis+AgAgDyANIA5srSADIAhsrXwgCiAEbK18ICpCEIh8ICtCIIh8IA0gCGytIAMgEEEQdiIPbK18ICNBEHYiECAEbK18IAogDmytfCIqQhCGQoCA/P8Pg3wiKz4CACARIA0gD2ytIAMgBWytfCAKIAhsrXwgECAObK18IAwgBGytfCAqQhCIfCANIAVsrSADIBJBEHYiEWytfCAQIAhsrXwgCiAPbK18ICRBEHYiEiAEbK18IAwgDmytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CACATIA0gEWytIAMgCWytfCAKIAVsrXwgECAPbK18IAwgCGytfCASIA5srXwgHCAEbK18ICpCEIh8IA0gCWytIAMgFEEQdiITbK18IBAgBWytfCAKIBFsrXwgEiAIbK18IAwgD2ytfCAlQRB2IhQgBGytfCAcIA5srXwiKkIQhkKAgPz/D4N8ICtCIIh8Iis+AgAgFSANIBNsrSADIAZsrXwgCiAJbK18IBAgEWytfCAMIAVsrXwgEiAPbK18IBwgCGytfCAUIA5srXwgHSAEbK18ICpCEIh8IA0gBmytIAMgFkEQdiIVbK18IBAgCWytfCAKIBNsrXwgEiAFbK18IAwgEWytfCAUIAhsrXwgHCAPbK18ICZBEHYiFiAEbK18IB0gDmytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CACAXIA0gFWytIAMgAmytfCAKIAZsrXwgECATbK18IAwgCWytfCASIBFsrXwgHCAFbK18IBQgD2ytfCAdIAhsrXwgFiAObK18IB4gBGytfCAqQhCIfCANIAJsrSADIBhBEHYiF2ytfCAQIAZsrXwgCiAVbK18IBIgCWytfCAMIBNsrXwgFCAFbK18IBwgEWytfCAWIAhsrXwgHSAPbK18ICdBEHYiGCAEbK18IB4gDmytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CACAZIA0gF2ytIAMgB2ytfCAKIAJsrXwgECAVbK18IAwgBmytfCASIBNsrXwgHCAJbK18IBQgEWytfCAdIAVsrXwgFiAPbK18IB4gCGytfCAYIA5srXwgHyAEbK18ICpCEIh8IA0gB2ytIAMgGkEQdiIZbK18IBAgAmytfCAKIBdsrXwgEiAGbK18IAwgFWytfCAUIAlsrXwgHCATbK18IBYgBWytfCAdIBFsrXwgGCAIbK18IB4gD2ytfCAoQRB2IhogBGytfCAfIA5srXwiKkIQhkKAgPz/D4N8ICtCIIh8Iis+AgAgGyANIBlsrSADIAtsrXwgCiAHbK18IBAgF2ytfCAMIAJsrXwgEiAVbK18IBwgBmytfCAUIBNsrXwgHSAJbK18IBYgEWytfCAeIAVsrXwgGCAPbK18IB8gCGytfCAaIA5srXwgASAEbK18ICpCEIh8IA0gC2ytIAMgIUEQdiIDbK18IBAgB2ytfCAKIBlsrXwgEiACbK18IAwgF2ytfCAUIAZsrXwgHCAVbK18IBYgCWytfCAdIBNsrXwgGCAFbK18IB4gEWytfCAaIAhsrXwgHyAPbK18IClBEHYiGyAEbK18IAEgDmytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CACAAIAogC2ytIA0gA2ytfCAQIBlsrXwgDCAHbK18IBIgF2ytfCAcIAJsrXwgFCAVbK18IB0gBmytfCAWIBNsrXwgHiAJbK18IBggEWytfCAfIAVsrXwgGiAPbK18IAEgCGytfCAbIA5srXwgKkIQiHwgECALbK0gCiADbK18IBIgB2ytfCAMIBlsrXwgFCACbK18IBwgF2ytfCAWIAZsrXwgHSAVbK18IBggCWytfCAeIBNsrXwgGiAFbK18IB8gEWytfCAbIAhsrXwgASAPbK18IipCEIZCgID8/w+DfCArQiCIfCIrPgIkIAAgDCALbK0gECADbK18IBIgGWytfCAcIAdsrXwgFCAXbK18IB0gAmytfCAWIBVsrXwgHiAGbK18IBggE2ytfCAfIAlsrXwgGiARbK18IAEgBWytfCAbIA9srXwgKkIQiHwgEiALbK0gDCADbK18IBQgB2ytfCAcIBlsrXwgFiACbK18IB0gF2ytfCAYIAZsrXwgHiAVbK18IBogCWytfCAfIBNsrXwgGyAFbK18IAEgEWytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CKCAAIBwgC2ytIBIgA2ytfCAUIBlsrXwgHSAHbK18IBYgF2ytfCAeIAJsrXwgGCAVbK18IB8gBmytfCAaIBNsrXwgASAJbK18IBsgEWytfCAqQhCIfCAUIAtsrSAcIANsrXwgFiAHbK18IB0gGWytfCAYIAJsrXwgHiAXbK18IBogBmytfCAfIBVsrXwgGyAJbK18IAEgE2ytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CLCAAIB0gC2ytIBQgA2ytfCAWIBlsrXwgHiAHbK18IBggF2ytfCAfIAJsrXwgGiAVbK18IAEgBmytfCAbIBNsrXwgKkIQiHwgFiALbK0gHSADbK18IBggB2ytfCAeIBlsrXwgGiACbK18IB8gF2ytfCAbIAZsrXwgASAVbK18IipCEIZCgID8/w+DfCArQiCIfCIrPgIwIAAgHiALbK0gFiADbK18IBggGWytfCAfIAdsrXwgGiAXbK18IAEgAmytfCAbIBVsrXwgKkIQiHwgGCALbK0gHiADbK18IBogB2ytfCAfIBlsrXwgGyACbK18IAEgF2ytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4CNCAAIB8gC2ytIBggA2ytfCAaIBlsrXwgASAHbK18IBsgF2ytfCAqQhCIfCAaIAtsrSAfIANsrXwgGyAHbK18IAEgGWytfCIqQhCGQoCA/P8Pg3wgK0IgiHwiKz4COCAAIBsgGWytIBogA2ytfCABIAtsrXwgKkIQiHwgGyALbK0gASADbK18IipCEIZCgID8/w+DfCArQiCIfCIrPgI8IABBDzYCACAqQhCIIBsgA2ytfCArQiCIfCIqQgBRBEAgICQCDwsgACAqPgJAIABBEDYCACAgJAIPCyAgIQIgA0EBRgRAIAEoAgQhCCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACKAIAIgFBEEsEQCABQRAQJwsgAkEEaiABQQJ0aiEEIAEEQCAIrSErQgAhKiACQQRqIQADQCAAIAAoAgCtICt+IixC/////w+DICp8Iio+AgAgKkIgiCAsQiCIfCEqIABBBGoiACAERw0ACyAqQgBSBEAgAUEQSQRAIAQgKj4CACACIAFBAWo2AgAFQZwMIAFBEBAoCwsLICAkAg8LIAJBADoARCACIApBf2ogA2oiBzYCACACQQhqIgRCADcCACAEQgA3AgggBEIANwIQIARCADcCGCAEQgA3AiAgBEIANwIoIARCADcCMCAEQQA2AjggAiABKAIErSAAKAIErX4iKj4CBCAqQiCIISoCQCAHQQFLBEBBAiEEQQEhBgJAAkACQAJAA0AgKkIgiCEsICqnIQkgBkEBaiILIAprIQUgBiAKSwR/IAUFQQAiBQsgAyAGSwR/IAsFIAMiCwtJBEAgLCEqA0AgBiAFayIMQRBPDQMgBUEQTw0EIAFBBGogBUECdGooAgCtIABBBGogDEECdGooAgCtfiAJrXwiLEIgiCAqfCEqICynIQkgBUEBaiIFIAtJDQALBSAsISoLIAZBEE8NAyACQQRqIAZBAnRqIAk2AgAgBEEBaiEJIAQgB0kEQCAEIQUgCSEEIAUhBgwBBSAqISsMBwsACwALQagMIAxBEBAoDAILQbQMIAVBEBAoDAELQcAMIAZBEBAoCwUgKiErCwsgK0IAUQRAIAchCAUgB0EQSQRAIAJBBGogB0ECdGogKz4CACACIAogA2oiCDYCAAVBzAwgB0EQECgLCyAIQQFLBEAgCCEBAkACQAJAA0AgAUF/aiIEQRBPDQEgAkEEaiAEQQJ0aigCAA0CIARBAUsEQCAEIQEMAQUgBCEBDAMLAAsAC0GwCyAEQRAQKAwBCyACIAE2AgALCyAAIAIpAgA3AgAgACACKQIINwIIIAAgAikCEDcCECAAIAIpAhg3AhggACACKQIgNwIgIAAgAikCKDcCKCAAIAIpAjA3AjAgACACKQI4NwI4IAAgAikCQDcCQCAgJAILCyQAIAEEfyAAQYCAgIB4RiABQX9GcQR/QQAFIAAgAW0LBUEACwv5CQIOfwZ+AkAjAiEJIwJB0ARqJAIgCSIIQQBBhAQQOhpBASACQQFqQRh0QRh1QR9xdCIFQQIQGCEOIAlBiARqIgMgASkCADcCACADIAEpAgg3AgggAyABKQIQNwIQIAMgASkCGDcCGCADIAEpAiA3AiAgAyABKQIoNwIoIAMgASkCMDcCMCADIAEpAjg3AjggAyABKQJANwJAIAMoAgAiAUEBRyADQQRqIgcoAgAiBEEAR3JFBEAgACAIQYQEEDwaIAkkAg8LIAVBf2ohECAIQYAEaiEFIAJB/wFxIg9BP3GtIRNBICAPa0E/ca0hFCABIQIDQAJAAkACQCAEaCIBBEAgBSAFKAIAIAFqNgIAIAJBEEsEQEEGIQEMBAtBICABayEEIAIEQCABrSEVIARBP3GtIRZCACERIANBBGogAkECdGohAQNAIAFBfGoiASgCAK0hEiABIBIgFYggEYQ+AgAgEiAWhiERIAEgB0cNAAsgAygCACIBQQFNDQMgAUF/aiINQRBPBEBBDCEBDAULIANBBGogDUECdGooAgAEQCABIQIFIAMgDTYCACANIQEMBAsFQQAhAgsFIAUoAgAiCkGABEkhBiAEIBBxIgEgDkwEQCAGRQRAQSUhAQwFCyAIIApqIAE6AAAgBSAFKAIAIgZBAWo2AgAgByAEIAFrIgE2AgAgAUEARyACQQFHckUEQEEBIQEMBAsgBSAPIAZqNgIAIAJBEEsEQEEqIQEMBQsgAkUEQEEAIQIMAwtCACERIANBBGogAkECdGohAQNAIAFBfGoiASgCAK0hEiABIBIgE4ggEYQ+AgAgEiAUhiERIAEgB0cNAAsgAygCACIBQQFNDQMgAUF/aiILQRBPBEBBMCEBDAULIANBBGogC0ECdGooAgAEQCABIQIMAwsgAyALNgIAIAshAQwDCyAGRQRAQREhAQwECyAIIApqIA4gAWs6AAAgBSAFKAIAQQFqNgIAIAJBEEsEQEETIQEMBAsgA0EEaiACQQJ0aiEGIAEgDmutIREgByEBAkACQAJAA0AgASAGRg0BIAFBBGohBCABIAEoAgCtIBF8IhE+AgAgEUIgiCIRQgBRDQIgBCEBDAALAAsgAkEQTwRAQRkhAQwGCyAGIBE+AgAgAyACQQFqIgE2AgAMAQsgAkEQSwRAQRshAQwFCyACBEAgAiEBBUEAIQIMAwsLQQAhBCADQQRqIAFBAnRqIQEDQCABQXxqIgEoAgAhBiABIAZBAXYgBHI2AgAgBkEfdCEEIAEgB0cNAAsgAygCACIBQQFNDQIgAUF/aiIMQRBPBEBBISEBDAQLIANBBGogDEECdGooAgAEQCABIQIFIAMgDDYCACAMIQEMAwsLCyAHKAIAIQQMAgsgAUEBRyAHKAIAIgRyBEAgASECDAIFQQMhAQsLCwJAAkACQAJAAkACQAJAAkACQAJAAkACQCABQQNrDi4ACwsBCwsLCwsCCwsLCwMLBAsLCwsLBQsGCwsLCwsHCwsLCAsLCwsJCwsLCwsKCwsgACAIQYQEEDwaIAkkAg8LIAJBEBAnDAkLQbALIA1BEBAoDAgLQawNIApBgAQQKAwHCyACQRAQJwwGC0GQDCACQRAQKAwFCyACQRAQJwwEC0GwCyAMQRAQKAwDC0GsDSAKQYAEECgMAgsgAkEQECcMAQtBsAsgC0EQECgLCwuhAgIFfwF+AkAgACgCACIBQRBLBEAgAUEQECcLIAFFBEAPCyAAQQRqIAFBAnRqIQNCACEGIABBBGohAQNAIAEgASgCAK1CAYYgBnwiBj4CACAGQiCIIQYgAUEEaiIBIANHDQALIAAoAgAhASAGQgBRBEAgASECBSABQRBJBEAgAEEEaiABQQJ0aiAGPgIAIAAgACgCAEEBaiICNgIABUGgDSABQRAQKAsLAkAgAkEIRgRAQQghAgJAAkADQCACQX9qIQEgAkUNBCABQRBPDQEgAEEEaiABQQJ0aigCACIEIAFBAnRBxAlqKAIAIgVGBEAgASECDAELCwwBC0G8CyABQRAQKAsgBCAFSQRADwsFIAJBCEkEQA8LCwsgAEHACRAWCwukBQEHfwJAIwIhBCMCQZABaiQCIAQhASAAKAIAIgJBCUkEQCABQdgMKQIANwIAIAFB4AwpAgA3AgggAUHoDCkCADcCECABQfAMKQIANwIYIAFB+AwpAgA3AiAgAUGADSkCADcCKCABQYgNKQIANwIwIAFBkA0pAgA3AjggAUGYDSkCADcCQAUgAEEINgIAIAEgAkF4ajYCACABQQRqIgIgAEEkaiIDKQIANwIAIAIgAykCCDcCCCACIAMpAhA3AhAgAiADKQIYNwIYIAFBJGoiAkIANwIAIAJCADcCCCACQgA3AhAgAkIANwIYIAJBADoAIAsgBEHIAGohAiABEBwgACABEBUgACgCACIBQQhLBEAgAEEINgIAIAIgAUF4ajYCACACQQRqIgEgAEEkaiIDKQIANwIAIAEgAykCCDcCCCABIAMpAhA3AhAgASADKQIYNwIYIAJBJGoiAUIANwIAIAFCADcCCCABQgA3AhAgAUIANwIYIAFBADoAICACEBwgACACEBUgACgCACEBCyABQQhGBEBBCCEDA0ACQCADQX9qIQIgA0UEQEEUIQMMAQsgAkEQTwRAQQshAwwBCyAAQQRqIAJBAnRqKAIAIgYgAkECdEHECWooAgAiB0YEQCACIQMMAgVBDCEDCwsLIANBC0YEQEG8CyACQRAQKAUgA0EMRgRAIAYgB0khBQUgA0EURgRAIAQkAg8LCwsFIAFBCEkhBQsgBUUEQCAAQcAJEBYgBCQCDwsgAUEBTQRAIAQkAg8LA0ACQCABQX9qIgFBEE8EQEERIQMMAQsgAEEEaiABQQJ0aigCAARAQRQhAwwBCyAAIAE2AgAgAUEBSw0BQRQhAwsLIANBEUYEQEGwCyABQRAQKAUgA0EURgRAIAQkAgsLCwuQAgICfwJ+AkAgACgCACIBQRBPBEBBxA0gAUEQECgLIABBBGogAUECdGpBADYCACAAKAIAQQFqIgFBEE8EQEG4DSABQRAQKAsgAEEEaiABQQJ0akEANgIAIAAgACgCAEECaiICNgIAIAJBEEsEQCACQRAQJwsgAEEEaiEBIAIEQEIAIQMFDwsgAEEEaiACQQJ0aiECA0AgASABKAIArSIEQtEHfiADfCIDPgIAIANCIIggBHwhAyABQQRqIgEgAkcNAAsgACgCACIBQQFNBEAPCwJAAkADQCABQX9qIgFBEE8NASAAQQRqIAFBAnRqKAIADQIgACABNgIAIAFBAUsNAAwCCwALQbALIAFBEBAoCwsL0BACD38EfgJAIwIhByMCQfACaiQCIAciAyABKQIANwIAIAMgASkCCDcCCCADIAEpAhA3AhAgAyABKQIYNwIYIAMgASkCIDcCICADIAEpAig3AiggAyABKQIwNwIwIAMgASkCODcCOCADIAEpAkA3AkAgB0HIAGoiBkHACSkDADcDACAGQcgJKQMANwMIIAZB0AkpAwA3AxAgBkHYCSkDADcDGCAGQeAJKQMANwMgIAZB6AkpAwA3AyggBkHwCSkDADcDMCAGQfgJKQMANwM4IAZBgAopAwA3A0AgB0GQAWoiBEGICikDADcDACAEQZAKKQMANwMIIARBmAopAwA3AxAgBEGgCikDADcDGCAEQagKKQMANwMgIARBsAopAwA3AyggBEG4CikDADcDMCAEQcAKKQMANwM4IARByAopAwA3A0AgB0HYAWoiBUHYDCkCADcCACAFQeAMKQIANwIIIAVB6AwpAgA3AhAgBUHwDCkCADcCGCAFQfgMKQIANwIgIAVBgA0pAgA3AiggBUGIDSkCADcCMCAFQZANKQIANwI4IAVBmA0pAgA3AkACQCADQQRqIgsoAgAiASADKAIAIgJyQQFLBEAgBkEEaiEMIAVBBGohDyAEQQRqIRACQAJAAkACQAJAAkACQAJAAkACQANAIAFoIggEQCACQRBLDQJBICAIayEBIAIEfyAIrSETIAFBP3GtIRRCACERIANBBGogAkECdGohAQNAIAFBfGoiASgCAK0hEiABIBIgE4ggEYQ+AgAgEiAUhiERIAEgC0cNAAsgAygCACIBQQFLBH8gAUF/aiIBQRBPDQUgA0EEaiABQQJ0aigCAAR/QQEFIAMgATYCAEEBCwVBAQsFQQELIQEDQCAQKAIAQQFxBEAgBEHACRAVCyAEKAIAIgJBEEsNBSACBEBBACEJIARBBGogAkECdGohAgNAIAJBfGoiAigCACEKIAIgCkEBdiAJcjYCACAKQR90IQkgAiAQRw0ACyAEKAIAIgJBAUsEQCACQX9qIgJBEE8NCCAEQQRqIAJBAnRqKAIARQRAIAQgAjYCAAsLCyABQQFqIQIgASAISQRAIAIhAQwBCwsLIAwoAgBoIggEQCAGKAIAIgFBEEsNBkEgIAhrIQIgAQR/IAitIRMgAkE/ca0hFEIAIREgBkEEaiABQQJ0aiEBA0AgAUF8aiIBKAIArSESIAEgEiATiCARhD4CACASIBSGIREgASAMRw0ACyAGKAIAIgFBAUsEfyABQX9qIgFBEE8NCSAGQQRqIAFBAnRqKAIABH9BAQUgBiABNgIAQQELBUEBCwVBAQshAQNAIA8oAgBBAXEEQCAFQcAJEBULIAUoAgAiAkEQSw0JIAIEQEEAIQkgBUEEaiACQQJ0aiECA0AgAkF8aiICKAIAIQogAiAKQQF2IAlyNgIAIApBH3QhCSACIA9HDQALIAUoAgAiAkEBSwRAIAJBf2oiAkEQTw0MIAVBBGogAkECdGooAgBFBEAgBSACNgIACwsLIAFBAWohAiABIAhJBEAgAiEBDAELCwsCQAJAAkAgAygCACIBIAYoAgAiAkYEQANAIAFBf2ohAiABRQ0CIAJBEE8NDiADQQRqIAJBAnRqKAIAIgEgBkEEaiACQQJ0aigCACIJRgRAIAIhAQwBCwsgASAJSQ0CBSABIAJJDQILCyADIAYQFiAEIAUQFgwBCyAGIAMQFiAFIAQQFgsgCygCACIBIAMoAgAiAnJBAU0EQCACIQ0gASEODA0LIAwoAgAgBigCAHJBAUsNACACIQ0gASEODAwLAAsgAkEQECcMCAtBsAsgAUEQECgMBwsgAkEQECcMBgtBsAsgAkEQECgMBQsgAUEQECcMBAtBsAsgAUEQECgMAwsgAkEQECcMAgtBsAsgAkEQECgMAQtBvAsgAkEQECgLBSACIQ0gASEOCwsgDUEBRiAOQQFGcQRAIAMgBCkDADcDACADIAQpAwg3AwggAyAEKQMQNwMQIAMgBCkDGDcDGCADIAQpAyA3AyAgAyAEKQMoNwMoIAMgBCkDMDcDMCADIAQpAzg3AzggAyAEKQNANwNABSADIAUpAwA3AwAgAyAFKQMINwMIIAMgBSkDEDcDECADIAUpAxg3AxggAyAFKQMgNwMgIAMgBSkDKDcDKCADIAUpAzA3AzAgAyAFKQM4NwM4IAMgBSkDQDcDQAsgB0GgAmohASADQcQAaiICLAAABEAgA0HACRAVIAIsAAAEQCACQQA6AAAgAxAbIAMoAgBBAUYgCygCAEVxBEAgAEHYDCkCADcCACAAQeAMKQIANwIIIABB6AwpAgA3AhAgAEHwDCkCADcCGCAAQfgMKQIANwIgIABBgA0pAgA3AiggAEGIDSkCADcCMCAAQZANKQIANwI4IABBmA0pAgA3AkAgByQCDwUgAUHACSkDADcDACABQcgJKQMANwMIIAFB0AkpAwA3AxAgAUHYCSkDADcDGCABQeAJKQMANwMgIAFB6AkpAwA3AyggAUHwCSkDADcDMCABQfgJKQMANwM4IAFBgAopAwA3A0AgASADEBYgACABKQIANwIAIAAgASkCCDcCCCAAIAEpAhA3AhAgACABKQIYNwIYIAAgASkCIDcCICAAIAEpAig3AiggACABKQIwNwIwIAAgASkCODcCOCAAIAEpAkA3AkAgByQCDwsACwsgAxAbIAAgAykCADcCACAAIAMpAgg3AgggACADKQIQNwIQIAAgAykCGDcCGCAAIAMpAiA3AiAgACADKQIoNwIoIAAgAykCMDcCMCAAIAMpAjg3AjggACADKQJANwJAIAckAgsLzx8BD38CQCMCIQwjAkGABWokAiAAQZABaiIELAAABEAgDCQCDwsgDCELIAxBuARqIgIgAEHIAGoiCikCADcCACACIAopAgg3AgggAiAKKQIQNwIQIAIgCikCGDcCGCACIAopAiA3AiAgAiAKKQIoNwIoIAIgCikCMDcCMCACIAopAjg3AjggAiAKKQJANwJAIAIgChAVIAxB8ANqIgEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgNBCEYEQEEIIQcCQAJAAkADQCAHQX9qIQMgB0UNBSADQRBPDQEgAUEEaiADQQJ0aigCACIHIANBAnRBxAlqKAIAIgVHDQIgAyEHDAALAAtBvAsgA0EQECgMAQsgByAFTw0CQQghDQsFIANBCE8NASADIQ0LDAELIAFBwAkQFiABKAIAIQ0LIAEoAgQhDiALIAFBCGoiAykCADcCACALIAMpAgg3AgggCyADKQIQNwIQIAsgAykCGDcCGCALIAMpAiA3AiAgCyADKQIoNwIoIAsgAykCMDcCMCALIAMpAjg3AjggDUEBRiAORXEEQCAEQQE6AAAgDCQCDwsgDEGoA2ohCCAMQeACaiEEIAxBmAJqIQUgDEGIAWohBiACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgDEHAAGoiCSABKQMANwMAIAkgASkDCDcDCCAJIAEpAxA3AxAgCSABKQMYNwMYIAkgASkDIDcDICAJIAEpAyg3AyggCSABKQMwNwMwIAkgASkDODcDOCAJIAEpA0A3A0AgAiAJKQMANwMAIAIgCSkDCDcDCCACIAkpAxA3AxAgAiAJKQMYNwMYIAIgCSkDIDcDICACIAkpAyg3AyggAiAJKQMwNwMwIAIgCSkDODcDOCACIAkpA0A3A0AgAiAJEBUgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0ACQAJAIAEoAgAiA0EIRgRAQQghBwJAAkACQANAIAdBf2ohAyAHRQ0FIANBEE8NASABQQRqIANBAnRqKAIAIgcgA0ECdEHECWooAgAiD0cNAiADIQcMAAsAC0G8CyADQRAQKAwBCyAHIA9PDQILBSADQQhPDQELDAELIAFBwAkQFgsgBCABKQMANwMAIAQgASkDCDcDCCAEIAEpAxA3AxAgBCABKQMYNwMYIAQgASkDIDcDICAEIAEpAyg3AyggBCABKQMwNwMwIAQgASkDODcDOCAEIAEpA0A3A0AgAiAEKQMANwMAIAIgBCkDCDcDCCACIAQpAxA3AxAgAiAEKQMYNwMYIAIgBCkDIDcDICACIAQpAyg3AyggAiAEKQMwNwMwIAIgBCkDODcDOCACIAQpA0A3A0AgAiAJEBUgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0ACQAJAIAEoAgAiA0EIRgRAQQghBwJAAkACQANAIAdBf2ohAyAHRQ0FIANBEE8NASABQQRqIANBAnRqKAIAIgcgA0ECdEHECWooAgAiCUcNAiADIQcMAAsAC0G8CyADQRAQKAwBCyAHIAlPDQILBSADQQhPDQELDAELIAFBwAkQFgsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiANNgIAIAIgDjYCBCACQQhqIgMgCykDADcDACADIAspAwg3AwggAyALKQMQNwMQIAMgCykDGDcDGCADIAspAyA3AyAgAyALKQMoNwMoIAMgCykDMDcDMCADIAspAzg3AzggCCACEB0gAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAIEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAYgASkDADcDACAGIAEpAwg3AwggBiABKQMQNwMQIAYgASkDGDcDGCAGIAEpAyA3AyAgBiABKQMoNwMoIAYgASkDMDcDMCAGIAEpAzg3AzggBiABKQNANwNAIAIgBikDADcDACACIAYpAwg3AwggAiAGKQMQNwMQIAIgBikDGDcDGCACIAYpAyA3AyAgAiAGKQMoNwMoIAIgBikDMDcDMCACIAYpAzg3AzggAiAGKQNANwNAIAIgBhAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyAEIAEpAwA3AwAgBCABKQMINwMIIAQgASkDEDcDECAEIAEpAxg3AxggBCABKQMgNwMgIAQgASkDKDcDKCAEIAEpAzA3AzAgBCABKQM4NwM4IAQgASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFSABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQAJAAkAgASgCACIDQQhGBEBBCCEHAkACQAJAA0AgB0F/aiEDIAdFDQUgA0EQTw0BIAFBBGogA0ECdGooAgAiByADQQJ0QcQJaigCACILRw0CIAMhBwwACwALQbwLIANBEBAoDAELIAcgC08NAgsFIANBCE8NAQsMAQsgAUHACRAWCyAIIAEpAwA3AwAgCCABKQMINwMIIAggASkDEDcDECAIIAEpAxg3AxggCCABKQMgNwMgIAggASkDKDcDKCAIIAEpAzA3AzAgCCABKQM4NwM4IAggASkDQDcDQCACIAQpAwA3AwAgAiAEKQMINwMIIAIgBCkDEDcDECACIAQpAxg3AxggAiAEKQMgNwMgIAIgBCkDKDcDKCACIAQpAzA3AzAgAiAEKQM4NwM4IAIgBCkDQDcDQCACIAgQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAMQdABaiIDIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAMQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAIIAEpAwA3AwAgCCABKQMINwMIIAggASkDEDcDECAIIAEpAxg3AxggCCABKQMgNwMgIAggASkDKDcDKCAIIAEpAzA3AzAgCCABKQM4NwM4IAggASkDQDcDQCACIAYpAwA3AwAgAiAGKQMINwMIIAIgBikDEDcDECACIAYpAxg3AxggAiAGKQMgNwMgIAIgBikDKDcDKCACIAYpAzA3AzAgAiAGKQM4NwM4IAIgBikDQDcDQCACIAgQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBCABKQMANwMAIAQgASkDCDcDCCAEIAEpAxA3AxAgBCABKQMYNwMYIAQgASkDIDcDICAEIAEpAyg3AyggBCABKQMwNwMwIAQgASkDODcDOCAEIAEpA0A3A0AgAiAEKQMANwMAIAIgBCkDCDcDCCACIAQpAxA3AxAgAiAEKQMYNwMYIAIgBCkDIDcDICACIAQpAyg3AyggAiAEKQMwNwMwIAIgBCkDODcDOCACIAQpA0A3A0AgAiAKEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgCiAFKQIANwIAIAogBSkCCDcCCCAKIAUpAhA3AhAgCiAFKQIYNwIYIAogBSkCIDcCICAKIAUpAig3AiggCiAFKQIwNwIwIAogBSkCODcCOCAKIAUpAkA3AkAgACADKQIANwIAIAAgAykCCDcCCCAAIAMpAhA3AhAgACADKQIYNwIYIAAgAykCIDcCICAAIAMpAig3AiggACADKQIwNwIwIAAgAykCODcCOCAAIAMpAkA3AkAgDCQCCwvCFgETfwJAIwIhCSMCQfC1AmokAiAJQZC0AmohAyAJQcizAmohBSAJQbiyAmohByAJQey1AmohCyAJIgRBCDYCACAEQZiv4LcBNgIEIARB24LKzwU2AgggBEHZ0bjuAjYCDCAEQdv57xQ2AhAgBEGHlpz0fDYCFCAEQZXFga0FNgIYIARBrPfyTjYCHCAEQf7M+c0HNgIgIARBJGoiBkIANwIAIAZCADcCCCAGQgA3AhAgBkIANwIYIAZBADoAICAEQQg2AkggBEHMAGoiD0G4qcNYNgIAIARBj6Gf4nk2AlAgBEGZqJW0ejYCVCAEQcjo3mg2AlggBEGokcTwADYCXCAEQfz3k+0FNgJgIARB5YiPtQI2AmQgBEH3tOvBBDYCaCAEQewAaiIGQgA3AgAgBkIANwIIIAZCADcCECAGQgA3AhggBkEAOgAgIARBkAFqIhBBADoAACAJQdi0AmoiASAEQZQBEDwaIAlB6JkBaiICIARBlAEQPBogAkGUAWogAUGUARA8GiACQagCaiABQZQBEDwaIAJBvANqIAFBlAEQPBogAkHQBGogAUGUARA8GiACQeQFaiABQZQBEDwaIAJB+AZqIAFBlAEQPBogAkGMCGogAUGUARA8GiACQaAJaiABQZQBEDwaIAJBtApqIAFBlAEQPBogAkHIC2ogAUGUARA8GiACQdwMaiABQZQBEDwaIAJB8A1qIAFBlAEQPBogAkGED2ogAUGUARA8GiACQZgQaiABQZQBEDwaIAJBrBFqIAFBlAEQPBogAkHAEmogAUGUARA8GiACQdQTaiABQZQBEDwaIAJB6BRqIAFBlAEQPBogAkH8FWogAUGUARA8GiACQZAXaiABQZQBEDwaIAJBpBhqIAFBlAEQPBogAkG4GWogAUGUARA8GiACQcwaaiABQZQBEDwaIAJB4BtqIAFBlAEQPBogAkH0HGogAUGUARA8GiACQYgeaiABQZQBEDwaIAJBnB9qIAFBlAEQPBogAkGwIGogAUGUARA8GiACQcQhaiABQZQBEDwaIAJB2CJqIAFBlAEQPBogAkHsI2ogAUGUARA8GiACQYAlaiABQZQBEDwaIAJBlCZqIAFBlAEQPBogAkGoJ2ogAUGUARA8GiACQbwoaiABQZQBEDwaIAJB0ClqIAFBlAEQPBogAkHkKmogAUGUARA8GiACQfgraiABQZQBEDwaIAJBjC1qIAFBlAEQPBogAkGgLmogAUGUARA8GiACQbQvaiABQZQBEDwaIAJByDBqIAFBlAEQPBogAkHcMWogAUGUARA8GiACQfAyaiABQZQBEDwaIAJBhDRqIAFBlAEQPBogAkGYNWogAUGUARA8GiACQaw2aiABQZQBEDwaIAJBwDdqIAFBlAEQPBogAkHUOGogAUGUARA8GiACQeg5aiABQZQBEDwaIAJB/DpqIAFBlAEQPBogAkGQPGogAUGUARA8GiACQaQ9aiABQZQBEDwaIAJBuD5qIAFBlAEQPBogAkHMP2ogAUGUARA8GiACQeDAAGogAUGUARA8GiACQfTBAGogAUGUARA8GiACQYjDAGogAUGUARA8GiACQZzEAGogAUGUARA8GiACQbDFAGogAUGUARA8GiACQcTGAGogAUGUARA8GiACQdjHAGogAUGUARA8GiACQezIAGogAUGUARA8GiACQYDKAGogAUGUARA8GiACQZTLAGogAUGUARA8GiAQLAAABH8gByAEQZABEDwaIAsgBEGRAWoiBi4AADsAACALIAYsAAI6AAJBAQUgBSAEKQMANwMAIAUgBCkDCDcDCCAFIAQpAxA3AxAgBSAEKQMYNwMYIAUgBCkDIDcDICAFIAQpAyg3AyggBSAEKQMwNwMwIAUgBCkDODcDOCAFIAQpA0A3A0AgBEHIAGoiBigCAEEBRiAPKAIARXEEQCADQdgMKQIANwIAIANB4AwpAgA3AgggA0HoDCkCADcCECADQfAMKQIANwIYIANB+AwpAgA3AiAgA0GADSkCADcCKCADQYgNKQIANwIwIANBkA0pAgA3AjggA0GYDSkCADcCQAUgAUHACSkDADcDACABQcgJKQMANwMIIAFB0AkpAwA3AxAgAUHYCSkDADcDGCABQeAJKQMANwMgIAFB6AkpAwA3AyggAUHwCSkDADcDMCABQfgJKQMANwM4IAFBgAopAwA3A0AgASAGEBYgAyABKQMANwMAIAMgASkDCDcDCCADIAEpAxA3AxAgAyABKQMYNwMYIAMgASkDIDcDICADIAEpAyg3AyggAyABKQMwNwMwIAMgASkDODcDOCADIAEpA0A3A0ALIAcgBSkDADcDACAHIAUpAwg3AwggByAFKQMQNwMQIAcgBSkDGDcDGCAHIAUpAyA3AyAgByAFKQMoNwMoIAcgBSkDMDcDMCAHIAUpAzg3AzggByAFKQNANwNAIAdByABqIgYgAykDADcDACAGIAMpAwg3AwggBiADKQMQNwMQIAYgAykDGDcDGCAGIAMpAyA3AyAgBiADKQMoNwMoIAYgAykDMDcDMCAGIAMpAzg3AzggBiADKQNANwNAQQALIQwgCUGYAWohDSAJQZDmAWoiCkGozABqIQggCiEGA0AgBiAHQZABEDwaIAYgDDoAkAEgBkGRAWoiDiALLgAAOwAAIA4gCywAAjoAAiAGQZQBaiIGIAhHDQALIA0gAkGozAAQPBogDUGozABqIApBqMwAEDwaIA1BlAFqIRMgBEHIAGohESAHQcgAaiEIIARBkQFqIRIgDUG8zQBqIg4hAkEBIQZBACEKA0AgBBAeIAQQHiAEEB4gBBAeIBMgCkGUAWxqIARBlAEQPBogECwAAAR/IAcgBEGQARA8GiALIBIuAAA7AAAgCyASLAACOgACQQEFIAUgBCkDADcDACAFIAQpAwg3AwggBSAEKQMQNwMQIAUgBCkDGDcDGCAFIAQpAyA3AyAgBSAEKQMoNwMoIAUgBCkDMDcDMCAFIAQpAzg3AzggBSAEKQNANwNAIBEoAgBBAUYgDygCAEVxBEAgA0HYDCkCADcCACADQeAMKQIANwIIIANB6AwpAgA3AhAgA0HwDCkCADcCGCADQfgMKQIANwIgIANBgA0pAgA3AiggA0GIDSkCADcCMCADQZANKQIANwI4IANBmA0pAgA3AkAFIAFBwAkpAwA3AwAgAUHICSkDADcDCCABQdAJKQMANwMQIAFB2AkpAwA3AxggAUHgCSkDADcDICABQegJKQMANwMoIAFB8AkpAwA3AzAgAUH4CSkDADcDOCABQYAKKQMANwNAIAEgERAWIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNACyAHIAUpAwA3AwAgByAFKQMINwMIIAcgBSkDEDcDECAHIAUpAxg3AxggByAFKQMgNwMgIAcgBSkDKDcDKCAHIAUpAzA3AzAgByAFKQM4NwM4IAcgBSkDQDcDQCAIIAMpAwA3AwAgCCADKQMINwMIIAggAykDEDcDECAIIAMpAxg3AxggCCADKQMgNwMgIAggAykDKDcDKCAIIAMpAzA3AzAgCCADKQM4NwM4IAggAykDQDcDQEEACyEMIAIgB0GQARA8GiAOIApBlAFsaiAMOgCQASAOIApBlAFsakGRAWoiCiALLgAAOwAAIAogCywAAjoAAiAOIAZBlAFsaiECIAZBAWoiDEHCAEcEQCAGIQogDCEGDAELCyAAIA1B0JgBEDwaIAkkAgsLwgwBEH8CQCMCIQsjAkGQCmokAiALIgcgAkEBEBkgC0GQCWoiBkIANwAAIAZCADcACCAGQgA3ABAgBkIANwAYIAZCADcAICAGQgA3ACggBkIANwAwIAZCADcAOCAGQgA3AEAgBkIANwBIIAZCADcAUCAGQgA3AFggBkIANwBgIAZCADcAaCAGQgA3AHAgBkIANwB4IAcoAoAEIglBgARLBEAgCUGABBAnCyALQbgHaiEOIAtB4AVqIQQgC0GIBGohBSAJRSEDIAlBBEkEfyAJBUEECyECAkAgAwRAQQAhDQUgCSACayEIIAchAyACIQkgByACaiECQQAhBwJAAkACQANAAkACQAJAAkACQAJAIAlBAWsOBAMCAQAECyADLAACQQJ0Qf8BcSADLAADQQN0Qf8BcWpBGHRBGHUgAywAAUEBdEH/AXFqQRh0QRh1IAMsAABqQRh0QRh1IQMMBAsgAywAAUEBdEH/AXEgAywAAkECdEH/AXFqQRh0QRh1IAMsAABqQRh0QRh1IQMMAwsgAywAAUEBdEH/AXEgAywAAGpBGHRBGHUhAwwCCyADLAAAIQMMAQsMAgsgB0GAAU8NAiAGIAdqIAM6AAAgB0EBaiEHIAhFIQwgCCAIQQRJBH8gCAVBBAsiCmshCCACIgMgCmohDyAMBEBBACEICyAMBEAgAiEPCyAMRQRAIAohCQsgDCACRXIEQCAHIQ0MBgUgDyECDAELAAsAC0HQDRAuDAELQeQNIAdBgAEQKAsLCyAFQYgKKQMANwMAIAVBkAopAwA3AwggBUGYCikDADcDECAFQaAKKQMANwMYIAVBqAopAwA3AyAgBUGwCikDADcDKCAFQbgKKQMANwMwIAVBwAopAwA3AzggBUHICikDADcDQCAFQcgAaiICQYgKKQMANwMAIAJBkAopAwA3AwggAkGYCikDADcDECACQaAKKQMANwMYIAJBqAopAwA3AyAgAkGwCikDADcDKCACQbgKKQMANwMwIAJBwAopAwA3AzggAkHICikDADcDQCAFQZABaiICQdgMKQIANwIAIAJB4AwpAgA3AgggAkHoDCkCADcCECACQfAMKQIANwIYIAJB+AwpAgA3AiAgAkGADSkCADcCKCACQYgNKQIANwIwIAJBkA0pAgA3AjggAkGYDSkCADcCQCAEQYgKKQMANwMAIARBkAopAwA3AwggBEGYCikDADcDECAEQaAKKQMANwMYIARBqAopAwA3AyAgBEGwCikDADcDKCAEQbgKKQMANwMwIARBwAopAwA3AzggBEHICikDADcDQCAEQcgAaiICQYgKKQMANwMAIAJBkAopAwA3AwggAkGYCikDADcDECACQaAKKQMANwMYIAJBqAopAwA3AyAgAkGwCikDADcDKCACQbgKKQMANwMwIAJBwAopAwA3AzggAkHICikDADcDQCAEQZABaiICQdgMKQIANwIAIAJB4AwpAgA3AgggAkHoDCkCADcCECACQfAMKQIANwIYIAJB+AwpAgA3AiAgAkGADSkCADcCKCACQYgNKQIANwIwIAJBkA0pAgA3AjggAkGYDSkCADcCQCANRSICBEAgBSAEECEgBSAEECEgBSAEECEgBSAEECEgBSAEECEgBSAEECEgBSAEECEgBSAEECEgBSAEECEgBSAEECEgDiAFQdgBEDwaIAAgDhAiIAskAg8FQQohCgsgBiANaiERIAYhCSAGQQFqIQMgAgR/IAkFIAMLIQYgAkEBc0EBcSEMAkACQAJAAkADQEEAIAprQRh0QRh1IRJBACEIIAYhAiAJIQMgDCEHA0AgAywAACIDIApBGHRBGHVGBEAgCEHCAE8NBCAEIAEgCEGUAWxqECMFIAMgEkYEQCAIQcIATw0GIAQgAUGozABqIAhBlAFsahAjCwsgAiIDIBFGIRAgA0EBaiEDIBAEfyACBSADCyEPIBBBAXMgB2ohDSAQRQRAIAchCAsgAkUgEHJFBEAgAiEDIA8hAiANIQcMAQsLIAUgBBAhIApBf2pBGHRBGHUhAiAKQRh0QRh1QQFMDQEgAiEKDAALAAsgDiAFQdgBEDwaIAAgDhAiIAskAg8LQfANIAhBwgAQKAwBC0H8DSAIQcIAECgLCwu9OgEPfwJAIwIhDCMCQeAKaiQCIAAoApABQQFGBEAgACgClAFFBEAgACABQdgBEDwaIAwkAg8LCyABKAKQAUEBRgRAIAEoApQBRQRAIAwkAg8LCyAMQYAJaiICIAFBkAFqIg4pAgA3AgAgAiAOKQIINwIIIAIgDikCEDcCECACIA4pAhg3AhggAiAOKQIgNwIgIAIgDikCKDcCKCACIA4pAjA3AjAgAiAOKQI4NwI4IAIgDikCQDcCQCACIA4QFyAMQbgIaiIDIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDCIGIAMpAwA3AwAgBiADKQMINwMIIAYgAykDEDcDECAGIAMpAxg3AxggBiADKQMgNwMgIAYgAykDKDcDKCAGIAMpAzA3AzAgBiADKQM4NwM4IAYgAykDQDcDQCACIABBkAFqIgkpAgA3AgAgAiAJKQIINwIIIAIgCSkCEDcCECACIAkpAhg3AhggAiAJKQIgNwIgIAIgCSkCKDcCKCACIAkpAjA3AjAgAiAJKQI4NwI4IAIgCSkCQDcCQCACIAkQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHIAGoiBSADKQMANwMAIAUgAykDCDcDCCAFIAMpAxA3AxAgBSADKQMYNwMYIAUgAykDIDcDICAFIAMpAyg3AyggBSADKQMwNwMwIAUgAykDODcDOCAFIAMpA0A3A0AgAiAAKQIANwIAIAIgACkCCDcCCCACIAApAhA3AhAgAiAAKQIYNwIYIAIgACkCIDcCICACIAApAig3AiggAiAAKQIwNwIwIAIgACkCODcCOCACIAApAkA3AkAgAiAGEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAxBkAFqIgcgAykDADcDACAHIAMpAwg3AwggByADKQMQNwMQIAcgAykDGDcDGCAHIAMpAyA3AyAgByADKQMoNwMoIAcgAykDMDcDMCAHIAMpAzg3AzggByADKQNANwNAIAIgASkCADcCACACIAEpAgg3AgggAiABKQIQNwIQIAIgASkCGDcCGCACIAEpAiA3AiAgAiABKQIoNwIoIAIgASkCMDcCMCACIAEpAjg3AjggAiABKQJANwJAIAIgBRAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAMQdgBaiIIIAMpAwA3AwAgCCADKQMINwMIIAggAykDEDcDECAIIAMpAxg3AxggCCADKQMgNwMgIAggAykDKDcDKCAIIAMpAzA3AzAgCCADKQM4NwM4IAggAykDQDcDQCACIABByABqIg0pAgA3AgAgAiANKQIINwIIIAIgDSkCEDcCECACIA0pAhg3AhggAiANKQIgNwIgIAIgDSkCKDcCKCACIA0pAjA3AjAgAiANKQI4NwI4IAIgDSkCQDcCQCACIAYQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHwB2oiBCADKQMANwMAIAQgAykDCDcDCCAEIAMpAxA3AxAgBCADKQMYNwMYIAQgAykDIDcDICAEIAMpAyg3AyggBCADKQMwNwMwIAQgAykDODcDOCAEIAMpA0A3A0AgAiAEKQMANwMAIAIgBCkDCDcDCCACIAQpAxA3AxAgAiAEKQMYNwMYIAIgBCkDIDcDICACIAQpAyg3AyggAiAEKQMwNwMwIAIgBCkDODcDOCACIAQpA0A3A0AgAiAOEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAxBoAJqIgogAykDADcDACAKIAMpAwg3AwggCiADKQMQNwMQIAogAykDGDcDGCAKIAMpAyA3AyAgCiADKQMoNwMoIAogAykDMDcDMCAKIAMpAzg3AzggCiADKQNANwNAIAIgAUHIAGoiASkCADcCACACIAEpAgg3AgggAiABKQIQNwIQIAIgASkCGDcCGCACIAEpAiA3AiAgAiABKQIoNwIoIAIgASkCMDcCMCACIAEpAjg3AjggAiABKQJANwJAIAIgBRAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAEIAMpAwA3AwAgBCADKQMINwMIIAQgAykDEDcDECAEIAMpAxg3AxggBCADKQMgNwMgIAQgAykDKDcDKCAEIAMpAzA3AzAgBCADKQM4NwM4IAQgAykDQDcDQCACIAQpAwA3AwAgAiAEKQMINwMIIAIgBCkDEDcDECACIAQpAxg3AxggAiAEKQMgNwMgIAIgBCkDKDcDKCACIAQpAzA3AzAgAiAEKQM4NwM4IAIgBCkDQDcDQCACIAkQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHoAmoiASADKQMANwMAIAEgAykDCDcDCCABIAMpAxA3AxAgASADKQMYNwMYIAEgAykDIDcDICABIAMpAyg3AyggASADKQMwNwMwIAEgAykDODcDOCABIAMpA0A3A0AgAiAHKQMANwMAIAIgBykDCDcDCCACIAcpAxA3AxAgAiAHKQMYNwMYIAIgBykDIDcDICACIAcpAyg3AyggAiAHKQMwNwMwIAIgBykDODcDOCACIAcpA0A3A0AgAiAIEBYgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAywARARAIANBwAkQFQsgDEGwA2oiCyADKQMANwMAIAsgAykDCDcDCCALIAMpAxA3AxAgCyADKQMYNwMYIAsgAykDIDcDICALIAMpAyg3AyggCyADKQMwNwMwIAsgAykDODcDOCALIAMpA0A3A0AgAiAKKQMANwMAIAIgCikDCDcDCCACIAopAxA3AxAgAiAKKQMYNwMYIAIgCikDIDcDICACIAopAyg3AyggAiAKKQMwNwMwIAIgCikDODcDOCACIAopA0A3A0AgAiABEBYgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAywARARAIANBwAkQFQsgDEH4A2oiCCADKQMANwMAIAggAykDCDcDCCAIIAMpAxA3AxAgCCADKQMYNwMYIAggAykDIDcDICAIIAMpAyg3AyggCCADKQMwNwMwIAggAykDODcDOCAIIAMpA0A3A0AgCygCAEEBRgRAIAsoAgRFBEACQAJAIAgoAgBBAUcNACAIKAIEDQAgABAkDAELIAJBiAopAwA3AwAgAkGQCikDADcDCCACQZgKKQMANwMQIAJBoAopAwA3AxggAkGoCikDADcDICACQbAKKQMANwMoIAJBuAopAwA3AzAgAkHACikDADcDOCACQcgKKQMANwNAIAJByABqIgFBiAopAwA3AwAgAUGQCikDADcDCCABQZgKKQMANwMQIAFBoAopAwA3AxggAUGoCikDADcDICABQbAKKQMANwMoIAFBuAopAwA3AzAgAUHACikDADcDOCABQcgKKQMANwNAIAJBkAFqIgFB2AwpAgA3AgAgAUHgDCkCADcCCCABQegMKQIANwIQIAFB8AwpAgA3AhggAUH4DCkCADcCICABQYANKQIANwIoIAFBiA0pAgA3AjAgAUGQDSkCADcCOCABQZgNKQIANwJAIAAgAkHYARA8GgsgDCQCDwsLIAxBqAdqIQUgAiALKQMANwMAIAIgCykDCDcDCCACIAspAxA3AxAgAiALKQMYNwMYIAIgCykDIDcDICACIAspAyg3AyggAiALKQMwNwMwIAIgCykDODcDOCACIAspA0A3A0AgAiALEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAxBwARqIgEgAykDADcDACABIAMpAwg3AwggASADKQMQNwMQIAEgAykDGDcDGCABIAMpAyA3AyAgASADKQMoNwMoIAEgAykDMDcDMCABIAMpAzg3AzggASADKQNANwNAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgARAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAMQYgFaiIHIAMpAwA3AwAgByADKQMINwMIIAcgAykDEDcDECAHIAMpAxg3AxggByADKQMgNwMgIAcgAykDKDcDKCAHIAMpAzA3AzAgByADKQM4NwM4IAcgAykDQDcDQCACIAEpAwA3AwAgAiABKQMINwMIIAIgASkDEDcDECACIAEpAxg3AxggAiABKQMgNwMgIAIgASkDKDcDKCACIAEpAzA3AzAgAiABKQM4NwM4IAIgASkDQDcDQCACIAsQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgDEHQBWoiDyADKQMANwMAIA8gAykDCDcDCCAPIAMpAxA3AxAgDyADKQMYNwMYIA8gAykDIDcDICAPIAMpAyg3AyggDyADKQMwNwMwIA8gAykDODcDOCAPIAMpA0A3A0AgAiAIKQMANwMAIAIgCCkDCDcDCCACIAgpAxA3AxAgAiAIKQMYNwMYIAIgCCkDIDcDICACIAgpAyg3AyggAiAIKQMwNwMwIAIgCCkDODcDOCACIAgpA0A3A0AgAiAIEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAQgAykDADcDACAEIAMpAwg3AwggBCADKQMQNwMQIAQgAykDGDcDGCAEIAMpAyA3AyAgBCADKQMoNwMoIAQgAykDMDcDMCAEIAMpAzg3AzggBCADKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgDxAVIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAAkACQCADKAIAIgFBCEYEQEEIIQYCQAJAAkADQCAGQX9qIQEgBkUNBSABQRBPDQEgA0EEaiABQQJ0aigCACIGIAFBAnRBxAlqKAIAIhBHDQIgASEGDAALAAtBvAsgAUEQECgMAQsgBiAQTw0CCwUgAUEITw0BCwwBCyADQcAJEBYLIAUgAykDADcDACAFIAMpAwg3AwggBSADKQMQNwMQIAUgAykDGDcDGCAFIAMpAyA3AyAgBSADKQMoNwMoIAUgAykDMDcDMCAFIAMpAzg3AzggBSADKQNANwNAIAIgBSkDADcDACACIAUpAwg3AwggAiAFKQMQNwMQIAIgBSkDGDcDGCACIAUpAyA3AyAgAiAFKQMoNwMoIAIgBSkDMDcDMCACIAUpAzg3AzggAiAFKQNANwNAIAIgBxAWIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMsAEQEQCADQcAJEBULIAxB4AZqIgEgAykDADcDACABIAMpAwg3AwggASADKQMQNwMQIAEgAykDGDcDGCABIAMpAyA3AyAgASADKQMoNwMoIAEgAykDMDcDMCABIAMpAzg3AzggASADKQNANwNAIAIgASkDADcDACACIAEpAwg3AwggAiABKQMQNwMQIAIgASkDGDcDGCACIAEpAyA3AyAgAiABKQMoNwMoIAIgASkDMDcDMCACIAEpAzg3AzggAiABKQNANwNAIAIgBxAWIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMsAEQEQCADQcAJEBULIAxBmAZqIgYgAykDADcDACAGIAMpAwg3AwggBiADKQMQNwMQIAYgAykDGDcDGCAGIAMpAyA3AyAgBiADKQMoNwMoIAYgAykDMDcDMCAGIAMpAzg3AzggBiADKQNANwNAIAAgBikCADcCACAAIAYpAgg3AgggACAGKQIQNwIQIAAgBikCGDcCGCAAIAYpAiA3AiAgACAGKQIoNwIoIAAgBikCMDcCMCAAIAYpAjg3AjggACAGKQJANwJAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgABAWIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMsAEQEQCADQcAJEBULIAUgAykDADcDACAFIAMpAwg3AwggBSADKQMQNwMQIAUgAykDGDcDGCAFIAMpAyA3AyAgBSADKQMoNwMoIAUgAykDMDcDMCAFIAMpAzg3AzggBSADKQNANwNAIAIgCCkDADcDACACIAgpAwg3AwggAiAIKQMQNwMQIAIgCCkDGDcDGCACIAgpAyA3AyAgAiAIKQMoNwMoIAIgCCkDMDcDMCACIAgpAzg3AzggAiAIKQNANwNAIAIgBRAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyABIAMpAwA3AwAgASADKQMINwMIIAEgAykDEDcDECABIAMpAxg3AxggASADKQMgNwMgIAEgAykDKDcDKCABIAMpAzA3AzAgASADKQM4NwM4IAEgAykDQDcDQCACIAopAwA3AwAgAiAKKQMINwMIIAIgCikDEDcDECACIAopAxg3AxggAiAKKQMgNwMgIAIgCikDKDcDKCACIAopAzA3AzAgAiAKKQM4NwM4IAIgCikDQDcDQCACIA8QFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgBCADKQMANwMAIAQgAykDCDcDCCAEIAMpAxA3AxAgBCADKQMYNwMYIAQgAykDIDcDICAEIAMpAyg3AyggBCADKQMwNwMwIAQgAykDODcDOCAEIAMpA0A3A0AgAiABKQMANwMAIAIgASkDCDcDCCACIAEpAxA3AxAgAiABKQMYNwMYIAIgASkDIDcDICACIAEpAyg3AyggAiABKQMwNwMwIAIgASkDODcDOCACIAEpA0A3A0AgAiAEEBYgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAywARARAIANBwAkQFQsgBiADKQMANwMAIAYgAykDCDcDCCAGIAMpAxA3AxAgBiADKQMYNwMYIAYgAykDIDcDICAGIAMpAyg3AyggBiADKQMwNwMwIAYgAykDODcDOCAGIAMpA0A3A0AgDSAGKQIANwIAIA0gBikCCDcCCCANIAYpAhA3AhAgDSAGKQIYNwIYIA0gBikCIDcCICANIAYpAig3AiggDSAGKQIwNwIwIA0gBikCODcCOCANIAYpAkA3AkAgAiAJKQIANwIAIAIgCSkCCDcCCCACIAkpAhA3AhAgAiAJKQIYNwIYIAIgCSkCIDcCICACIAkpAig3AiggAiAJKQIwNwIwIAIgCSkCODcCOCACIAkpAkA3AkAgAiAOEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAQgAykDADcDACAEIAMpAwg3AwggBCADKQMQNwMQIAQgAykDGDcDGCAEIAMpAyA3AyAgBCADKQMoNwMoIAQgAykDMDcDMCAEIAMpAzg3AzggBCADKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgCxAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAFIAMpAwA3AwAgBSADKQMINwMIIAUgAykDEDcDECAFIAMpAxg3AxggBSADKQMgNwMgIAUgAykDKDcDKCAFIAMpAzA3AzAgBSADKQM4NwM4IAUgAykDQDcDQCAJIAUpAgA3AgAgCSAFKQIINwIIIAkgBSkCEDcCECAJIAUpAhg3AhggCSAFKQIgNwIgIAkgBSkCKDcCKCAJIAUpAjA3AjAgCSAFKQI4NwI4IAkgBSkCQDcCQCAMJAILC94KAQt/AkAjAiEJIwJBgAVqJAIgCUG4BGohAiAJQfADaiEDIAlBqANqIQQgCUHgAmohBSAJQZgCaiEIIAlB0AFqIQcgCUHAAGoiCiABQZABEDwaIAEoApABIQsgASgClAEhDCAJIgYgAUGYAWoiASkCADcCACAGIAEpAgg3AgggBiABKQIQNwIQIAYgASkCGDcCGCAGIAEpAiA3AiAgBiABKQIoNwIoIAYgASkCMDcCMCAGIAEpAjg3AjggC0EBRiAMRXEEQCAAQYgOQZQBEDwaIAkkAgUgAiALNgIAIAIgDDYCBCACQQhqIgEgBikDADcDACABIAYpAwg3AwggASAGKQMQNwMQIAEgBikDGDcDGCABIAYpAyA3AyAgASAGKQMoNwMoIAEgBikDMDcDMCABIAYpAzg3AzggByACEB0gAiAHKQMANwMAIAIgBykDCDcDCCACIAcpAxA3AxAgAiAHKQMYNwMYIAIgBykDIDcDICACIAcpAyg3AyggAiAHKQMwNwMwIAIgBykDODcDOCACIAcpA0A3A0AgAiAHEBcgAyACKQMANwMAIAMgAikDCDcDCCADIAIpAxA3AxAgAyACKQMYNwMYIAMgAikDIDcDICADIAIpAyg3AyggAyACKQMwNwMwIAMgAikDODcDOCADIAIpA0A3A0AgAxAbIAggAykDADcDACAIIAMpAwg3AwggCCADKQMQNwMQIAggAykDGDcDGCAIIAMpAyA3AyAgCCADKQMoNwMoIAggAykDMDcDMCAIIAMpAzg3AzggCCADKQNANwNAIAIgCikDADcDACACIAopAwg3AwggAiAKKQMQNwMQIAIgCikDGDcDGCACIAopAyA3AyAgAiAKKQMoNwMoIAIgCikDMDcDMCACIAopAzg3AzggAiAKKQNANwNAIAIgCBAXIAMgAikDADcDACADIAIpAwg3AwggAyACKQMQNwMQIAMgAikDGDcDGCADIAIpAyA3AyAgAyACKQMoNwMoIAMgAikDMDcDMCADIAIpAzg3AzggAyACKQNANwNAIAMQGyAFIAMpAwA3AwAgBSADKQMINwMIIAUgAykDEDcDECAFIAMpAxg3AxggBSADKQMgNwMgIAUgAykDKDcDKCAFIAMpAzA3AzAgBSADKQM4NwM4IAUgAykDQDcDQCACIApByABqIgEpAwA3AwAgAiABKQMINwMIIAIgASkDEDcDECACIAEpAxg3AxggAiABKQMgNwMgIAIgASkDKDcDKCACIAEpAzA3AzAgAiABKQM4NwM4IAIgASkDQDcDQCACIAgQFyADIAIpAwA3AwAgAyACKQMINwMIIAMgAikDEDcDECADIAIpAxg3AxggAyACKQMgNwMgIAMgAikDKDcDKCADIAIpAzA3AzAgAyACKQM4NwM4IAMgAikDQDcDQCADEBsgBCADKQMANwMAIAQgAykDCDcDCCAEIAMpAxA3AxAgBCADKQMYNwMYIAQgAykDIDcDICAEIAMpAyg3AyggBCADKQMwNwMwIAQgAykDODcDOCAEIAMpA0A3A0AgBCAHEBcgBBAbIAAgBSkCADcCACAAIAUpAgg3AgggACAFKQIQNwIQIAAgBSkCGDcCGCAAIAUpAiA3AiAgACAFKQIoNwIoIAAgBSkCMDcCMCAAIAUpAjg3AjggACAFKQJANwJAIABByABqIgEgBCkCADcCACABIAQpAgg3AgggASAEKQIQNwIQIAEgBCkCGDcCGCABIAQpAiA3AiAgASAEKQIoNwIoIAEgBCkCMDcCMCABIAQpAjg3AjggASAEKQJANwJAIABBADoAkAEgCSQCCwsLhC0BDX8CQCMCIQwjAkHQCWokAiAMQbgIaiEDIAxB4AZqIQIgACgCkAFBAUYEQCAAKAKUAUUEQCABLACQASEHIAMgAUGQARA8GiAHQQFxBEAgAkGICikDADcDACACQZAKKQMANwMIIAJBmAopAwA3AxAgAkGgCikDADcDGCACQagKKQMANwMgIAJBsAopAwA3AyggAkG4CikDADcDMCACQcAKKQMANwM4IAJByAopAwA3A0AgAkHIAGoiAUGICikDADcDACABQZAKKQMANwMIIAFBmAopAwA3AxAgAUGgCikDADcDGCABQagKKQMANwMgIAFBsAopAwA3AyggAUG4CikDADcDMCABQcAKKQMANwM4IAFByAopAwA3A0AgAkGQAWoiAUHYDCkCADcCACABQeAMKQIANwIIIAFB6AwpAgA3AhAgAUHwDCkCADcCGCABQfgMKQIANwIgIAFBgA0pAgA3AiggAUGIDSkCADcCMCABQZANKQIANwI4IAFBmA0pAgA3AkAFIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAJByABqIgEgA0HIAGoiBykDADcDACABIAcpAwg3AwggASAHKQMQNwMQIAEgBykDGDcDGCABIAcpAyA3AyAgASAHKQMoNwMoIAEgBykDMDcDMCABIAcpAzg3AzggASAHKQNANwNAIAJBkAFqIgFBiAopAwA3AwAgAUGQCikDADcDCCABQZgKKQMANwMQIAFBoAopAwA3AxggAUGoCikDADcDICABQbAKKQMANwMoIAFBuAopAwA3AzAgAUHACikDADcDOCABQcgKKQMANwNACyAAIAJB2AEQPBogDCQCDwsLIAEsAJABBEAgDCQCDwsgAyAAQZABaiIKKQIANwIAIAMgCikCCDcCCCADIAopAhA3AhAgAyAKKQIYNwIYIAMgCikCIDcCICADIAopAig3AiggAyAKKQIwNwIwIAMgCikCODcCOCADIAopAkA3AkAgAyAKEBcgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAhAbIAwiByACKQMANwMAIAcgAikDCDcDCCAHIAIpAxA3AxAgByACKQMYNwMYIAcgAikDIDcDICAHIAIpAyg3AyggByACKQMwNwMwIAcgAikDODcDOCAHIAIpA0A3A0AgAyABKQIANwIAIAMgASkCCDcCCCADIAEpAhA3AhAgAyABKQIYNwIYIAMgASkCIDcCICADIAEpAig3AiggAyABKQIwNwIwIAMgASkCODcCOCADIAEpAkA3AkAgAyAHEBcgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAhAbIAxByABqIgQgAikDADcDACAEIAIpAwg3AwggBCACKQMQNwMQIAQgAikDGDcDGCAEIAIpAyA3AyAgBCACKQMoNwMoIAQgAikDMDcDMCAEIAIpAzg3AzggBCACKQNANwNAIAMgAUHIAGoiASkCADcCACADIAEpAgg3AgggAyABKQIQNwIQIAMgASkCGDcCGCADIAEpAiA3AiAgAyABKQIoNwIoIAMgASkCMDcCMCADIAEpAjg3AjggAyABKQJANwJAIAMgBxAXIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIQGyAMQZABaiIBIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABIAoQFyABEBsgAyAAKQIANwIAIAMgACkCCDcCCCADIAApAhA3AhAgAyAAKQIYNwIYIAMgACkCIDcCICADIAApAig3AiggAyAAKQIwNwIwIAMgACkCODcCOCADIAApAkA3AkAgAyAEEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiwARARAIAJBwAkQFQsgDEHYAWoiCSACKQMANwMAIAkgAikDCDcDCCAJIAIpAxA3AxAgCSACKQMYNwMYIAkgAikDIDcDICAJIAIpAyg3AyggCSACKQMwNwMwIAkgAikDODcDOCAJIAIpA0A3A0AgAyAAQcgAaiIEKQIANwIAIAMgBCkCCDcCCCADIAQpAhA3AhAgAyAEKQIYNwIYIAMgBCkCIDcCICADIAQpAig3AiggAyAEKQIwNwIwIAMgBCkCODcCOCADIAQpAkA3AkAgAyABEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiwARARAIAJBwAkQFQsgDEGgAmoiBSACKQMANwMAIAUgAikDCDcDCCAFIAIpAxA3AxAgBSACKQMYNwMYIAUgAikDIDcDICAFIAIpAyg3AyggBSACKQMwNwMwIAUgAikDODcDOCAFIAIpA0A3A0AgCSgCAEEBRgRAIAkoAgRFBEACQAJAIAUoAgBBAUcNACAFKAIEDQAgABAkDAELIABBiAopAgA3AgAgAEGQCikCADcCCCAAQZgKKQIANwIQIABBoAopAgA3AhggAEGoCikCADcCICAAQbAKKQIANwIoIABBuAopAgA3AjAgAEHACikCADcCOCAAQcgKKQIANwJAIARBiAopAgA3AgAgBEGQCikCADcCCCAEQZgKKQIANwIQIARBoAopAgA3AhggBEGoCikCADcCICAEQbAKKQIANwIoIARBuAopAgA3AjAgBEHACikCADcCOCAEQcgKKQIANwJAIApB2AwpAgA3AgAgCkHgDCkCADcCCCAKQegMKQIANwIQIApB8AwpAgA3AhggCkH4DCkCADcCICAKQYANKQIANwIoIApBiA0pAgA3AjAgCkGQDSkCADcCOCAKQZgNKQIANwJACyAMJAIPCwsgDEHQBWohBiADIAkpAwA3AwAgAyAJKQMINwMIIAMgCSkDEDcDECADIAkpAxg3AxggAyAJKQMgNwMgIAMgCSkDKDcDKCADIAkpAzA3AzAgAyAJKQM4NwM4IAMgCSkDQDcDQCADIAkQFyACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACEBsgDEHoAmoiASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgAyAAKQIANwIAIAMgACkCCDcCCCADIAApAhA3AhAgAyAAKQIYNwIYIAMgACkCIDcCICADIAApAig3AiggAyAAKQIwNwIwIAMgACkCODcCOCADIAApAkA3AkAgAyABEBcgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAhAbIAxBsANqIgsgAikDADcDACALIAIpAwg3AwggCyACKQMQNwMQIAsgAikDGDcDGCALIAIpAyA3AyAgCyACKQMoNwMoIAsgAikDMDcDMCALIAIpAzg3AzggCyACKQNANwNAIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNAIAMgCRAXIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIQGyAMQfgDaiINIAIpAwA3AwAgDSACKQMINwMIIA0gAikDEDcDECANIAIpAxg3AxggDSACKQMgNwMgIA0gAikDKDcDKCANIAIpAzA3AzAgDSACKQM4NwM4IA0gAikDQDcDQCADIAUpAwA3AwAgAyAFKQMINwMIIAMgBSkDEDcDECADIAUpAxg3AxggAyAFKQMgNwMgIAMgBSkDKDcDKCADIAUpAzA3AzAgAyAFKQM4NwM4IAMgBSkDQDcDQCADIAUQFyACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACEBsgDEGYBmoiCCACKQMANwMAIAggAikDCDcDCCAIIAIpAxA3AxAgCCACKQMYNwMYIAggAikDIDcDICAIIAIpAyg3AyggCCACKQMwNwMwIAggAikDODcDOCAIIAIpA0A3A0AgAyAIKQMANwMAIAMgCCkDCDcDCCADIAgpAxA3AxAgAyAIKQMYNwMYIAMgCCkDIDcDICADIAgpAyg3AyggAyAIKQMwNwMwIAMgCCkDODcDOCADIAgpA0A3A0AgAyANEBUgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0ACQAJAIAIoAgAiAUEIRgRAQQghBwJAAkACQANAIAdBf2ohASAHRQ0FIAFBEE8NASACQQRqIAFBAnRqKAIAIgcgAUECdEHECWooAgAiDkcNAiABIQcMAAsAC0G8CyABQRAQKAwBCyAHIA5PDQILBSABQQhPDQELDAELIAJBwAkQFgsgBiACKQMANwMAIAYgAikDCDcDCCAGIAIpAxA3AxAgBiACKQMYNwMYIAYgAikDIDcDICAGIAIpAyg3AyggBiACKQMwNwMwIAYgAikDODcDOCAGIAIpA0A3A0AgAyAGKQMANwMAIAMgBikDCDcDCCADIAYpAxA3AxAgAyAGKQMYNwMYIAMgBikDIDcDICADIAYpAyg3AyggAyAGKQMwNwMwIAMgBikDODcDOCADIAYpA0A3A0AgAyALEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiALEBYgAkHEAGoiASwAAARAA0AgAkHACRAVIAEsAAANAAsLIAxBiAVqIgEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAAgASkCADcCACAAIAEpAgg3AgggACABKQIQNwIQIAAgASkCGDcCGCAAIAEpAiA3AiAgACABKQIoNwIoIAAgASkCMDcCMCAAIAEpAjg3AjggACABKQJANwJAIAMgCykDADcDACADIAspAwg3AwggAyALKQMQNwMQIAMgCykDGDcDGCADIAspAyA3AyAgAyALKQMoNwMoIAMgCykDMDcDMCADIAspAzg3AzggAyALKQNANwNAIAMgABAWIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIsAEQEQCACQcAJEBULIAYgAikDADcDACAGIAIpAwg3AwggBiACKQMQNwMQIAYgAikDGDcDGCAGIAIpAyA3AyAgBiACKQMoNwMoIAYgAikDMDcDMCAGIAIpAzg3AzggBiACKQNANwNAIAMgBSkDADcDACADIAUpAwg3AwggAyAFKQMQNwMQIAMgBSkDGDcDGCADIAUpAyA3AyAgAyAFKQMoNwMoIAMgBSkDMDcDMCADIAUpAzg3AzggAyAFKQNANwNAIAMgBhAXIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIQGyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCADIAQpAgA3AgAgAyAEKQIINwIIIAMgBCkCEDcCECADIAQpAhg3AhggAyAEKQIgNwIgIAMgBCkCKDcCKCADIAQpAjA3AjAgAyAEKQI4NwI4IAMgBCkCQDcCQCADIA0QFyACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACEBsgCCACKQMANwMAIAggAikDCDcDCCAIIAIpAxA3AxAgCCACKQMYNwMYIAggAikDIDcDICAIIAIpAyg3AyggCCACKQMwNwMwIAggAikDODcDOCAIIAIpA0A3A0AgAyABKQMANwMAIAMgASkDCDcDCCADIAEpAxA3AxAgAyABKQMYNwMYIAMgASkDIDcDICADIAEpAyg3AyggAyABKQMwNwMwIAMgASkDODcDOCADIAEpA0A3A0AgAyAIEBYgAiADKQMANwMAIAIgAykDCDcDCCACIAMpAxA3AxAgAiADKQMYNwMYIAIgAykDIDcDICACIAMpAyg3AyggAiADKQMwNwMwIAIgAykDODcDOCACIAMpA0A3A0AgAiwARARAIAJBwAkQFQsgDEHABGoiACACKQMANwMAIAAgAikDCDcDCCAAIAIpAxA3AxAgACACKQMYNwMYIAAgAikDIDcDICAAIAIpAyg3AyggACACKQMwNwMwIAAgAikDODcDOCAAIAIpA0A3A0AgBCAAKQIANwIAIAQgACkCCDcCCCAEIAApAhA3AhAgBCAAKQIYNwIYIAQgACkCIDcCICAEIAApAig3AiggBCAAKQIwNwIwIAQgACkCODcCOCAEIAApAkA3AkAgCiAJEBcgChAbIAwkAgsLklcBE38CQCMCIREjAkHwB2okAiAAKAKQAUEBRiIIBEAgACgClAFFBEAgESQCDwsLIBFBqAdqIQIgEUHgBmohASARQZgGaiEDIBFB0AVqIQUgEUGIBWohBiARQcAEaiEOIBFB+ANqIQcgEUGwA2ohCyARQegCaiENIBFBoAJqIQQgEUHYAWohCSARQZABaiEKIBFByABqIRAgESEPIABBkAFqIRICfwJAIAhFDQAgACgClAFBAUcNACACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgCSABKQMANwMAIAkgASkDCDcDCCAJIAEpAxA3AxAgCSABKQMYNwMYIAkgASkDIDcDICAJIAEpAyg3AyggCSABKQMwNwMwIAkgASkDODcDOCAJIAEpA0A3A0AgAiAAQcgAaiIMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiAMEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAQgASkDADcDACAEIAEpAwg3AwggBCABKQMQNwMQIAQgASkDGDcDGCAEIAEpAyA3AyAgBCABKQMoNwMoIAQgASkDMDcDMCAEIAEpAzg3AzggBCABKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgBBAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyANIAEpAwA3AwAgDSABKQMINwMIIA0gASkDEDcDECANIAEpAxg3AxggDSABKQMgNwMgIA0gASkDKDcDKCANIAEpAzA3AzAgDSABKQM4NwM4IA0gASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAQQFSABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQAJAAkAgASgCACIEQQhGBEBBCCEIAkACQAJAA0AgCEF/aiEEIAhFDQUgBEEQTw0BIAFBBGogBEECdGooAgAiCCAEQQJ0QcQJaigCACITRw0CIAQhCAwACwALQbwLIARBEBAoDAELIAggE08NAgsFIARBCE8NAQsMAQsgAUHACRAWCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAJEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgBiABKQMANwMAIAYgASkDCDcDCCAGIAEpAxA3AxAgBiABKQMYNwMYIAYgASkDIDcDICAGIAEpAyg3AyggBiABKQMwNwMwIAYgASkDODcDOCAGIAEpA0A3A0AgAiAGKQMANwMAIAIgBikDCDcDCCACIAYpAxA3AxAgAiAGKQMYNwMYIAIgBikDIDcDICACIAYpAyg3AyggAiAGKQMwNwMwIAIgBikDODcDOCACIAYpA0A3A0AgAiANEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgCyABKQMANwMAIAsgASkDCDcDCCALIAEpAxA3AxAgCyABKQMYNwMYIAsgASkDIDcDICALIAEpAyg3AyggCyABKQMwNwMwIAsgASkDODcDOCALIAEpA0A3A0AgCxAaIAIgCSkDADcDACACIAkpAwg3AwggAiAJKQMQNwMQIAIgCSkDGDcDGCACIAkpAyA3AyAgAiAJKQMoNwMoIAIgCSkDMDcDMCACIAkpAzg3AzggAiAJKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIhNHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCATTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNAIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIglHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCAJTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAcgASkDADcDACAHIAEpAwg3AwggByABKQMQNwMQIAcgASkDGDcDGCAHIAEpAyA3AyAgByABKQMoNwMoIAcgASkDMDcDMCAHIAEpAzg3AzggByABKQNANwNAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgBxAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAFIAEpAwA3AwAgBSABKQMINwMIIAUgASkDEDcDECAFIAEpAxg3AxggBSABKQMgNwMgIAUgASkDKDcDKCAFIAEpAzA3AzAgBSABKQM4NwM4IAUgASkDQDcDQCACIAUpAwA3AwAgAiAFKQMINwMIIAIgBSkDEDcDECACIAUpAxg3AxggAiAFKQMgNwMgIAIgBSkDKDcDKCACIAUpAzA3AzAgAiAFKQM4NwM4IAIgBSkDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAOIAEpAwA3AwAgDiABKQMINwMIIA4gASkDEDcDECAOIAEpAxg3AxggDiABKQMgNwMgIA4gASkDKDcDKCAOIAEpAzA3AzAgDiABKQM4NwM4IA4gASkDQDcDQCAGIA0pAwA3AwAgBiANKQMINwMIIAYgDSkDEDcDECAGIA0pAxg3AxggBiANKQMgNwMgIAYgDSkDKDcDKCAGIA0pAzA3AzAgBiANKQM4NwM4IAYgDSkDQDcDQCAGEBogBhAaIAYQGiAPIA4pAwA3AwAgDyAOKQMINwMIIA8gDikDEDcDECAPIA4pAxg3AxggDyAOKQMgNwMgIA8gDikDKDcDKCAPIA4pAzA3AzAgDyAOKQM4NwM4IA8gDikDQDcDQCACIAspAwA3AwAgAiALKQMINwMIIAIgCykDEDcDECACIAspAxg3AxggAiALKQMgNwMgIAIgCykDKDcDKCACIAspAzA3AzAgAiALKQM4NwM4IAIgCykDQDcDQCACIA4QFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAcpAwA3AwAgAiAHKQMINwMIIAIgBykDEDcDECACIAcpAxg3AxggAiAHKQMgNwMgIAIgBykDKDcDKCACIAcpAzA3AzAgAiAHKQM4NwM4IAIgBykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAGEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgECABKQMANwMAIBAgASkDCDcDCCAQIAEpAxA3AxAgECABKQMYNwMYIBAgASkDIDcDICAQIAEpAyg3AyggECABKQMwNwMwIBAgASkDODcDOCAQIAEpA0A3A0AgAiAMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiAMEBUgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0ACQAJAIAEoAgAiBEEIRgRAQQghCAJAAkACQANAIAhBf2ohBCAIRQ0FIARBEE8NASABQQRqIARBAnRqKAIAIgggBEECdEHECWooAgAiAkcNAiAEIQgMAAsAC0G8CyAEQRAQKAwBCyAIIAJPDQILBSAEQQhPDQELDAELIAFBwAkQFgsgCiABKQMANwMAIAogASkDCDcDCCAKIAEpAxA3AxAgCiABKQMYNwMYIAogASkDIDcDICAKIAEpAyg3AyggCiABKQMwNwMwIAogASkDODcDOCAKIAEpA0A3A0AgDAwBCyACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAAQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgCSABKQMANwMAIAkgASkDCDcDCCAJIAEpAxA3AxAgCSABKQMYNwMYIAkgASkDIDcDICAJIAEpAyg3AyggCSABKQMwNwMwIAkgASkDODcDOCAJIAEpA0A3A0AgAiAAQcgAaiIMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiAMEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAQgASkDADcDACAEIAEpAwg3AwggBCABKQMQNwMQIAQgASkDGDcDGCAEIAEpAyA3AyAgBCABKQMoNwMoIAQgASkDMDcDMCAEIAEpAzg3AzggBCABKQNANwNAIAIgBCkDADcDACACIAQpAwg3AwggAiAEKQMQNwMQIAIgBCkDGDcDGCACIAQpAyA3AyAgAiAEKQMoNwMoIAIgBCkDMDcDMCACIAQpAzg3AzggAiAEKQNANwNAIAIgBBAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyANIAEpAwA3AwAgDSABKQMINwMIIA0gASkDEDcDECANIAEpAxg3AxggDSABKQMgNwMgIA0gASkDKDcDKCANIAEpAzA3AzAgDSABKQM4NwM4IA0gASkDQDcDQCACIAApAgA3AgAgAiAAKQIINwIIIAIgACkCEDcCECACIAApAhg3AhggAiAAKQIgNwIgIAIgACkCKDcCKCACIAApAjA3AjAgAiAAKQI4NwI4IAIgACkCQDcCQCACIAQQFSABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQAJAAkAgASgCACIEQQhGBEBBCCEIAkACQAJAA0AgCEF/aiEEIAhFDQUgBEEQTw0BIAFBBGogBEECdGooAgAiCCAEQQJ0QcQJaigCACITRw0CIAQhCAwACwALQbwLIARBEBAoDAELIAggE08NAgsFIARBCE8NAQsMAQsgAUHACRAWCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAJEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgBiABKQMANwMAIAYgASkDCDcDCCAGIAEpAxA3AxAgBiABKQMYNwMYIAYgASkDIDcDICAGIAEpAyg3AyggBiABKQMwNwMwIAYgASkDODcDOCAGIAEpA0A3A0AgAiAGKQMANwMAIAIgBikDCDcDCCACIAYpAxA3AxAgAiAGKQMYNwMYIAIgBikDIDcDICACIAYpAyg3AyggAiAGKQMwNwMwIAIgBikDODcDOCACIAYpA0A3A0AgAiANEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgCyABKQMANwMAIAsgASkDCDcDCCALIAEpAxA3AxAgCyABKQMYNwMYIAsgASkDIDcDICALIAEpAyg3AyggCyABKQMwNwMwIAsgASkDODcDOCALIAEpA0A3A0AgCxAaIAIgCSkDADcDACACIAkpAwg3AwggAiAJKQMQNwMQIAIgCSkDGDcDGCACIAkpAyA3AyAgAiAJKQMoNwMoIAIgCSkDMDcDMCACIAkpAzg3AzggAiAJKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIhNHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCATTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAMgASkDADcDACADIAEpAwg3AwggAyABKQMQNwMQIAMgASkDGDcDGCADIAEpAyA3AyAgAyABKQMoNwMoIAMgASkDMDcDMCADIAEpAzg3AzggAyABKQNANwNAIAIgAykDADcDACACIAMpAwg3AwggAiADKQMQNwMQIAIgAykDGDcDGCACIAMpAyA3AyAgAiADKQMoNwMoIAIgAykDMDcDMCACIAMpAzg3AzggAiADKQNANwNAIAIgCRAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIglHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCAJTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAcgASkDADcDACAHIAEpAwg3AwggByABKQMQNwMQIAcgASkDGDcDGCAHIAEpAyA3AyAgByABKQMoNwMoIAcgASkDMDcDMCAHIAEpAzg3AzggByABKQNANwNAIAIgBykDADcDACACIAcpAwg3AwggAiAHKQMQNwMQIAIgBykDGDcDGCACIAcpAyA3AyAgAiAHKQMoNwMoIAIgBykDMDcDMCACIAcpAzg3AzggAiAHKQNANwNAIAIgBxAXIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAIAEQGyAOIAEpAwA3AwAgDiABKQMINwMIIA4gASkDEDcDECAOIAEpAxg3AxggDiABKQMgNwMgIA4gASkDKDcDKCAOIAEpAzA3AzAgDiABKQM4NwM4IA4gASkDQDcDQCAGIA0pAwA3AwAgBiANKQMINwMIIAYgDSkDEDcDECAGIA0pAxg3AxggBiANKQMgNwMgIAYgDSkDKDcDKCAGIA0pAzA3AzAgBiANKQM4NwM4IAYgDSkDQDcDQCAGEBogBhAaIAYQGiACIA4pAwA3AwAgAiAOKQMINwMIIAIgDikDEDcDECACIA4pAxg3AxggAiAOKQMgNwMgIAIgDikDKDcDKCACIA4pAzA3AzAgAiAOKQM4NwM4IAIgDikDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAMpAwA3AwAgAiADKQMINwMIIAIgAykDEDcDECACIAMpAxg3AxggAiADKQMgNwMgIAIgAykDKDcDKCACIAMpAzA3AzAgAiADKQM4NwM4IAIgAykDQDcDQCACIAsQFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyAPIAEpAwA3AwAgDyABKQMINwMIIA8gASkDEDcDECAPIAEpAxg3AxggDyABKQMgNwMgIA8gASkDKDcDKCAPIAEpAzA3AzAgDyABKQM4NwM4IA8gASkDQDcDQCACIAspAwA3AwAgAiALKQMINwMIIAIgCykDEDcDECACIAspAxg3AxggAiALKQMgNwMgIAIgCykDKDcDKCACIAspAzA3AzAgAiALKQM4NwM4IAIgCykDQDcDQCACIA8QFiABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABLABEBEAgAUHACRAVCyADIAEpAwA3AwAgAyABKQMINwMIIAMgASkDEDcDECADIAEpAxg3AxggAyABKQMgNwMgIAMgASkDKDcDKCADIAEpAzA3AzAgAyABKQM4NwM4IAMgASkDQDcDQCACIAcpAwA3AwAgAiAHKQMINwMIIAIgBykDEDcDECACIAcpAxg3AxggAiAHKQMgNwMgIAIgBykDKDcDKCACIAcpAzA3AzAgAiAHKQM4NwM4IAIgBykDQDcDQCACIAMQFyABIAIpAwA3AwAgASACKQMINwMIIAEgAikDEDcDECABIAIpAxg3AxggASACKQMgNwMgIAEgAikDKDcDKCABIAIpAzA3AzAgASACKQM4NwM4IAEgAikDQDcDQCABEBsgBSABKQMANwMAIAUgASkDCDcDCCAFIAEpAxA3AxAgBSABKQMYNwMYIAUgASkDIDcDICAFIAEpAyg3AyggBSABKQMwNwMwIAUgASkDODcDOCAFIAEpA0A3A0AgAiAFKQMANwMAIAIgBSkDCDcDCCACIAUpAxA3AxAgAiAFKQMYNwMYIAIgBSkDIDcDICACIAUpAyg3AyggAiAFKQMwNwMwIAIgBSkDODcDOCACIAUpA0A3A0AgAiAGEBYgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgASwARARAIAFBwAkQFQsgECABKQMANwMAIBAgASkDCDcDCCAQIAEpAxA3AxAgECABKQMYNwMYIBAgASkDIDcDICAQIAEpAyg3AyggECABKQMwNwMwIBAgASkDODcDOCAQIAEpA0A3A0AgAiAMKQIANwIAIAIgDCkCCDcCCCACIAwpAhA3AhAgAiAMKQIYNwIYIAIgDCkCIDcCICACIAwpAig3AiggAiAMKQIwNwIwIAIgDCkCODcCOCACIAwpAkA3AkAgAiASEBcgASACKQMANwMAIAEgAikDCDcDCCABIAIpAxA3AxAgASACKQMYNwMYIAEgAikDIDcDICABIAIpAyg3AyggASACKQMwNwMwIAEgAikDODcDOCABIAIpA0A3A0AgARAbIAogASkDADcDACAKIAEpAwg3AwggCiABKQMQNwMQIAogASkDGDcDGCAKIAEpAyA3AyAgCiABKQMoNwMoIAogASkDMDcDMCAKIAEpAzg3AzggCiABKQNANwNAIAIgCikDADcDACACIAopAwg3AwggAiAKKQMQNwMQIAIgCikDGDcDGCACIAopAyA3AyAgAiAKKQMoNwMoIAIgCikDMDcDMCACIAopAzg3AzggAiAKKQNANwNAIAIgChAVIAEgAikDADcDACABIAIpAwg3AwggASACKQMQNwMQIAEgAikDGDcDGCABIAIpAyA3AyAgASACKQMoNwMoIAEgAikDMDcDMCABIAIpAzg3AzggASACKQNANwNAAkACQCABKAIAIgRBCEYEQEEIIQgCQAJAAkADQCAIQX9qIQQgCEUNBSAEQRBPDQEgAUEEaiAEQQJ0aigCACIIIARBAnRBxAlqKAIAIgJHDQIgBCEIDAALAAtBvAsgBEEQECgMAQsgCCACTw0CCwUgBEEITw0BCwwBCyABQcAJEBYLIAogASkDADcDACAKIAEpAwg3AwggCiABKQMQNwMQIAogASkDGDcDGCAKIAEpAyA3AyAgCiABKQMoNwMoIAogASkDMDcDMCAKIAEpAzg3AzggCiABKQNANwNAIAwLIQQgACAPKQIANwIAIAAgDykCCDcCCCAAIA8pAhA3AhAgACAPKQIYNwIYIAAgDykCIDcCICAAIA8pAig3AiggACAPKQIwNwIwIAAgDykCODcCOCAAIA8pAkA3AkAgBCAQKQIANwIAIAQgECkCCDcCCCAEIBApAhA3AhAgBCAQKQIYNwIYIAQgECkCIDcCICAEIBApAig3AiggBCAQKQIwNwIwIAQgECkCODcCOCAEIBApAkA3AkAgEiAKKQIANwIAIBIgCikCCDcCCCASIAopAhA3AhAgEiAKKQIYNwIYIBIgCikCIDcCICASIAopAig3AiggEiAKKQIwNwIwIBIgCikCODcCOCASIAopAkA3AkAgESQCCwukBAEQfwJ/IwIhAyMCQZABaiQCIAFBIEcEQCADJAJBAA8LIAAoAhwQOyEBIAAoAhgiAhA7IQQgACgCFCIFEDshByAAKAIQIggQOyEJIAAoAgwiChA7IQsgACgCCCIMEDshDSAAKAIEIg4QOyEPIAAoAgAiEBA7IREgA0HIAGoiAEEAOgBEIABBCDYCACAAIAE2AgQgACAENgIIIAAgBzYCDCAAIAk2AhAgACALNgIUIAAgDTYCGCAAIA82AhwgACARNgIgIABBJGoiAUIANwIAIAFCADcCCCABQgA3AhAgAUIANwIYIAAgEAR/QQgFIA4Ef0EHBSAMBH9BBgUgCgR/QQUFIAgEf0EEBSAFBH9BAwUgAgR/QQIFQQELCwsLCwsLIgE2AgAgAyICIAApAwA3AwAgAiAAKQMINwMIIAIgACkDEDcDECACIAApAxg3AxggAiAAKQMgNwMgIAIgACkDKDcDKCACIAApAzA3AzAgAiAAKQM4NwM4IAIgACkDQDcDQAJAAkACQCACKAIAIgRBCEYEQEEIIQECQAJAAkADQCABQX9qIQAgAUUNBiAAQRBPDQEgAkEEaiAAQQJ0aigCACIBIABBAnRB7ApqKAIAIgVHDQIgACEBDAALAAtBvAsgAEEQECgMAQsgASAFSQ0CDAMLBSAEQQhJDQEMAgsMAgsgBEEBRyACKAIEQQBHckUNAEEBIQYMAQtBACEGCyADJAIgBgsLvQYBD38CQCMCIQgjAkHgAWokAiADQSBJBEBBICADECcLIAghBSACKAIcEDshCSACKAIYEDshCiACKAIUEDshCyACKAIQEDshDCACKAIMEDshDSACKAIIEDshDiACKAIEEDshDyACKAIAEDshBiAIQcgAaiIEQQA6AEQgBCADQQJ2IgI2AgAgBCAJNgIEIAQgCjYCCCAEIAs2AgwgBCAMNgIQIAQgDTYCFCAEIA42AhggBCAPNgIcIAQgBjYCICAEQSRqIgNCADcCACADQgA3AgggA0IANwIQIANCADcCGAJAAkADQAJAIAJBf2oiA0EQTw0CIARBBGogA0ECdGooAgAEQCACIQcMAQsgA0EBSwRAIAMhAgwCBSADIQcLCwsMAQtBsAsgA0EQECgLIAQgBzYCACAFIAQpAwA3AwAgBSAEKQMINwMIIAUgBCkDEDcDECAFIAQpAxg3AxggBSAEKQMgNwMgIAUgBCkDKDcDKCAFIAQpAzA3AzAgBSAEKQM4NwM4IAUgBCkDQDcDQAJAAkAgBSgCACIGQQhGBEBBCCECAkACQAJAA0AgAkF/aiEDIAJFDQYgA0EQTw0BIAVBBGogA0ECdGooAgAiByADQQJ0QewKaigCACICRw0CIAMhAgwACwALQbwLIANBEBAoDAELIAcgAkkNAgsFIAZBCEkNAQsMAQsgBkEBRgRAIAUoAgRFDQELIAQgASAFECAgBCgCBBA7IRAgBCgCCBA7IREgBCgCDBA7IRIgBCgCEBA7IQkgBCgCFBA7IQogBCgCGBA7IQsgBCgCHBA7IQwgBCgCIBA7IQ0gBCgCTBA7IQ4gBCgCUBA7IQ8gBCgCVBA7IQYgBCgCWBA7IQUgBCgCXBA7IQcgBCgCYBA7IQMgBCgCZBA7IQIgBCgCaBA7IQEgAEEBOgAAIABBBDoAASAAIA02AAIgACAMNgAGIAAgCzYACiAAIAo2AA4gACAJNgASIAAgEjYAFiAAIBE2ABogACAQNgAeIAAgATYAIiAAIAI2ACYgACADNgAqIAAgBzYALiAAIAU2ADIgACAGNgA2IAAgDzYAOiAAIA42AD4gCCQCDwsgAEEAOgAAIAgkAgsLdgECfwJAIwIhAiMCQTBqJAIgAkEoaiIDIAA2AgAgAkEsaiIAIAE2AgAgAkEYaiIBIAM2AgAgAUEBNgIEIAEgADYCCCABQQE2AgwgAkGsDzYCACACQQI2AgQgAkEANgIIIAIgATYCECACQQI2AhQgAkG8DxAsCwt1AQJ/AkAjAiEDIwJBMGokAiADQShqIgQgATYCACADQSxqIgEgAjYCACADQRhqIgIgATYCACACQQE2AgQgAiAENgIIIAJBATYCDCADQZwPNgIAIANBAjYCBCADQQA2AgggAyACNgIQIANBAjYCFCADIAAQLAsLDwAgAQR/IAAgAXAFQQALCw8AIAEEfyAAIAFuBUEACwvNAgEHfwJ/IwIhBSMCQTBqJAIgBSEEIAAoAgAiAEGPzgBLBEBBJyEGA0AgAEGQzgAQKSECIABBkM4AECohAyACQeQAECpBAXQhByACQeQAEClBAXQhCCAEIAZBfGoiAmogB0GQF2ouAAA7AAAgBCAGQX5qaiAIQZAXai4AADsAACAAQf/B1y9LBEAgAiEGIAMhAAwBBSADIQALCwVBJyECCyAAQeMASgRAIABB5AAQKUEBdCEDIABB5AAQKiEAIAQgAkF+aiICaiADQZAXai4AADsAAAsgAEEKSAR/IAQgAkF/aiIDaiAAQf8BcUEwajoAACABQQFBrL8BQQAgBCADIgBqQScgAGsQLSEAIAUkAiAABSAEIAJBfmoiA2ogAEEBdEGQF2ouAAA7AAAgAUEBQay/AUEAIAQgAyIAakEnIABrEC0hACAFJAIgAAsLC3QBBH8CQCMCIQIjAkEwaiQCIAEoAgAhAyABKAIEIQQgASgCCCEFIAIiASAAKQIANwIAIAEgACkCCDcCCCABIAApAhA3AhAgAkEYaiIAIAEpAgA3AgAgACABKQIINwIIIAAgASkCEDcCECAAIAMgBCAFEA4LC/cRAQ1/An8jAiEMIwJBEGokAiAAKAIAIQgCQAJAIAEEQCAIQQFxBEBBKyEGDAIFQQAhDkEAIQYgBSEHCwVBLSEGDAELDAELQQEhDiAFQQFqIQcLIAhBBHEEfyACIANqIQsgAwRAIAIhAUEAIQkDQCABLAAAQcABcUGAAUYgCWohCSABQQFqIgEgC0cNAAsFQQAhCQsgByADaiAJayEHQQEFQQALIREgDEEEaiEBIAAoAghFBEAgDkEBRgRAIAAoAhghDSAAKAIcIQogAUEANgIAIAZBgAFJBEAgASAGOgAAQQEhBwUgBkGAEEkEf0FAIQhBASELQQIhByABBSAGQYCABEkEfyABQWA6AABBgH8hCEECIQtBAyEHIAFBAWoFIAFBcDoAACABQYB/OgABQYB/IQhBAyELQQQhByABQQJqCwsiCSAIOgAAIAEgC2ogBkE/cUGAf3I6AAALIA0gASAHIAooAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwsgAEEYaiEBIBEEQCABKAIAIAIgAyAAQRxqIgAoAgAoAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwUgAEEcaiEACyABKAIAIAQgBSAAKAIAKAIMQQNxQQJqEQAAIQAgDCQCIAAPCyAAKAIMIgogB00EQCAOQQFGBEAgACgCGCENIAAoAhwhCiABQQA2AgAgBkGAAUkEQCABIAY6AABBASEHBSAGQYAQSQR/QUAhCEEBIQtBAiEHIAEFIAZBgIAESQR/IAFBYDoAAEGAfyEIQQIhC0EDIQcgAUEBagUgAUFwOgAAIAFBgH86AAFBgH8hCEEDIQtBBCEHIAFBAmoLCyIJIAg6AAAgASALaiAGQT9xQYB/cjoAAAsgDSABIAcgCigCDEEDcUECahEAAEH/AXEEQCAMJAJBAQ8LCyAAQRhqIQEgEQRAIAEoAgAgAiADIABBHGoiACgCACgCDEEDcUECahEAAEH/AXEEQCAMJAJBAQ8LBSAAQRxqIQALIAEoAgAgBCAFIAAoAgAoAgxBA3FBAmoRAAAhACAMJAIgAA8LIAwhCSAIQQhxRQRAIAogB2shBwJAAkACQAJAIAAsADAiCEEDRgR/QQEFIAgLQQNxDgMAAgECCyAHIQhBACEHDAILIAdBAWpBAXYhCCAHQQF2IQcMAQtBACEICyAJQQA2AgAgACgCBCIKQYABSQR/IAkgCjoAAEEBBSAKQYAQSQR/IApBBnZBH3FBQHIhD0EBIRBBAiENIAkFIApBgIAESQR/IAkgCkEMdkEPcUFgcjoAACAKQQZ2QT9xQYB/ciEPQQIhEEEDIQ0gCUEBagUgCSAKQRJ2Qf8BcUFwcjoAACAJIApBDHZBP3FBgH9yOgABIApBBnZBP3FBgH9yIQ9BAyEQQQQhDSAJQQJqCwsiCyAPOgAAIAkgEGogCkE/cUGAf3I6AAAgDQshCyAAQRhqIQ0gAEEcaiEKQQAhAAJAAkADQCAAIAdJBEAgAEEBaiEAIA0oAgAgCSALIAooAgAoAgxBA3FBAmoRAABB/wFxDQIMAQsLDAELIAwkAkEBDwsCQAJAIA5BAUcNACANKAIAIRAgCigCACESIAFBADYCACAGQYABSQRAIAEgBjoAAEEBIQcFIAZBgBBJBH9BQCEOQQEhD0ECIQcgAQUgBkGAgARJBH8gAUFgOgAAQYB/IQ5BAiEPQQMhByABQQFqBSABQXA6AAAgAUGAfzoAAUGAfyEOQQMhD0EEIQcgAUECagsLIgAgDjoAACABIA9qIAZBP3FBgH9yOgAACyAQIAEgByASKAIMQQNxQQJqEQAAQf8BcUUNAAwBCyARBEAgDSgCACACIAMgCigCACgCDEEDcUECahEAAEH/AXENAQsgDSgCACAEIAUgCigCACgCDEEDcUECahEAAEH/AXFFBEBBACEAAkACQANAIAAgCE8NASAAQQFqIQAgDSgCACAJIAsgCigCACgCDEEDcUECahEAAEH/AXFFDQAMAgsACyAMJAJBAA8LIAwkAkEBDwsLIAwkAkEBDwsgAEEEaiIPQTA2AgAgAEEwaiIQQQE6AAAgDkEBRgRAIAAoAhghDiAAKAIcIRIgAUEANgIAIAZBgAFJBEAgASAGOgAAQQEhCAUgBkGAEEkEf0FAIQtBASENQQIhCCABBSAGQYCABEkEfyABQWA6AABBgH8hC0ECIQ1BAyEIIAFBAWoFIAFBcDoAACABQYB/OgABQYB/IQtBAyENQQQhCCABQQJqCwsiCSALOgAAIAEgDWogBkE/cUGAf3I6AAALIA4gASAIIBIoAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwsgEQRAIAAoAhggAiADIAAoAhwoAgxBA3FBAmoRAABB/wFxBEAgDCQCQQEPCwsgCiAHayECAkACQAJAAkAgECwAACIDQQNGBH9BAQUgAwtBA3EOAwACAQILIAIhA0EAIQIMAgsgAkEBakEBdiEDIAJBAXYhAgwBC0EAIQMLIAFBADYCACAPKAIAIgZBgAFJBH8gASAGOgAAQQEFIAZBgBBJBH8gBkEGdkEfcUFAciEIQQEhC0ECIQcgAQUgBkGAgARJBH8gASAGQQx2QQ9xQWByOgAAIAZBBnZBP3FBgH9yIQhBAiELQQMhByABQQFqBSABIAZBEnZB/wFxQXByOgAAIAEgBkEMdkE/cUGAf3I6AAEgBkEGdkE/cUGAf3IhCEEDIQtBBCEHIAFBAmoLCyIJIAg6AAAgASALaiAGQT9xQYB/cjoAACAHCyEJIABBGGohByAAQRxqIQZBACEAAkACQANAIAAgAkkEQCAAQQFqIQAgBygCACABIAkgBigCACgCDEEDcUECahEAAEH/AXENAgwBCwsMAQsgDCQCQQEPCyAHKAIAIAQgBSAGKAIAKAIMQQNxQQJqEQAAQf8BcQRAIAwkAkEBDwVBACEACwJAAkADQCAAIANPDQEgAEEBaiEAIAcoAgAgASAJIAYoAgAoAgxBA3FBAmoRAABB/wFxRQ0ADAILAAsgDCQCQQAPCyAMJAJBAQsLiwEBBn8CQCMCIQEjAkEwaiQCIAAoAgQhAyAAKAIIIQQgACgCDCEFIAAoAhAhBiABQRhqIgIgACgCADYCACACIAM2AgQgASIAIAI2AgAgAEEBNgIEIABBADYCCCAAQfyxATYCECAAQQA2AhQgAUEgaiIBIAQ2AgAgASAFNgIEIAEgBjYCCCAAIAEQLAsLdgECfwJAIwIhAiMCQTBqJAIgAkEoaiIDIAA2AgAgAkEsaiIAIAE2AgAgAkEYaiIBIAM2AgAgAUEBNgIEIAEgADYCCCABQQE2AgwgAkHIDzYCACACQQI2AgQgAkEANgIIIAIgATYCECACQQI2AhQgAkHYDxAsCwswAQJ/An8jAiEBIwJBEGokAiABIgIgACgCPBA4NgIAQQYgAhABEDMhACABJAIgAAsLawEDfwJ/IwIhBCMCQSBqJAIgBCEDIARBEGohBSAAQQM2AiQgACgCAEHAAHFFBEAgAyAAKAI8NgIAIANBk6gBNgIEIAMgBTYCCEE2IAMQBARAIABBfzoASwsLIAAgASACEDchACAEJAIgAAsLZQECfwJ/IwIhBCMCQSBqJAIgBCIDIAAoAjw2AgAgA0EANgIEIAMgATYCCCADIARBFGoiADYCDCADIAI2AhBBjAEgAxACEDNBAEgEfyAAQX82AgBBfwUgACgCAAshACAEJAIgAAsLGgAgAEGAYEsEfxA0QQAgAGs2AgBBfwUgAAsLCAAQNUHAAGoLBAAQNgsFAEHgEAv9AgELfwJ/IwIhBSMCQTBqJAIgBUEQaiEGIAVBIGoiAyAAQRxqIgkoAgAiBDYCACADIABBFGoiCigCACAEayIENgIEIAMgATYCCCADIAI2AgwgBSIBIABBPGoiDCgCADYCACABIAM2AgQgAUECNgIIAkACQCAEIAJqIgRBkgEgARAGEDMiAUYNAEECIQcDQCABQQBOBEAgBCABayEEIANBCGohCCABIAMoAgQiDUsiCwRAIAghAwsgC0EfdEEfdSAHaiEHIAMgAygCACABIAsEfyANBUEAC2siAWo2AgAgA0EEaiIIIAgoAgAgAWs2AgAgBiAMKAIANgIAIAYgAzYCBCAGIAc2AgggBEGSASAGEAYQMyIBRg0CDAELCyAAQQA2AhAgCUEANgIAIApBADYCACAAIAAoAgBBIHI2AgAgB0ECRgR/QQAFIAIgAygCBGsLIQIMAQsgACAAKAIsIgEgACgCMGo2AhAgCSABNgIAIAogATYCAAsgBSQCIAILCwQAIAALUAECfwJ/IAIEfwNAIAAsAAAiAyABLAAAIgRGBEAgAEEBaiEAIAFBAWohAUEAIAJBf2oiAkUNAxoMAQsLIANB/wFxIARB/wFxawVBAAsLIgALnQIBBH8CfyAAIAJqIQQgAUH/AXEhASACQcMATgRAA0AgAEEDcQRAIAAgAToAACAAQQFqIQAMAQsLIARBfHEiBUHAAGshBiABIAFBCHRyIAFBEHRyIAFBGHRyIQMDQCAAIAZMBEAgACADNgIAIAAgAzYCBCAAIAM2AgggACADNgIMIAAgAzYCECAAIAM2AhQgACADNgIYIAAgAzYCHCAAIAM2AiAgACADNgIkIAAgAzYCKCAAIAM2AiwgACADNgIwIAAgAzYCNCAAIAM2AjggACADNgI8IABBwABqIQAMAQsLA0AgACAFSARAIAAgAzYCACAAQQRqIQAMAQsLCwNAIAAgBEgEQCAAIAE6AAAgAEEBaiEADAELCyAEIAJrCwsrACAAQf8BcUEYdCAAQQh1Qf8BcUEQdHIgAEEQdUH/AXFBCHRyIABBGHZyC8kDAQN/An8gAkGAwABOBEAgACABIAIQAw8LIAAhBCAAIAJqIQMgAEEDcSABQQNxRgRAA0AgAEEDcQRAIAJFBEAgBA8LIAAgASwAADoAACAAQQFqIQAgAUEBaiEBIAJBAWshAgwBCwsgA0F8cSICQcAAayEFA0AgACAFTARAIAAgASgCADYCACAAIAEoAgQ2AgQgACABKAIINgIIIAAgASgCDDYCDCAAIAEoAhA2AhAgACABKAIUNgIUIAAgASgCGDYCGCAAIAEoAhw2AhwgACABKAIgNgIgIAAgASgCJDYCJCAAIAEoAig2AiggACABKAIsNgIsIAAgASgCMDYCMCAAIAEoAjQ2AjQgACABKAI4NgI4IAAgASgCPDYCPCAAQcAAaiEAIAFBwABqIQEMAQsLA0AgACACSARAIAAgASgCADYCACAAQQRqIQAgAUEEaiEBDAELCwUgA0EEayECA0AgACACSARAIAAgASwAADoAACAAIAEsAAE6AAEgACABLAACOgACIAAgASwAAzoAAyAAQQRqIQAgAUEEaiEBDAELCwsDQCAAIANIBEAgACABLAAAOgAAIABBAWohACABQQFqIQEMAQsLIAQLCwsAAn9BABAAQQALCwsAAn9BARAAQQALCwsAAn9BAhAAQQALCwu9DA0AQYAIC+QBAQAAAAAAAACCgAAAAAAAAIqAAAAAAACAAIAAgAAAAICLgAAAAAAAAAEAAIAAAAAAgYAAgAAAAIAJgAAAAAAAgIoAAAAAAAAAiAAAAAAAAAAJgACAAAAAAAoAAIAAAAAAi4AAgAAAAACLAAAAAAAAgImAAAAAAACAA4AAAAAAAIACgAAAAAAAgIAAAAAAAACACoAAAAAAAAAKAACAAAAAgIGAAIAAAACAgIAAAAAAAIABAACAAAAAAAiAAIAAAACACAAAAC/8///+////////////////////////////////////AEGICgsFAQAAAAEAQdAKCzyxCQAAIgAAAPYCAABYCQAAWQAAADwBAAAIAAAAQUE20Ixe0r87oEiv5tyuuv7///////////////////8AQbALC6kBMwoAACIAAADwAgAA0wkAAGAAAAA9AAAA0wkAAGAAAACBAAAA0wkAAGAAAACLAAAA0wkAAGAAAACTAAAA0wkAAGAAAACbAAAA0wkAAGAAAADvAAAA0wkAAGAAAAD3AAAA0wkAAGAAAAC6AAAA0wkAAGAAAABeAQAA0wkAAGAAAAAxAQAA0wkAAGAAAAAyAQAA0wkAAGAAAAA4AQAA0wkAAGAAAAA9AQAAAQBBoA0LadMJAABgAAAAbgMAAFUKAABcAAAAEAAAADMKAAAiAAAA9gIAANMJAABgAAAAHgQAABQLAAAoAAAAsQoAAGMAAABCAAAAsQoAAGMAAAA9AAAAsQoAAGMAAABQAAAAsQoAAGMAAABSAAAAAQBB0A4LAQEAQZgPC00BAAAAXgsAACAAAAB+CwAAEgAAAFgMAAAGAAAAXgwAACIAAAA8CwAAIgAAAKACAACADAAAFgAAAJYMAAANAAAAPAsAACIAAACmAgAABQBB8A8LAQEAQYgQCw4BAAAAAgAAALRfAAAABABBoBALAQEAQa8QCwUK/////wBBnBILAiRZAEHUEgvPBuQHAAAvaG9tZS9tYWNpZWovLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvdGlueS1rZWNjYWstMS4yLjEvc3JjL2xpYi5ycy9jaGVja291dC9zcmMvbGliY29yZS9zbGljZS9tb2QucnMvaG9tZS9tYWNpZWovLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvdGlueS1zZWNwMjU2azEtMC4xLjAvc3JjL2JpZ19udW0ucnMvY2hlY2tvdXQvc3JjL2xpYmNvcmUvc2xpY2UvbW9kLnJzL2hvbWUvbWFjaWVqLy5jYXJnby9yZWdpc3RyeS9zcmMvZ2l0aHViLmNvbS0xZWNjNjI5OWRiOWVjODIzL3Rpbnktc2VjcDI1NmsxLTAuMS4wL3NyYy9uYWYucnMvaG9tZS9tYWNpZWovLmNhcmdvL3JlZ2lzdHJ5L3NyYy9naXRodWIuY29tLTFlY2M2Mjk5ZGI5ZWM4MjMvdGlueS1zZWNwMjU2azEtMC4xLjAvc3JjL2VjX3BvaW50X2cucnNpbnRlcm5hbCBlcnJvcjogZW50ZXJlZCB1bnJlYWNoYWJsZSBjb2RlL2NoZWNrb3V0L3NyYy9saWJjb3JlL3NsaWNlL21vZC5yc2luZGV4IG91dCBvZiBib3VuZHM6IHRoZSBsZW4gaXMgIGJ1dCB0aGUgaW5kZXggaXMgMDAwMTAyMDMwNDA1MDYwNzA4MDkxMDExMTIxMzE0MTUxNjE3MTgxOTIwMjEyMjIzMjQyNTI2MjcyODI5MzAzMTMyMzMzNDM1MzYzNzM4Mzk0MDQxNDI0MzQ0NDU0NjQ3NDg0OTUwNTE1MjUzNTQ1NTU2NTc1ODU5NjA2MTYyNjM2NDY1NjY2NzY4Njk3MDcxNzI3Mzc0NzU3Njc3Nzg3OTgwODE4MjgzODQ4NTg2ODc4ODg5OTA5MTkyOTM5NDk1OTY5Nzk4OTlpbmRleCAgb3V0IG9mIHJhbmdlIGZvciBzbGljZSBvZiBsZW5ndGggc2xpY2UgaW5kZXggc3RhcnRzIGF0ICBidXQgZW5kcyBhdCA=', 'base64'); diff --git a/js/src/api/local/ethkey/index.js b/js/src/api/local/ethkey/index.js deleted file mode 100644 index 07ca34ba11ed1128d5c9e8d7ad6e9732eb95e780..0000000000000000000000000000000000000000 --- a/js/src/api/local/ethkey/index.js +++ /dev/null @@ -1,47 +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 . - -import workerPool from './workerPool'; - -export function createKeyObject (key, password) { - return workerPool.action('createKeyObject', { key, password }) - .then((obj) => JSON.parse(obj)); -} - -export function decryptPrivateKey (keyObject, password) { - return workerPool - .action('decryptPrivateKey', { keyObject, password }) - .then((privateKey) => { - if (privateKey) { - return Buffer.from(privateKey); - } - - return null; - }); -} - -export function phraseToAddress (phrase) { - return phraseToWallet(phrase) - .then((wallet) => wallet.address); -} - -export function phraseToWallet (phrase) { - return workerPool.action('phraseToWallet', phrase); -} - -export function verifySecret (secret) { - return workerPool.action('verifySecret', secret); -} diff --git a/js/src/api/local/ethkey/index.spec.js b/js/src/api/local/ethkey/index.spec.js deleted file mode 100644 index ce4cc29df9ba1ed70481740a70e9b1a5e1cc525e..0000000000000000000000000000000000000000 --- a/js/src/api/local/ethkey/index.spec.js +++ /dev/null @@ -1,58 +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 . - -import { randomPhrase } from '@parity/wordlist'; -import { phraseToAddress, phraseToWallet } from './'; - -// TODO: Skipping until Node.js 8.0 comes out and we can test WebAssembly -describe.skip('api/local/ethkey', () => { - describe('phraseToAddress', function () { - this.timeout(30000); - - it('generates a valid address', () => { - const phrase = randomPhrase(12); - - return phraseToAddress(phrase).then((address) => { - expect(address.length).to.be.equal(42); - expect(address.slice(0, 4)).to.be.equal('0x00'); - }); - }); - - it('generates valid address for empty phrase', () => { - return phraseToAddress('').then((address) => { - expect(address).to.be.equal('0x00a329c0648769a73afac7f9381e08fb43dbea72'); - }); - }); - }); - - describe('phraseToWallet', function () { - this.timeout(30000); - - it('generates a valid wallet object', () => { - const phrase = randomPhrase(12); - - return phraseToWallet(phrase).then((wallet) => { - expect(wallet.address.length).to.be.equal(42); - expect(wallet.secret.length).to.be.equal(66); - expect(wallet.public.length).to.be.equal(130); - - expect(wallet.address.slice(0, 4)).to.be.equal('0x00'); - expect(wallet.secret.slice(0, 2)).to.be.equal('0x'); - expect(wallet.public.slice(0, 2)).to.be.equal('0x'); - }); - }); - }); -}); diff --git a/js/src/api/local/ethkey/worker.js b/js/src/api/local/ethkey/worker.js deleted file mode 100644 index 76ccf06b2271a6645d7bb365b065ed37116e7aa0..0000000000000000000000000000000000000000 --- a/js/src/api/local/ethkey/worker.js +++ /dev/null @@ -1,138 +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 . - -import { bytesToHex } from '~/api/util/format'; -import { extern, slice } from './ethkey.js'; - -const isWorker = typeof self !== 'undefined'; - -// Stay compatible between environments -if (!isWorker) { - const scope = typeof global === 'undefined' ? window : global; - - scope.self = scope; -} - -// keythereum should never be used outside of the browser -let keythereum = require('keythereum'); - -if (isWorker) { - keythereum = self.keythereum; -} - -function route ({ action, payload }) { - if (action in actions) { - return actions[action](payload); - } - - return null; -} - -const input = slice(extern._input_ptr(), 1024); -const secret = slice(extern._secret_ptr(), 32); -const publicKey = slice(extern._public_ptr(), 64); -const address = slice(extern._address_ptr(), 20); - -extern._ecpointg(); - -const actions = { - phraseToWallet (phrase) { - const phraseUtf8 = Buffer.from(phrase, 'utf8'); - - if (phraseUtf8.length > input.length) { - throw new Error('Phrase is too long!'); - } - - input.set(phraseUtf8); - - extern._brain(phraseUtf8.length); - - const wallet = { - secret: bytesToHex(secret), - public: bytesToHex(publicKey), - address: bytesToHex(address) - }; - - return wallet; - }, - - verifySecret (key) { - const keyBuf = Buffer.from(key.slice(2), 'hex'); - - secret.set(keyBuf); - - return extern._verify_secret(); - }, - - createKeyObject ({ key, password }) { - key = Buffer.from(key); - password = Buffer.from(password); - - const iv = keythereum.crypto.randomBytes(16); - const salt = keythereum.crypto.randomBytes(32); - const keyObject = keythereum.dump(password, key, salt, iv); - - return JSON.stringify(keyObject); - }, - - decryptPrivateKey ({ keyObject, password }) { - password = Buffer.from(password); - - try { - const key = keythereum.recover(password, keyObject); - - // Convert to array to safely send from the worker - return Array.from(key); - } catch (e) { - return null; - } - } -}; - -self.onmessage = function ({ data }) { - try { - const result = route(data); - - postMessage([null, result]); - } catch (err) { - console.error(err); - postMessage([err.toString(), null]); - } -}; - -// Emulate a web worker in Node.js -class KeyWorker { - postMessage (data) { - // Force async - setTimeout(() => { - try { - const result = route(data); - - this.onmessage({ data: [null, result] }); - } catch (err) { - this.onmessage({ data: [err, null] }); - } - }, 0); - } - - onmessage (event) { - // no-op to be overriden - } -} - -if (exports != null) { - exports.KeyWorker = KeyWorker; -} diff --git a/js/src/api/local/ethkey/workerPool.js b/js/src/api/local/ethkey/workerPool.js deleted file mode 100644 index d7db73b419be0ac35fd9cddf67ff5bf24c37802b..0000000000000000000000000000000000000000 --- a/js/src/api/local/ethkey/workerPool.js +++ /dev/null @@ -1,105 +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 . - -// Allow a web worker in the browser, with a fallback for Node.js -const hasWebWorkers = typeof Worker !== 'undefined'; -const KeyWorker = hasWebWorkers ? require('worker-loader!./worker') - : require('./worker').KeyWorker; - -class WorkerContainer { - busy = false; - _worker = new KeyWorker(); - - action (action, payload) { - if (this.busy) { - throw new Error('Cannot issue an action on a busy worker!'); - } - - this.busy = true; - - return new Promise((resolve, reject) => { - this._worker.postMessage({ action, payload }); - this._worker.onmessage = ({ data }) => { - const [err, result] = data; - - this.busy = false; - - if (err) { - // `err` ought to be a String - reject(new Error(err)); - } else { - resolve(result); - } - }; - }); - } -} - -class WorkerPool { - pool = [ - new WorkerContainer(), - new WorkerContainer() - ]; - - queue = []; - - _getContainer () { - return this.pool.find((container) => !container.busy); - } - - action (action, payload) { - let container = this.pool.find((container) => !container.busy); - - let promise; - - // const start = Date.now(); - - if (container) { - promise = container.action(action, payload); - } else { - promise = new Promise((resolve, reject) => { - this.queue.push([action, payload, resolve]); - }); - } - - return promise - .catch((err) => { - this.processQueue(); - - throw err; - }) - .then((result) => { - this.processQueue(); - - // console.log('Work done in ', Date.now() - start); - - return result; - }); - } - - processQueue () { - let container = this._getContainer(); - - while (container && this.queue.length > 0) { - const [action, payload, resolve] = this.queue.shift(); - - resolve(container.action(action, payload)); - container = this._getContainer(); - } - } -} - -export default new WorkerPool(); diff --git a/js/src/api/local/index.js b/js/src/api/local/index.js deleted file mode 100644 index 190a38ea4f612115624cd8533a842c4cecfbe24b..0000000000000000000000000000000000000000 --- a/js/src/api/local/index.js +++ /dev/null @@ -1,17 +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 . - -export default null; diff --git a/js/src/api/local/localAccountsMiddleware.js b/js/src/api/local/localAccountsMiddleware.js deleted file mode 100644 index c452f541afa5fcb332ccb1b465b4ec86908b83f5..0000000000000000000000000000000000000000 --- a/js/src/api/local/localAccountsMiddleware.js +++ /dev/null @@ -1,288 +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 . - -import EthereumTx from 'ethereumjs-tx'; -import accounts from './accounts'; -import transactions from './transactions'; -import { Middleware } from '../transport'; -import { inNumber16 } from '../format/input'; -import { phraseToWallet, phraseToAddress, verifySecret } from './ethkey'; -import { randomPhrase } from '@parity/wordlist'; - -export default class LocalAccountsMiddleware extends Middleware { - constructor (transport) { - super(transport); - - const register = this.register.bind(this); - - register('eth_accounts', () => { - return accounts.accountAddresses(); - }); - - register('eth_coinbase', () => { - return accounts.lastAddress; - }); - - register('parity_accountsInfo', () => { - return accounts.map(({ name }) => { - return { name }; - }); - }); - - register('parity_allAccountsInfo', () => { - return accounts.map(({ name, meta, uuid }) => { - return { name, meta, uuid }; - }); - }); - - register('parity_changePassword', ([address, oldPassword, newPassword]) => { - const account = accounts.get(address); - - return account - .decryptPrivateKey(oldPassword) - .then((privateKey) => { - if (!privateKey) { - return false; - } - - account.changePassword(privateKey, newPassword); - - return true; - }); - }); - - register('parity_checkRequest', ([id]) => { - return transactions.hash(id) || Promise.resolve(null); - }); - - register('parity_dappsList', () => { - return []; - }); - - register('parity_defaultAccount', () => { - return accounts.dappsDefaultAddress; - }); - - register('parity_exportAccount', ([address, password]) => { - const account = accounts.get(address); - - if (!password) { - password = ''; - } - - return account.isValidPassword(password) - .then((isValid) => { - if (!isValid) { - throw new Error('Invalid password'); - } - - return account.export(); - }); - }); - - register('parity_generateSecretPhrase', () => { - return randomPhrase(12); - }); - - register('parity_getNewDappsAddresses', () => { - return accounts.accountAddresses(); - }); - - register('parity_getNewDappsDefaultAddress', () => { - return accounts.dappsDefaultAddress; - }); - - register('parity_hardwareAccountsInfo', () => { - return {}; - }); - - register('parity_newAccountFromPhrase', ([phrase, password]) => { - return phraseToWallet(phrase) - .then((wallet) => { - return accounts.create(wallet.secret, password); - }); - }); - - register('parity_newAccountFromSecret', ([secret, password]) => { - return verifySecret(secret) - .then((isValid) => { - if (!isValid) { - throw new Error('Invalid secret key'); - } - - return accounts.create(secret, password); - }); - }); - - register('parity_newAccountFromWallet', ([json, password]) => { - if (!password) { - password = ''; - } - - return accounts.restoreFromWallet(JSON.parse(json), password); - }); - - register('parity_setAccountMeta', ([address, meta]) => { - accounts.getLazyCreate(address).meta = meta; - - return true; - }); - - register('parity_setAccountName', ([address, name]) => { - accounts.getLazyCreate(address).name = name; - - return true; - }); - - register('parity_setNewDappsDefaultAddress', ([address]) => { - accounts.dappsDefaultAddress = address; - - return true; - }); - - register('parity_postTransaction', ([tx]) => { - if (!tx.from) { - tx.from = accounts.lastAddress; - } - - tx.nonce = null; - tx.condition = null; - - return transactions.add(tx); - }); - - register('parity_phraseToAddress', ([phrase]) => { - return phraseToAddress(phrase); - }); - - register('parity_useLocalAccounts', () => { - return true; - }); - - register('parity_listGethAccounts', () => { - return []; - }); - - register('parity_listOpenedVaults', () => { - return []; - }); - - register('parity_listRecentDapps', () => { - return {}; - }); - - register('parity_listVaults', () => { - return []; - }); - - register('parity_wsUrl', () => { - // This is a hack, will be replaced by a `hostname` setting on the node itself - return `${window.location.hostname}:8546`; - }); - - register('parity_dappsUrl', () => { - // This is a hack, will be replaced by a `hostname` setting on the node itself - return `${window.location.hostname}:8545`; - }); - - register('parity_hashContent', () => { - throw new Error('Functionality unavailable on a public wallet.'); - }); - - register('parity_killAccount', ([address, password]) => { - return accounts.remove(address, password); - }); - - register('parity_removeAddress', ([address]) => { - return accounts.remove(address, null); - }); - - register('parity_testPassword', ([address, password]) => { - const account = accounts.get(address); - - return account.isValidPassword(password); - }); - - register('parity_upgradeReady', () => { - return false; - }); - - register('signer_confirmRequest', ([id, modify, password]) => { - const { - gasPrice, - gas: gasLimit, - from, - to, - value, - data - } = Object.assign(transactions.get(id), modify); - - transactions.lock(id); - - const account = accounts.get(from); - - return Promise.all([ - this.rpcRequest('parity_nextNonce', [from]), - account.decryptPrivateKey(password) - ]) - .catch((err) => { - transactions.unlock(id); - - // transaction got unlocked, can propagate rejection further - throw err; - }) - .then(([nonce, privateKey]) => { - if (!privateKey) { - transactions.unlock(id); - - throw new Error('Invalid password'); - } - - const tx = new EthereumTx({ - nonce, - to, - data, - gasLimit: inNumber16(gasLimit), - gasPrice: inNumber16(gasPrice), - value: inNumber16(value) - }); - - tx.sign(privateKey); - - const serializedTx = `0x${tx.serialize().toString('hex')}`; - - return this.rpcRequest('eth_sendRawTransaction', [serializedTx]); - }) - .then((hash) => { - transactions.confirm(id, hash); - - return {}; - }); - }); - - register('signer_generateAuthorizationToken', () => { - return ''; - }); - - register('signer_rejectRequest', ([id]) => { - return transactions.reject(id); - }); - - register('signer_requestsToConfirm', () => { - return transactions.requestsToConfirm(); - }); - } -} diff --git a/js/src/api/local/localAccountsMiddleware.spec.js b/js/src/api/local/localAccountsMiddleware.spec.js deleted file mode 100644 index b3de3992d1d064137d844333d33b30d800422899..0000000000000000000000000000000000000000 --- a/js/src/api/local/localAccountsMiddleware.spec.js +++ /dev/null @@ -1,157 +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 . - -import LocalAccountsMiddleware from './localAccountsMiddleware'; -import JsonRpcBase from '../transport/jsonRpcBase'; - -const RPC_RESPONSE = Symbol('RPC response'); -const ADDRESS = '0x00a329c0648769a73afac7f9381e08fb43dbea72'; -const SECRET = '0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7'; -const PASSWORD = 'password'; - -const FOO_PHRASE = 'foobar'; -const FOO_PASSWORD = 'foopass'; -const FOO_ADDRESS = '0x007ef7ac1058e5955e366ab9d6b6c4ebcc937e7e'; - -class MockedTransport extends JsonRpcBase { - _execute (method, params) { - return RPC_RESPONSE; - } -} - -// Skip till all CI runs on Node 8+ -describe.skip('api/local/LocalAccountsMiddleware', function () { - this.timeout(30000); - - let transport; - - beforeEach(() => { - transport = new MockedTransport(); - transport.addMiddleware(LocalAccountsMiddleware); - - // Same as `parity_newAccountFromPhrase` with empty phrase - return transport - .execute('parity_newAccountFromSecret', SECRET, PASSWORD) - .catch((_err) => { - // Ignore the error - all instances of LocalAccountsMiddleware - // share account storage - }); - }); - - it('registers all necessary methods', () => { - return Promise - .all([ - 'eth_accounts', - 'eth_coinbase', - 'parity_accountsInfo', - 'parity_allAccountsInfo', - 'parity_changePassword', - 'parity_checkRequest', - 'parity_defaultAccount', - 'parity_generateSecretPhrase', - 'parity_getNewDappsAddresses', - 'parity_hardwareAccountsInfo', - 'parity_newAccountFromPhrase', - 'parity_newAccountFromSecret', - 'parity_setAccountMeta', - 'parity_setAccountName', - 'parity_postTransaction', - 'parity_phraseToAddress', - 'parity_useLocalAccounts', - 'parity_listGethAccounts', - 'parity_listOpenedVaults', - 'parity_listRecentDapps', - 'parity_listVaults', - 'parity_killAccount', - 'parity_testPassword', - 'signer_confirmRequest', - 'signer_rejectRequest', - 'signer_requestsToConfirm' - ].map((method) => { - return transport - .execute(method) - .then((result) => { - expect(result).not.to.be.equal(RPC_RESPONSE); - }) - // Some errors are expected here since we are calling methods - // without parameters. - .catch((_) => {}); - })); - }); - - it('allows non-registered methods through', () => { - return transport - .execute('eth_getBalance', '0x407d73d8a49eeb85d32cf465507dd71d507100c1') - .then((result) => { - expect(result).to.be.equal(RPC_RESPONSE); - }); - }); - - it('can handle `eth_accounts`', () => { - return transport - .execute('eth_accounts') - .then((accounts) => { - expect(accounts.length).to.be.equal(1); - expect(accounts[0]).to.be.equal(ADDRESS); - }); - }); - - it('can handle `parity_defaultAccount`', () => { - return transport - .execute('parity_defaultAccount') - .then((address) => { - expect(address).to.be.equal(ADDRESS); - }); - }); - - it('can handle `parity_phraseToAddress`', () => { - return transport - .execute('parity_phraseToAddress', '') - .then((address) => { - expect(address).to.be.equal(ADDRESS); - - return transport.execute('parity_phraseToAddress', FOO_PHRASE); - }) - .then((address) => { - expect(address).to.be.equal(FOO_ADDRESS); - }); - }); - - it('can create and kill an account', () => { - return transport - .execute('parity_newAccountFromPhrase', FOO_PHRASE, FOO_PASSWORD) - .then((address) => { - expect(address).to.be.equal(FOO_ADDRESS); - - return transport.execute('eth_accounts'); - }) - .then((accounts) => { - expect(accounts.length).to.be.equal(2); - expect(accounts.includes(FOO_ADDRESS)).to.be.true; - - return transport.execute('parity_killAccount', FOO_ADDRESS, FOO_PASSWORD); - }) - .then((result) => { - expect(result).to.be.true; - - return transport.execute('eth_accounts'); - }) - .then((accounts) => { - expect(accounts.length).to.be.equal(1); - expect(accounts.includes(FOO_ADDRESS)).to.be.false; - }); - }); -}); diff --git a/js/src/api/local/transactions.js b/js/src/api/local/transactions.js deleted file mode 100644 index 421e730123d9eadb6ecd3d0140a1bc53d1d4e986..0000000000000000000000000000000000000000 --- a/js/src/api/local/transactions.js +++ /dev/null @@ -1,147 +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 . - -import { toHex } from '../util/format'; -import { TransportError } from '../transport'; - -const AWAITING = Symbol('awaiting'); -const LOCKED = Symbol('locked'); -const CONFIRMED = Symbol('confirmed'); -const REJECTED = Symbol('rejected'); - -class Transactions { - constructor () { - this.reset(); - } - - // should only really be needed in the constructor and tests - reset () { - this._id = 1; - this._states = {}; - } - - nextId () { - return toHex(this._id++); - } - - add (tx) { - const id = this.nextId(); - - this._states[id] = { - status: AWAITING, - transaction: tx - }; - - return id; - } - - get (id) { - const state = this._states[id]; - - if (!state || state.status !== AWAITING) { - return null; - } - - return state.transaction; - } - - lock (id) { - const state = this._states[id]; - - if (!state || state.status !== AWAITING) { - throw new Error('Trying to lock an invalid transaction'); - } - - state.status = LOCKED; - } - - unlock (id) { - const state = this._states[id]; - - if (!state || state.status !== LOCKED) { - throw new Error('Trying to unlock an invalid transaction'); - } - - state.status = AWAITING; - } - - hash (id) { - const state = this._states[id]; - - if (!state) { - return null; - } - - switch (state.status) { - case REJECTED: - throw TransportError.requestRejected(); - case CONFIRMED: - return state.hash; - default: - return null; - } - } - - confirm (id, hash) { - const state = this._states[id]; - const status = state ? state.status : null; - - switch (status) { - case AWAITING: break; - case LOCKED: break; - default: throw new Error('Trying to confirm an invalid transaction'); - } - - state.hash = hash; - state.status = CONFIRMED; - } - - reject (id) { - const state = this._states[id]; - - if (!state) { - return false; - } - - state.status = REJECTED; - - return true; - } - - requestsToConfirm () { - const result = []; - - Object.keys(this._states).forEach((id) => { - const state = this._states[id]; - - if (state.status === AWAITING) { - result.push({ - id, - origin: { - signer: '0x0' - }, - payload: { - sendTransaction: state.transaction - } - }); - } - }); - - return result; - } -} - -export default new Transactions(); diff --git a/js/src/api/local/transactions.spec.js b/js/src/api/local/transactions.spec.js deleted file mode 100644 index 65f2d8ddc3951d66d35bc83c38037e14002de647..0000000000000000000000000000000000000000 --- a/js/src/api/local/transactions.spec.js +++ /dev/null @@ -1,85 +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 . - -import transactions from './transactions'; -import { TransportError } from '../transport/error'; - -const DUMMY_TX = 'dummy'; - -describe('api/local/transactions', () => { - beforeEach(() => { - transactions.reset(); - }); - - it('can store transactions', () => { - const id1 = transactions.add(DUMMY_TX); - const id2 = transactions.add(DUMMY_TX); - const requests = transactions.requestsToConfirm(); - - expect(id1).to.be.equal('0x1'); - expect(id2).to.be.equal('0x2'); - expect(requests.length).to.be.equal(2); - expect(requests[0].id).to.be.equal(id1); - expect(requests[1].id).to.be.equal(id2); - expect(requests[0].payload.sendTransaction).to.be.equal(DUMMY_TX); - expect(requests[1].payload.sendTransaction).to.be.equal(DUMMY_TX); - }); - - it('can confirm transactions', () => { - const id1 = transactions.add(DUMMY_TX); - const id2 = transactions.add(DUMMY_TX); - - const hash1 = '0x1111111111111111111111111111111111111111'; - const hash2 = '0x2222222222222222222222222222222222222222'; - - transactions.confirm(id1, hash1); - transactions.confirm(id2, hash2); - - const requests = transactions.requestsToConfirm(); - - expect(requests.length).to.be.equal(0); - expect(transactions.hash(id1)).to.be.equal(hash1); - expect(transactions.hash(id2)).to.be.equal(hash2); - }); - - it('can reject transactions', () => { - const id = transactions.add(DUMMY_TX); - - transactions.reject(id); - - const requests = transactions.requestsToConfirm(); - - expect(requests.length).to.be.equal(0); - expect(() => transactions.hash(id)).to.throw(TransportError); - }); - - it('can lock and confirm transactions', () => { - const id = transactions.add(DUMMY_TX); - const hash = '0x1111111111111111111111111111111111111111'; - - transactions.lock(id); - - const requests = transactions.requestsToConfirm(); - - expect(requests.length).to.be.equal(0); - expect(transactions.get(id)).to.be.null; - expect(transactions.hash(id)).to.be.null; - - transactions.confirm(id, hash); - - expect(transactions.hash(id)).to.be.equal(hash); - }); -}); diff --git a/js/src/api/pubsub/eth/eth.js b/js/src/api/pubsub/eth/eth.js deleted file mode 100644 index 0bbc85bec395f0fb955c3f9da8ba56dba4676edd..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/eth/eth.js +++ /dev/null @@ -1,227 +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 . -import PubsubBase from '../pubsubBase'; - -import { inAddress, inBlockNumber, inHex, inNumber16, inOptions, inFilter } from '../../format/input'; -import { outAddress, outBlock, outNumber, outTransaction, outSyncing, outReceipt, outLog } from '../../format/output'; - -export default class Eth extends PubsubBase { - constructor (transport) { - super(transport); - this._api = 'parity'; - } - - newHeads (callback) { - return this.addListener('eth', 'newHeads', callback); - } - - logs (callback) { - throw Error('not supported yet'); - } - - // eth API - protocolVersion (callback) { - return this.addListener(this._api, 'eth_protocolVersion', callback); - } - - syncing (callback) { - return this.addListener(this._api, 'eth_syncing', (error, data) => { - error - ? callback(error) - : callback(null, outSyncing(data)); - }); - } - - hashrate (callback) { - return this.addListener(this._api, 'eth_hashrate', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - coinbase (callback) { - return this.addListener(this._api, 'eth_coinbase', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }); - } - - mining (callback) { - return this.addListener(this._api, 'eth_mining', callback); - } - - gasPrice (callback) { - return this.addListener(this._api, 'eth_gasPrice', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - accounts (callback) { - return this.addListener(this._api, 'eth_accounts', (error, accounts) => { - error - ? callback(error) - : callback(null, (accounts || []).map(outAddress)); - }); - } - - blockNumber (callback) { - return this.addListener(this._api, 'eth_blockNumber', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - getBalance (callback, address, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_getBalance', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inAddress(address), inBlockNumber(blockNumber)]); - } - - getStorageAt (callback, address, index = 0, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_getStorageAt', callback, [inAddress(address), inNumber16(index), inBlockNumber(blockNumber)]); - } - - getBlockByHash (callback, hash, full = false) { - return this.addListener(this._api, 'eth_getBlockByHash', (error, data) => { - error - ? callback(error) - : callback(null, outBlock(data)); - }, [inHex(hash), full]); - } - - getBlockByNumber (callback, blockNumber = 'latest', full = false) { - return this.addListener(this._api, 'eth_getBlockByNumber', (error, data) => { - error - ? callback(error) - : callback(null, outBlock(data)); - }, [inBlockNumber(blockNumber), full]); - } - - getTransactionCount (callback, address, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_getTransactionCount', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inAddress(address), inBlockNumber(blockNumber)]); - } - - getBlockTransactionCountByHash (callback, hash) { - return this.addListener(this._api, 'eth_getBlockTransactionCountByHash', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inHex(hash)]); - } - - getBlockTransactionCountByNumber (callback, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_getBlockTransactionCountByNumber', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inBlockNumber(blockNumber)]); - } - - getUncleCountByBlockHash (callback, hash) { - return this.addListener(this._api, 'eth_getUncleCountByBlockHash', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inHex(hash)]); - } - - getUncleCountByBlockNumber (callback, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_getUncleCountByBlockNumber', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inBlockNumber(blockNumber)]); - } - - getCode (callback, address, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_getCode', callback, [inAddress(address), inBlockNumber(blockNumber)]); - } - - call (callback, options, blockNumber = 'latest') { - return this.addListener(this._api, 'eth_call', callback, [inOptions(options), inBlockNumber(blockNumber)]); - } - - estimateGas (callback, options) { - return this.addListener(this._api, 'eth_estimateGas', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inOptions(options)]); - } - - getTransactionByHash (callback, hash) { - return this.addListener(this._api, 'eth_getTransactionByHash', (error, data) => { - error - ? callback(error) - : callback(null, outTransaction(data)); - }, [inHex(hash)]); - } - - getTransactionByBlockHashAndIndex (callback, hash, index = 0) { - return this.addListener(this._api, 'eth_getTransactionByBlockHashAndIndex', (error, data) => { - error - ? callback(error) - : callback(null, outTransaction(data)); - }, [inHex(hash), inNumber16(index)]); - } - - getTransactionByBlockNumberAndIndex (callback, blockNumber = 'latest', index = 0) { - return this.addListener(this._api, 'eth_getTransactionByBlockNumberAndIndex', (error, data) => { - error - ? callback(error) - : callback(null, outTransaction(data)); - }, [inBlockNumber(blockNumber), inNumber16(index)]); - } - - getTransactionReceipt (callback, txhash) { - return this.addListener(this._api, 'eth_getTransactionReceipt', (error, data) => { - error - ? callback(error) - : callback(null, outReceipt(data)); - }, [inHex(txhash)]); - } - - getUncleByBlockHashAndIndex (callback, hash, index = 0) { - return this.addListener(this._api, 'eth_getUncleByBlockHashAndIndex', callback, [inHex(hash), inNumber16(index)]); - } - - getUncleByBlockNumberAndIndex (callback, blockNumber = 'latest', index = 0) { - return this.addListener(this._api, 'eth_getUncleByBlockNumberAndIndex', callback, [inBlockNumber(blockNumber), inNumber16(index)]); - } - - getLogs (callback, options) { - return this.addListener(this._api, 'eth_getLogs', (error, logs) => { - error - ? callback(error) - : callback(null, (logs) => logs.map(outLog)); - }, [inFilter(options)]); - } - - getWork (callback) { - return this.addListener(this._api, 'eth_getWork', callback); - } -} diff --git a/js/src/api/pubsub/eth/index.js b/js/src/api/pubsub/eth/index.js deleted file mode 100644 index 3b8d1994c3401a1acd24fbe0a336682141bca548..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/eth/index.js +++ /dev/null @@ -1,16 +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 . -export default from './eth'; diff --git a/js/src/api/pubsub/index.js b/js/src/api/pubsub/index.js deleted file mode 100644 index bf342e1de95317686b7b6458499e96cbcbd81e0e..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/index.js +++ /dev/null @@ -1,16 +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 . -export default from './pubsub'; diff --git a/js/src/api/pubsub/net/index.js b/js/src/api/pubsub/net/index.js deleted file mode 100644 index 6d13847c5352357752b98cb9e9c0a62c24c679d5..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/net/index.js +++ /dev/null @@ -1,16 +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 . -export default from './net'; diff --git a/js/src/api/pubsub/net/net.js b/js/src/api/pubsub/net/net.js deleted file mode 100644 index e1dc3c4e16e8b5f0a83340c5e2db7e7a295836eb..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/net/net.js +++ /dev/null @@ -1,42 +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 . -import PubsubBase from '../pubsubBase'; - -import { outNumber } from '../../format/output'; - -export default class Net extends PubsubBase { - constructor (transport) { - super(transport); - this._api = 'parity'; - } - - // net API - version (callback) { - return this.addListener(this._api, 'net_version', callback); - } - - peerCount (callback) { - return this.addListener(this._api, 'net_peerCount', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - listening (callback) { - return this.addListener(this._api, 'net_listening', callback); - } -} diff --git a/js/src/api/pubsub/parity/index.js b/js/src/api/pubsub/parity/index.js deleted file mode 100644 index 33ce7aa7fa412dec16c81ee75a722a841eaeb4ba..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/parity/index.js +++ /dev/null @@ -1,16 +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 . -export default from './parity'; diff --git a/js/src/api/pubsub/parity/parity.js b/js/src/api/pubsub/parity/parity.js deleted file mode 100644 index bf18effa18e6ec1255be82b0b9c7a5902194f042..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/parity/parity.js +++ /dev/null @@ -1,355 +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 . - -import PubsubBase from '../pubsubBase'; -import { inAddress, inBlockNumber, inData, inHex, inDeriveHash, inDeriveIndex } from '../../format/input'; -import { outAccountInfo, outAddress, outBlock, outChainStatus, outHistogram, outHwAccountInfo, outNodeKind, outNumber, outPeers, outTransaction, outAddresses, outRecentDapps, outVaultMeta } from '../../format/output'; - -export default class Parity extends PubsubBase { - constructor (transport) { - super(transport); - this._api = 'parity'; - } - - // parity API - accountsInfo (callback) { - return this.addListener(this._api, 'parity_accountsInfo', (error, data) => { - error - ? callback(error) - : callback(null, outAccountInfo(data)); - }); - } - - hardwareAccountsInfo (callback) { - return this.addListener(this._api, 'parity_hardwareAccountsInfo', (error, data) => { - error - ? callback(error) - : callback(null, outHwAccountInfo(data)); - }); - } - - defaultAccount (callback) { - return this.addListener(this._api, 'parity_defaultAccount', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }); - } - - transactionsLimit (callback) { - return this.addListener(this._api, 'parity_transactionsLimit', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - extraData (callback) { - return this.addListener(this._api, 'parity_extraData', callback); - } - - gasFloorTarget (callback) { - return this.addListener(this._api, 'parity_gasFloorTarget', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - gasCeilTarget (callback) { - return this.addListener(this._api, 'parity_gasCeilTarget', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - minGasPrice (callback) { - return this.addListener(this._api, 'parity_minGasPrice', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - devLogs (callback) { - return this.addListener(this._api, 'parity_devLogs', callback); - } - - devLogsLevels (callback) { - return this.addListener(this._api, 'parity_devLogsLevels', callback); - } - - netChain (callback) { - return this.addListener(this._api, 'parity_netChain', callback); - } - - netPeers (callback) { - return this.addListener(this._api, 'parity_netPeers', (error, data) => { - error - ? callback(error) - : callback(null, outPeers(data)); - }); - } - - netPort (callback) { - return this.addListener(this._api, 'parity_netPort', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - rpcSettings (callback) { - return this.addListener(this._api, 'parity_rpcSettings', callback); - } - - nodeName (callback) { - return this.addListener(this._api, 'parity_nodeName', callback); - } - - defaultExtraData (callback) { - return this.addListener(this._api, 'parity_defaultExtraData', callback); - } - - gasPriceHistogram (callback) { - return this.addListener(this._api, 'parity_gasPriceHistogram', (error, data) => { - error - ? callback(error) - : callback(null, outHistogram(data)); - }); - } - - unsignedTransactionsCount (callback) { - return this.addListener(this._api, 'parity_unsignedTransactionsCount', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }); - } - - registryAddress (callback) { - return this.addListener(this._api, 'parity_registryAddress', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }); - } - - listAccounts (callback, count, offset = null, blockNumber = 'latest') { - return this.addListener(this._api, 'parity_listAccounts', (error, data) => { - error - ? callback(error) - : callback(null, (data) => (data || []).map(outAddress)); - }, [count, inAddress(offset), inBlockNumber(blockNumber)]); - } - - listStorageKeys (callback, address, count, hash = null, blockNumber = 'latest') { - return this.addListener(this._api, 'parity_listStorageKeys', callback, [inAddress(address), count, inHex(hash), inBlockNumber(blockNumber)]); - } - - pendingTransactions (callback) { - return this.addListener(this._api, 'parity_pendingTransactions', (error, data) => { - error - ? callback(error) - : callback(null, outTransaction(data)); - }); - } - - futureTransactions (callback) { - return this.addListener(this._api, 'parity_futureTransactions', (error, data) => { - error - ? callback(error) - : callback(null, outTransaction(data)); - }); - } - - pendingTransactionsStats (callback) { - return this.addListener(this._api, 'parity_pendingTransactionsStats', callback); - } - - localTransactions (callback) { - return this.addListener(this._api, 'parity_localTransactions', (error, transactions) => { - error - ? callback(error) - : callback(null, transactions => { - Object.values(transactions) - .filter(tx => tx.transaction) - .map(tx => { - tx.transaction = outTransaction(tx.transaction); - }); - return transactions; - }); - }); - } - - dappsUrl (callback) { - return this.addListener(this._api, 'parity_dappsUrl', callback); - } - - wsUrl (callback) { - return this.addListener(this._api, 'parity_wsUrl', callback); - } - - nextNonce (callback, account) { - return this.addListener(this._api, 'parity_nextNonce', (error, data) => { - error - ? callback(error) - : callback(null, outNumber(data)); - }, [inAddress(account)]); - } - - mode (callback) { - return this.addListener(this._api, 'parity_mode', callback); - } - - chain (callback) { - return this.addListener(this._api, 'parity_chain', callback); - } - - enode (callback) { - return this.addListener(this._api, 'parity_enode', callback); - } - - consensusCapability (callback) { - return this.addListener(this._api, 'parity_consensusCapability', callback); - } - - versionInfo (callback) { - return this.addListener(this._api, 'parity_versionInfo', callback); - } - - releasesInfo (callback) { - return this.addListener(this._api, 'parity_releasesInfo', callback); - } - - chainStatus (callback) { - return this.addListener(this._api, 'parity_chainStatus', (error, data) => { - error - ? callback(error) - : callback(null, outChainStatus(data)); - }); - } - - nodeKind (callback) { - return this.addListener(this._api, 'parity_nodeKind', (error, data) => { - error - ? callback(error) - : callback(null, outNodeKind(data)); - }); - } - - getBlockHeaderByNumber (callback, blockNumber = 'latest') { - return this.addListener(this._api, 'parity_getBlockHeaderByNumber', (error, data) => { - error - ? callback(error) - : callback(null, outBlock(data)); - }, [inBlockNumber(blockNumber)]); - } - - cidV0 (callback, data) { - return this.addListener(this._api, 'parity_cidV0', callback, [inData(data)]); - } - - // parity accounts API (only secure API or configured to be exposed) - allAccountsInfo (callback) { - return this._addListener(this._api, 'parity_allAccountsInfo', (error, data) => { - error - ? callback(error) - : callback(null, outAccountInfo(data)); - }); - } - - getDappAddresses (callback, dappId) { - return this._addListener(this._api, 'parity_getDappAddresses', (error, data) => { - error - ? callback(error) - : callback(null, outAddresses(data)); - }, [dappId]); - } - - getDappDefaultAddress (callback, dappId) { - return this._addListener(this._api, 'parity_getDappDefaultAddress', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }, [dappId]); - } - - getNewDappsAddresses (callback) { - return this._addListener(this._api, 'parity_getDappDefaultAddress', (error, addresses) => { - error - ? callback(error) - : callback(null, addresses ? addresses.map(outAddress) : null); - }); - } - - getNewDappsDefaultAddress (callback) { - return this._addListener(this._api, 'parity_getNewDappsDefaultAddress', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }); - } - - listRecentDapps (callback) { - return this._addListener(this._api, 'parity_listRecentDapps', (error, data) => { - error - ? callback(error) - : callback(null, outRecentDapps(data)); - }); - } - - listGethAccounts (callback) { - return this._addListener(this._api, 'parity_listGethAccounts', (error, data) => { - error - ? callback(error) - : callback(null, outAddresses(data)); - }); - } - - listVaults (callback) { - return this._addListener(this._api, 'parity_listVaults', callback); - } - - listOpenedVaults (callback) { - return this._addListener(this._api, 'parity_listOpenedVaults', callback); - } - - getVaultMeta (callback, vaultName) { - return this._addListener(this._api, 'parity_getVaultMeta', (error, data) => { - error - ? callback(error) - : callback(null, outVaultMeta(data)); - }, [vaultName]); - } - - deriveAddressHash (callback, address, password, hash, shouldSave) { - return this._addListener(this._api, 'parity_deriveAddressHash', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }, [inAddress(address), password, inDeriveHash(hash), !!shouldSave]); - } - - deriveAddressIndex (callback, address, password, index, shouldSave) { - return this._addListener(this._api, 'parity_deriveAddressIndex', (error, data) => { - error - ? callback(error) - : callback(null, outAddress(data)); - }, [inAddress(address), password, inDeriveIndex(index), !!shouldSave]); - } -} diff --git a/js/src/api/pubsub/pubsub.js b/js/src/api/pubsub/pubsub.js deleted file mode 100644 index edbc201ae5c3ca1e766349b449a4256dcba1d2d7..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/pubsub.js +++ /dev/null @@ -1,50 +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 . - -import Eth from './eth'; -import Parity from './parity'; -import Net from './net'; - -import { isFunction } from '../util/types'; - -export default class Pubsub { - constructor (transport) { - if (!transport || !isFunction(transport.subscribe)) { - throw new Error('Pubsub API needs transport with subscribe() function defined. (WebSocket)'); - } - - this._eth = new Eth(transport); - this._net = new Net(transport); - this._parity = new Parity(transport); - } - - get net () { - return this._net; - } - - get eth () { - return this._eth; - } - - get parity () { - return this._parity; - } - - unsubscribe (subscriptionIds) { - // subscriptions are namespace independent. Thus we can simply removeListener from any. - return this._parity.removeListener(subscriptionIds); - } -} diff --git a/js/src/api/pubsub/pubsub.spec.js b/js/src/api/pubsub/pubsub.spec.js deleted file mode 100644 index 10fcd2edb7a58c91ad5d3fd732755fda8c3dcd63..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/pubsub.spec.js +++ /dev/null @@ -1,613 +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 . - -import BigNumber from 'bignumber.js'; -import { TEST_WS_URL, mockWs } from '../../../test/mockRpc'; -import { isBigNumber } from '../../../test/types'; - -import Ws from '../transport/ws'; -import Pubsub from './pubsub'; - -describe('api/pubsub/Pubsub', () => { - let scope; - let instance; - const address = '0x63Cf90D3f0410092FC0fca41846f596223979195'; - - describe('accountsInfo', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: { - '0x63cf90d3f0410092fc0fca41846f596223979195': { - name: 'name', uuid: 'uuid', meta: '{"data":"data"}' - } - }, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('retrieves the available account info', (done) => { - instance.parity.accountsInfo((error, result) => { - expect(error).to.be.null; - expect(result).to.deep.equal({ - '0x63Cf90D3f0410092FC0fca41846f596223979195': { - name: 'name', uuid: 'uuid', meta: { - data: 'data' - } - } - }); - done(); - }); - }); - }); - - describe('Unsubscribe', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2 }, - { method: 'parity_unsubscribe', reply: true }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('Promise gets resolved on success.', (done) => { - instance.parity.accountsInfo().then(s => { - instance.parity.unsubscribe(s).then(b => { - expect(b).to.be.true; - }); - }); - done(); - }); - }); - - describe('chainStatus', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: { - 'blockGap': [0x123, 0x456] - }, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('retrieves the chain status', (done) => { - instance.parity.chainStatus((error, result) => { - expect(error).to.be.null; - expect(result).to.deep.equal({ - 'blockGap': [new BigNumber(0x123), new BigNumber(0x456)] - }); - done(); - }); - }); - }); - - describe('gasFloorTarget', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123456', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the gasfloor, formatted', (done) => { - instance.parity.gasFloorTarget((error, result) => { - expect(error).to.be.null; - expect(isBigNumber(result)).to.be.true; - expect(result.eq(0x123456)).to.be.true; - done(); - }); - }); - }); - - describe('transactionsLimit', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: 1024, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the tx limit, formatted', (done) => { - instance.parity.transactionsLimit((error, result) => { - expect(error).to.be.null; - expect(isBigNumber(result)).to.be.true; - expect(result.eq(1024)).to.be.true; - done(); - }); - }); - }); - - describe('minGasPrice', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123456', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the min gasprice, formatted', (done) => { - instance.parity.minGasPrice((error, result) => { - expect(error).to.be.null; - expect(isBigNumber(result)).to.be.true; - expect(result.eq(0x123456)).to.be.true; - done(); - }); - }); - }); - - describe('netPeers', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: { active: 123, connected: 456, max: 789, peers: [] }, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the peer structure, formatted', (done) => { - instance.parity.netPeers((error, peers) => { - expect(error).to.be.null; - expect(peers.active.eq(123)).to.be.true; - expect(peers.connected.eq(456)).to.be.true; - expect(peers.max.eq(789)).to.be.true; - done(); - }); - }); - }); - - describe('netPort', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: 33030, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the connected port, formatted', (done) => { - instance.parity.netPort((error, count) => { - expect(error).to.be.null; - expect(isBigNumber(count)).to.be.true; - expect(count.eq(33030)).to.be.true; - done(); - }); - }); - }); - -// Eth API - describe('accounts', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: [address.toLowerCase()], - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns a list of accounts, formatted', (done) => { - instance.eth.accounts((error, accounts) => { - expect(error).to.be.null; - expect(accounts).to.deep.equal([address]); - done(); - }); - }); - }); - - describe('newHeads', () => { - beforeEach(() => { - scope = mockWs([{ method: 'eth_subscribe', reply: 2, subscription: { - method: 'eth_subscription', - params: { - result: '0x123456', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns newHeads for eth_subscribe', (done) => { - instance.eth.newHeads((error, blockNumber) => { - expect(error).to.be.null; - expect(blockNumber).to.equal('0x123456'); - done(); - }); - }); - }); - - describe('blockNumber', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123456', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the current blockNumber, formatted', (done) => { - instance.eth.blockNumber((error, blockNumber) => { - expect(error).to.be.null; - expect(isBigNumber(blockNumber)).to.be.true; - expect(blockNumber.toString(16)).to.equal('123456'); - done(); - }); - }); - }); - - describe('call', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: [], - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('formats the input options & blockNumber', (done) => { - instance.eth.call((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_call', [{ data: '0x12345678' }, 'earliest']]); - done(); - }, { data: '12345678' }, 'earliest'); - }); - - it('provides a latest blockNumber when not specified', (done) => { - instance.eth.call((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_call', [{ data: '0x12345678' }, 'latest']]); - done(); - }, { data: '12345678' }); - }); - }); - - describe('coinbase', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: address.toLowerCase(), - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the coinbase, formatted', (done) => { - instance.eth.coinbase((error, account) => { - expect(error).to.be.null; - expect(account).to.deep.equal(address); - done(); - }); - }); - }); - - describe('estimateGas', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('converts the options correctly', (done) => { - instance.eth.estimateGas((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_estimateGas', [{ gas: '0x5208' }]]); - done(); - }, { gas: 21000 }); - }); - - it('returns the gas used, formatted', (done) => { - instance.eth.estimateGas((error, gas) => { - expect(error).to.be.null; - expect(isBigNumber(gas)).to.be.true; - expect(gas.toString(16)).to.deep.equal('123'); - done(); - }); - }); - }); - - describe('gasPrice', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns the gas price, formatted', (done) => { - instance.eth.gasPrice((error, price) => { - expect(error).to.be.null; - expect(isBigNumber(price)).to.be.true; - expect(price.toString(16)).to.deep.equal('123'); - done(); - }); - }); - }); - - describe('getBalance', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('passes in the address (default blockNumber)', (done) => { - instance.eth.getBalance((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBalance', [address.toLowerCase(), 'latest']]); - done(); - }, address); - }); - - it('passes in the address & blockNumber', (done) => { - instance.eth.getBalance((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBalance', [address.toLowerCase(), '0x456']]); - done(); - }, address, 0x456); - }); - - it('returns the balance', (done) => { - instance.eth.getBalance((error, balance) => { - expect(error).to.be.null; - expect(isBigNumber(balance)).to.be.true; - expect(balance.toString(16)).to.deep.equal('123'); - done(); - }, address); - }); - }); - - describe('getBlockByHash', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: { miner: address.toLowerCase() }, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('formats the input hash as a hash, default full', (done) => { - instance.eth.getBlockByHash((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByHash', ['0x1234', false]]); - done(); - }, '1234'); - }); - - it('formats the input hash as a hash, full true', (done) => { - instance.eth.getBlockByHash((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByHash', ['0x1234', true]]); - done(); - }, '1234', true); - }); - - it('formats the output into block', (done) => { - instance.eth.getBlockByHash((error, block) => { - expect(error).to.be.null; - expect(block.miner).to.equal(address); - done(); - }, '1234'); - }); - }); - - describe('getBlockByNumber', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: { miner: address.toLowerCase() }, - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('assumes blockNumber latest & full false', (done) => { - instance.eth.getBlockByNumber((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByNumber', ['latest', false]]); - done(); - }); - }); - - it('uses input blockNumber & full false', (done) => { - instance.eth.getBlockByNumber((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByNumber', ['0x1234', false]]); - done(); - }, '0x1234'); - }); - - it('formats the input blockNumber, full true', (done) => { - instance.eth.getBlockByNumber((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByNumber', ['0x1234', true]]); - done(); - }, 0x1234, true); - }); - - it('formats the output into block', (done) => { - instance.eth.getBlockByNumber((error, block) => { - expect(error).to.be.null; - expect(block.miner).to.equal(address); - done(); - }, 0x1234); - }); - }); - - describe('getTransactionCount', () => { - beforeEach(() => { - scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: { - method: 'parity_subscription', - params: { - result: '0x123', - subscription: 2 - } - } }]); - instance = new Pubsub(new Ws(TEST_WS_URL)); - }); - - afterEach(() => { - scope.stop(); - }); - - it('passes in the address (default blockNumber)', (done) => { - instance.eth.getTransactionCount((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getTransactionCount', [address.toLowerCase(), 'latest']]); - done(); - }, address); - }); - - it('passes in the address & blockNumber', (done) => { - instance.eth.getTransactionCount((error) => { - expect(error).to.be.null; - expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getTransactionCount', [address.toLowerCase(), '0x456']]); - done(); - }, address, 0x456); - }); - - it('returns the count, formatted', (done) => { - instance.eth.getTransactionCount((error, count) => { - expect(error).to.be.null; - expect(isBigNumber(count)).to.be.true; - expect(count.toString(16)).to.equal('123'); - done(); - }, address, 0x456); - }); - }); -}); diff --git a/js/src/api/pubsub/pubsubBase.js b/js/src/api/pubsub/pubsubBase.js deleted file mode 100644 index fcc7525d5b8d5451c797319bc823b1671ff6cd5f..0000000000000000000000000000000000000000 --- a/js/src/api/pubsub/pubsubBase.js +++ /dev/null @@ -1,37 +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 . - -export default class PubsubBase { - // Provider for websocket pubsub transport - constructor (transport) { - this._transport = transport; - } - - addListener (module, eventName, callback, eventParams) { - return eventParams - ? this._transport.subscribe(module, callback, eventName, eventParams) - : this._transport.subscribe(module, callback, eventName, []); - // this._transport.subscribe(module, callback, eventName); After Patch from tomac is merged to master! => eth_subscribe does not support empty array as params - } - - removeListener (subscriptionIds) { - return this._transport.unsubscribe(subscriptionIds); - } - - unsubscribe (subscriptionIds) { - return this.removeListener(subscriptionIds); - } -} diff --git a/js/src/api/rpc/db/db.js b/js/src/api/rpc/db/db.js deleted file mode 100644 index c87911b8d76ab6484f6048bdd0d43682bfead41f..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/db/db.js +++ /dev/null @@ -1,43 +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 . - -import { inHex } from '../../format/input'; - -export default class Db { - constructor (transport) { - this._transport = transport; - } - - getHex (dbName, keyName) { - return this._transport - .execute('db_getHex', dbName, keyName); - } - - getString (dbName, keyName) { - return this._transport - .execute('db_getString', dbName, keyName); - } - - putHex (dbName, keyName, hexData) { - return this._transport - .execute('db_putHex', dbName, keyName, inHex(hexData)); - } - - putString (dbName, keyName, stringData) { - return this._transport - .execute('db_putString', dbName, keyName, stringData); - } -} diff --git a/js/src/api/rpc/db/db.spec.js b/js/src/api/rpc/db/db.spec.js deleted file mode 100644 index 94256931b97e1e338a14562770bba79548ce717e..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/db/db.spec.js +++ /dev/null @@ -1,38 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; - -import Http from '../../transport/http'; -import Db from './db'; - -const instance = new Db(new Http(TEST_HTTP_URL, -1)); - -describe('api/rpc/Db', () => { - let scope; - - describe('putHex', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'db_putHex', reply: { result: [] } }]); - }); - - it('formats the inputs correctly', () => { - return instance.putHex('db', 'key', '1234').then(() => { - expect(scope.body.db_putHex.params).to.deep.equal(['db', 'key', '0x1234']); - }); - }); - }); -}); diff --git a/js/src/api/rpc/db/index.js b/js/src/api/rpc/db/index.js deleted file mode 100644 index 0dc25441b61df7d795517891723c5ee987095590..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/db/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './db'; diff --git a/js/src/api/rpc/eth/eth.e2e.js b/js/src/api/rpc/eth/eth.e2e.js deleted file mode 100644 index 1c8d95a0b9701566b8a27827a07744f19b9c4f43..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/eth/eth.e2e.js +++ /dev/null @@ -1,170 +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 . - -import { createHttpApi } from '../../../../test/e2e/ethapi'; -import { isAddress } from '../../../../test/types'; - -describe('ethapi.eth', () => { - const ethapi = createHttpApi(); - const address = '0x63cf90d3f0410092fc0fca41846f596223979195'; - - let latestBlockNumber; - let latestBlockHash; - - describe('accounts', () => { - it('returns the available accounts', () => { - return ethapi.eth.accounts().then((accounts) => { - accounts.forEach((account) => { - expect(isAddress(account)).to.be.true; - }); - }); - }); - }); - - describe('blockNumber', () => { - it('returns the current blockNumber', () => { - return ethapi.eth.blockNumber().then((blockNumber) => { - latestBlockNumber = blockNumber; - expect(blockNumber.gt(0xabcde)).to.be.true; - }); - }); - }); - - describe('coinbase', () => { - it('returns the coinbase', () => { - return ethapi.eth.coinbase().then((coinbase) => { - expect(isAddress(coinbase)).to.be.true; - }); - }); - }); - - describe('gasPrice', () => { - it('returns the current gasPrice', () => { - return ethapi.eth.gasPrice().then((gasPrice) => { - expect(gasPrice.gt(0)).to.be.true; - }); - }); - }); - - describe('getBalance', () => { - it('returns the balance for latest block', () => { - return ethapi.eth.getBalance(address).then((balance) => { - expect(balance.gt(0)).to.be.true; - }); - }); - - it('returns the balance for a very early block', () => { - const atBlock = '0x65432'; - const atValue = '18e07120a6e164fee1b'; - - return ethapi.eth - .getBalance(address, atBlock) - .then((balance) => { - expect(balance.toString(16)).to.equal(atValue); - }) - .catch((error) => { - // Parity doesn't support pruned-before-block balance lookups - expect(error.message).to.match(/not supported/); - }); - }); - - it('returns the balance for a recent/out-of-pruning-range block', () => { - return ethapi.eth - .getBalance(address, latestBlockNumber.minus(1000)) - .then((balance) => { - expect(balance.gt(0)).to.be.true; - }); - }); - }); - - describe('getBlockByNumber', () => { - it('returns the latest block', () => { - return ethapi.eth.getBlockByNumber().then((block) => { - expect(block).to.be.ok; - }); - }); - - it('returns a block by blockNumber', () => { - return ethapi.eth.getBlockByNumber(latestBlockNumber).then((block) => { - latestBlockHash = block.hash; - expect(block).to.be.ok; - }); - }); - - it('returns a block by blockNumber (full)', () => { - return ethapi.eth.getBlockByNumber(latestBlockNumber, true).then((block) => { - expect(block).to.be.ok; - }); - }); - }); - - describe('getBlockByHash', () => { - it('returns the specified block', () => { - return ethapi.eth.getBlockByHash(latestBlockHash).then((block) => { - expect(block).to.be.ok; - expect(block.hash).to.equal(latestBlockHash); - }); - }); - - it('returns the specified block (full)', () => { - return ethapi.eth.getBlockByHash(latestBlockHash, true).then((block) => { - expect(block).to.be.ok; - expect(block.hash).to.equal(latestBlockHash); - }); - }); - }); - - describe('getBlockTransactionCountByHash', () => { - it('returns the transactions of the specified hash', () => { - return ethapi.eth.getBlockTransactionCountByHash(latestBlockHash).then((count) => { - expect(count).to.be.ok; - expect(count.gte(0)).to.be.true; - }); - }); - }); - - describe('getBlockTransactionCountByNumber', () => { - it('returns the transactions of latest', () => { - return ethapi.eth.getBlockTransactionCountByNumber().then((count) => { - expect(count).to.be.ok; - expect(count.gte(0)).to.be.true; - }); - }); - - it('returns the transactions of a specified number', () => { - return ethapi.eth.getBlockTransactionCountByNumber(latestBlockNumber).then((count) => { - expect(count).to.be.ok; - expect(count.gte(0)).to.be.true; - }); - }); - }); - - describe('getTransactionCount', () => { - it('returns the count for an address', () => { - return ethapi.eth.getTransactionCount(address).then((count) => { - expect(count).to.be.ok; - expect(count.gte(0x1000c2)).to.be.ok; - }); - }); - - it('returns the count for an address at specified blockNumber', () => { - return ethapi.eth.getTransactionCount(address, latestBlockNumber).then((count) => { - expect(count).to.be.ok; - expect(count.gte(0x1000c2)).to.be.ok; - }); - }); - }); -}); diff --git a/js/src/api/rpc/eth/eth.js b/js/src/api/rpc/eth/eth.js deleted file mode 100644 index ffde938ea954ca5fe8d1182ae4d4bcad0a424d26..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/eth/eth.js +++ /dev/null @@ -1,321 +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 . - -import { inAddress, inBlockNumber, inData, inFilter, inHash, inHex, inNumber16, inOptions } from '../../format/input'; -import { outAddress, outBlock, outLog, outNumber, outReceipt, outSyncing, outTransaction } from '../../format/output'; - -export default class Eth { - constructor (transport) { - this._transport = transport; - } - - accounts () { - return this._transport - .execute('eth_accounts') - .then((accounts) => (accounts || []).map(outAddress)); - } - - blockNumber () { - return this._transport - .execute('eth_blockNumber') - .then(outNumber); - } - - call (options, blockNumber = 'latest') { - return this._transport - .execute('eth_call', inOptions(options), inBlockNumber(blockNumber)); - } - - coinbase () { - return this._transport - .execute('eth_coinbase') - .then(outAddress); - } - - compileLLL (code) { - return this._transport - .execute('eth_compileLLL', inData(code)); - } - - compileSerpent (code) { - return this._transport - .execute('eth_compileSerpent', inData(code)); - } - - compileSolidity (code) { - return this._transport - .execute('eth_compileSolidity', inData(code)); - } - - estimateGas (options) { - return this._transport - .execute('eth_estimateGas', inOptions(options)) - .then(outNumber); - } - - fetchQueuedTransactions () { - return this._transport - .execute('eth_fetchQueuedTransactions'); - } - - flush () { - return this._transport - .execute('eth_flush'); - } - - gasPrice () { - return this._transport - .execute('eth_gasPrice') - .then(outNumber); - } - - getBalance (address, blockNumber = 'latest') { - return this._transport - .execute('eth_getBalance', inAddress(address), inBlockNumber(blockNumber)) - .then(outNumber); - } - - getBlockByHash (hash, full = false) { - return this._transport - .execute('eth_getBlockByHash', inHex(hash), full) - .then(outBlock); - } - - getBlockByNumber (blockNumber = 'latest', full = false) { - return this._transport - .execute('eth_getBlockByNumber', inBlockNumber(blockNumber), full) - .then(outBlock); - } - - getBlockTransactionCountByHash (hash) { - return this._transport - .execute('eth_getBlockTransactionCountByHash', inHex(hash)) - .then(outNumber); - } - - getBlockTransactionCountByNumber (blockNumber = 'latest') { - return this._transport - .execute('eth_getBlockTransactionCountByNumber', inBlockNumber(blockNumber)) - .then(outNumber); - } - - getCode (address, blockNumber = 'latest') { - return this._transport - .execute('eth_getCode', inAddress(address), inBlockNumber(blockNumber)); - } - - getCompilers () { - return this._transport - .execute('eth_getCompilers'); - } - - getFilterChanges (filterId) { - return this._transport - .execute('eth_getFilterChanges', inNumber16(filterId)) - .then((logs) => logs.map(outLog)); - } - - getFilterChangesEx (filterId) { - return this._transport - .execute('eth_getFilterChangesEx', inNumber16(filterId)); - } - - getFilterLogs (filterId) { - return this._transport - .execute('eth_getFilterLogs', inNumber16(filterId)) - .then((logs) => logs.map(outLog)); - } - - getFilterLogsEx (filterId) { - return this._transport - .execute('eth_getFilterLogsEx', inNumber16(filterId)); - } - - getLogs (options) { - return this._transport - .execute('eth_getLogs', inFilter(options)) - .then((logs) => logs.map(outLog)); - } - - getLogsEx (options) { - return this._transport - .execute('eth_getLogsEx', inFilter(options)); - } - - getStorageAt (address, index = 0, blockNumber = 'latest') { - return this._transport - .execute('eth_getStorageAt', inAddress(address), inNumber16(index), inBlockNumber(blockNumber)); - } - - getTransactionByBlockHashAndIndex (hash, index = 0) { - return this._transport - .execute('eth_getTransactionByBlockHashAndIndex', inHex(hash), inNumber16(index)) - .then(outTransaction); - } - - getTransactionByBlockNumberAndIndex (blockNumber = 'latest', index = 0) { - return this._transport - .execute('eth_getTransactionByBlockNumberAndIndex', inBlockNumber(blockNumber), inNumber16(index)) - .then(outTransaction); - } - - getTransactionByHash (hash) { - return this._transport - .execute('eth_getTransactionByHash', inHex(hash)) - .then(outTransaction); - } - - getTransactionCount (address, blockNumber = 'latest') { - return this._transport - .execute('eth_getTransactionCount', inAddress(address), inBlockNumber(blockNumber)) - .then(outNumber); - } - - getTransactionReceipt (txhash) { - return this._transport - .execute('eth_getTransactionReceipt', inHex(txhash)) - .then(outReceipt); - } - - getUncleByBlockHashAndIndex (hash, index = 0) { - return this._transport - .execute('eth_getUncleByBlockHashAndIndex', inHex(hash), inNumber16(index)); - } - - getUncleByBlockNumberAndIndex (blockNumber = 'latest', index = 0) { - return this._transport - .execute('eth_getUncleByBlockNumberAndIndex', inBlockNumber(blockNumber), inNumber16(index)); - } - - getUncleCountByBlockHash (hash) { - return this._transport - .execute('eth_getUncleCountByBlockHash', inHex(hash)) - .then(outNumber); - } - - getUncleCountByBlockNumber (blockNumber = 'latest') { - return this._transport - .execute('eth_getUncleCountByBlockNumber', inBlockNumber(blockNumber)) - .then(outNumber); - } - - getWork () { - return this._transport - .execute('eth_getWork'); - } - - hashrate () { - return this._transport - .execute('eth_hashrate') - .then(outNumber); - } - - inspectTransaction () { - return this._transport - .execute('eth_inspectTransaction'); - } - - mining () { - return this._transport - .execute('eth_mining'); - } - - newBlockFilter () { - return this._transport - .execute('eth_newBlockFilter'); - } - - newFilter (options) { - return this._transport - .execute('eth_newFilter', inFilter(options)); - } - - newFilterEx (options) { - return this._transport - .execute('eth_newFilterEx', inFilter(options)); - } - - newPendingTransactionFilter () { - return this._transport - .execute('eth_newPendingTransactionFilter'); - } - - notePassword () { - return this._transport - .execute('eth_notePassword'); - } - - pendingTransactions () { - return this._transport - .execute('eth_pendingTransactions'); - } - - protocolVersion () { - return this._transport - .execute('eth_protocolVersion'); - } - - register () { - return this._transport - .execute('eth_register'); - } - - sendRawTransaction (data) { - return this._transport - .execute('eth_sendRawTransaction', inData(data)); - } - - sendTransaction (options) { - return this._transport - .execute('eth_sendTransaction', inOptions(options)); - } - - sign (address, hash) { - return this._transport - .execute('eth_sign', inAddress(address), inHash(hash)); - } - - signTransaction (options) { - return this._transport - .execute('eth_signTransaction', inOptions(options)); - } - - submitHashrate (hashrate, clientId) { - return this._transport - .execute('eth_submitHashrate', inNumber16(hashrate), clientId); - } - - submitWork (nonce, powHash, mixDigest) { - return this._transport - .execute('eth_submitWork', inNumber16(nonce), powHash, mixDigest); - } - - syncing () { - return this._transport - .execute('eth_syncing') - .then(outSyncing); - } - - uninstallFilter (filterId) { - return this._transport - .execute('eth_uninstallFilter', inHex(filterId)); - } - - unregister () { - return this._transport - .execute('eth_unregister'); - } -} diff --git a/js/src/api/rpc/eth/eth.spec.js b/js/src/api/rpc/eth/eth.spec.js deleted file mode 100644 index 2738fd2dea73e9e57d0635bbd5c8dabd54130fe2..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/eth/eth.spec.js +++ /dev/null @@ -1,474 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; -import { isBigNumber } from '../../../../test/types'; - -import Http from '../../transport/http'; -import Eth from './eth'; - -const instance = new Eth(new Http(TEST_HTTP_URL, -1)); - -describe('rpc/Eth', () => { - const address = '0x63Cf90D3f0410092FC0fca41846f596223979195'; - let scope; - - describe('accounts', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_accounts', reply: { result: [address.toLowerCase()] } }]); - }); - - it('returns a list of accounts, formatted', () => { - return instance.accounts().then((accounts) => { - expect(accounts).to.deep.equal([address]); - }); - }); - }); - - describe('blockNumber', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_blockNumber', reply: { result: '0x123456' } }]); - }); - - it('returns the current blockNumber, formatted', () => { - return instance.blockNumber().then((blockNumber) => { - expect(isBigNumber(blockNumber)).to.be.true; - expect(blockNumber.toString(16)).to.equal('123456'); - }); - }); - }); - - describe('call', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_call', reply: { result: [] } }]); - }); - - it('formats the input options & blockNumber', () => { - return instance.call({ data: '12345678' }, 'earliest').then(() => { - expect(scope.body.eth_call.params).to.deep.equal([{ data: '0x12345678' }, 'earliest']); - }); - }); - - it('provides a latest blockNumber when not specified', () => { - return instance.call({ data: '12345678' }).then(() => { - expect(scope.body.eth_call.params).to.deep.equal([{ data: '0x12345678' }, 'latest']); - }); - }); - }); - - describe('coinbase', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_coinbase', reply: { result: address.toLowerCase() } }]); - }); - - it('returns the coinbase, formatted', () => { - return instance.coinbase().then((account) => { - expect(account).to.deep.equal(address); - }); - }); - }); - - ['LLL', 'Serpent', 'Solidity'].forEach((type) => { - const method = `compile${type}`; - - describe(method, () => { - beforeEach(() => { - scope = mockHttp([{ method: `eth_${method}`, reply: { result: '0x123' } }]); - }); - - it('formats the input as data, returns the output', () => { - return instance[method]('0xabcdef').then((result) => { - expect(scope.body[`eth_${method}`].params).to.deep.equal(['0xabcdef']); - expect(result).to.equal('0x123'); - }); - }); - }); - }); - - describe('estimateGas', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_estimateGas', reply: { result: '0x123' } }]); - }); - - it('converts the options correctly', () => { - return instance.estimateGas({ gas: 21000 }).then(() => { - expect(scope.body.eth_estimateGas.params).to.deep.equal([{ gas: '0x5208' }]); - }); - }); - - it('returns the gas used', () => { - return instance.estimateGas({}).then((gas) => { - expect(isBigNumber(gas)).to.be.true; - expect(gas.toString(16)).to.deep.equal('123'); - }); - }); - }); - - describe('gasPrice', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_gasPrice', reply: { result: '0x123' } }]); - }); - - it('returns the fomratted price', () => { - return instance.gasPrice().then((price) => { - expect(isBigNumber(price)).to.be.true; - expect(price.toString(16)).to.deep.equal('123'); - }); - }); - }); - - describe('getBalance', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getBalance', reply: { result: '0x123' } }]); - }); - - it('passes in the address (default blockNumber)', () => { - return instance.getBalance(address).then(() => { - expect(scope.body.eth_getBalance.params).to.deep.equal([address.toLowerCase(), 'latest']); - }); - }); - - it('passes in the address & blockNumber', () => { - return instance.getBalance(address, 0x456).then(() => { - expect(scope.body.eth_getBalance.params).to.deep.equal([address.toLowerCase(), '0x456']); - }); - }); - - it('returns the balance', () => { - return instance.getBalance(address, 0x123).then((balance) => { - expect(isBigNumber(balance)).to.be.true; - expect(balance.toString(16)).to.deep.equal('123'); - }); - }); - }); - - describe('getBlockByHash', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getBlockByHash', reply: { result: { miner: address.toLowerCase() } } }]); - }); - - it('formats the input hash as a hash, default full', () => { - return instance.getBlockByHash('1234').then(() => { - expect(scope.body.eth_getBlockByHash.params).to.deep.equal(['0x1234', false]); - }); - }); - - it('formats the input hash as a hash, full true', () => { - return instance.getBlockByHash('1234', true).then(() => { - expect(scope.body.eth_getBlockByHash.params).to.deep.equal(['0x1234', true]); - }); - }); - - it('formats the output into block', () => { - return instance.getBlockByHash('1234').then((block) => { - expect(block.miner).to.equal(address); - }); - }); - }); - - describe('getBlockByNumber', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getBlockByNumber', reply: { result: { miner: address.toLowerCase() } } }]); - }); - - it('assumes blockNumber latest & full false', () => { - return instance.getBlockByNumber().then(() => { - expect(scope.body.eth_getBlockByNumber.params).to.deep.equal(['latest', false]); - }); - }); - - it('uses input blockNumber & full false', () => { - return instance.getBlockByNumber('0x1234').then(() => { - expect(scope.body.eth_getBlockByNumber.params).to.deep.equal(['0x1234', false]); - }); - }); - - it('formats the input blockNumber, full true', () => { - return instance.getBlockByNumber(0x1234, true).then(() => { - expect(scope.body.eth_getBlockByNumber.params).to.deep.equal(['0x1234', true]); - }); - }); - - it('formats the output into block', () => { - return instance.getBlockByNumber(0x1234).then((block) => { - expect(block.miner).to.equal(address); - }); - }); - }); - - describe('getBlockTransactionCountByHash', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getBlockTransactionCountByHash', reply: { result: '0x123' } }]); - }); - - it('formats input hash properly', () => { - return instance.getBlockTransactionCountByHash('abcdef').then(() => { - expect(scope.body.eth_getBlockTransactionCountByHash.params).to.deep.equal(['0xabcdef']); - }); - }); - - it('formats the output number', () => { - return instance.getBlockTransactionCountByHash('0x1234').then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.toString(16)).to.equal('123'); - }); - }); - }); - - describe('getBlockTransactionCountByNumber', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getBlockTransactionCountByNumber', reply: { result: '0x123' } }]); - }); - - it('specified blockNumber latest when none specified', () => { - return instance.getBlockTransactionCountByNumber().then(() => { - expect(scope.body.eth_getBlockTransactionCountByNumber.params).to.deep.equal(['latest']); - }); - }); - - it('formats input blockNumber properly', () => { - return instance.getBlockTransactionCountByNumber(0xabcdef).then(() => { - expect(scope.body.eth_getBlockTransactionCountByNumber.params).to.deep.equal(['0xabcdef']); - }); - }); - - it('formats the output number', () => { - return instance.getBlockTransactionCountByNumber('0x1234').then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.toString(16)).to.equal('123'); - }); - }); - }); - - describe('getCode', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getCode', reply: { result: '0x1234567890' } }]); - }); - - it('passes in the address (default blockNumber)', () => { - return instance.getCode(address).then(() => { - expect(scope.body.eth_getCode.params).to.deep.equal([address.toLowerCase(), 'latest']); - }); - }); - - it('passes in the address & blockNumber', () => { - return instance.getCode(address, 0x456).then(() => { - expect(scope.body.eth_getCode.params).to.deep.equal([address.toLowerCase(), '0x456']); - }); - }); - - it('returns the code', () => { - return instance.getCode(address, 0x123).then((code) => { - expect(code).to.equal('0x1234567890'); - }); - }); - }); - - describe('getStorageAt', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getStorageAt', reply: { result: '0x1234567890' } }]); - }); - - it('passes in the address (default index& blockNumber)', () => { - return instance.getStorageAt(address).then(() => { - expect(scope.body.eth_getStorageAt.params).to.deep.equal([address.toLowerCase(), '0x0', 'latest']); - }); - }); - - it('passes in the address, index & blockNumber', () => { - return instance.getStorageAt(address, 15, 0x456).then(() => { - expect(scope.body.eth_getStorageAt.params).to.deep.equal([address.toLowerCase(), '0xf', '0x456']); - }); - }); - - it('returns the storage', () => { - return instance.getStorageAt(address, 0x123).then((storage) => { - expect(storage).to.equal('0x1234567890'); - }); - }); - }); - - describe('getTransactionByBlockHashAndIndex', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getTransactionByBlockHashAndIndex', reply: { result: { to: address.toLowerCase() } } }]); - }); - - it('passes in the hash (default index)', () => { - return instance.getTransactionByBlockHashAndIndex('12345').then(() => { - expect(scope.body.eth_getTransactionByBlockHashAndIndex.params).to.deep.equal(['0x12345', '0x0']); - }); - }); - - it('passes in the hash & specified index', () => { - return instance.getTransactionByBlockHashAndIndex('6789', 0x456).then(() => { - expect(scope.body.eth_getTransactionByBlockHashAndIndex.params).to.deep.equal(['0x6789', '0x456']); - }); - }); - - it('returns the formatted transaction', () => { - return instance.getTransactionByBlockHashAndIndex('6789', 0x123).then((tx) => { - expect(tx).to.deep.equal({ to: address }); - }); - }); - }); - - describe('getTransactionByBlockNumberAndIndex', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getTransactionByBlockNumberAndIndex', reply: { result: { to: address.toLowerCase() } } }]); - }); - - it('passes in the default parameters', () => { - return instance.getTransactionByBlockNumberAndIndex().then(() => { - expect(scope.body.eth_getTransactionByBlockNumberAndIndex.params).to.deep.equal(['latest', '0x0']); - }); - }); - - it('passes in the blockNumber & specified index', () => { - return instance.getTransactionByBlockNumberAndIndex('0x6789', 0x456).then(() => { - expect(scope.body.eth_getTransactionByBlockNumberAndIndex.params).to.deep.equal(['0x6789', '0x456']); - }); - }); - - it('returns the formatted transaction', () => { - return instance.getTransactionByBlockNumberAndIndex('0x6789', 0x123).then((tx) => { - expect(tx).to.deep.equal({ to: address }); - }); - }); - }); - - describe('getTransactionByHash', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getTransactionByHash', reply: { result: { to: address.toLowerCase() } } }]); - }); - - it('passes in the hash', () => { - return instance.getTransactionByHash('12345').then(() => { - expect(scope.body.eth_getTransactionByHash.params).to.deep.equal(['0x12345']); - }); - }); - - it('returns the formatted transaction', () => { - return instance.getTransactionByHash('6789').then((tx) => { - expect(tx).to.deep.equal({ to: address }); - }); - }); - }); - - describe('getTransactionCount', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getTransactionCount', reply: { result: '0x123' } }]); - }); - - it('passes in the address (default blockNumber)', () => { - return instance.getTransactionCount(address).then(() => { - expect(scope.body.eth_getTransactionCount.params).to.deep.equal([address.toLowerCase(), 'latest']); - }); - }); - - it('passes in the address & blockNumber', () => { - return instance.getTransactionCount(address, 0x456).then(() => { - expect(scope.body.eth_getTransactionCount.params).to.deep.equal([address.toLowerCase(), '0x456']); - }); - }); - - it('returns the count, formatted', () => { - return instance.getTransactionCount(address, 0x123).then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.toString(16)).to.equal('123'); - }); - }); - }); - - describe('getUncleByBlockHashAndIndex', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getUncleByBlockHashAndIndex', reply: { result: [] } }]); - }); - - it('passes in the hash (default index)', () => { - return instance.getUncleByBlockHashAndIndex('12345').then(() => { - expect(scope.body.eth_getUncleByBlockHashAndIndex.params).to.deep.equal(['0x12345', '0x0']); - }); - }); - - it('passes in the hash & specified index', () => { - return instance.getUncleByBlockHashAndIndex('6789', 0x456).then(() => { - expect(scope.body.eth_getUncleByBlockHashAndIndex.params).to.deep.equal(['0x6789', '0x456']); - }); - }); - }); - - describe('getUncleByBlockNumberAndIndex', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getUncleByBlockNumberAndIndex', reply: { result: [] } }]); - }); - - it('passes in the default parameters', () => { - return instance.getUncleByBlockNumberAndIndex().then(() => { - expect(scope.body.eth_getUncleByBlockNumberAndIndex.params).to.deep.equal(['latest', '0x0']); - }); - }); - - it('passes in the blockNumber & specified index', () => { - return instance.getUncleByBlockNumberAndIndex('0x6789', 0x456).then(() => { - expect(scope.body.eth_getUncleByBlockNumberAndIndex.params).to.deep.equal(['0x6789', '0x456']); - }); - }); - }); - - describe('getUncleCountByBlockHash', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getUncleCountByBlockHash', reply: { result: '0x123' } }]); - }); - - it('passes in the hash', () => { - return instance.getUncleCountByBlockHash('12345').then(() => { - expect(scope.body.eth_getUncleCountByBlockHash.params).to.deep.equal(['0x12345']); - }); - }); - - it('formats the output number', () => { - return instance.getUncleCountByBlockHash('0x1234').then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.toString(16)).to.equal('123'); - }); - }); - }); - - describe('getUncleCountByBlockNumber', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'eth_getUncleCountByBlockNumber', reply: { result: '0x123' } }]); - }); - - it('passes in the default parameters', () => { - return instance.getUncleCountByBlockNumber().then(() => { - expect(scope.body.eth_getUncleCountByBlockNumber.params).to.deep.equal(['latest']); - }); - }); - - it('passes in the blockNumber', () => { - return instance.getUncleCountByBlockNumber('0x6789').then(() => { - expect(scope.body.eth_getUncleCountByBlockNumber.params).to.deep.equal(['0x6789']); - }); - }); - - it('formats the output number', () => { - return instance.getUncleCountByBlockNumber('0x1234').then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.toString(16)).to.equal('123'); - }); - }); - }); -}); diff --git a/js/src/api/rpc/eth/index.js b/js/src/api/rpc/eth/index.js deleted file mode 100644 index 25a7b3cb459cc2d1bb6d624fca666fe10fa1b889..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/eth/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './eth'; diff --git a/js/src/api/rpc/index.js b/js/src/api/rpc/index.js deleted file mode 100644 index c8fa0032bc749a172242a8d69cab7a47032eec49..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/index.js +++ /dev/null @@ -1,25 +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 . - -export Db from './db'; -export Eth from './eth'; -export Parity from './parity'; -export Net from './net'; -export Personal from './personal'; -export Shh from './shh'; -export Signer from './signer'; -export Trace from './trace'; -export Web3 from './web3'; diff --git a/js/src/api/rpc/net/index.js b/js/src/api/rpc/net/index.js deleted file mode 100644 index 457eeed79a2dd4c7aff4bcc891fc2ea8b010586f..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/net/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './net'; diff --git a/js/src/api/rpc/net/net.e2e.js b/js/src/api/rpc/net/net.e2e.js deleted file mode 100644 index c477e2605befb9e6931f36f8dda32e6fb9bfdee2..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/net/net.e2e.js +++ /dev/null @@ -1,46 +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 . - -import { createHttpApi } from '../../../../test/e2e/ethapi'; -import { isBoolean } from '../../../../test/types'; - -describe('ethapi.net', () => { - const ethapi = createHttpApi(); - - describe('listening', () => { - it('returns the listening status', () => { - return ethapi.net.listening().then((status) => { - expect(isBoolean(status)).to.be.true; - }); - }); - }); - - describe('peerCount', () => { - it('returns the peer count', () => { - return ethapi.net.peerCount().then((count) => { - expect(count.gte(0)).to.be.true; - }); - }); - }); - - describe('version', () => { - it('returns the version', () => { - return ethapi.net.version().then((version) => { - expect(version).to.be.ok; - }); - }); - }); -}); diff --git a/js/src/api/rpc/net/net.js b/js/src/api/rpc/net/net.js deleted file mode 100644 index 9b14f69d520003d8101c0e861dabdd9c2fbc5ded..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/net/net.js +++ /dev/null @@ -1,39 +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 . - -import { outNumber } from '../../format/output'; - -export default class Net { - constructor (transport) { - this._transport = transport; - } - - listening () { - return this._transport - .execute('net_listening'); - } - - peerCount () { - return this._transport - .execute('net_peerCount') - .then(outNumber); - } - - version () { - return this._transport - .execute('net_version'); - } -} diff --git a/js/src/api/rpc/net/net.spec.js b/js/src/api/rpc/net/net.spec.js deleted file mode 100644 index 07ad52076d9500696245a4ae430a6cc35a51b958..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/net/net.spec.js +++ /dev/null @@ -1,36 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; -import { isBigNumber } from '../../../../test/types'; - -import Http from '../../transport/http'; -import Net from './net'; - -const instance = new Net(new Http(TEST_HTTP_URL, -1)); - -describe('api/rpc/Net', () => { - describe('peerCount', () => { - it('returns the connected peers, formatted', () => { - mockHttp([{ method: 'net_peerCount', reply: { result: '0x123456' } }]); - - return instance.peerCount().then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.eq(0x123456)).to.be.true; - }); - }); - }); -}); diff --git a/js/src/api/rpc/parity/index.js b/js/src/api/rpc/parity/index.js deleted file mode 100644 index 7fe520c606fa64436bb8b833267a26d839f943f4..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/parity/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './parity'; diff --git a/js/src/api/rpc/parity/parity.e2e.js b/js/src/api/rpc/parity/parity.e2e.js deleted file mode 100644 index 8820d570a648e6f4eb51ad1b21c3945a62f16f9a..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/parity/parity.e2e.js +++ /dev/null @@ -1,79 +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 . - -import { createHttpApi } from '../../../../test/e2e/ethapi'; - -describe('ethapi.parity', () => { - const ethapi = createHttpApi(); - - describe('chainStatus', () => { - it('returns and translates the status', () => { - return ethapi.parity.chainStatus().then((value) => { - expect(value).to.be.ok; - }); - }); - }); - - describe('gasFloorTarget', () => { - it('returns and translates the target', () => { - return ethapi.parity.gasFloorTarget().then((value) => { - expect(value.gt(0)).to.be.true; - }); - }); - }); - - describe('gasPriceHistogram', () => { - it('returns and translates the target', () => { - return ethapi.parity.gasPriceHistogram().then((result) => { - expect(Object.keys(result)).to.deep.equal(['bucketBounds', 'counts']); - expect(result.bucketBounds.length > 0).to.be.true; - expect(result.counts.length > 0).to.be.true; - }); - }); - }); - - describe('netChain', () => { - it('returns and the chain', () => { - return ethapi.parity.netChain().then((value) => { - expect(value).to.equal('morden'); - }); - }); - }); - - describe('netPort', () => { - it('returns and translates the port', () => { - return ethapi.parity.netPort().then((value) => { - expect(value.gt(0)).to.be.true; - }); - }); - }); - - describe('transactionsLimit', () => { - it('returns and translates the limit', () => { - return ethapi.parity.transactionsLimit().then((value) => { - expect(value.gt(0)).to.be.true; - }); - }); - }); - - describe('rpcSettings', () => { - it('returns and translates the settings', () => { - return ethapi.parity.rpcSettings().then((value) => { - expect(value).to.be.ok; - }); - }); - }); -}); diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js deleted file mode 100644 index 59ccb58845a68696bfcd8efaf5a860539eba590e..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/parity/parity.js +++ /dev/null @@ -1,578 +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 . - -import { inAddress, inAddresses, inBlockNumber, inData, inDeriveHash, inDeriveIndex, inHex, inNumber16, inOptions } from '../../format/input'; -import { outAccountInfo, outAddress, outAddresses, outBlock, outChainStatus, outHistogram, outHwAccountInfo, outNodeKind, outNumber, outPeers, outRecentDapps, outTransaction, outVaultMeta } from '../../format/output'; - -export default class Parity { - constructor (transport) { - this._transport = transport; - } - - acceptNonReservedPeers () { - return this._transport - .execute('parity_acceptNonReservedPeers'); - } - - accountsInfo () { - return this._transport - .execute('parity_accountsInfo') - .then(outAccountInfo); - } - - allAccountsInfo () { - return this._transport - .execute('parity_allAccountsInfo') - .then(outAccountInfo); - } - - addReservedPeer (enode) { - return this._transport - .execute('parity_addReservedPeer', enode); - } - - chainStatus () { - return this._transport - .execute('parity_chainStatus') - .then(outChainStatus); - } - - changePassword (account, password, newPassword) { - return this._transport - .execute('parity_changePassword', inAddress(account), password, newPassword); - } - - changeVault (account, vaultName) { - return this._transport - .execute('parity_changeVault', inAddress(account), vaultName); - } - - changeVaultPassword (vaultName, password) { - return this._transport - .execute('parity_changeVaultPassword', vaultName, password); - } - - checkRequest (requestId) { - return this._transport - .execute('parity_checkRequest', inNumber16(requestId)); - } - - cidV0 (data) { - return this._transport - .execute('parity_cidV0', inData(data)); - } - - closeVault (vaultName) { - return this._transport - .execute('parity_closeVault', vaultName); - } - - composeTransaction (options) { - return this._transport - .execute('parity_composeTransaction', inOptions(options)); - } - - consensusCapability () { - return this._transport - .execute('parity_consensusCapability'); - } - - dappsList () { - return this._transport - .execute('parity_dappsList'); - } - - dappsRefresh () { - return this._transport - .execute('parity_dappsRefresh'); - } - - dappsUrl () { - return this._transport - .execute('parity_dappsUrl'); - } - - decryptMessage (address, data) { - return this._transport - .execute('parity_decryptMessage', inAddress(address), inHex(data)); - } - - defaultAccount () { - return this._transport - .execute('parity_defaultAccount') - .then(outAddress); - } - - defaultExtraData () { - return this._transport - .execute('parity_defaultExtraData'); - } - - devLogs () { - return this._transport - .execute('parity_devLogs'); - } - - devLogsLevels () { - return this._transport - .execute('parity_devLogsLevels'); - } - - deriveAddressHash (address, password, hash, shouldSave) { - return this._transport - .execute('parity_deriveAddressHash', inAddress(address), password, inDeriveHash(hash), !!shouldSave) - .then(outAddress); - } - - deriveAddressIndex (address, password, index, shouldSave) { - return this._transport - .execute('parity_deriveAddressIndex', inAddress(address), password, inDeriveIndex(index), !!shouldSave) - .then(outAddress); - } - - dropNonReservedPeers () { - return this._transport - .execute('parity_dropNonReservedPeers'); - } - - enode () { - return this._transport - .execute('parity_enode'); - } - - encryptMessage (pubkey, data) { - return this._transport - .execute('parity_encryptMessage', inHex(pubkey), inHex(data)); - } - - executeUpgrade () { - return this._transport - .execute('parity_executeUpgrade'); - } - - exportAccount (address, password) { - return this._transport - .execute('parity_exportAccount', inAddress(address), password); - } - - extraData () { - return this._transport - .execute('parity_extraData'); - } - - futureTransactions () { - return this._transport - .execute('parity_futureTransactions'); - } - - gasCeilTarget () { - return this._transport - .execute('parity_gasCeilTarget') - .then(outNumber); - } - - gasFloorTarget () { - return this._transport - .execute('parity_gasFloorTarget') - .then(outNumber); - } - - gasPriceHistogram () { - return this._transport - .execute('parity_gasPriceHistogram') - .then(outHistogram); - } - - generateSecretPhrase () { - return this._transport - .execute('parity_generateSecretPhrase'); - } - - getBlockHeaderByNumber (blockNumber = 'latest') { - return this._transport - .execute('parity_getBlockHeaderByNumber', inBlockNumber(blockNumber)) - .then(outBlock); - } - - getDappAddresses (dappId) { - return this._transport - .execute('parity_getDappAddresses', dappId) - .then(outAddresses); - } - - getDappDefaultAddress (dappId) { - return this._transport - .execute('parity_getDappDefaultAddress', dappId) - .then(outAddress); - } - - getNewDappsAddresses () { - return this._transport - .execute('parity_getNewDappsAddresses') - .then((addresses) => addresses ? addresses.map(outAddress) : null); - } - - getNewDappsDefaultAddress () { - return this._transport - .execute('parity_getNewDappsDefaultAddress') - .then(outAddress); - } - - getVaultMeta (vaultName) { - return this._transport - .execute('parity_getVaultMeta', vaultName) - .then(outVaultMeta); - } - - hardwareAccountsInfo () { - return this._transport - .execute('parity_hardwareAccountsInfo') - .then(outHwAccountInfo); - } - - hashContent (url) { - return this._transport - .execute('parity_hashContent', url); - } - - importGethAccounts (accounts) { - return this._transport - .execute('parity_importGethAccounts', inAddresses(accounts)) - .then(outAddresses); - } - - killAccount (account, password) { - return this._transport - .execute('parity_killAccount', inAddress(account), password); - } - - listAccounts (count, offset = null, blockNumber = 'latest') { - return this._transport - .execute('parity_listAccounts', count, inAddress(offset), inBlockNumber(blockNumber)) - .then((accounts) => (accounts || []).map(outAddress)); - } - - listOpenedVaults () { - return this._transport - .execute('parity_listOpenedVaults'); - } - - listVaults () { - return this._transport - .execute('parity_listVaults'); - } - - listRecentDapps () { - return this._transport - .execute('parity_listRecentDapps') - .then(outRecentDapps); - } - - listStorageKeys (address, count, hash = null, blockNumber = 'latest') { - return this._transport - .execute('parity_listStorageKeys', inAddress(address), count, inHex(hash), inBlockNumber(blockNumber)); - } - - removeAddress (address) { - return this._transport - .execute('parity_removeAddress', inAddress(address)); - } - - listGethAccounts () { - return this._transport - .execute('parity_listGethAccounts') - .then(outAddresses); - } - - localTransactions () { - return this._transport - .execute('parity_localTransactions') - .then(transactions => { - Object.values(transactions) - .filter(tx => tx.transaction) - .map(tx => { - tx.transaction = outTransaction(tx.transaction); - }); - return transactions; - }); - } - - minGasPrice () { - return this._transport - .execute('parity_minGasPrice') - .then(outNumber); - } - - mode () { - return this._transport - .execute('parity_mode'); - } - - // DEPRECATED - use chain instead. - netChain () { - return this._transport - .execute('parity_chain'); - } - - nodeKind () { - return this._transport - .execute('parity_nodeKind') - .then(outNodeKind); - } - - chain () { - return this._transport - .execute('parity_chain'); - } - - netPeers () { - return this._transport - .execute('parity_netPeers') - .then(outPeers); - } - - netMaxPeers () { - return this._transport - .execute('parity_netMaxPeers') - .then(outNumber); - } - - netPort () { - return this._transport - .execute('parity_netPort') - .then(outNumber); - } - - newAccountFromPhrase (phrase, password) { - return this._transport - .execute('parity_newAccountFromPhrase', phrase, password) - .then(outAddress); - } - - newAccountFromSecret (secret, password) { - return this._transport - .execute('parity_newAccountFromSecret', inHex(secret), password) - .then(outAddress); - } - - newAccountFromWallet (json, password) { - return this._transport - .execute('parity_newAccountFromWallet', json, password) - .then(outAddress); - } - - newVault (vaultName, password) { - return this._transport - .execute('parity_newVault', vaultName, password); - } - - nextNonce (account) { - return this._transport - .execute('parity_nextNonce', inAddress(account)) - .then(outNumber); - } - - nodeHealth () { - return this._transport - .execute('parity_nodeHealth'); - } - - nodeName () { - return this._transport - .execute('parity_nodeName'); - } - - openVault (vaultName, password) { - return this._transport - .execute('parity_openVault', vaultName, password); - } - - pendingTransactions () { - return this._transport - .execute('parity_pendingTransactions') - .then(data => data.map(outTransaction)); - } - - pendingTransactionsStats () { - return this._transport - .execute('parity_pendingTransactionsStats'); - } - - phraseToAddress (phrase) { - return this._transport - .execute('parity_phraseToAddress', phrase) - .then(outAddress); - } - - postSign (address, hash) { - return this._transport - .execute('parity_postSign', inAddress(address), inHex(hash)); - } - - postTransaction (options = {}) { - return this._transport - .execute('parity_postTransaction', inOptions(options)); - } - - registryAddress () { - return this._transport - .execute('parity_registryAddress') - .then(outAddress); - } - - releasesInfo () { - return this._transport - .execute('parity_releasesInfo'); - } - - removeReservedPeer (enode) { - return this._transport - .execute('parity_removeReservedPeer', enode); - } - - removeTransaction (hash) { - return this._transport - .execute('parity_removeTransaction', inHex(hash)) - .then(outTransaction); - } - - rpcSettings () { - return this._transport - .execute('parity_rpcSettings'); - } - - setAccountName (address, name) { - return this._transport - .execute('parity_setAccountName', inAddress(address), name); - } - - setAccountMeta (address, meta) { - return this._transport - .execute('parity_setAccountMeta', inAddress(address), JSON.stringify(meta)); - } - - setAuthor (address) { - return this._transport - .execute('parity_setAuthor', inAddress(address)); - } - - setDappAddresses (dappId, addresses) { - return this._transport - .execute('parity_setDappAddresses', dappId, inAddresses(addresses)); - } - - setDappDefaultAddress (dappId, address) { - return this._transport - .execute('parity_setDappDefaultAddress', dappId, address ? inAddress(address) : null); - } - - setEngineSigner (address, password) { - return this._transport - .execute('parity_setEngineSigner', inAddress(address), password); - } - - setExtraData (data) { - return this._transport - .execute('parity_setExtraData', inData(data)); - } - - setGasCeilTarget (quantity) { - return this._transport - .execute('parity_setGasCeilTarget', inNumber16(quantity)); - } - - setGasFloorTarget (quantity) { - return this._transport - .execute('parity_setGasFloorTarget', inNumber16(quantity)); - } - - setMaxTransactionGas (quantity) { - return this._transport - .execute('parity_setMaxTransactionGas', inNumber16(quantity)); - } - - setMinGasPrice (quantity) { - return this._transport - .execute('parity_setMinGasPrice', inNumber16(quantity)); - } - - setMode (mode) { - return this._transport - .execute('parity_setMode', mode); - } - - setChain (specName) { - return this._transport - .execute('parity_setChain', specName); - } - - setNewDappsAddresses (addresses) { - return this._transport - .execute('parity_setNewDappsAddresses', addresses ? inAddresses(addresses) : null); - } - - setNewDappsDefaultAddress (address) { - return this._transport - .execute('parity_setNewDappsDefaultAddress', inAddress(address)); - } - - setTransactionsLimit (quantity) { - return this._transport - .execute('parity_setTransactionsLimit', inNumber16(quantity)); - } - - setVaultMeta (vaultName, meta) { - return this._transport - .execute('parity_setVaultMeta', vaultName, JSON.stringify(meta)); - } - - signMessage (address, password, messageHash) { - return this._transport - .execute('parity_signMessage', inAddress(address), password, inHex(messageHash)); - } - - testPassword (account, password) { - return this._transport - .execute('parity_testPassword', inAddress(account), password); - } - - transactionsLimit () { - return this._transport - .execute('parity_transactionsLimit') - .then(outNumber); - } - - unsignedTransactionsCount () { - return this._transport - .execute('parity_unsignedTransactionsCount') - .then(outNumber); - } - - upgradeReady () { - return this._transport - .execute('parity_upgradeReady'); - } - - versionInfo () { - return this._transport - .execute('parity_versionInfo'); - } - - wsUrl () { - return this._transport - .execute('parity_wsUrl'); - } -} diff --git a/js/src/api/rpc/parity/parity.spec.js b/js/src/api/rpc/parity/parity.spec.js deleted file mode 100644 index 6ba7a1c83f9ab40488fcf7986fd42f617e78f490..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/parity/parity.spec.js +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -import BigNumber from 'bignumber.js'; -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; -import { isBigNumber } from '../../../../test/types'; - -import Http from '../../transport/http'; -import Parity from './parity'; - -const instance = new Parity(new Http(TEST_HTTP_URL, -1)); - -describe('api/rpc/parity', () => { - describe('accountsInfo', () => { - it('retrieves the available account info', () => { - mockHttp([{ method: 'parity_accountsInfo', reply: { - result: { - '0x63cf90d3f0410092fc0fca41846f596223979195': { - name: 'name', uuid: 'uuid', meta: '{"data":"data"}' - } - } - } }]); - - return instance.accountsInfo().then((result) => { - expect(result).to.deep.equal({ - '0x63Cf90D3f0410092FC0fca41846f596223979195': { - name: 'name', uuid: 'uuid', meta: { - data: 'data' - } - } - }); - }); - }); - }); - - describe('chainStatus', () => { - it('retrieves the chain status', () => { - mockHttp([{ method: 'parity_chainStatus', reply: { - result: { - 'blockGap': [0x123, 0x456] - } - } }]); - - return instance.chainStatus().then((result) => { - expect(result).to.deep.equal({ - 'blockGap': [new BigNumber(0x123), new BigNumber(0x456)] - }); - }); - }); - }); - - describe('gasFloorTarget', () => { - it('returns the gasfloor, formatted', () => { - mockHttp([{ method: 'parity_gasFloorTarget', reply: { result: '0x123456' } }]); - - return instance.gasFloorTarget().then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.eq(0x123456)).to.be.true; - }); - }); - }); - - describe('importGethAccounts', () => { - const ACCOUNTS = ['0x63cf90d3f0410092fc0fca41846f596223979195']; - let scope; - - beforeEach(() => { - scope = mockHttp([{ method: 'parity_importGethAccounts', reply: { result: ACCOUNTS } }]); - }); - - it('passes the addresses through', () => { - return instance.importGethAccounts(ACCOUNTS).then((result) => { - expect(scope.body['parity_importGethAccounts'].params).to.deep.equal([ACCOUNTS]); - }); - }); - }); - - describe('minGasPrice', () => { - it('returns the min gasprice, formatted', () => { - mockHttp([{ method: 'parity_minGasPrice', reply: { result: '0x123456' } }]); - - return instance.minGasPrice().then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.eq(0x123456)).to.be.true; - }); - }); - }); - - describe('netMaxPeers', () => { - it('returns the max peers, formatted', () => { - mockHttp([{ method: 'parity_netMaxPeers', reply: { result: 25 } }]); - - return instance.netMaxPeers().then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.eq(25)).to.be.true; - }); - }); - }); - - describe('netPeers', () => { - it('returns the peer structure, formatted', () => { - mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789, peers: [] } } }]); - - return instance.netPeers().then((peers) => { - expect(peers.active.eq(123)).to.be.true; - expect(peers.connected.eq(456)).to.be.true; - expect(peers.max.eq(789)).to.be.true; - }); - }); - }); - - describe('netPort', () => { - it('returns the connected port, formatted', () => { - mockHttp([{ method: 'parity_netPort', reply: { result: 33030 } }]); - - return instance.netPort().then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.eq(33030)).to.be.true; - }); - }); - }); - - describe('transactionsLimit', () => { - it('returns the tx limit, formatted', () => { - mockHttp([{ method: 'parity_transactionsLimit', reply: { result: 1024 } }]); - - return instance.transactionsLimit().then((count) => { - expect(isBigNumber(count)).to.be.true; - expect(count.eq(1024)).to.be.true; - }); - }); - }); -}); diff --git a/js/src/api/rpc/personal/index.js b/js/src/api/rpc/personal/index.js deleted file mode 100644 index ec999344202ffe8de88b0b14c6fb9f0ad42862e1..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/personal/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './personal'; diff --git a/js/src/api/rpc/personal/personal.e2e.js b/js/src/api/rpc/personal/personal.e2e.js deleted file mode 100644 index d83e9b81114b4e34087d714dfa37188a060f242a..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/personal/personal.e2e.js +++ /dev/null @@ -1,53 +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 . - -import { createHttpApi } from '../../../../test/e2e/ethapi'; -import { isAddress, isBoolean } from '../../../../test/types'; - -describe.skip('ethapi.personal', () => { - const ethapi = createHttpApi(); - const password = 'P@55word'; - let address; - - describe('newAccount', () => { - it('creates a new account', () => { - return ethapi.personal.newAccount(password).then((_address) => { - address = _address; - expect(isAddress(address)).to.be.ok; - }); - }); - }); - - describe('listAccounts', () => { - it('has the newly-created account', () => { - return ethapi.personal.listAccounts(password).then((accounts) => { - expect(accounts.filter((_address) => _address === address)).to.deep.equal([address]); - accounts.forEach((account) => { - expect(isAddress(account)).to.be.true; - }); - }); - }); - }); - - describe('unlockAccount', () => { - it('unlocks the newly-created account', () => { - return ethapi.personal.unlockAccount(address, password).then((result) => { - expect(isBoolean(result)).to.be.true; - expect(result).to.be.true; - }); - }); - }); -}); diff --git a/js/src/api/rpc/personal/personal.js b/js/src/api/rpc/personal/personal.js deleted file mode 100644 index dd9c40f6262a8f1a9eaa28b65e437b3827ec4f6f..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/personal/personal.js +++ /dev/null @@ -1,46 +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 . - -import { inAddress, inNumber10, inOptions } from '../../format/input'; -import { outAddress } from '../../format/output'; - -export default class Personal { - constructor (transport) { - this._transport = transport; - } - - listAccounts () { - return this._transport - .execute('personal_listAccounts') - .then((accounts) => (accounts || []).map(outAddress)); - } - - newAccount (password) { - return this._transport - .execute('personal_newAccount', password) - .then(outAddress); - } - - sendTransaction (options, password) { - return this._transport - .execute('personal_sendTransaction', inOptions(options), password); - } - - unlockAccount (account, password, duration = 1) { - return this._transport - .execute('personal_unlockAccount', inAddress(account), password, inNumber10(duration)); - } -} diff --git a/js/src/api/rpc/personal/personal.spec.js b/js/src/api/rpc/personal/personal.spec.js deleted file mode 100644 index d67bb9dec8ff4f9d9477dc8aa79ce42a2c5a6900..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/personal/personal.spec.js +++ /dev/null @@ -1,75 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; - -import Http from '../../transport/http'; -import Personal from './personal'; - -const instance = new Personal(new Http(TEST_HTTP_URL, -1)); - -describe('rpc/Personal', () => { - const account = '0x63cf90d3f0410092fc0fca41846f596223979195'; - const checksum = '0x63Cf90D3f0410092FC0fca41846f596223979195'; - let scope; - - describe('listAccounts', () => { - it('retrieves a list of available accounts', () => { - scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: [account] } }]); - - return instance.listAccounts().then((result) => { - expect(result).to.deep.equal([checksum]); - }); - }); - - it('returns an empty list when none available', () => { - scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: null } }]); - - return instance.listAccounts().then((result) => { - expect(result).to.deep.equal([]); - }); - }); - }); - - describe('newAccount', () => { - it('passes the password, returning the address', () => { - scope = mockHttp([{ method: 'personal_newAccount', reply: { result: account } }]); - - return instance.newAccount('password').then((result) => { - expect(scope.body.personal_newAccount.params).to.deep.equal(['password']); - expect(result).to.equal(checksum); - }); - }); - }); - - describe('unlockAccount', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'personal_unlockAccount', reply: { result: [] } }]); - }); - - it('passes account, password & duration', () => { - return instance.unlockAccount(account, 'password', 0xf).then(() => { - expect(scope.body.personal_unlockAccount.params).to.deep.equal([account, 'password', 15]); - }); - }); - - it('provides a default duration when not specified', () => { - return instance.unlockAccount(account, 'password').then(() => { - expect(scope.body.personal_unlockAccount.params).to.deep.equal([account, 'password', 1]); - }); - }); - }); -}); diff --git a/js/src/api/rpc/shh/index.js b/js/src/api/rpc/shh/index.js deleted file mode 100644 index 1094fe4379e2b57a51017feec499ee61485de497..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/shh/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './shh'; diff --git a/js/src/api/rpc/shh/shh.js b/js/src/api/rpc/shh/shh.js deleted file mode 100644 index c58754abfb0059aaad898e93bc6c3a536d894f3a..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/shh/shh.js +++ /dev/null @@ -1,91 +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 . - -export default class Shh { - constructor (transport) { - this._transport = transport; - } - - info () { - return this._transport - .execute('shh_info'); - } - - newKeyPair () { - return this._transport - .execute('shh_newKeyPair'); - } - - addPrivateKey (privKey) { - return this._transport - .execute('shh_addPrivateKey', privKey); - } - - newSymKey () { - return this._transport - .execute('shh_newSymKey'); - } - - getPublicKey (identity) { - return this._transport - .execute('shh_getPublicKey', identity); - } - - getPrivateKey (identity) { - return this._transport - .execute('shh_getPrivateKey', identity); - } - - getSymKey (identity) { - return this._transport - .execute('shh_getSymKey', identity); - } - - deleteKey (identity) { - return this._transport - .execute('shh_deleteKey', identity); - } - - post (messageObj) { - return this._transport - .execute('shh_post', messageObj); - } - - newMessageFilter (filterObj) { - return this._transport - .execute('shh_newMessageFilter', filterObj); - } - - getFilterMessages (filterId) { - return this._transport - .execute('shh_getFilterMessages', filterId); - } - - deleteMessageFilter (filterId) { - return this._transport - .execute('shh_deleteMessageFilter', filterId); - } - - subscribe (filterObj, callback) { - return this._transport - .subscribe('shh', callback, filterObj); - } - - unsubscribe (subscriptionId) { - return this._transport - .unsubscribe(subscriptionId); - } -} diff --git a/js/src/api/rpc/signer/index.js b/js/src/api/rpc/signer/index.js deleted file mode 100644 index cc1e4dc1c57e2cb118cec7f9694fb48cf160351f..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/signer/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './signer'; diff --git a/js/src/api/rpc/signer/signer.js b/js/src/api/rpc/signer/signer.js deleted file mode 100644 index 915b811589e75b3541fcadb28d90ea2b989e93d3..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/signer/signer.js +++ /dev/null @@ -1,65 +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 . - -import { inData, inNumber16, inOptions } from '../../format/input'; -import { outSignerRequest } from '../../format/output'; - -export default class Signer { - constructor (transport) { - this._transport = transport; - } - - confirmRequest (requestId, options, password) { - return this._transport - .execute('signer_confirmRequest', inNumber16(requestId), inOptions(options), password); - } - - confirmRequestRaw (requestId, data) { - return this._transport - .execute('signer_confirmRequestRaw', inNumber16(requestId), inData(data)); - } - - confirmRequestWithToken (requestId, options, password) { - return this._transport - .execute('signer_confirmRequestWithToken', inNumber16(requestId), inOptions(options), password); - } - - generateAuthorizationToken () { - return this._transport - .execute('signer_generateAuthorizationToken'); - } - - generateWebProxyAccessToken (domain) { - return this._transport - .execute('signer_generateWebProxyAccessToken', domain); - } - - rejectRequest (requestId) { - return this._transport - .execute('signer_rejectRequest', inNumber16(requestId)); - } - - requestsToConfirm () { - return this._transport - .execute('signer_requestsToConfirm') - .then((requests) => (requests || []).map(outSignerRequest)); - } - - signerEnabled () { - return this._transport - .execute('signer_signerEnabled'); - } -} diff --git a/js/src/api/rpc/trace/index.js b/js/src/api/rpc/trace/index.js deleted file mode 100644 index 8d02aed452147c04224bec40853d04fd0a405951..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/trace/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './trace'; diff --git a/js/src/api/rpc/trace/trace.e2e.js b/js/src/api/rpc/trace/trace.e2e.js deleted file mode 100644 index ffbef0ed68b5f3e530384e84b1d93515741ef620..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/trace/trace.e2e.js +++ /dev/null @@ -1,45 +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 . - -import { createHttpApi } from '../../../../test/e2e/ethapi'; - -describe('ethapi.trace', () => { - const ethapi = createHttpApi(); - - describe('block', () => { - it('returns the latest block traces', () => { - return ethapi.trace.block().then((traces) => { - expect(traces).to.be.ok; - }); - }); - - it('returns traces for a specified block', () => { - return ethapi.trace.block('0x65432').then((traces) => { - expect(traces).to.be.ok; - }); - }); - }); - - describe('replayTransaction', () => { - it('returns traces for a specific transaction', () => { - return ethapi.eth.getBlockByNumber().then((latestBlock) => { - return ethapi.trace.replayTransaction(latestBlock.transactions[0]).then((traces) => { - expect(traces).to.be.ok; - }); - }); - }); - }); -}); diff --git a/js/src/api/rpc/trace/trace.js b/js/src/api/rpc/trace/trace.js deleted file mode 100644 index 26b19b378926cb666e2c629f855855c7ea2a039b..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/trace/trace.js +++ /dev/null @@ -1,66 +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 . - -import { inBlockNumber, inData, inHex, inNumber16, inOptions, inTraceFilter, inTraceType } from '../../format/input'; -import { outTraces, outTraceReplay } from '../../format/output'; - -export default class Trace { - constructor (transport) { - this._transport = transport; - } - - block (blockNumber = 'latest') { - return this._transport - .execute('trace_block', inBlockNumber(blockNumber)) - .then(outTraces); - } - - call (options, whatTrace = ['trace'], blockNumber = 'latest') { - return this._transport - .execute('trace_call', inOptions(options), inTraceType(whatTrace), inBlockNumber(blockNumber)) - .then(outTraceReplay); - } - - filter (filterObj) { - return this._transport - .execute('trace_filter', inTraceFilter(filterObj)) - .then(outTraces); - } - - get (txHash, position) { - return this._transport - .execute('trace_get', inHex(txHash), inNumber16(position)) - .then(outTraces); - } - - rawTransaction (data, whatTrace = ['trace']) { - return this._transport - .execute('trace_rawTransaction', inData(data), inTraceType(whatTrace)) - .then(outTraceReplay); - } - - replayTransaction (txHash, whatTrace = ['trace']) { - return this._transport - .execute('trace_replayTransaction', txHash, inTraceType(whatTrace)) - .then(outTraceReplay); - } - - transaction (txHash) { - return this._transport - .execute('trace_transaction', inHex(txHash)) - .then(outTraces); - } -} diff --git a/js/src/api/rpc/trace/trace.spec.js b/js/src/api/rpc/trace/trace.spec.js deleted file mode 100644 index 267d1240f1b0c2b14668b7d01dc00744f05115fe..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/trace/trace.spec.js +++ /dev/null @@ -1,44 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; - -import Http from '../../transport/http'; -import Trace from './trace'; - -const instance = new Trace(new Http(TEST_HTTP_URL, -1)); - -describe('api/rpc/Trace', () => { - let scope; - - describe('block', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'trace_block', reply: { result: [] } }]); - }); - - it('assumes latest blockNumber when not specified', () => { - return instance.block().then(() => { - expect(scope.body.trace_block.params).to.deep.equal(['latest']); - }); - }); - - it('passed specified blockNumber', () => { - return instance.block(0x123).then(() => { - expect(scope.body.trace_block.params).to.deep.equal(['0x123']); - }); - }); - }); -}); diff --git a/js/src/api/rpc/web3/index.js b/js/src/api/rpc/web3/index.js deleted file mode 100644 index c2590ec1150dd0ed0c57c1ed3cd9f7deb287e183..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/web3/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './web3'; diff --git a/js/src/api/rpc/web3/web3.e2e.js b/js/src/api/rpc/web3/web3.e2e.js deleted file mode 100644 index 2c8243a4fb933fb263d2acc13ecc5cf44a7cd591..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/web3/web3.e2e.js +++ /dev/null @@ -1,44 +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 . - -import { createHttpApi } from '../../../../test/e2e/ethapi'; -import { isHexNumber } from '../../../../test/types'; - -describe('ethapi.web3', () => { - const ethapi = createHttpApi(); - - describe('clientVersion', () => { - it('returns the client version', () => { - return ethapi.web3.clientVersion().then((version) => { - const [client] = version.split('/'); - - expect(client === 'Parity' || client === 'Geth').to.be.ok; - }); - }); - }); - - describe('sha3', () => { - it('returns a keccak256 sha', () => { - const sha = '0xa7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf'; - const hexStr = 'baz()'.split('').map((char) => char.charCodeAt(0).toString(16)).join(''); - - return ethapi.web3.sha3(`0x${hexStr}`).then((hash) => { - expect(isHexNumber(hash)).to.be.true; - expect(hash).to.equal(sha); - }); - }); - }); -}); diff --git a/js/src/api/rpc/web3/web3.js b/js/src/api/rpc/web3/web3.js deleted file mode 100644 index 21b2d77f1e359b10e0df5da14185ad948656e630..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/web3/web3.js +++ /dev/null @@ -1,33 +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 . - -import { inHex } from '../../format/input'; - -export default class Web3 { - constructor (transport) { - this._transport = transport; - } - - clientVersion () { - return this._transport - .execute('web3_clientVersion'); - } - - sha3 (hexStr) { - return this._transport - .execute('web3_sha3', inHex(hexStr)); - } -} diff --git a/js/src/api/rpc/web3/web3.spec.js b/js/src/api/rpc/web3/web3.spec.js deleted file mode 100644 index b46679b82a7a8a2285ba7afc0f07bf9f135a20d2..0000000000000000000000000000000000000000 --- a/js/src/api/rpc/web3/web3.spec.js +++ /dev/null @@ -1,38 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; - -import Http from '../../transport/http'; -import Web3 from './web3'; - -const instance = new Web3(new Http(TEST_HTTP_URL, -1)); - -describe('api/rpc/Web3', () => { - let scope; - - describe('sha3', () => { - beforeEach(() => { - scope = mockHttp([{ method: 'web3_sha3', reply: { result: [] } }]); - }); - - it('formats the inputs correctly', () => { - return instance.sha3('1234').then(() => { - expect(scope.body.web3_sha3.params).to.deep.equal(['0x1234']); - }); - }); - }); -}); diff --git a/js/src/api/subscriptions/eth.js b/js/src/api/subscriptions/eth.js deleted file mode 100644 index 8e56f335f7e527a90107efb0efff6ba0a26440ec..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/eth.js +++ /dev/null @@ -1,63 +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 . - -import BigNumber from 'bignumber.js'; - -export default class Eth { - constructor (updateSubscriptions, api) { - this._api = api; - this._updateSubscriptions = updateSubscriptions; - this._started = false; - - this._lastBlock = new BigNumber(-1); - this._pollTimerId = null; - } - - get isStarted () { - return this._started; - } - - start () { - this._started = true; - - return this._blockNumber(); - } - - _blockNumber = () => { - const nextTimeout = (timeout = 1000) => { - this._pollTimerId = setTimeout(() => { - this._blockNumber(); - }, timeout); - }; - - if (!this._api.transport.isConnected) { - nextTimeout(500); - return; - } - - return this._api.eth - .blockNumber() - .then((blockNumber) => { - if (!blockNumber.eq(this._lastBlock)) { - this._lastBlock = blockNumber; - this._updateSubscriptions('eth_blockNumber', null, blockNumber); - } - - nextTimeout(); - }) - .catch(() => nextTimeout()); - } -} diff --git a/js/src/api/subscriptions/eth.spec.js b/js/src/api/subscriptions/eth.spec.js deleted file mode 100644 index 3f5ee81d66f8a4c51ea67adbf94fd405cf792998..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/eth.spec.js +++ /dev/null @@ -1,101 +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 . - -import BigNumber from 'bignumber.js'; -import sinon from 'sinon'; - -import Eth from './eth'; - -const START_BLOCK = 5000; - -function stubApi (blockNumber) { - const _calls = { - blockNumber: [] - }; - - return { - _calls, - transport: { - isConnected: true - }, - eth: { - blockNumber: () => { - const stub = sinon.stub().resolves(new BigNumber(blockNumber || START_BLOCK))(); - - _calls.blockNumber.push(stub); - return stub; - } - } - }; -} - -describe('api/subscriptions/eth', () => { - let api; - let eth; - let cb; - - beforeEach(() => { - api = stubApi(); - cb = sinon.stub(); - eth = new Eth(cb, api); - }); - - describe('constructor', () => { - it('starts the instance in a stopped state', () => { - expect(eth.isStarted).to.be.false; - }); - }); - - describe('start', () => { - describe('blockNumber available', () => { - beforeEach(() => { - return eth.start(); - }); - - it('sets the started status', () => { - expect(eth.isStarted).to.be.true; - }); - - it('calls eth_blockNumber', () => { - expect(api._calls.blockNumber.length).to.be.ok; - }); - - it('updates subscribers', () => { - expect(cb).to.have.been.calledWith('eth_blockNumber', null, new BigNumber(START_BLOCK)); - }); - }); - - describe('blockNumber not available', () => { - beforeEach(() => { - api = stubApi(-1); - eth = new Eth(cb, api); - return eth.start(); - }); - - it('sets the started status', () => { - expect(eth.isStarted).to.be.true; - }); - - it('calls eth_blockNumber', () => { - expect(api._calls.blockNumber.length).to.be.ok; - }); - - it('does not update subscribers', () => { - expect(cb).not.to.been.called; - }); - }); - }); -}); diff --git a/js/src/api/subscriptions/index.js b/js/src/api/subscriptions/index.js deleted file mode 100644 index 07856faefd7c84c6d4fd71d229c7728f281ab5c1..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/index.js +++ /dev/null @@ -1,19 +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 . - -export Logging from './logging'; - -export default from './manager'; diff --git a/js/src/api/subscriptions/logging.js b/js/src/api/subscriptions/logging.js deleted file mode 100644 index 545742dff7f75f7ebdf41fc7e608ed6288ced2ee..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/logging.js +++ /dev/null @@ -1,44 +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 . - -let instance = null; - -export default class Logging { - constructor (updateSubscriptions) { - this._updateSubscriptions = updateSubscriptions; - - instance = this; - } - - get isStarted () { - return true; - } - - start () { - } - - static send (method, params, json) { - if (!instance) { - return; - } - - return instance._updateSubscriptions('logging', null, { - method, - params, - json - }); - } -} diff --git a/js/src/api/subscriptions/logging.spec.js b/js/src/api/subscriptions/logging.spec.js deleted file mode 100644 index f155696b779277dc9851f6a04f66c90e4d02db13..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/logging.spec.js +++ /dev/null @@ -1,49 +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 . - -import sinon from 'sinon'; - -import Logging from './logging'; - -describe('api/subscriptions/logging', () => { - let cb; - let logging; - - beforeEach(() => { - cb = sinon.stub(); - logging = new Logging(cb); - }); - - describe('constructor', () => { - it('starts the instance in a started state', () => { - expect(logging.isStarted).to.be.true; - }); - }); - - describe('send', () => { - const method = 'method'; - const params = 'params'; - const json = 'json'; - - beforeEach(() => { - Logging.send(method, params, json); - }); - - it('calls the subscription update', () => { - expect(cb).to.have.been.calledWith('logging', null, { method, params, json }); - }); - }); -}); diff --git a/js/src/api/subscriptions/manager.js b/js/src/api/subscriptions/manager.js deleted file mode 100644 index 6ca2f401502be3c45dff9c19de5174b457aad8b6..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/manager.js +++ /dev/null @@ -1,137 +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 . - -import { isError } from '../util/types'; - -import Eth from './eth'; -import Logging from './logging'; -import Personal from './personal'; -import Signer from './signer'; - -const events = { - 'logging': { module: 'logging' }, - 'eth_blockNumber': { module: 'eth' }, - 'parity_accountsInfo': { module: 'personal' }, - 'parity_allAccountsInfo': { module: 'personal' }, - 'parity_defaultAccount': { module: 'personal' }, - 'parity_postTransaction': { module: 'signer' }, - 'eth_accounts': { module: 'personal' }, - 'signer_requestsToConfirm': { module: 'signer' } -}; - -export default class Manager { - constructor (api) { - this._api = api; - - this.subscriptions = []; - this.values = {}; - - Object.keys(events).forEach((subscriptionName) => { - this.values[subscriptionName] = { - error: null, - data: null - }; - }); - - this._logging = new Logging(this._updateSubscriptions); - this._eth = new Eth(this._updateSubscriptions, api); - this._personal = new Personal(this._updateSubscriptions, api, this); - this._signer = new Signer(this._updateSubscriptions, api, this); - } - - _validateType (subscriptionName) { - const subscription = events[subscriptionName]; - - if (!subscription) { - return new Error(`${subscriptionName} is not a valid interface, subscribe using one of ${Object.keys(events).join(', ')}`); - } - - return subscription; - } - - subscribe (subscriptionName, callback, autoRemove = false) { - return new Promise((resolve, reject) => { - const subscription = this._validateType(subscriptionName); - - if (isError(subscription)) { - reject(subscription); - return; - } - - const subscriptionId = this.subscriptions.length; - const { error, data } = this.values[subscriptionName]; - const engine = this[`_${subscription.module}`]; - - this.subscriptions[subscriptionId] = { - name: subscriptionName, - id: subscriptionId, - autoRemove, - callback - }; - - if (!engine.isStarted) { - engine.start(); - } else if (error !== null || data !== null) { - this._sendData(subscriptionId, error, data); - } - - resolve(subscriptionId); - }); - } - - unsubscribe (subscriptionId) { - return new Promise((resolve, reject) => { - if (!this.subscriptions[subscriptionId]) { - reject(new Error(`Cannot find subscription ${subscriptionId}`)); - return; - } - - delete this.subscriptions[subscriptionId]; - resolve(); - }); - } - - _sendData (subscriptionId, error, data) { - const { autoRemove, callback } = this.subscriptions[subscriptionId]; - let result = true; - - try { - result = callback(error, data); - } catch (error) { - console.error(`Unable to update callback for subscriptionId ${subscriptionId}`, error); - } - - if (autoRemove && result && typeof result === 'boolean') { - this.unsubscribe(subscriptionId); - } - } - - _updateSubscriptions = (subscriptionName, error, data) => { - const subscriptions = this.subscriptions - .filter(subscription => subscription.name === subscriptionName); - - this.values[subscriptionName] = { error, data }; - - subscriptions - .forEach((subscription) => { - this._sendData(subscription.id, error, data); - }); - } -} - -export { - events -}; diff --git a/js/src/api/subscriptions/manager.spec.js b/js/src/api/subscriptions/manager.spec.js deleted file mode 100644 index df708a36dcbb933f23c20185c07ccae3dabb3874..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/manager.spec.js +++ /dev/null @@ -1,134 +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 . - -import sinon from 'sinon'; - -import Manager, { events } from './manager'; - -function newStub () { - const start = () => manager._updateSubscriptions(manager.__test, null, 'test'); - - const manager = new Manager({ - transport: { - isConnected: true - } - }); - - manager._eth = { - isStarted: false, - start - }; - - manager._personal = { - isStarted: false, - start - }; - - manager._signer = { - isStarted: false, - start - }; - - return manager; -} - -describe('api/subscriptions/manager', () => { - let manager; - - beforeEach(() => { - manager = newStub(); - }); - - describe('constructor', () => { - it('sets up the subscription types & defaults', () => { - expect(manager.subscriptions).to.be.an.array; - expect(Object.keys(manager.values)).to.deep.equal(Object.keys(events)); - }); - }); - - describe('subscriptions', () => { - Object - .keys(events) - .filter((eventName) => eventName.indexOf('_') !== -1) - .forEach((eventName) => { - const { module } = events[eventName]; - let engine; - let cb; - let subscriptionId; - - describe(eventName, () => { - beforeEach(() => { - engine = manager[`_${module}`]; - manager.__test = eventName; - cb = sinon.stub(); - sinon.spy(engine, 'start'); - - return manager - .subscribe(eventName, cb) - .then((_subscriptionId) => { - subscriptionId = _subscriptionId; - }); - }); - - it(`puts the ${module} engine in a started state`, () => { - expect(engine.start).to.have.been.called; - }); - - it('returns a subscriptionId', () => { - expect(subscriptionId).to.be.a.number; - }); - - it('calls the subscription callback with updated values', () => { - expect(cb).to.have.been.calledWith(null, 'test'); - }); - }); - }); - }); - - describe('unsubscriptions', () => { - Object - .keys(events) - .filter((eventName) => eventName.indexOf('_') !== -1) - .forEach((eventName) => { - const { module } = events[eventName]; - let engine; - let cb; - - describe(eventName, () => { - beforeEach(() => { - engine = manager[`_${module}`]; - manager.__test = eventName; - cb = sinon.stub(); - sinon.spy(engine, 'start'); - - return manager - .subscribe(eventName, cb) - .then((_subscriptionId) => { - manager.unsubscribe(_subscriptionId); - }) - .then(() => { - manager._updateSubscriptions(manager.__test, null, 'test2'); - }); - }); - - it('does not call the callback after unsubscription', () => { - expect(cb).to.have.been.calledWith(null, 'test'); - expect(cb).to.not.have.been.calledWith(null, 'test2'); - }); - }); - }); - }); -}); diff --git a/js/src/api/subscriptions/personal.js b/js/src/api/subscriptions/personal.js deleted file mode 100644 index fa7ae823ca99a1283a155e778c3453dcb7ebbc01..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/personal.js +++ /dev/null @@ -1,135 +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 . - -export default class Personal { - constructor (updateSubscriptions, api, subscriber) { - this._subscriber = subscriber; - this._api = api; - this._updateSubscriptions = updateSubscriptions; - this._started = false; - - this._lastDefaultAccount = '0x0'; - this._pollTimerId = null; - } - - get isStarted () { - return this._started; - } - - start () { - this._started = true; - - return Promise.all([ - this._defaultAccount(), - this._listAccounts(), - this._accountsInfo(), - this._loggingSubscribe() - ]); - } - - // FIXME: Because of the different API instances, the "wait for valid changes" approach - // doesn't work. Since the defaultAccount is critical to operation, we poll in exactly - // same way we do in ../eth (ala eth_blockNumber) and update. This should be moved - // to pub-sub as it becomes available - _defaultAccount = (timerDisabled = false) => { - const nextTimeout = (timeout = 1000) => { - if (!timerDisabled) { - this._pollTimerId = setTimeout(() => { - this._defaultAccount(); - }, timeout); - } - }; - - if (!this._api.transport.isConnected) { - nextTimeout(500); - return; - } - - return this._api.parity - .defaultAccount() - .then((defaultAccount) => { - if (this._lastDefaultAccount !== defaultAccount) { - this._lastDefaultAccount = defaultAccount; - this._updateSubscriptions('parity_defaultAccount', null, defaultAccount); - } - - nextTimeout(); - }) - .catch(() => nextTimeout()); - } - - _listAccounts = () => { - return this._api.eth - .accounts() - .then((accounts) => { - this._updateSubscriptions('eth_accounts', null, accounts); - }); - } - - _accountsInfo = () => { - return this._api.parity - .accountsInfo() - .then((info) => { - this._updateSubscriptions('parity_accountsInfo', null, info); - - return this._api.parity - .allAccountsInfo() - .catch(() => { - // NOTE: This fails on non-secure APIs, swallow error - return {}; - }) - .then((allInfo) => { - this._updateSubscriptions('parity_allAccountsInfo', null, allInfo); - }); - }); - } - - _loggingSubscribe () { - return this._subscriber.subscribe('logging', (error, data) => { - if (error || !data) { - return; - } - - switch (data.method) { - case 'parity_closeVault': - case 'parity_openVault': - case 'parity_killAccount': - case 'parity_importGethAccounts': - case 'parity_newAccountFromPhrase': - case 'parity_newAccountFromWallet': - case 'personal_newAccount': - this._defaultAccount(true); - this._listAccounts(); - this._accountsInfo(); - return; - - case 'parity_removeAddress': - case 'parity_setAccountName': - case 'parity_setAccountMeta': - this._accountsInfo(); - return; - - case 'parity_setDappAddresses': - case 'parity_setDappDefaultAddress': - case 'parity_setNewDappsAddresses': - case 'parity_setNewDappsDefaultAddress': - this._defaultAccount(true); - this._listAccounts(); - return; - } - }); - } -} diff --git a/js/src/api/subscriptions/personal.spec.js b/js/src/api/subscriptions/personal.spec.js deleted file mode 100644 index ac046d25099dc78af3c4e2b54b191d008e58ab64..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/personal.spec.js +++ /dev/null @@ -1,156 +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 . - -import sinon from 'sinon'; - -import Personal from './personal'; - -const TEST_DEFAULT = '0xfa64203C044691aA57251aF95f4b48d85eC00Dd5'; -const TEST_INFO = { - [TEST_DEFAULT]: { - name: 'test' - } -}; -const TEST_LIST = [TEST_DEFAULT]; - -function stubApi (accounts, info) { - const _calls = { - accountsInfo: [], - allAccountsInfo: [], - listAccounts: [], - defaultAccount: [] - }; - - return { - _calls, - transport: { - isConnected: true - }, - parity: { - accountsInfo: () => { - const stub = sinon.stub().resolves(info || TEST_INFO)(); - - _calls.accountsInfo.push(stub); - return stub; - }, - allAccountsInfo: () => { - const stub = sinon.stub().resolves(info || TEST_INFO)(); - - _calls.allAccountsInfo.push(stub); - return stub; - }, - defaultAccount: () => { - const stub = sinon.stub().resolves(Object.keys(info || TEST_INFO)[0])(); - - _calls.defaultAccount.push(stub); - return stub; - } - }, - eth: { - accounts: () => { - const stub = sinon.stub().resolves(accounts || TEST_LIST)(); - - _calls.listAccounts.push(stub); - return stub; - } - } - }; -} - -function stubLogging () { - return { - subscribe: sinon.stub() - }; -} - -describe('api/subscriptions/personal', () => { - let api; - let cb; - let logging; - let personal; - - beforeEach(() => { - api = stubApi(); - cb = sinon.stub(); - logging = stubLogging(); - personal = new Personal(cb, api, logging); - }); - - describe('constructor', () => { - it('starts the instance in a stopped state', () => { - expect(personal.isStarted).to.be.false; - }); - }); - - describe('start', () => { - describe('info available', () => { - beforeEach(() => { - return personal.start(); - }); - - it('sets the started status', () => { - expect(personal.isStarted).to.be.true; - }); - - it('calls parity_accountsInfo', () => { - expect(api._calls.accountsInfo.length).to.be.ok; - }); - - it('calls parity_allAccountsInfo', () => { - expect(api._calls.allAccountsInfo.length).to.be.ok; - }); - - it('calls eth_accounts', () => { - expect(api._calls.listAccounts.length).to.be.ok; - }); - - it('updates subscribers', () => { - expect(cb).to.have.been.calledWith('parity_defaultAccount', null, TEST_DEFAULT); - expect(cb).to.have.been.calledWith('eth_accounts', null, TEST_LIST); - expect(cb).to.have.been.calledWith('parity_accountsInfo', null, TEST_INFO); - expect(cb).to.have.been.calledWith('parity_allAccountsInfo', null, TEST_INFO); - }); - }); - - describe('info not available', () => { - beforeEach(() => { - api = stubApi([], {}); - personal = new Personal(cb, api, logging); - return personal.start(); - }); - - it('sets the started status', () => { - expect(personal.isStarted).to.be.true; - }); - - it('calls parity_defaultAccount', () => { - expect(api._calls.defaultAccount.length).to.be.ok; - }); - - it('calls personal_accountsInfo', () => { - expect(api._calls.accountsInfo.length).to.be.ok; - }); - - it('calls personal_allAccountsInfo', () => { - expect(api._calls.allAccountsInfo.length).to.be.ok; - }); - - it('calls personal_listAccounts', () => { - expect(api._calls.listAccounts.length).to.be.ok; - }); - }); - }); -}); diff --git a/js/src/api/subscriptions/signer.js b/js/src/api/subscriptions/signer.js deleted file mode 100644 index 2215ed7f3df6e312df49446d85ec67879fdea163..0000000000000000000000000000000000000000 --- a/js/src/api/subscriptions/signer.js +++ /dev/null @@ -1,91 +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 . - -import { outTransaction } from '../format/output'; - -export default class Signer { - constructor (updateSubscriptions, api, subscriber) { - this._subscriber = subscriber; - this._api = api; - this._updateSubscriptions = updateSubscriptions; - this._started = false; - } - - get isStarted () { - return this._started; - } - - start () { - this._started = true; - - return Promise.all([ - this._listRequests(true), - this._loggingSubscribe() - ]); - } - - _listRequests = (doTimeout) => { - const nextTimeout = (timeout = 1000) => { - if (doTimeout) { - setTimeout(() => { - this._listRequests(true); - }, timeout); - } - }; - - if (!this._api.transport.isConnected) { - nextTimeout(500); - return; - } - - return this._api.signer - .requestsToConfirm() - .then((requests) => { - this._updateSubscriptions('signer_requestsToConfirm', null, requests); - nextTimeout(); - }) - .catch(() => nextTimeout()); - } - - _postTransaction (data) { - const request = { - transaction: outTransaction(data.params[0]), - requestId: data.json.result.result - }; - - this._updateSubscriptions('parity_postTransaction', null, request); - } - - _loggingSubscribe () { - return this._subscriber.subscribe('logging', (error, data) => { - if (error || !data) { - return; - } - - switch (data.method) { - case 'eth_sendTransaction': - case 'eth_sendRawTransaction': - this._listRequests(false); - return; - - case 'parity_postTransaction': - this._postTransaction(data); - this._listRequests(false); - return; - } - }); - } -} diff --git a/js/src/api/transport/error.js b/js/src/api/transport/error.js deleted file mode 100644 index 9049705fab5bcca78a0d63d20a3b73076bf8a4de..0000000000000000000000000000000000000000 --- a/js/src/api/transport/error.js +++ /dev/null @@ -1,61 +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 . - -import ExtendableError from 'es6-error'; - -export const ERROR_CODES = { - UNSUPPORTED_REQUEST: -32000, - NO_WORK: -32001, - NO_AUTHOR: -32002, - NO_NEW_WORK: -32003, - NO_WORK_REQUIRED: -32004, - NOT_ENOUGH_DATA: -32006, - UNKNOWN_ERROR: -32009, - TRANSACTION_ERROR: -32010, - EXECUTION_ERROR: -32015, - EXCEPTION_ERROR: -32016, - ACCOUNT_LOCKED: -32020, - PASSWORD_INVALID: -32021, - ACCOUNT_ERROR: -32023, - SIGNER_DISABLED: -32030, - DAPPS_DISABLED: -32031, - NETWORK_DISABLED: -32035, - REQUEST_REJECTED: -32040, - REQUEST_REJECTED_LIMIT: -32041, - REQUEST_NOT_FOUND: -32042, - COMPILATION_ERROR: -32050, - ENCRYPTION_ERROR: -32055, - FETCH_ERROR: -32060, - INVALID_PARAMS: -32602 -}; - -export default class TransportError extends ExtendableError { - static requestRejected (method = null) { - return new TransportError(method, ERROR_CODES.REQUEST_REJECTED, 'Request has been rejected.'); - } - - constructor (method, code, message) { - const m = `${method}: ${code}: ${message}`; - - super(m); - - this.code = code; - this.type = Object.keys(ERROR_CODES).find((k) => ERROR_CODES[k] === code) || ''; - - this.method = method; - this.text = message; - } -} diff --git a/js/src/api/transport/http/http.e2e.js b/js/src/api/transport/http/http.e2e.js deleted file mode 100644 index af2fb1fbb31332c3bce258212b0e1a32fd4226cb..0000000000000000000000000000000000000000 --- a/js/src/api/transport/http/http.e2e.js +++ /dev/null @@ -1,29 +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 . - -import Http from './http'; - -const http = new Http('http://localhost:8545'); - -describe('transport/Http', () => { - it('connects and makes a call to web3_clientVersion', () => { - return http.execute('web3_clientVersion').then((version) => { - const [client] = version.split('/'); - - expect(client === 'Geth' || client === 'Parity').to.be.ok; - }); - }); -}); diff --git a/js/src/api/transport/http/http.js b/js/src/api/transport/http/http.js deleted file mode 100644 index 66ef2dec7908543f2191d45dd89708563d58681c..0000000000000000000000000000000000000000 --- a/js/src/api/transport/http/http.js +++ /dev/null @@ -1,103 +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 . - -import { Logging } from '../../subscriptions'; -import JsonRpcBase from '../jsonRpcBase'; -import TransportError from '../error'; - -/* global fetch */ -export default class Http extends JsonRpcBase { - constructor (url, connectTimeout = 1000) { - super(); - - this._connected = true; - this._url = url; - this._connectTimeout = connectTimeout; - - this._pollConnection(); - } - - _encodeOptions (method, params) { - const json = this.encode(method, params); - - this.log(json); - - return { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - 'Content-Length': json.length - }, - body: json - }; - } - - _execute (method, params) { - const request = this._encodeOptions(method, params); - - return fetch(this._url, request) - .catch((error) => { - this._setDisconnected(); - throw error; - }) - .then((response) => { - this._setConnected(); - - if (response.status !== 200) { - this._setDisconnected(); - this.error(JSON.stringify({ status: response.status, statusText: response.statusText })); - console.error(`${method}(${JSON.stringify(params)}): ${response.status}: ${response.statusText}`); - - throw new Error(`${response.status}: ${response.statusText}`); - } - - return response.json(); - }) - .then((response) => { - Logging.send(method, params, { request, response }); - - if (response.error) { - this.error(JSON.stringify(response)); - console.error(`${method}(${JSON.stringify(params)}): ${response.error.code}: ${response.error.message}`); - - const error = new TransportError(method, response.error.code, response.error.message); - - throw error; - } - - this.log(JSON.stringify(response)); - return response.result; - }); - } - - _pollConnection = () => { - if (this._connectTimeout <= 0) { - return; - } - - const nextTimeout = () => setTimeout(this._pollConnection, this._connectTimeout); - - this - .execute('net_listening') - .then(() => nextTimeout()) - .catch(() => nextTimeout()); - } - - set url (url) { - this._url = url; - } -} diff --git a/js/src/api/transport/http/http.spec.js b/js/src/api/transport/http/http.spec.js deleted file mode 100644 index 3d08e17a4493cbf16b87851b011f9ae4986ccdc8..0000000000000000000000000000000000000000 --- a/js/src/api/transport/http/http.spec.js +++ /dev/null @@ -1,142 +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 . - -import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc'; -import Http from './http'; - -const transport = new Http(TEST_HTTP_URL, -1); - -describe('api/transport/Http', () => { - describe('instance', () => { - it('encodes the options correctly', () => { - const opt = transport._encodeOptions('someMethod', ['param']); - const enc = { - method: 'POST', - headers: { - 'Accept': 'application/json', - 'Content-Type': 'application/json', - 'Content-Length': 65 - }, - body: `{"jsonrpc":"2.0","method":"someMethod","params":["param"],"id":${transport._id - 1}}` - }; - - expect(opt).to.deep.equal(enc); - }); - }); - - describe('transport emitter', () => { - it('emits close event', (done) => { - transport.once('close', () => { - done(); - }); - - transport.execute('eth_call'); - }); - - it('emits open event', (done) => { - mockHttp([{ method: 'eth_call', reply: { result: '' } }]); - - transport.once('open', () => { - done(); - }); - - transport.execute('eth_call'); - }); - }); - - describe('transport', () => { - const RESULT = ['this is some result']; - - let scope; - let result; - - beforeEach(() => { - scope = mockHttp([{ method: 'eth_call', reply: { result: RESULT } }]); - - return transport - .execute('eth_call', 1, 2, 3, 'test') - .then((_result) => { - result = _result; - }); - }); - - it('makes POST', () => { - expect(scope.isDone()).to.be.true; - }); - - it('sets jsonrpc', () => { - expect(scope.body.eth_call.jsonrpc).to.equal('2.0'); - }); - - it('sets the method', () => { - expect(scope.body.eth_call.method).to.equal('eth_call'); - }); - - it('passes the params', () => { - expect(scope.body.eth_call.params).to.deep.equal([1, 2, 3, 'test']); - }); - - it('increments the id', () => { - expect(scope.body.eth_call.id).not.to.equal(0); - }); - - it('passes the actual result back', () => { - expect(result).to.deep.equal(RESULT); - }); - }); - - describe('HTTP errors', () => { - let scope; - let error; - - beforeEach(() => { - scope = mockHttp([{ method: 'eth_call', reply: {}, code: 500 }]); - - return transport - .execute('eth_call') - .catch((_error) => { - error = _error; - }); - }); - - it('returns HTTP errors as throws', () => { - expect(scope.isDone()).to.be.true; - expect(error.message).to.match(/Internal Server Error/); - }); - }); - - describe('RPC errors', () => { - const ERROR = { code: -1, message: 'ERROR: RPC failure' }; - - let scope; - let error; - - beforeEach(() => { - scope = mockHttp([{ method: 'eth_call', reply: { error: ERROR } }]); - - return transport - .execute('eth_call') - .catch((_error) => { - error = _error; - }); - }); - - it('returns RPC errors as throws', () => { - expect(scope.isDone()).to.be.true; - expect(error.message).to.match(/RPC failure/); - }); - }); -}); diff --git a/js/src/api/transport/http/index.js b/js/src/api/transport/http/index.js deleted file mode 100644 index dfd1721653582cd273d0313bdadb6de30c251ed8..0000000000000000000000000000000000000000 --- a/js/src/api/transport/http/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './http'; diff --git a/js/src/api/transport/index.js b/js/src/api/transport/index.js deleted file mode 100644 index fdd3861a84e051a32470025ac32f1a10a78c85ea..0000000000000000000000000000000000000000 --- a/js/src/api/transport/index.js +++ /dev/null @@ -1,20 +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 . - -export Http from './http'; -export Ws from './ws'; -export TransportError from './error'; -export Middleware from './middleware'; diff --git a/js/src/api/transport/jsonRpcBase.js b/js/src/api/transport/jsonRpcBase.js deleted file mode 100644 index 819e1f496ff723aea7c2b995c83052d25d0f10a9..0000000000000000000000000000000000000000 --- a/js/src/api/transport/jsonRpcBase.js +++ /dev/null @@ -1,145 +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 . - -import EventEmitter from 'eventemitter3'; -import { Logging } from '../subscriptions'; - -export default class JsonRpcBase extends EventEmitter { - constructor () { - super(); - - this._id = 1; - this._debug = false; - this._connected = false; - this._middlewareList = Promise.resolve([]); - } - - encode (method, params) { - const json = JSON.stringify({ - jsonrpc: '2.0', - method: method, - params: params, - id: this._id++ - }); - - return json; - } - - addMiddleware (Middleware) { - this._middlewareList = Promise - .all([ - Middleware, - this._middlewareList - ]) - .then(([Middleware, middlewareList]) => { - // Do nothing if `handlerPromise` resolves to a null-y value. - if (Middleware == null) { - return middlewareList; - } - - // don't mutate the original array - return middlewareList.concat([new Middleware(this)]); - }); - } - - _wrapSuccessResult (result) { - return { - id: this._id, - jsonrpc: '2.0', - result - }; - } - - _wrapErrorResult (error) { - return { - id: this._id, - jsonrpc: '2.0', - error: { - code: error.code, - message: error.text - } - }; - } - - execute (method, ...params) { - return this._middlewareList.then((middlewareList) => { - for (const middleware of middlewareList) { - const res = middleware.handle(method, params); - - if (res != null) { - return Promise - .resolve(res) - .then((res) => { - const result = this._wrapSuccessResult(res); - const json = this.encode(method, params); - - Logging.send(method, params, { json, result }); - - return res; - }); - } - } - - return this._execute(method, params); - }); - } - - _execute () { - throw new Error('Missing implementation of JsonRpcBase#_execute'); - } - - _setConnected () { - if (!this._connected) { - this._connected = true; - this.emit('open'); - } - } - - _setDisconnected () { - if (this._connected) { - this._connected = false; - this.emit('close'); - } - } - - get id () { - return this._id; - } - - get isDebug () { - return this._debug; - } - - get isConnected () { - return this._connected; - } - - setDebug (flag) { - this._debug = flag; - } - - error (error) { - if (this.isDebug) { - console.error(error); - } - } - - log (log) { - if (this.isDebug) { - console.log(log); - } - } -} diff --git a/js/src/api/transport/jsonRpcBase.spec.js b/js/src/api/transport/jsonRpcBase.spec.js deleted file mode 100644 index 6c3b955647eaa1dcc3b81a8d4d1a62edf3a40360..0000000000000000000000000000000000000000 --- a/js/src/api/transport/jsonRpcBase.spec.js +++ /dev/null @@ -1,88 +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 . - -import sinon from 'sinon'; - -import JsonRpcBase from './jsonRpcBase'; - -const base = new JsonRpcBase(); - -describe('api/transport/JsonRpcBase', () => { - describe('encode', () => { - it('encodes the body correctly, incrementing id', () => { - const id = base.id; - const bdy = base.encode('someMethod', ['param1', 'param2']); - const enc = `{"jsonrpc":"2.0","method":"someMethod","params":["param1","param2"],"id":${id}}`; - - expect(bdy).to.equal(enc); - expect(base.id - id).to.equal(1); - }); - }); - - describe('setDebug', () => { - it('starts with disabled flag', () => { - expect(base.isDebug).to.be.false; - }); - - it('true flag switches on', () => { - base.setDebug(true); - expect(base.isDebug).to.be.true; - }); - - it('false flag switches off', () => { - base.setDebug(true); - expect(base.isDebug).to.be.true; - base.setDebug(false); - expect(base.isDebug).to.be.false; - }); - - describe('logging', () => { - beforeEach(() => { - sinon.spy(console, 'log'); - sinon.spy(console, 'error'); - }); - - afterEach(() => { - console.log.restore(); - console.error.restore(); - }); - - it('does not log errors with flag off', () => { - base.setDebug(false); - base.log('error'); - expect(console.log).to.not.be.called; - }); - - it('does not log errors with flag off', () => { - base.setDebug(false); - base.error('error'); - expect(console.error).to.not.be.called; - }); - - it('does log errors with flag on', () => { - base.setDebug(true); - base.log('error'); - expect(console.log).to.be.called; - }); - - it('does log errors with flag on', () => { - base.setDebug(true); - base.error('error'); - expect(console.error).to.be.called; - }); - }); - }); -}); diff --git a/js/src/api/transport/middleware.js b/js/src/api/transport/middleware.js deleted file mode 100644 index ef029b1cbc8db9b3ca94c2cd4915e77ec2426a67..0000000000000000000000000000000000000000 --- a/js/src/api/transport/middleware.js +++ /dev/null @@ -1,44 +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 . - -export default class Middleware { - constructor (transport) { - this._transport = transport; - this._handlers = {}; - } - - register (method, handler) { - if (method in this._handlers) { - throw new Error(`${method} is already defined in the middleware!`); - } - - this._handlers[method] = handler; - } - - handle (method, params) { - const handler = this._handlers[method]; - - if (handler != null) { - return handler(params); - } - - return null; - } - - rpcRequest (method, params) { - return this._transport._execute(method, params); - } -} diff --git a/js/src/api/transport/middleware.spec.js b/js/src/api/transport/middleware.spec.js deleted file mode 100644 index 4ae894135bcc79c7bb8177eb8ac26cc5e1fc3cca..0000000000000000000000000000000000000000 --- a/js/src/api/transport/middleware.spec.js +++ /dev/null @@ -1,62 +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 . - -import Middleware from './middleware'; -import JsonRpcBase from './jsonRpcBase'; - -const MOCKED = 'mocked!'; - -class MockTransport extends JsonRpcBase { - _execute () { - return Promise.resolve(MOCKED); - } -} - -class MockMiddleware extends Middleware { - constructor (transport) { - super(transport); - - this.register('mock_rpc', ([num]) => num); - this.register('mock_null', () => null); - } -} - -describe('api/transport/Middleware', () => { - let transport; - - beforeEach(() => { - transport = new MockTransport(); - transport.addMiddleware(MockMiddleware); - }); - - it('Routes requests to middleware', () => { - return transport.execute('mock_rpc', 100).then((num) => { - expect(num).to.be.equal(100); - }); - }); - - it('Passes non-mocked requests through', () => { - return transport.execute('not_moced', 200).then((result) => { - expect(result).to.be.equal(MOCKED); - }); - }); - - it('Passes mocked requests through, if middleware returns null', () => { - return transport.execute('mock_null', 300).then((result) => { - expect(result).to.be.equal(MOCKED); - }); - }); -}); diff --git a/js/src/api/transport/ws/index.js b/js/src/api/transport/ws/index.js deleted file mode 100644 index 7ab0be1310c387b669817e2bc9f1387a86d7b68a..0000000000000000000000000000000000000000 --- a/js/src/api/transport/ws/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './ws'; diff --git a/js/src/api/transport/ws/ws.e2e.js b/js/src/api/transport/ws/ws.e2e.js deleted file mode 100644 index 42e47451c3bba3d8c44436d73997f94e21653274..0000000000000000000000000000000000000000 --- a/js/src/api/transport/ws/ws.e2e.js +++ /dev/null @@ -1,29 +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 . - -import Ws from './ws'; - -const ws = new Ws('ws://localhost:8546/'); - -describe('transport/Ws', () => { - it('connects and makes a call to web3_clientVersion', () => { - return ws.execute('web3_clientVersion').then((version) => { - const [client] = version.split('/'); - - expect(client === 'Geth' || client === 'Parity').to.be.ok; - }); - }); -}); diff --git a/js/src/api/transport/ws/ws.js b/js/src/api/transport/ws/ws.js deleted file mode 100644 index 9c276772dc366cd297110a0f62c9ba0f33b84005..0000000000000000000000000000000000000000 --- a/js/src/api/transport/ws/ws.js +++ /dev/null @@ -1,387 +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 . - -import { keccak_256 } from 'js-sha3'; // eslint-disable-line camelcase - -import { Logging } from '../../subscriptions'; -import JsonRpcBase from '../jsonRpcBase'; -import TransportError from '../error'; - -/* global WebSocket */ -export default class Ws extends JsonRpcBase { - // token is optional (secure API) - constructor (url, token = null, autoconnect = true) { - super(); - - this._url = url; - this._token = token; - this._messages = {}; - this._subscriptions = { 'eth_subscription': [], 'parity_subscription': [], 'shh_subscription': [] }; - this._sessionHash = null; - - this._connecting = false; - this._connected = false; - this._lastError = null; - this._autoConnect = autoconnect; - this._retries = 0; - this._reconnectTimeoutId = null; - - this._connectPromise = null; - this._connectPromiseFunctions = {}; - - if (autoconnect) { - this.connect(); - } - } - - updateToken (token, connect = true) { - this._token = token; - // this._autoConnect = true; - - if (connect) { - this.connect(); - } - } - - connect () { - if (this._connected) { - return Promise.resolve(); - } - - if (this._connecting) { - return this._connectPromise || Promise.resolve(); - } - - if (this._reconnectTimeoutId) { - window.clearTimeout(this._reconnectTimeoutId); - this._reconnectTimeoutId = null; - } - - if (this._ws) { - this._ws.onerror = null; - this._ws.onopen = null; - this._ws.onclose = null; - this._ws.onmessage = null; - this._ws.close(); - this._ws = null; - this._sessionHash = null; - } - this._connecting = true; - this._connected = false; - this._lastError = null; - - // rpc secure API - if (this._token) { - const time = parseInt(new Date().getTime() / 1000, 10); - const sha3 = keccak_256(`${this._token}:${time}`); - const hash = `${sha3}_${time}`; - - this._sessionHash = sha3; - this._ws = new WebSocket(this._url, hash); - // non-secure API - } else { - this._ws = new WebSocket(this._url); - } - - this._ws.onerror = this._onError; - this._ws.onopen = this._onOpen; - this._ws.onclose = this._onClose; - this._ws.onmessage = this._onMessage; - - // Get counts in dev mode only - if (process.env.NODE_ENV === 'development') { - this._count = 0; - this._lastCount = { - timestamp: Date.now(), - count: 0 - }; - - window.setInterval(() => { - const n = this._count - this._lastCount.count; - const t = (Date.now() - this._lastCount.timestamp) / 1000; - const s = Math.round(1000 * n / t) / 1000; - - if (this._debug) { - console.log('::parityWS', `speed: ${s} req/s`, `count: ${this._count}`, `(+${n})`); - } - - this._lastCount = { - timestamp: Date.now(), - count: this._count - }; - }, 5000); - - window._parityWS = this; - } - - this._connectPromise = new Promise((resolve, reject) => { - this._connectPromiseFunctions = { resolve, reject }; - }); - - return this._connectPromise; - } - - _onOpen = (event) => { - this._setConnected(); - this._connecting = false; - this._retries = 0; - - Object.keys(this._messages) - .filter((id) => this._messages[id].queued) - .forEach(this._send); - - this._connectPromiseFunctions.resolve(); - - this._connectPromise = null; - this._connectPromiseFunctions = {}; - } - - _onClose = (event) => { - this._setDisconnected(); - this._connecting = false; - - event.timestamp = Date.now(); - this._lastError = event; - - if (this._autoConnect) { - const timeout = this.retryTimeout; - - const time = timeout < 1000 - ? Math.round(timeout) + 'ms' - : (Math.round(timeout / 10) / 100) + 's'; - - console.log('ws:onClose', `trying again in ${time}...`); - - this._reconnectTimeoutId = setTimeout(() => { - this.connect(); - }, timeout); - - return; - } - - if (this._connectPromise) { - this._connectPromiseFunctions.reject(event); - - this._connectPromise = null; - this._connectPromiseFunctions = {}; - } - - console.log('ws:onClose'); - } - - _onError = (event) => { - // Only print error if the WS is connected - // ie. don't print if error == closed - window.setTimeout(() => { - if (this._connected) { - console.error('ws:onError'); - - event.timestamp = Date.now(); - this._lastError = event; - - if (this._connectPromise) { - this._connectPromiseFunctions.reject(event); - - this._connectPromise = null; - this._connectPromiseFunctions = {}; - } - } - }, 50); - } - - _extract = (result) => { - const { result: res, id, method, params } = result; - const msg = this._messages[id]; - - // initial pubsub ACK - if (id && msg.subscription) { - // save subscription to map subId -> messageId - this._subscriptions[msg.subscription][res] = id; - // resolve promise with messageId because subId's can collide (eth/parity) - msg.resolve(id); - // save subId for unsubscribing later - msg.subId = res; - return msg; - } - - // normal message - if (id) { - return msg; - } - - // pubsub format - if (method.includes('subscription')) { - const messageId = this._messages[this._subscriptions[method][params.subscription]]; - - if (messageId) { - return messageId; - } else { - throw Error(`Received Subscription which is already unsubscribed ${JSON.stringify(result)}`); - } - } - - throw Error(`Unknown message format: No ID or subscription ${JSON.stringify(result)}`); - } - - _onMessage = (event) => { - try { - const result = JSON.parse(event.data); - const { method, params, json, resolve, reject, callback, subscription } = this._extract(result); - - Logging.send(method, params, { json, result }); - - result.error = (result.params && result.params.error) || result.error; - if (result.error) { - this.error(event.data); - - // Don't print error if request rejected or not is not yet up... - if (!/(rejected|not yet up)/.test(result.error.message)) { - console.error(`${method}(${JSON.stringify(params)}): ${result.error.code}: ${result.error.message}`); - } - - const error = new TransportError(method, result.error.code, result.error.message); - - if (result.id) { - reject(error); - } else { - callback(error); - } - - delete this._messages[result.id]; - return; - } - - // if not initial subscription message resolve & delete - if (result.id && !subscription) { - resolve(result.result); - delete this._messages[result.id]; - } else if (result.params) { - callback(null, result.params.result); - } - } catch (e) { - console.error('ws::_onMessage', event.data, e); - } - } - - _send = (id) => { - const message = this._messages[id]; - - if (this._connected) { - if (process.env.NODE_ENV === 'development') { - this._count++; - } - - return this._ws.send(message.json); - } - - message.queued = !this._connected; - message.timestamp = Date.now(); - } - - _execute (method, params) { - return new Promise((resolve, reject) => { - const id = this.id; - const json = this.encode(method, params); - - this._messages[id] = { id, method, params, json, resolve, reject }; - this._send(id); - }); - } - - _methodsFromApi (api) { - const method = `${api}_subscribe`; - const uMethod = `${api}_unsubscribe`; - const subscription = `${api}_subscription`; - - return { method, uMethod, subscription }; - } - - subscribe (api, callback, ...params) { - return new Promise((resolve, reject) => { - const id = this.id; - const { method, uMethod, subscription } = this._methodsFromApi(api); - const json = this.encode(method, params); - - this._messages[id] = { id, method, uMethod, params, json, resolve, reject, callback, subscription }; - - this._send(id); - }); - } - - unsubscribe (messageId) { - return new Promise((resolve, reject) => { - const id = this.id; - const { subId, uMethod, subscription } = this._messages[messageId]; - const params = [subId]; - const json = this.encode(uMethod, params); - const uResolve = (v) => { - delete this._messages[messageId]; - delete this._subscriptions[subscription][subId]; - resolve(v); - }; - - this._messages[id] = { id, method: uMethod, params, json, resolve: uResolve, reject }; - this._send(id); - }); - } - - set url (url) { - this._url = url; - } - - get token () { - return this._token; - } - - get sessionHash () { - return this._sessionHash; - } - - get isAutoConnect () { - return this._autoConnect; - } - - get isConnecting () { - return this._connecting; - } - - get lastError () { - return this._lastError; - } - - /** - * Exponential Timeout for Retries - * - * @see http://dthain.blogspot.de/2009/02/exponential-backoff-in-distributed.html - */ - get retryTimeout () { - // R between 1 and 2 - const R = Math.random() + 1; - // Initial timeout (100ms) - const T = 100; - // Exponential Factor - const F = 2; - // Max timeout (4s) - const M = 4000; - // Current number of retries - const N = this._retries; - - // Increase retries number - this._retries++; - - return Math.min(R * T * Math.pow(F, N), M); - } -} diff --git a/js/src/api/transport/ws/ws.spec.js b/js/src/api/transport/ws/ws.spec.js deleted file mode 100644 index 0d3c9836f5e7941af3544f19845427b2c0fd3d26..0000000000000000000000000000000000000000 --- a/js/src/api/transport/ws/ws.spec.js +++ /dev/null @@ -1,116 +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 . - -import { TEST_WS_URL, mockWs } from '../../../../test/mockRpc'; -import Ws from './ws'; - -describe('api/transport/Ws', () => { - let transport; - let scope; - - describe('transport emitter', () => { - const connect = () => { - const scope = mockWs(); - const transport = new Ws(TEST_WS_URL); - - return { transport, scope }; - }; - - it('emits open event', (done) => { - const { transport, scope } = connect(); - - transport.once('open', () => { - done(); - }); - - scope.stop(); - }); - - it('emits close event', (done) => { - const { transport, scope } = connect(); - - transport.once('open', () => { - scope.server.close(); - }); - - transport.once('close', () => { - done(); - }); - }); - }); - - describe('transport', () => { - let result; - - beforeEach(() => { - scope = mockWs([{ method: 'test_anyCall', reply: 'TestResult' }]); - transport = new Ws(TEST_WS_URL); - - return transport - .execute('test_anyCall', 1, 2, 3) - .then((_result) => { - result = _result; - }); - }); - - afterEach(() => { - scope.stop(); - }); - - it('makes call', () => { - expect(scope.isDone()).to.be.true; - }); - - it('sets jsonrpc', () => { - expect(scope.body.test_anyCall.jsonrpc).to.equal('2.0'); - }); - - it('sets the method', () => { - expect(scope.body.test_anyCall.method).to.equal('test_anyCall'); - }); - - it('passes the params', () => { - expect(scope.body.test_anyCall.params).to.deep.equal([1, 2, 3]); - }); - - it('increments the id', () => { - expect(scope.body.test_anyCall.id).not.to.equal(0); - }); - - it('passes the actual result back', () => { - expect(result).to.equal('TestResult'); - }); - }); - - describe('errors', () => { - beforeEach(() => { - scope = mockWs([{ method: 'test_anyCall', reply: { error: { code: 1, message: 'TestError' } } }]); - transport = new Ws(TEST_WS_URL); - }); - - afterEach(() => { - scope.stop(); - }); - - it('returns RPC errors when encountered', () => { - return transport - .execute('test_anyCall') - .catch((error) => { - expect(error).to.match(/TestError/); - }); - }); - }); -}); diff --git a/js/src/api/util/decode.js b/js/src/api/util/decode.js deleted file mode 100644 index 926a5a8a15439b8c49ac3b27cd66c2e190ece91d..0000000000000000000000000000000000000000 --- a/js/src/api/util/decode.js +++ /dev/null @@ -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 . - -import { isHex } from './types'; - -import Func from '../../abi/spec/function'; -import { fromParamType, toParamType } from '../../abi/spec/paramType/format'; - -export function decodeCallData (data) { - if (!isHex(data)) { - throw new Error('Input to decodeCallData should be a hex value'); - } - - if (data.substr(0, 2) === '0x') { - return decodeCallData(data.slice(2)); - } - - if (data.length < 8) { - throw new Error('Input to decodeCallData should be method signature + data'); - } - - const signature = data.substr(0, 8); - const paramdata = data.substr(8); - - return { - signature: `0x${signature}`, - paramdata: `0x${paramdata}` - }; -} - -export function decodeMethodInput (methodAbi, paramdata) { - if (!methodAbi) { - throw new Error('decodeMethodInput should receive valid method-specific ABI'); - } - - if (paramdata && paramdata.length) { - if (!isHex(paramdata)) { - throw new Error('Input to decodeMethodInput should be a hex value'); - } - - if (paramdata.substr(0, 2) === '0x') { - return decodeMethodInput(methodAbi, paramdata.slice(2)); - } - } - - return new Func(methodAbi).decodeInput(paramdata).map((decoded) => decoded.value); -} - -// takes a method in form name(...,types) and returns the inferred abi definition -export function methodToAbi (method) { - const length = method.length; - const typesStart = method.indexOf('('); - const typesEnd = method.indexOf(')'); - - if (typesStart === -1) { - throw new Error(`Missing start ( in call to decodeMethod with ${method}`); - } else if (typesEnd === -1) { - throw new Error(`Missing end ) in call to decodeMethod with ${method}`); - } else if (typesEnd < typesStart) { - throw new Error(`End ) is before start ( in call to decodeMethod with ${method}`); - } else if (typesEnd !== length - 1) { - throw new Error(`Extra characters after end ) in call to decodeMethod with ${method}`); - } - - const name = method.substr(0, typesStart); - const types = method.substr(typesStart + 1, length - (typesStart + 1) - 1).split(','); - const inputs = types.filter((_type) => _type.length).map((_type) => { - const type = fromParamType(toParamType(_type)); - - return { type }; - }); - - return { type: 'function', name, inputs }; -} - -export function abiDecode (inputTypes, data) { - return decodeMethodInput({ - inputs: inputTypes.map((type) => { - return { type }; - }) - }, data); -} diff --git a/js/src/api/util/decode.spec.js b/js/src/api/util/decode.spec.js deleted file mode 100644 index 006c6a86392f78c99123e399b16d19ab195a94f7..0000000000000000000000000000000000000000 --- a/js/src/api/util/decode.spec.js +++ /dev/null @@ -1,105 +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 . - -import BigNumber from 'bignumber.js'; -import { abiDecode, decodeCallData, decodeMethodInput, methodToAbi } from './decode'; - -describe('api/util/decode', () => { - const METH = '0x70a08231'; - const ENCO = '0x70a082310000000000000000000000005A5eFF38DA95b0D58b6C616f2699168B480953C9'; - const DATA = '0x0000000000000000000000005A5eFF38DA95b0D58b6C616f2699168B480953C9'; - - describe('decodeCallData', () => { - it('throws on non-hex inputs', () => { - expect(() => decodeCallData('invalid')).to.throw(/should be a hex value/); - }); - - it('throws when invalid signature length', () => { - expect(() => decodeCallData(METH.slice(-6))).to.throw(/should be method signature/); - }); - - it('splits valid inputs properly', () => { - expect(decodeCallData(ENCO)).to.deep.equal({ - signature: METH, - paramdata: DATA - }); - }); - }); - - describe('decodeMethodInput', () => { - it('expects a valid ABI', () => { - expect(() => decodeMethodInput(null, null)).to.throw(/should receive valid method/); - }); - - it('expect valid hex parameter data', () => { - expect(() => decodeMethodInput({}, 'invalid')).to.throw(/should be a hex value/); - }); - - it('correctly decodes valid inputs', () => { - expect( - decodeMethodInput({ - type: 'function', - inputs: [ - { type: 'uint' } - ] - }, DATA) - ).to.deep.equal( - [ new BigNumber('0x5a5eff38da95b0d58b6c616f2699168b480953c9') ] - ); - }); - }); - - describe('methodToAbi', () => { - it('throws when no start ( specified', () => { - expect(() => methodToAbi('invalid,uint,bool)')).to.throw(/Missing start \(/); - }); - - it('throws when no end ) specified', () => { - expect(() => methodToAbi('invalid(uint,bool')).to.throw(/Missing end \)/); - }); - - it('throws when end ) is not in the last position', () => { - expect(() => methodToAbi('invalid(uint,bool)2')).to.throw(/Extra characters after end \)/); - }); - - it('throws when start ( is after end )', () => { - expect(() => methodToAbi('invalid)uint,bool(')).to.throw(/End \) is before start \(/); - }); - - it('throws when invalid types are present', () => { - expect(() => methodToAbi('method(invalidType,bool,uint)')).to.throw(/Cannot convert invalidType/); - }); - - it('returns a valid methodabi for a valid method', () => { - expect(methodToAbi('valid(uint,bool)')).to.deep.equals({ - type: 'function', - name: 'valid', - inputs: [ - { type: 'uint256' }, - { type: 'bool' } - ] - }); - }); - }); - - describe('abiDecode', () => { - it('correctly decodes valid inputs', () => { - expect(abiDecode(['uint'], DATA)).to.deep.equal( - [ new BigNumber('0x5a5eff38da95b0d58b6c616f2699168b480953c9') ] - ); - }); - }); -}); diff --git a/js/src/api/util/encode.js b/js/src/api/util/encode.js deleted file mode 100644 index f18fbbe2b7b1045765449333ce052861df995440..0000000000000000000000000000000000000000 --- a/js/src/api/util/encode.js +++ /dev/null @@ -1,69 +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 . - -import Abi from '~/abi'; -import Func from '~/abi/spec/function'; - -import { abiDecode } from './decode'; -import { cleanupValue } from './format'; -import { sha3 } from './sha3'; - -export function encodeMethodCallAbi (methodAbi = {}, values = []) { - const func = new Func(methodAbi); - const tokens = Abi.encodeTokens(func.inputParamTypes(), values); - const call = func.encodeCall(tokens); - - return `0x${call}`; -} - -export function abiEncode (methodName, inputTypes, data) { - const result = encodeMethodCallAbi({ - name: methodName || '', - type: 'function', - inputs: inputTypes.map((type) => { - return { type }; - }) - }, data); - - return result; -} - -export function abiUnencode (abi, data) { - const callsig = data.substr(2, 8); - const op = abi.find((field) => { - return field.type === 'function' && - abiSignature(field.name, field.inputs.map((input) => input.type)).substr(2, 8) === callsig; - }); - - if (!op) { - console.warn(`Unknown function ID: ${callsig}`); - return null; - } - - let argsByIndex = abiDecode(op.inputs.map((field) => field.type), '0x' + data.substr(10)) - .map((value, index) => cleanupValue(value, op.inputs[index].type)); - const argsByName = op.inputs.reduce((result, field, index) => { - result[field.name] = argsByIndex[index]; - - return result; - }, {}); - - return [op.name, argsByName, argsByIndex]; -} - -export function abiSignature (name, inputs) { - return sha3(`${name}(${inputs.join()})`); -} diff --git a/js/src/api/util/encode.spec.js b/js/src/api/util/encode.spec.js deleted file mode 100644 index 7847f06ecc804fe6bd89c731c279e114e0086419..0000000000000000000000000000000000000000 --- a/js/src/api/util/encode.spec.js +++ /dev/null @@ -1,90 +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 . - -import { abiEncode, abiUnencode, abiSignature, encodeMethodCallAbi } from './encode'; - -const ABI = { - type: 'function', - name: 'valid', - inputs: [ - { type: 'uint256' }, - { type: 'bool' } - ] -}; - -const RESULT = [ - 'f87fa141', - '0000000000000000000000000000000000000000000000000000000000000123', - '0000000000000000000000000000000000000000000000000000000000000001' -].join(''); -const VARIABLE = [ - '5a6fbce0', - 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', - '0000000000000000000000000000000000000000000000000000000000000040', - '000000000000000000000000000000000000000000000000000000000000000f', - '687474703a2f2f666f6f2e6261722f0000000000000000000000000000000000' -].join(''); - -describe('api/util/encode', () => { - describe('encodeMethodCallAbi', () => { - it('encodes calls with the correct result', () => { - expect(encodeMethodCallAbi(ABI, [0x123, true])).to.equal(`0x${RESULT}`); - }); - }); - - describe('abiEncode', () => { - it('encodes calls with the correct result', () => { - expect(abiEncode('valid', ['uint256', 'bool'], [0x123, true])).to.equal(`0x${RESULT}`); - }); - - it('encodes variable values', () => { - expect( - abiEncode( - 'hintUrl', ['bytes32', 'string'], ['0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'http://foo.bar/'] - ) - ).to.equal(`0x${VARIABLE}`); - }); - - it('encodes only the data with null name', () => { - expect( - abiEncode(null, ['uint256', 'bool'], [0x123, true]) - ).to.equal(`0x${RESULT.substr(8)}`); - }); - }); - - describe('abiUnencode', () => { - it('decodes data correctly from abi', () => { - expect( - abiUnencode([{ - name: 'test', - type: 'function', - inputs: [ - { type: 'uint', name: 'arga' } - ] - }], '0x1acb6f7700000000000000000000000000000038') - ).to.deep.equal(['test', { arga: 56 }, [56]]); - }); - }); - - // Same example as in abi/util/signature.spec.js - describe('abiSignature', () => { - it('encodes baz(uint32,bool) correctly', () => { - expect( - abiSignature('baz', ['uint32', 'bool']) - ).to.equal('0xcdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2'); - }); - }); -}); diff --git a/js/src/api/util/format.js b/js/src/api/util/format.js deleted file mode 100644 index 6a4a81d4004dee944817fde894c2eaeb9169269f..0000000000000000000000000000000000000000 --- a/js/src/api/util/format.js +++ /dev/null @@ -1,106 +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 . - -import { range } from 'lodash'; - -export function bytesToHex (bytes) { - return '0x' + Buffer.from(bytes).toString('hex'); -} - -export function cleanupValue (value, type) { - // TODO: make work with arbitrary depth arrays - if (value instanceof Array && type.match(/bytes[0-9]+/)) { - // figure out if it's an ASCII string hiding in there: - let ascii = ''; - - for (let index = 0, ended = false; index < value.length && ascii !== null; ++index) { - const val = value[index]; - - if (val === 0) { - ended = true; - } else { - ascii += String.fromCharCode(val); - } - - if ((ended && val !== 0) || (!ended && (val < 32 || val >= 128))) { - ascii = null; - } - } - - value = ascii === null - ? bytesToHex(value) - : ascii; - } - - if (type.substr(0, 4) === 'uint' && +type.substr(4) <= 48) { - value = +value; - } - - return value; -} - -export function hexToBytes (hex) { - const raw = toHex(hex).slice(2); - const bytes = []; - - for (let i = 0; i < raw.length; i += 2) { - bytes.push(parseInt(raw.substr(i, 2), 16)); - } - - return bytes; -} - -export function hexToAscii (hex) { - const bytes = hexToBytes(hex); - const str = bytes.map((byte) => String.fromCharCode(byte)).join(''); - - return str; -} - -export function bytesToAscii (bytes) { - return bytes.map((b) => String.fromCharCode(b % 512)).join(''); -} - -export function asciiToHex (string) { - return '0x' + string.split('') - .map(s => s.charCodeAt(0)) - .map(s => s < 0x10 ? '0' + s.toString(16) : s.toString(16)) - .join(''); -} - -export function padRight (input, length) { - const value = toHex(input).substr(2, length * 2); - - return '0x' + value + range(length * 2 - value.length).map(() => '0').join(''); -} - -export function padLeft (input, length) { - const value = toHex(input).substr(2, length * 2); - - return '0x' + range(length * 2 - value.length).map(() => '0').join('') + value; -} - -export function toHex (str) { - if (str && str.toString) { - str = str.toString(16); - } - - if (str && str.substr(0, 2) === '0x') { - return str.toLowerCase(); - } - - return `0x${(str || '').toLowerCase()}`; -} diff --git a/js/src/api/util/format.spec.js b/js/src/api/util/format.spec.js deleted file mode 100644 index ba7a3994e049b7762626df5dbca12c599de8bc8c..0000000000000000000000000000000000000000 --- a/js/src/api/util/format.spec.js +++ /dev/null @@ -1,94 +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 . - -import { bytesToHex, cleanupValue, hexToBytes, hexToAscii, bytesToAscii, asciiToHex } from './format'; - -describe('api/util/format', () => { - describe('bytesToHex', () => { - it('correctly converts an empty array', () => { - expect(bytesToHex([])).to.equal('0x'); - }); - - it('correctly converts a non-empty array', () => { - expect(bytesToHex([0, 15, 16])).to.equal('0x000f10'); - }); - }); - - describe('cleanupValue', () => { - it('returns unknown values as the original', () => { - expect(cleanupValue('original', 'unknown')).to.equal('original'); - }); - - it('returns ascii arrays as ascii', () => { - expect(cleanupValue([97, 115, 99, 105, 105, 0], 'bytes32')).to.equal('ascii'); - }); - - it('returns non-ascii arrays as hex strings', () => { - expect(cleanupValue([97, 200, 0, 0], 'bytes4')).to.equal('0x61c80000'); - }); - - it('returns uint (>48) as the original', () => { - expect(cleanupValue('original', 'uint49')).to.equal('original'); - }); - - it('returns uint (<=48) as the number value', () => { - expect(cleanupValue('12345', 'uint48')).to.equal(12345); - }); - }); - - describe('hexToBytes', () => { - it('correctly converts an empty string', () => { - expect(hexToBytes('')).to.deep.equal([]); - expect(hexToBytes('0x')).to.deep.equal([]); - }); - - it('correctly converts a non-empty string', () => { - expect(hexToBytes('0x000f10')).to.deep.equal([0, 15, 16]); - }); - }); - - describe('asciiToHex', () => { - it('correctly converts an empty string', () => { - expect(asciiToHex('')).to.equal('0x'); - }); - - it('correctly converts a non-empty string', () => { - expect(asciiToHex('abc')).to.equal('0x616263'); - expect(asciiToHex('a\nb')).to.equal('0x610a62'); - }); - }); - - describe('hexToAscii', () => { - it('correctly converts an empty string', () => { - expect(hexToAscii('')).to.equal(''); - expect(hexToAscii('0x')).to.equal(''); - }); - - it('correctly converts a non-empty string', () => { - expect(hexToAscii('0x616263')).to.equal('abc'); - }); - }); - - describe('bytesToAscii', () => { - it('correctly converts an empty string', () => { - expect(bytesToAscii([])).to.equal(''); - }); - - it('correctly converts a non-empty string', () => { - expect(bytesToAscii([97, 98, 99])).to.equal('abc'); - }); - }); -}); diff --git a/js/src/api/util/identity.js b/js/src/api/util/identity.js deleted file mode 100644 index 4df7ab9bb23a4af8e7eed248aed752a432831256..0000000000000000000000000000000000000000 --- a/js/src/api/util/identity.js +++ /dev/null @@ -1,30 +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 . - -import blockies from 'blockies'; - -// jsdom doesn't have all the browser features, blockies fail -const TEST_ENV = process.env.NODE_ENV === 'test'; - -export function createIdentityImg (address, scale = 8) { - return TEST_ENV - ? 'test-createIdentityImg' - : blockies({ - seed: (address || '').toLowerCase(), - size: 8, - scale - }).toDataURL(); -} diff --git a/js/src/api/util/index.js b/js/src/api/util/index.js deleted file mode 100644 index 30328856bd59215d6a9d0b853d1080ed5c9f87ab..0000000000000000000000000000000000000000 --- a/js/src/api/util/index.js +++ /dev/null @@ -1,51 +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 . - -import { isAddress as isAddressValid, toChecksumAddress } from '../../abi/util/address'; -import { abiDecode, decodeCallData, decodeMethodInput, methodToAbi } from './decode'; -import { abiEncode, abiUnencode, abiSignature, encodeMethodCallAbi } from './encode'; -import { bytesToHex, hexToAscii, hexToBytes, asciiToHex, cleanupValue } from './format'; -import { fromWei, toWei } from './wei'; -import { sha3 } from './sha3'; -import { isArray, isFunction, isHex, isInstanceOf, isString } from './types'; -import { createIdentityImg } from './identity'; - -export default { - abiDecode, - abiEncode, - abiUnencode, - abiSignature, - cleanupValue, - isAddressValid, - isArray, - isFunction, - isHex, - isInstanceOf, - isString, - bytesToHex, - hexToAscii, - hexToBytes, - asciiToHex, - createIdentityImg, - decodeCallData, - decodeMethodInput, - encodeMethodCallAbi, - methodToAbi, - fromWei, - toChecksumAddress, - toWei, - sha3 -}; diff --git a/js/src/api/util/sha3.js b/js/src/api/util/sha3.js deleted file mode 100644 index 3ca49cc8e6f54aa60bd66801769ab4c5938803a8..0000000000000000000000000000000000000000 --- a/js/src/api/util/sha3.js +++ /dev/null @@ -1,36 +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 . - -import { keccak_256 } from 'js-sha3'; // eslint-disable-line - -import { hexToBytes } from './format'; -import { isHex } from './types'; - -export function sha3 (value, options) { - const forceHex = options && options.encoding === 'hex'; - - if (forceHex || (!options && isHex(value))) { - const bytes = hexToBytes(value); - - return sha3(bytes); - } - - const hash = keccak_256(value); - - return `0x${hash}`; -} - -sha3.text = (val) => sha3(val, { encoding: 'raw' }); diff --git a/js/src/api/util/sha3.spec.js b/js/src/api/util/sha3.spec.js deleted file mode 100644 index a5c93d9404aa157a7cd000c983b1f2799ee45d41..0000000000000000000000000000000000000000 --- a/js/src/api/util/sha3.spec.js +++ /dev/null @@ -1,46 +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 . - -import { sha3 } from './sha3'; - -describe('api/util/sha3', () => { - describe('sha3', () => { - it('constructs a correct sha3 value', () => { - expect(sha3('jacogr')).to.equal('0x2f4ff4b5a87abbd2edfed699db48a97744e028c7f7ce36444d40d29d792aa4dc'); - }); - - it('constructs a correct sha3 encoded as hex', () => { - const key = '000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298' + '0000000000000000000000000000000000000000000000000000000000000001'; - - expect(sha3(key, { encoding: 'hex' })).to.equal('0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9'); - expect(sha3(`0x${key}`, { encoding: 'hex' })).to.equal('0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9'); - }); - - it('constructs a correct sha3 from Uint8Array', () => { - expect(sha3('01020304', { encoding: 'hex' })).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); - expect(sha3(Uint8Array.from([1, 2, 3, 4]))).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); - }); - - it('should interpret as bytes by default', () => { - expect(sha3('0x01020304')).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); - }); - - it('should force text if option is passed', () => { - expect(sha3('0x01020304', { encoding: 'raw' })).to.equal('0x16bff43de576d28857dcba65a56fc17c5e93c09bd6a709268eff8e62025ae869'); - expect(sha3.text('0x01020304')).to.equal('0x16bff43de576d28857dcba65a56fc17c5e93c09bd6a709268eff8e62025ae869'); - }); - }); -}); diff --git a/js/src/api/util/types.js b/js/src/api/util/types.js deleted file mode 100644 index f4278cb5179de20bcb1c0668de9c4c58eab304bd..0000000000000000000000000000000000000000 --- a/js/src/api/util/types.js +++ /dev/null @@ -1,60 +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 . - -const HEXDIGITS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; - -export function isArray (test) { - return Object.prototype.toString.call(test) === '[object Array]'; -} - -export function isError (test) { - return Object.prototype.toString.call(test) === '[object Error]'; -} - -export function isFunction (test) { - return Object.prototype.toString.call(test) === '[object Function]'; -} - -export function isHex (_test) { - if (!isString(_test)) { - return false; - } - - if (_test.substr(0, 2) === '0x') { - return isHex(_test.slice(2)); - } - - const test = _test.toLowerCase(); - let hex = true; - - for (let idx = 0; hex && idx < test.length; idx++) { - hex = HEXDIGITS.includes(test[idx]); - } - - return hex; -} - -export function isObject (test) { - return Object.prototype.toString.call(test) === '[object Object]'; -} - -export function isString (test) { - return Object.prototype.toString.call(test) === '[object String]'; -} - -export function isInstanceOf (test, clazz) { - return test instanceof clazz; -} diff --git a/js/src/api/util/types.spec.js b/js/src/api/util/types.spec.js deleted file mode 100644 index c8672f8884ffb43300bc2a5f426c115b41c1f1ae..0000000000000000000000000000000000000000 --- a/js/src/api/util/types.spec.js +++ /dev/null @@ -1,118 +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 . - -import sinon from 'sinon'; - -import { isArray, isError, isFunction, isHex, isInstanceOf, isObject, isString } from './types'; -import Eth from '../rpc/eth'; - -describe('api/util/types', () => { - describe('isArray', () => { - it('correctly identifies null as false', () => { - expect(isArray(null)).to.be.false; - }); - - it('correctly identifies empty array as true', () => { - expect(isArray([])).to.be.true; - }); - - it('correctly identifies array as true', () => { - expect(isArray([1, 2, 3])).to.be.true; - }); - }); - - describe('isError', () => { - it('correctly identifies null as false', () => { - expect(isError(null)).to.be.false; - }); - - it('correctly identifies Error as true', () => { - expect(isError(new Error('an error'))).to.be.true; - }); - }); - - describe('isFunction', () => { - it('correctly identifies null as false', () => { - expect(isFunction(null)).to.be.false; - }); - - it('correctly identifies function as true', () => { - expect(isFunction(sinon.stub())).to.be.true; - }); - }); - - describe('isHex', () => { - it('correctly identifies hex by leading 0x', () => { - expect(isHex('0x123')).to.be.true; - }); - - it('correctly identifies hex without leading 0x', () => { - expect(isHex('123')).to.be.true; - }); - - it('correctly identifies non-hex values', () => { - expect(isHex('123j')).to.be.false; - }); - - it('correctly indentifies non-string values', () => { - expect(isHex(false)).to.be.false; - expect(isHex()).to.be.false; - expect(isHex([1, 2, 3])).to.be.false; - }); - }); - - describe('isInstanceOf', () => { - it('correctly identifies build-in instanceof', () => { - expect(isInstanceOf(new String('123'), String)).to.be.true; // eslint-disable-line no-new-wrappers - }); - - it('correctly identifies own instanceof', () => { - expect(isInstanceOf(new Eth({}), Eth)).to.be.true; - }); - - it('correctly reports false for own', () => { - expect(isInstanceOf({}, Eth)).to.be.false; - }); - }); - - describe('isObject', () => { - it('correctly identifies empty object as object', () => { - expect(isObject({})).to.be.true; - }); - - it('correctly identifies non-empty object as object', () => { - expect(isObject({ data: '123' })).to.be.true; - }); - - it('correctly identifies Arrays as non-objects', () => { - expect(isObject([1, 2, 3])).to.be.false; - }); - - it('correctly identifies Strings as non-objects', () => { - expect(isObject('123')).to.be.false; - }); - }); - - describe('isString', () => { - it('correctly identifies empty string as string', () => { - expect(isString('')).to.be.true; - }); - - it('correctly identifies string as string', () => { - expect(isString('123')).to.be.true; - }); - }); -}); diff --git a/js/src/api/util/wei.js b/js/src/api/util/wei.js deleted file mode 100644 index d17df69583715ded6e8af71673c0fedf723a649e..0000000000000000000000000000000000000000 --- a/js/src/api/util/wei.js +++ /dev/null @@ -1,37 +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 . - -import BigNumber from 'bignumber.js'; - -const UNITS = ['wei', 'ada', 'babbage', 'shannon', 'szabo', 'finney', 'ether', 'kether', 'mether', 'gether', 'tether']; - -export function _getUnitMultiplier (unit) { - const position = UNITS.indexOf(unit.toLowerCase()); - - if (position === -1) { - throw new Error(`Unknown unit ${unit} passed to wei formatter`); - } - - return 10 ** (position * 3); -} - -export function fromWei (value, unit = 'ether') { - return new BigNumber(value).div(_getUnitMultiplier(unit)); -} - -export function toWei (value, unit = 'ether') { - return new BigNumber(value).mul(_getUnitMultiplier(unit)); -} diff --git a/js/src/api/util/wei.spec.js b/js/src/api/util/wei.spec.js deleted file mode 100644 index 4476a4db6106e68ef5b3412dae12ab7772a71e6e..0000000000000000000000000000000000000000 --- a/js/src/api/util/wei.spec.js +++ /dev/null @@ -1,57 +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 . - -import { _getUnitMultiplier, fromWei, toWei } from './wei'; - -describe('api/util/wei', () => { - describe('_getUnitMultiplier', () => { - it('returns 10^0 for wei', () => { - expect(_getUnitMultiplier('wei')).to.equal(10 ** 0); - }); - - it('returns 10^15 for finney', () => { - expect(_getUnitMultiplier('finney')).to.equal(10 ** 15); - }); - - it('returns 10^18 for ether', () => { - expect(_getUnitMultiplier('ether')).to.equal(10 ** 18); - }); - - it('throws an error on invalid units', () => { - expect(() => _getUnitMultiplier('invalid')).to.throw(/passed to wei formatter/); - }); - }); - - describe('fromWei', () => { - it('formats into ether when nothing specified', () => { - expect(fromWei('1230000000000000000').toString()).to.equal('1.23'); - }); - - it('formats into finney when specified', () => { - expect(fromWei('1230000000000000000', 'finney').toString()).to.equal('1230'); - }); - }); - - describe('toWei', () => { - it('formats from ether when nothing specified', () => { - expect(toWei(1.23).toString()).to.equal('1230000000000000000'); - }); - - it('formats from finney when specified', () => { - expect(toWei(1230, 'finney').toString()).to.equal('1230000000000000000'); - }); - }); -}); diff --git a/js/src/config.js b/js/src/config.js deleted file mode 100644 index 5113e9399b68530fe7a9c96e3b2bbf568447271f..0000000000000000000000000000000000000000 --- a/js/src/config.js +++ /dev/null @@ -1,40 +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 . - -import LogLevel from 'loglevel'; - -export const LOG_KEYS = { - Balances: { - key: 'balances', - desc: 'Balances fetching' - }, - CertificationsMiddleware: { - key: 'certifications.middleware', - desc: 'Certifications Middleware' - }, - TransferModalStore: { - key: 'modalsTransferStore', - desc: 'Transfer modal MobX store' - }, - Signer: { - key: 'secureApi', - desc: 'The Signer and the Secure API' - } -}; - -export const getLogger = (LOG_KEY) => { - return LogLevel.getLogger(LOG_KEY.key); -}; diff --git a/js/src/contracts/abi/badgereg.json b/js/src/contracts/abi/badgereg.json deleted file mode 100644 index 6ae56393be3b3c4a091b7fe56e885521d34a57b7..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/badgereg.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"fromName","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"badgeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_newAddr","type":"address"}],"name":"setAddress","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"badge","outputs":[{"name":"addr","type":"address"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/basiccoin.json b/js/src/contracts/abi/basiccoin.json deleted file mode 100644 index 0bdc66666fcb4e4f15ca48dbe128c62474367415..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/basiccoin.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"base","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"_totalSupply","type":"uint256"},{"name":"_owner","type":"address"}],"type":"constructor"},{"payable":false,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/basiccoinmanager.json b/js/src/contracts/abi/basiccoinmanager.json deleted file mode 100644 index cafe09735c6d4f425e302f60001402d668fad002..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/basiccoinmanager.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"countByOwner","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"base","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"get","outputs":[{"name":"coin","type":"address"},{"name":"owner","type":"address"},{"name":"tokenreg","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_totalSupply","type":"uint256"},{"name":"_tla","type":"string"},{"name":"_name","type":"string"},{"name":"_tokenreg","type":"address"}],"name":"deploy","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_index","type":"uint256"}],"name":"getByOwner","outputs":[{"name":"coin","type":"address"},{"name":"owner","type":"address"},{"name":"tokenreg","type":"address"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"tokenreg","type":"address"},{"indexed":true,"name":"coin","type":"address"}],"name":"Created","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/certifier.json b/js/src/contracts/abi/certifier.json deleted file mode 100644 index 905ddde6cb3346948ddedaaa0f089058d1c5c5f0..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/certifier.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"}] \ No newline at end of file diff --git a/js/src/contracts/abi/consensys-multisig-wallet.json b/js/src/contracts/abi/consensys-multisig-wallet.json deleted file mode 100644 index 79623637d1c7e051e15aba65ae59c020f9821b20..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/consensys-multisig-wallet.json +++ /dev/null @@ -1,510 +0,0 @@ -[ - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "owners", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "owner", - "type": "address" - } - ], - "name": "removeOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "revokeConfirmation", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "address" - } - ], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - }, - { - "name": "", - "type": "address" - } - ], - "name": "confirmations", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "pending", - "type": "bool" - }, - { - "name": "executed", - "type": "bool" - } - ], - "name": "getTransactionCount", - "outputs": [ - { - "name": "count", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "owner", - "type": "address" - } - ], - "name": "addOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "isConfirmed", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "getConfirmationCount", - "outputs": [ - { - "name": "count", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "uint256" - } - ], - "name": "transactions", - "outputs": [ - { - "name": "destination", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - }, - { - "name": "executed", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getOwners", - "outputs": [ - { - "name": "", - "type": "address[]" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "from", - "type": "uint256" - }, - { - "name": "to", - "type": "uint256" - }, - { - "name": "pending", - "type": "bool" - }, - { - "name": "executed", - "type": "bool" - } - ], - "name": "getTransactionIds", - "outputs": [ - { - "name": "_transactionIds", - "type": "uint256[]" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "getConfirmations", - "outputs": [ - { - "name": "_confirmations", - "type": "address[]" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "transactionCount", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_required", - "type": "uint256" - } - ], - "name": "changeRequirement", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "confirmTransaction", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "destination", - "type": "address" - }, - { - "name": "value", - "type": "uint256" - }, - { - "name": "data", - "type": "bytes" - } - ], - "name": "submitTransaction", - "outputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_OWNER_COUNT", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "required", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "owner", - "type": "address" - }, - { - "name": "newOwner", - "type": "address" - } - ], - "name": "replaceOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "transactionId", - "type": "uint256" - } - ], - "name": "executeTransaction", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "inputs": [ - { - "name": "_owners", - "type": "address[]" - }, - { - "name": "_required", - "type": "uint256" - } - ], - "payable": false, - "type": "constructor" - }, - { - "payable": true, - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Confirmation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Revocation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Submission", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "Execution", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "transactionId", - "type": "uint256" - } - ], - "name": "ExecutionFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "sender", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "OwnerAddition", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "owner", - "type": "address" - } - ], - "name": "OwnerRemoval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "required", - "type": "uint256" - } - ], - "name": "RequirementChange", - "type": "event" - } -] diff --git a/js/src/contracts/abi/dappreg.json b/js/src/contracts/abi/dappreg.json deleted file mode 100644 index f6bec35af13d798dd239543bc1b0673ef12a4fdd..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/dappreg.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"bytes32"}],"name":"get","outputs":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"setDappOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"at","outputs":[{"name":"id","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"register","outputs":[],"payable":true,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/eip20.json b/js/src/contracts/abi/eip20.json deleted file mode 100644 index 6937e28c85b0e428e092fe89ae54c950b6899baa..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/eip20.json +++ /dev/null @@ -1,163 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "name": "_spender", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSupply", - "outputs": [ - { - "name": "total", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "name": "balance", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - } - ], - "name": "transfer", - "outputs": [ - { - "name": "success", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_owner", - "type": "address" - }, - { - "name": "_spender", - "type": "address" - } - ], - "name": "allowance", - "outputs": [ - { - "name": "remaining", - "type": "uint256" - } - ], - "type": "function" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "from", - "type": "address" - }, - { - "indexed": true, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "name": "spender", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - } -] diff --git a/js/src/contracts/abi/email-verification.json b/js/src/contracts/abi/email-verification.json deleted file mode 100644 index 3bb0fe65004bc729912526b39c6e4d5573bc7288..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/email-verification.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"reverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"},{"name":"_emailHash","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_emailHash","type":"bytes32"}],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":true,"name":"emailHash","type":"bytes32"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":true,"name":"emailHash","type":"bytes32"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] \ No newline at end of file diff --git a/js/src/contracts/abi/foundation-multisig-wallet.json b/js/src/contracts/abi/foundation-multisig-wallet.json deleted file mode 100644 index 752407e62521735187cfb94d932bf37cbd30baef..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/foundation-multisig-wallet.json +++ /dev/null @@ -1,476 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "removeOwner", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_addr", - "type": "address" - } - ], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_numOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_lastDay", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "resetSpentToday", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_spentToday", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "addOwner", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_required", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_h", - "type": "bytes32" - } - ], - "name": "confirm", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_newLimit", - "type": "uint256" - } - ], - "name": "setDailyLimit", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "execute", - "outputs": [ - { - "name": "_r", - "type": "bytes32" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_operation", - "type": "bytes32" - } - ], - "name": "revoke", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_newRequired", - "type": "uint256" - } - ], - "name": "changeRequirement", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_operation", - "type": "bytes32" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "hasConfirmed", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "ownerIndex", - "type": "uint256" - } - ], - "name": "getOwner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - } - ], - "name": "kill", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "name": "changeOwner", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_dailyLimit", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "inputs": [ - { - "name": "_owners", - "type": "address[]" - }, - { - "name": "_required", - "type": "uint256" - }, - { - "name": "_daylimit", - "type": "uint256" - } - ], - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "operation", - "type": "bytes32" - } - ], - "name": "Confirmation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "operation", - "type": "bytes32" - } - ], - "name": "Revoke", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldOwner", - "type": "address" - }, - { - "indexed": false, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldOwner", - "type": "address" - } - ], - "name": "OwnerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "newRequirement", - "type": "uint256" - } - ], - "name": "RequirementChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "_from", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "name": "created", - "type": "address" - } - ], - "name": "SingleTransact", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "operation", - "type": "bytes32" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "data", - "type": "bytes" - }, - { - "indexed": false, - "name": "created", - "type": "address" - } - ], - "name": "MultiTransact", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "operation", - "type": "bytes32" - }, - { - "indexed": false, - "name": "initiator", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "data", - "type": "bytes" - } - ], - "name": "ConfirmationNeeded", - "type": "event" - } -] diff --git a/js/src/contracts/abi/gavcoin.json b/js/src/contracts/abi/gavcoin.json deleted file mode 100644 index 5170326f5a4b58fe3b64ff40b306ae2e297e062a..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/gavcoin.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_maxPrice","type":"uint256"}],"name":"buyin","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"remaining","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_price","type":"uint256"},{"name":"_units","type":"uint256"}],"name":"refund","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"price","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":true,"name":"price","type":"uint256"},{"indexed":true,"name":"amount","type":"uint256"}],"name":"Buyin","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"buyer","type":"address"},{"indexed":true,"name":"price","type":"uint256"},{"indexed":true,"name":"amount","type":"uint256"}],"name":"Refund","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"price","type":"uint256"}],"name":"NewTranch","type":"event"}] diff --git a/js/src/contracts/abi/githubhint.json b/js/src/contracts/abi/githubhint.json deleted file mode 100644 index bdbc162e4e516fa8732371a846465d199b1504cd..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/githubhint.json +++ /dev/null @@ -1,81 +0,0 @@ -[ - { - "constant":false, - "inputs":[ - { - "name":"_content", - "type":"bytes32" - }, - { - "name":"_url", - "type":"string" - } - ], - "name":"hintURL", - "outputs":[ - - ], - "type":"function" - }, - { - "constant":false, - "inputs":[ - { - "name":"_content", - "type":"bytes32" - }, - { - "name":"_accountSlashRepo", - "type":"string" - }, - { - "name":"_commit", - "type":"bytes20" - } - ], - "name":"hint", - "outputs":[ - - ], - "type":"function" - }, - { - "constant":true, - "inputs":[ - { - "name":"", - "type":"bytes32" - } - ], - "name":"entries", - "outputs":[ - { - "name":"accountSlashRepo", - "type":"string" - }, - { - "name":"commit", - "type":"bytes20" - }, - { - "name":"owner", - "type":"address" - } - ], - "type":"function" - }, - { - "constant":false, - "inputs":[ - { - "name":"_content", - "type":"bytes32" - } - ], - "name":"unhint", - "outputs":[ - - ], - "type":"function" - } -] diff --git a/js/src/contracts/abi/index.js b/js/src/contracts/abi/index.js deleted file mode 100644 index f475cce070b8b813008721987ccaa19c3497be0e..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/index.js +++ /dev/null @@ -1,31 +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 . - -export badgereg from './badgereg.json'; -export basiccoin from './basiccoin.json'; -export basiccoinmanager from './basiccoinmanager.json'; -export dappreg from './dappreg.json'; -export eip20 from './eip20.json'; -export emailverification from './email-verification.json'; -export gavcoin from './gavcoin.json'; -export githubhint from './githubhint.json'; -export owned from './owned.json'; -export registry from './registry.json'; -export registry2 from './registry2.json'; -export signaturereg from './signaturereg.json'; -export smsverification from './sms-verification.json'; -export tokenreg from './tokenreg.json'; -export foundationWallet from './foundation-multisig-wallet.json'; diff --git a/js/src/contracts/abi/old-wallet.json b/js/src/contracts/abi/old-wallet.json deleted file mode 100644 index 9300697422f5c730aff1d7a802cf6b2e6777b04f..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/old-wallet.json +++ /dev/null @@ -1,466 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "removeOwner", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_addr", - "type": "address" - } - ], - "name": "isOwner", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_numOwners", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_lastDay", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "resetSpentToday", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_spentToday", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_owner", - "type": "address" - } - ], - "name": "addOwner", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_required", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_h", - "type": "bytes32" - } - ], - "name": "confirm", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_newLimit", - "type": "uint256" - } - ], - "name": "setDailyLimit", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - }, - { - "name": "_value", - "type": "uint256" - }, - { - "name": "_data", - "type": "bytes" - } - ], - "name": "execute", - "outputs": [ - { - "name": "_r", - "type": "bytes32" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_operation", - "type": "bytes32" - } - ], - "name": "revoke", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_newRequired", - "type": "uint256" - } - ], - "name": "changeRequirement", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "_operation", - "type": "bytes32" - }, - { - "name": "_owner", - "type": "address" - } - ], - "name": "hasConfirmed", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "ownerIndex", - "type": "uint256" - } - ], - "name": "getOwner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_to", - "type": "address" - } - ], - "name": "kill", - "outputs": [], - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_from", - "type": "address" - }, - { - "name": "_to", - "type": "address" - } - ], - "name": "changeOwner", - "outputs": [], - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "m_dailyLimit", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "type": "function" - }, - { - "inputs": [ - { - "name": "_owners", - "type": "address[]" - }, - { - "name": "_required", - "type": "uint256" - }, - { - "name": "_daylimit", - "type": "uint256" - } - ], - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "operation", - "type": "bytes32" - } - ], - "name": "Confirmation", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "operation", - "type": "bytes32" - } - ], - "name": "Revoke", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldOwner", - "type": "address" - }, - { - "indexed": false, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnerAdded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "oldOwner", - "type": "address" - } - ], - "name": "OwnerRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "newRequirement", - "type": "uint256" - } - ], - "name": "RequirementChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "_from", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - } - ], - "name": "Deposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "data", - "type": "bytes" - } - ], - "name": "SingleTransact", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "owner", - "type": "address" - }, - { - "indexed": false, - "name": "operation", - "type": "bytes32" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "data", - "type": "bytes" - } - ], - "name": "MultiTransact", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "name": "operation", - "type": "bytes32" - }, - { - "indexed": false, - "name": "initiator", - "type": "address" - }, - { - "indexed": false, - "name": "value", - "type": "uint256" - }, - { - "indexed": false, - "name": "to", - "type": "address" - }, - { - "indexed": false, - "name": "data", - "type": "bytes" - } - ], - "name": "ConfirmationNeeded", - "type": "event" - } -] diff --git a/js/src/contracts/abi/owned.json b/js/src/contracts/abi/owned.json deleted file mode 100644 index ccfeed85d06bc7e2bc78498968eaab93d88fde24..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/owned.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/registry.json b/js/src/contracts/abi/registry.json deleted file mode 100644 index f97dc20c72abad7ffb31de847af50f1a26b4e0af..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/registry.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"set","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"key","type":"string"},{"indexed":false,"name":"plainKey","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/registry2.json b/js/src/contracts/abi/registry2.json deleted file mode 100644 index 922b9b7e24ab05ff864e83fda4ddb124acfc246b..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/registry2.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"canReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"setData","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"hasReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getReverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"confirmReverseAs","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"key","type":"string"},{"indexed":false,"name":"plainKey","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/abi/signaturereg.json b/js/src/contracts/abi/signaturereg.json deleted file mode 100644 index a9b109ecd463a4873c3597eec690e20819132ef7..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/signaturereg.json +++ /dev/null @@ -1,128 +0,0 @@ -[ - { - "constant": false, - "inputs": [ - { - "name": "_new", - "type": "address" - } - ], - "name": "setOwner", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalSignatures", - "outputs": [ - { - "name": "", - "type": "uint256" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "owner", - "outputs": [ - { - "name": "", - "type": "address" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "drain", - "outputs": [], - "payable": false, - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "name": "", - "type": "bytes4" - } - ], - "name": "entries", - "outputs": [ - { - "name": "", - "type": "string" - } - ], - "payable": false, - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "name": "_method", - "type": "string" - } - ], - "name": "register", - "outputs": [ - { - "name": "", - "type": "bool" - } - ], - "payable": false, - "type": "function" - }, - { - "inputs": [], - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "creator", - "type": "address" - }, - { - "indexed": true, - "name": "signature", - "type": "bytes4" - }, - { - "indexed": false, - "name": "method", - "type": "string" - } - ], - "name": "Registered", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "name": "old", - "type": "address" - }, - { - "indexed": true, - "name": "current", - "type": "address" - } - ], - "name": "NewOwner", - "type": "event" - } -] diff --git a/js/src/contracts/abi/sms-verification.json b/js/src/contracts/abi/sms-verification.json deleted file mode 100644 index 3eb5492a41d893bfc4ba09d63e5879be9f44f826..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/sms-verification.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"request","outputs":[],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"},{"name":"_puzzle","type":"bytes32"}],"name":"puzzle","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_code","type":"bytes32"}],"name":"confirm","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"delegate","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Requested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"},{"indexed":false,"name":"puzzle","type":"bytes32"}],"name":"Puzzled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] \ No newline at end of file diff --git a/js/src/contracts/abi/tokenreg.json b/js/src/contracts/abi/tokenreg.json deleted file mode 100644 index e56a13eec48aa4dc1ae9f558b3a080c24174c065..0000000000000000000000000000000000000000 --- a/js/src/contracts/abi/tokenreg.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"token","outputs":[{"name":"addr","type":"address"},{"name":"tla","type":"string"},{"name":"base","type":"uint256"},{"name":"name","type":"string"},{"name":"owner","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_tla","type":"string"},{"name":"_base","type":"uint256"},{"name":"_name","type":"string"}],"name":"register","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_tla","type":"string"},{"name":"_base","type":"uint256"},{"name":"_name","type":"string"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"_tla","type":"string"}],"name":"fromTLA","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"base","type":"uint256"},{"name":"name","type":"string"},{"name":"owner","type":"address"}],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"tokenCount","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"tla","type":"string"},{"name":"base","type":"uint256"},{"name":"name","type":"string"},{"name":"owner","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tla","type":"string"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"},{"indexed":false,"name":"name","type":"string"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tla","type":"string"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/contracts/badgereg.js b/js/src/contracts/badgereg.js deleted file mode 100644 index a1782cb30174443013ffcad17f7b00f9c9dec50c..0000000000000000000000000000000000000000 --- a/js/src/contracts/badgereg.js +++ /dev/null @@ -1,128 +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 . - -import { bytesToHex, hexToAscii } from '~/api/util/format'; - -import ABI from './abi/certifier.json'; - -const ZERO20 = '0x0000000000000000000000000000000000000000'; -const ZERO32 = '0x0000000000000000000000000000000000000000000000000000000000000000'; - -export default class BadgeReg { - constructor (api, registry) { - this._api = api; - this._registry = registry; - - registry.getContract('badgereg'); - this.certifiers = []; // by id - this.contracts = {}; // by name - } - - getContract () { - return this._registry.getContract('badgereg'); - } - - certifierCount () { - return this - .getContract() - .then((badgeReg) => { - return badgeReg.instance.badgeCount.call({}, []) - .then((count) => count.valueOf()); - }); - } - - fetchCertifier (id) { - if (this.certifiers[id]) { - return Promise.resolve(this.certifiers[id]); - } - - return this - .getContract() - .then((badgeReg) => { - return badgeReg.instance.badge.call({}, [ id ]); - }) - .then(([ address, name ]) => { - if (address === ZERO20) { - throw new Error(`Certifier ${id} does not exist.`); - } - - name = bytesToHex(name); - name = name === ZERO32 - ? null - : hexToAscii(name); - - return this.fetchMeta(id) - .then(({ title, icon }) => { - const data = { address, id, name, title, icon }; - - this.certifiers[id] = data; - return data; - }); - }); - } - - fetchCertifierByName (name) { - return this - .getContract() - .then((badgeReg) => { - return badgeReg.instance.fromName.call({}, [ name ]); - }) - .then(([ id, address, owner ]) => { - if (address === ZERO20) { - throw new Error(`Certifier ${name} does not exist.`); - } - - return this.fetchMeta(id) - .then(({ title, icon }) => { - const data = { address, id, name, title, icon }; - - this.certifiers[id] = data; - return data; - }); - }); - } - - fetchMeta (id) { - return this - .getContract() - .then((badgeReg) => { - return Promise.all([ - badgeReg.instance.meta.call({}, [id, 'TITLE']), - badgeReg.instance.meta.call({}, [id, 'IMG']) - ]); - }) - .then(([ title, icon ]) => { - title = bytesToHex(title); - title = title === ZERO32 ? null : hexToAscii(title); - - if (bytesToHex(icon) === ZERO32) { - icon = null; - } - - return { title, icon }; - }); - } - - checkIfCertified (certifier, address) { - if (!this.contracts[certifier]) { - this.contracts[certifier] = this._api.newContract(ABI, certifier); - } - - const contract = this.contracts[certifier]; - - return contract.instance.certified.call({}, [address]); - } -} diff --git a/js/src/contracts/code/index.js b/js/src/contracts/code/index.js deleted file mode 100644 index 1081c9afa4752209a12e5035b1ecba24de7cf7f2..0000000000000000000000000000000000000000 --- a/js/src/contracts/code/index.js +++ /dev/null @@ -1,21 +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 . - -import { wallet } from './wallet'; - -export { - wallet -}; diff --git a/js/src/contracts/code/wallet.js b/js/src/contracts/code/wallet.js deleted file mode 100644 index ab60bfc9831c2df74c905372da3ad5f482baacb5..0000000000000000000000000000000000000000 --- a/js/src/contracts/code/wallet.js +++ /dev/null @@ -1,32 +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 . - -/** - * @version Solidity v0.4.10 - Optimized - * @from https://github.com/paritytech/parity/blob/6b0e4f9098be6b841353e7c4f116aa86b7c2e3d6/js/src/contracts/snippets/enhanced-wallet.sol - * @date 20-Jul-2017 @ 16h00 UTC - */ -export const walletCompiler = 'v0.4.10+commit.f0d539ae'; -export const walletSource = 'https://github.com/paritytech/parity/blob/c4196a5de31e0b97ec42d5263d9db404cea4a776/js/src/contracts/snippets/enhanced-wallet.sol'; -export const wallet = '0x6060604052341561000c57fe5b60405161048538038061048583398101604090815281516020830151918301519201915b604080517f696e697457616c6c657428616464726573735b5d2c75696e743235362c75696e81527f7432353629000000000000000000000000000000000000000000000000000000602080830191909152915190819003602501902084516000829052909173_____________WalletLibrary______________91600281019160049182010290819038829003903960006000600483016000866127105a03f45b505050505050505b61039d806100e86000396000f300606060405236156100725763ffffffff60e060020a6000350416632f54bf6e811461012d5780634123cb6b1461015d578063523750931461017f578063659010e7146101a1578063746c9171146101c3578063c2cf7326146101e5578063c41a360a14610218578063f1736d8614610247575b61012b5b60003411156100c75760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a1610127565b60003611156101275773_____________WalletLibrary______________600160a060020a0316600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f4151561012457fe5b50505b5b5b565b005b341561013557fe5b610149600160a060020a0360043516610269565b604080519115158252519081900360200190f35b341561016557fe5b61016d6102cd565b60408051918252519081900360200190f35b341561018757fe5b61016d6102d3565b60408051918252519081900360200190f35b34156101a957fe5b61016d6102d9565b60408051918252519081900360200190f35b34156101cb57fe5b61016d6102df565b60408051918252519081900360200190f35b34156101ed57fe5b610149600435600160a060020a03602435166102e5565b604080519115158252519081900360200190f35b341561022057fe5b61022b60043561034a565b60408051600160a060020a039092168252519081900360200190f35b341561024f57fe5b61016d61036b565b60408051918252519081900360200190f35b600073_____________WalletLibrary______________600160a060020a0316600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f415156102bf57fe5b50506040515190505b919050565b60015481565b60045481565b60035481565b60005481565b600073_____________WalletLibrary______________600160a060020a0316600036600060405160200152604051808383808284378201915050925050506020604051808303818560325a03f4151561033b57fe5b50506040515190505b92915050565b6000600560018301610100811061035d57fe5b0160005b505490505b919050565b600254815600a165627a7a72305820c20a8475c42598c198f6629bada37e1b234da85ac2c0cbac3d96089030b180400029'; -export const walletLibrary = '0x6060604052341561000c57fe5b5b61170f8061001c6000396000f300606060405236156101015763ffffffff60e060020a600035041663173825d981146101575780632f54bf6e146101755780634123cb6b146101a557806352375093146101c75780635c52c2f5146101e9578063659010e7146101fb5780637065cb481461021d578063746c91711461023b578063797af6271461025d5780639da5e0eb14610284578063b20d30a914610299578063b61d27f6146102ae578063b75c7dc6146102ec578063ba51a6df14610301578063c2cf732614610316578063c41a360a14610349578063c57c5f6014610378578063cbf0b0c0146103cf578063e46dcfeb146103ed578063f00d4b5d14610449578063f1736d861461046d575b6101555b60003411156101525760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b5b565b005b341561015f57fe5b610155600160a060020a036004351661048f565b005b341561017d57fe5b610191600160a060020a036004351661057d565b604080519115158252519081900360200190f35b34156101ad57fe5b6101b561059e565b60408051918252519081900360200190f35b34156101cf57fe5b6101b56105a4565b60408051918252519081900360200190f35b34156101f157fe5b6101556105aa565b005b341561020357fe5b6101b56105e1565b60408051918252519081900360200190f35b341561022557fe5b610155600160a060020a03600435166105e7565b005b341561024357fe5b6101b56106d7565b60408051918252519081900360200190f35b341561026557fe5b6101916004356106dd565b604080519115158252519081900360200190f35b341561028c57fe5b610155600435610a30565b005b34156102a157fe5b610155600435610a56565b005b34156102b657fe5b6101b560048035600160a060020a0316906024803591604435918201910135610a8e565b60408051918252519081900360200190f35b34156102f457fe5b610155600435610d71565b005b341561030957fe5b610155600435610e1c565b005b341561031e57fe5b610191600435600160a060020a0360243516610e9e565b604080519115158252519081900360200190f35b341561035157fe5b61035c600435610ef3565b60408051600160a060020a039092168252519081900360200190f35b341561038057fe5b6101556004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437509496505093359350610f1492505050565b005b34156103d757fe5b610155600160a060020a0360043516610ff9565b005b34156103f557fe5b6101556004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437509496505084359460200135935061103792505050565b005b341561045157fe5b610155600160a060020a0360043581169060243516611062565b005b341561047557fe5b6101b561115c565b60408051918252519081900360200190f35b60006000366040518083838082843782019150509250505060405180910390206104b881611162565b1561057657600160a060020a0383166000908152610105602052604090205491508115156104e557610576565b60016001540360005411156104f957610576565b6000600583610100811061050957fe5b0160005b5055600160a060020a038316600090815261010560205260408120556105316112cd565b6105396113bd565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a15b5b5b505050565b600160a060020a03811660009081526101056020526040812054115b919050565b60015481565b60045481565b6000366040518083838082843782019150509250505060405180910390206105d181611162565b156105dc5760006003555b5b5b50565b60035481565b60003660405180838380828437820191505092505050604051809103902061060e81611162565b156106d15761061c8261057d565b15610626576106d1565b61062e6112cd565b60015460fa9010610641576106416113bd565b5b60015460fa9010610652576106d1565b60018054810190819055600160a060020a03831690600590610100811061067557fe5b0160005b5055600154600160a060020a03831660008181526101056020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b5b5b5050565b60005481565b60006000826106eb81611162565b15610a265760008481526101086020526040902054600160a060020a031615158061072757506000848152610108602052604090206001015415155b80610754575060008481526101086020526040902060029081015461010060018216150260001901160415155b15610a265760008481526101086020526040902054600160a060020a0316151561082c57600084815261010860209081526040918290206001808201546002928301805486516000199482161561010002949094011693909304601f810185900485028301850190955284825261082594909391929183018282801561081b5780601f106107f05761010080835404028352916020019161081b565b820191906000526020600020905b8154815290600101906020018083116107fe57829003601f168201915b50505050506114f9565b91506108e4565b60008481526101086020526040908190208054600180830154935160029384018054600160a060020a0390941695949093919283928592918116156101000260001901160480156108be5780601f10610893576101008083540402835291602001916108be565b820191906000526020600020905b8154815290600101906020018083116108a157829003601f168201915b505091505060006040518083038185876185025a03f19250505015156108e45760006000fd5b5b6000848152610108602090815260409182902060018082015482548551600160a060020a033381811683529682018c90529681018390529086166060820181905295881660a082015260c06080820181815260029586018054958616156101000260001901909516959095049082018190527fe3a3a4111a84df27d76b68dc721e65c7711605ea5eee4afd3a9c58195217365c968b959394909390928a9290919060e0830190859080156109da5780601f106109af576101008083540402835291602001916109da565b820191906000526020600020905b8154815290600101906020018083116109bd57829003601f168201915b505097505050505050505060405180910390a16000848152610108602052604081208054600160a060020a03191681556001810182905590610a1f600283018261158e565b5050600192505b5b5b5b5050919050565b60006001541115610a415760006000fd5b6002819055610a4e611513565b6004555b5b50565b600036604051808383808284378201915050925050506040518091039020610a7d81611162565b156106d15760028290555b5b5b5050565b60006000610a9b3361057d565b15610d645782158015610ab25750610ab285611522565b5b80610ac057506000546001145b15610c0357600160a060020a0386161515610b1657610b0f8585858080601f016020809104026020016040519081016040528093929190818152602001838380828437506114f9945050505050565b9050610b57565b85600160a060020a03168585856040518083838082843782019150509250505060006040518083038185876185025a03f1925050501515610b575760006000fd5b5b7f9738cd1a8777c86b011f7b01d87d484217dc6ab5154a9d41eda5d14af8caf2923386888787866040518087600160a060020a0316600160a060020a0316815260200186815260200185600160a060020a0316600160a060020a031681526020018060200183600160a060020a0316600160a060020a0316815260200182810382528585828181526020019250808284376040519201829003995090975050505050505050a1610d64565b600036436040518084848082843791909101928352505060408051602092819003830190206000818152610108909352912054909450600160a060020a0316159150508015610c62575060008281526101086020526040902060010154155b8015610c8f5750600082815261010860205260409020600290810154610100600182161502600019011604155b15610cd3576000828152610108602052604090208054600160a060020a031916600160a060020a03881617815560018101869055610cd19060020185856115d6565b505b610cdc826106dd565b1515610d645760408051838152600160a060020a033381811660208401529282018890528816606082015260a0608082018181529082018690527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32928592909189918b918a918a9160c082018484808284376040519201829003995090975050505050505050a15b5b5b5b5b50949350505050565b600160a060020a033316600090815261010560205260408120549080821515610d9957610e15565b50506000828152610106602052604081206001810154600284900a929083161115610e155780546001908101825581018054839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5b50505050565b600036604051808383808284378201915050925050506040518091039020610e4381611162565b156106d157600154821115610e57576106d1565b6000829055610e646112cd565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15b5b5b5050565b600082815261010660209081526040808320600160a060020a038516845261010590925282205482811515610ed65760009350610eea565b8160020a9050808360010154166000141593505b50505092915050565b60006005600183016101008110610f0657fe5b0160005b505490505b919050565b600060006001541115610f275760006000fd5b825160019081018155600160a060020a033316906005905b0160005b505550600160a060020a033316600090815261010560205260408120600190555b8251811015610fed578281815181101515610f7b57fe5b60209081029091010151600160a060020a03166005600283016101008110610f9f57fe5b0160005b50819055508060020161010560008584815181101515610fbf57fe5b90602001906020020151600160a060020a03168152602001908152602001600020819055505b600101610f64565b60008290555b5b505050565b60003660405180838380828437820191505092505050604051809103902061102081611162565b156106d15781600160a060020a0316ff5b5b5b5050565b600060015411156110485760006000fd5b61105181610a30565b6105768383610f14565b5b5b505050565b600060003660405180838380828437820191505092505050604051809103902061108b81611162565b15610e15576110998361057d565b156110a357610e15565b600160a060020a0384166000908152610105602052604090205491508115156110cb57610e15565b6110d36112cd565b600160a060020a03831660058361010081106110eb57fe5b0160005b5055600160a060020a0380851660008181526101056020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b5b5b50505050565b60025481565b600160a060020a03331660009081526101056020526040812054818082151561118a576112c3565b600085815261010660205260409020805490925015156111ed576000805483556001808401919091556101078054916111c591908301611655565b60028301819055610107805487929081106111dc57fe5b906000526020600020900160005b50555b8260020a905080826001015416600014156112c35760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a18154600190116112b057600085815261010660205260409020600201546101078054909190811061127357fe5b906000526020600020900160005b5060009081905585815261010660205260408120818155600180820183905560029091019190915593506112c3565b8154600019018255600182018054821790555b5b5b505050919050565b6101075460005b818110156113ab576101086000610107838154811015156112f157fe5b906000526020600020900160005b50548152602081019190915260400160009081208054600160a060020a03191681556001810182905590611336600283018261158e565b505061010780548290811061134757fe5b906000526020600020900160005b5054156113a25761010660006101078381548110151561137157fe5b906000526020600020900160005b505481526020810191909152604001600090812081815560018101829055600201555b5b6001016112d4565b6106d1610107600061167f565b5b5050565b60015b6001548110156105dc575b600154811080156113ee575060058161010081106113e557fe5b0160005b505415155b156113fb576001016113cb565b5b60016001541180156114225750600154600590610100811061141a57fe5b0160005b5054155b1561143657600180546000190190556113fb565b6001548110801561145c5750600154600590610100811061145357fe5b0160005b505415155b80156114795750600581610100811061147157fe5b0160005b5054155b156114f057600154600590610100811061148f57fe5b0160005b505460058261010081106114a357fe5b0160005b505580610105600060058361010081106114bd57fe5b0160005b505481526020019081526020016000208190555060006005600154610100811015156114e957fe5b0160005b50555b6113c0565b5b50565b600081516020830184f09050803b15610000575b92915050565b600062015180425b0490505b90565b600061152d3361057d565b156105995760045461153d611513565b1115611554576000600355611550611513565b6004555b6003548281011080159061156e5750600254826003540111155b15611583575060038054820190556001610599565b5060005b5b5b919050565b50805460018160011615610100020316600290046000825580601f106115b457506105dc565b601f0160209004906000526020600020908101906105dc91906116a1565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106116175782800160ff19823516178555611644565b82800160010185558215611644579182015b82811115611644578235825591602001919060010190611629565b5b506116519291506116a1565b5090565b815481835581811511610576576000838152602090206105769181019083016116a1565b5b505050565b50805460008255906000526020600020908101906105dc91906116a1565b5b50565b61151f91905b8082111561165157600081556001016116a7565b5090565b90565b61151f91905b8082111561165157600081556001016116a7565b5090565b905600a165627a7a723058209a3af51063f944081cd5ee8601e4e655f25cf7bc219a7983cda60f163f1709a70029'; -export const walletLibraryABI = '[{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"removeOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"m_numOwners","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"m_lastDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"resetSpentToday","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"m_spentToday","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"}],"name":"addOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"m_required","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_h","type":"bytes32"}],"name":"confirm","outputs":[{"name":"o_success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_limit","type":"uint256"}],"name":"initDaylimit","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newLimit","type":"uint256"}],"name":"setDailyLimit","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"execute","outputs":[{"name":"o_hash","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_operation","type":"bytes32"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newRequired","type":"uint256"}],"name":"changeRequirement","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_operation","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"hasConfirmed","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"ownerIndex","type":"uint256"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owners","type":"address[]"},{"name":"_required","type":"uint256"}],"name":"initMultiowned","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"}],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_owners","type":"address[]"},{"name":"_required","type":"uint256"},{"name":"_daylimit","type":"uint256"}],"name":"initWallet","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"m_dailyLimit","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"operation","type":"bytes32"}],"name":"Confirmation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"operation","type":"bytes32"}],"name":"Revoke","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldOwner","type":"address"},{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newOwner","type":"address"}],"name":"OwnerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"oldOwner","type":"address"}],"name":"OwnerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newRequirement","type":"uint256"}],"name":"RequirementChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_from","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"data","type":"bytes"},{"indexed":false,"name":"created","type":"address"}],"name":"SingleTransact","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"owner","type":"address"},{"indexed":false,"name":"operation","type":"bytes32"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"data","type":"bytes"},{"indexed":false,"name":"created","type":"address"}],"name":"MultiTransact","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"operation","type":"bytes32"},{"indexed":false,"name":"initiator","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"data","type":"bytes"}],"name":"ConfirmationNeeded","type":"event"}]'; -export const walletSourceURL = 'https://github.com/paritytech/parity/blob/6b0e4f9098be6b841353e7c4f116aa86b7c2e3d6/js/src/contracts/snippets/enhanced-wallet.sol'; -export const walletLibraryRegKey = 'walletLibrary.v.2'; - -// Used if no Wallet Library found in registry... -// Compiled from `wallet.sol` using Solidity v0.4.9 - Optimized -export const fullWalletCode = '0x6060604052341561000c57fe5b60405161166d38038061166d83398101604090815281516020830151918301519201915b805b83835b815160019081018155600090600160a060020a033316906002905b0160005b505550600160a060020a033316600090815261010260205260408120600190555b82518110156100fd57828181518110151561008c57fe5b60209081029091010151600160a060020a0316600282810161010081106100af57fe5b0160005b508190555080600201610102600085848151811015156100cf57fe5b90602001906020020151600160a060020a03168152602001908152602001600020819055505b600101610075565b60008290555b50505061010581905561012164010000000061138f61013082021704565b610107555b505b50505061013f565b600062015180425b0490505b90565b61151f8061014e6000396000f300606060405236156100e05763ffffffff60e060020a600035041663173825d981146101365780632f54bf6e146101545780634123cb6b1461018457806352375093146101a65780635c52c2f5146101c8578063659010e7146101da5780637065cb48146101fc578063746c91711461021a578063797af6271461023c578063b20d30a914610263578063b61d27f614610278578063b75c7dc6146102b6578063ba51a6df146102cb578063c2cf7326146102e0578063c41a360a14610313578063cbf0b0c014610342578063f00d4b5d14610360578063f1736d8614610384575b6101345b60003411156101315760408051600160a060020a033316815234602082015281517fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c929181900390910190a15b5b565b005b341561013e57fe5b610134600160a060020a03600435166103a6565b005b341561015c57fe5b610170600160a060020a0360043516610494565b604080519115158252519081900360200190f35b341561018c57fe5b6101946104b5565b60408051918252519081900360200190f35b34156101ae57fe5b6101946104bb565b60408051918252519081900360200190f35b34156101d057fe5b6101346104c2565b005b34156101e257fe5b6101946104fa565b60408051918252519081900360200190f35b341561020457fe5b610134600160a060020a0360043516610501565b005b341561022257fe5b6101946105f1565b60408051918252519081900360200190f35b341561024457fe5b6101706004356105f7565b604080519115158252519081900360200190f35b341561026b57fe5b610134600435610949565b005b341561028057fe5b61019460048035600160a060020a0316906024803591604435918201910135610982565b60408051918252519081900360200190f35b34156102be57fe5b610134600435610c64565b005b34156102d357fe5b610134600435610d0f565b005b34156102e857fe5b610170600435600160a060020a0360243516610d91565b604080519115158252519081900360200190f35b341561031b57fe5b610326600435610de6565b60408051600160a060020a039092168252519081900360200190f35b341561034a57fe5b610134600160a060020a0360043516610e07565b005b341561036857fe5b610134600160a060020a0360043581169060243516610e45565b005b341561038c57fe5b610194610f3f565b60408051918252519081900360200190f35b60006000366040518083838082843782019150509250505060405180910390206103cf81610f46565b1561048d57600160a060020a0383166000908152610102602052604090205491508115156103fc5761048d565b60016001540360005411156104105761048d565b6000600283610100811061042057fe5b0160005b5055600160a060020a038316600090815261010260205260408120556104486110b1565b610450611132565b60408051600160a060020a038516815290517f58619076adf5bb0943d100ef88d52d7c3fd691b19d3a9071b555b651fbf418da9181900360200190a15b5b5b505050565b600160a060020a03811660009081526101026020526040812054115b919050565b60015481565b6101075481565b6000366040518083838082843782019150509250505060405180910390206104e981610f46565b156104f5576000610106555b5b5b50565b6101065481565b60003660405180838380828437820191505092505050604051809103902061052881610f46565b156105eb5761053682610494565b15610540576105eb565b6105486110b1565b60015460fa901061055b5761055b611132565b5b60015460fa901061056c576105eb565b60018054810190819055600160a060020a03831690600290610100811061058f57fe5b0160005b5055600154600160a060020a03831660008181526101026020908152604091829020939093558051918252517f994a936646fe87ffe4f1e469d3d6aa417d6b855598397f323de5b449f765f0c3929181900390910190a15b5b5b5050565b60005481565b600060008261060581610f46565b1561093f5760008481526101086020526040902054600160a060020a031615158061064157506000848152610108602052604090206001015415155b8061066e575060008481526101086020526040902060029081015461010060018216150260001901160415155b1561093f5760008481526101086020526040902054600160a060020a0316151561074657600084815261010860209081526040918290206001808201546002928301805486516000199482161561010002949094011693909304601f810185900485028301850190955284825261073f9490939192918301828280156107355780601f1061070a57610100808354040283529160200191610735565b820191906000526020600020905b81548152906001019060200180831161071857829003601f168201915b505050505061126e565b91506107fd565b60008481526101086020526040908190208054600180830154935160029384018054600160a060020a0390941695949093919283928592918116156101000260001901160480156107d85780601f106107ad576101008083540402835291602001916107d8565b820191906000526020600020905b8154815290600101906020018083116107bb57829003601f168201915b505091505060006040518083038185876185025a03f19250505015156107fd57610000565b5b6000848152610108602090815260409182902060018082015482548551600160a060020a033381811683529682018c90529681018390529086166060820181905295881660a082015260c06080820181815260029586018054958616156101000260001901909516959095049082018190527fe3a3a4111a84df27d76b68dc721e65c7711605ea5eee4afd3a9c58195217365c968b959394909390928a9290919060e0830190859080156108f35780601f106108c8576101008083540402835291602001916108f3565b820191906000526020600020905b8154815290600101906020018083116108d657829003601f168201915b505097505050505050505060405180910390a16000848152610108602052604081208054600160a060020a03191681556001810182905590610938600283018261139e565b5050600192505b5b5b5b5050919050565b60003660405180838380828437820191505092505050604051809103902061097081610f46565b156105eb576101058290555b5b5b5050565b6000600061098f33610494565b15610c5757821580156109a657506109a685611288565b5b806109b457506000546001145b15610af657600160a060020a0386161515610a0a57610a038585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375061126e945050505050565b9050610a4a565b85600160a060020a03168585856040518083838082843782019150509250505060006040518083038185876185025a03f1925050501515610a4a57610000565b5b7f9738cd1a8777c86b011f7b01d87d484217dc6ab5154a9d41eda5d14af8caf2923386888787866040518087600160a060020a0316600160a060020a0316815260200186815260200185600160a060020a0316600160a060020a031681526020018060200183600160a060020a0316600160a060020a0316815260200182810382528585828181526020019250808284376040519201829003995090975050505050505050a1610c57565b600036436040518084848082843791909101928352505060408051602092819003830190206000818152610108909352912054909450600160a060020a0316159150508015610b55575060008281526101086020526040902060010154155b8015610b825750600082815261010860205260409020600290810154610100600182161502600019011604155b15610bc6576000828152610108602052604090208054600160a060020a031916600160a060020a03881617815560018101869055610bc49060020185856113e6565b505b610bcf826105f7565b1515610c575760408051838152600160a060020a033381811660208401529282018890528816606082015260a0608082018181529082018690527f1733cbb53659d713b79580f79f3f9ff215f78a7c7aa45890f3b89fc5cddfbf32928592909189918b918a918a9160c082018484808284376040519201829003995090975050505050505050a15b5b5b5b5b50949350505050565b600160a060020a033316600090815261010260205260408120549080821515610c8c57610d08565b50506000828152610103602052604081206001810154600284900a929083161115610d085780546001908101825581018054839003905560408051600160a060020a03331681526020810186905281517fc7fb647e59b18047309aa15aad418e5d7ca96d173ad704f1031a2c3d7591734b929181900390910190a15b5b50505050565b600036604051808383808284378201915050925050506040518091039020610d3681610f46565b156105eb57600154821115610d4a576105eb565b6000829055610d576110b1565b6040805183815290517facbdb084c721332ac59f9b8e392196c9eb0e4932862da8eb9beaf0dad4f550da9181900360200190a15b5b5b5050565b600082815261010360209081526040808320600160a060020a038516845261010290925282205482811515610dc95760009350610ddd565b8160020a9050808360010154166000141593505b50505092915050565b60006002600183016101008110610df957fe5b0160005b505490505b919050565b600036604051808383808284378201915050925050506040518091039020610e2e81610f46565b156105eb5781600160a060020a0316ff5b5b5b5050565b6000600036604051808383808284378201915050925050506040518091039020610e6e81610f46565b15610d0857610e7c83610494565b15610e8657610d08565b600160a060020a038416600090815261010260205260409020549150811515610eae57610d08565b610eb66110b1565b600160a060020a0383166002836101008110610ece57fe5b0160005b5055600160a060020a0380851660008181526101026020908152604080832083905593871680835291849020869055835192835282015281517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c929181900390910190a15b5b5b50505050565b6101055481565b600160a060020a033316600090815261010260205260408120548180821515610f6e576110a7565b60008581526101036020526040902080549092501515610fd157600080548355600180840191909155610104805491610fa991908301611465565b6002830181905561010480548792908110610fc057fe5b906000526020600020900160005b50555b8260020a905080826001015416600014156110a75760408051600160a060020a03331681526020810187905281517fe1c52dc63b719ade82e8bea94cc41a0d5d28e4aaf536adb5e9cccc9ff8c1aeda929181900390910190a181546001901161109457600085815261010360205260409020600201546101048054909190811061105757fe5b906000526020600020900160005b5060009081905585815261010360205260408120818155600180820183905560029091019190915593506110a7565b8154600019018255600182018054821790555b5b5b505050919050565b6101045460005b81811015611125576101086000610104838154811015156110d557fe5b906000526020600020900160005b50548152602081019190915260400160009081208054600160a060020a0319168155600181018290559061111a600283018261139e565b50505b6001016110b8565b6105eb6112fb565b5b5050565b60015b6001548110156104f5575b600154811080156111635750600281610100811061115a57fe5b0160005b505415155b1561117057600101611140565b5b60016001541180156111975750600154600290610100811061118f57fe5b0160005b5054155b156111ab5760018054600019019055611170565b600154811080156111d1575060015460029061010081106111c857fe5b0160005b505415155b80156111ee575060028161010081106111e657fe5b0160005b5054155b1561126557600154600290610100811061120457fe5b0160005b5054600282610100811061121857fe5b0160005b5055806101026000600283610100811061123257fe5b0160005b5054815260200190815260200160002081905550600060026001546101008110151561125e57fe5b0160005b50555b611135565b5b50565b600081516020830184f09050803b15610000575b92915050565b600061129333610494565b156104b057610107546112a461138f565b11156112bd576000610106556112b861138f565b610107555b61010654828101108015906112da57506101055482610106540111155b156112f0575061010680548201905560016104b0565b5060005b5b5b919050565b6101045460005b8181101561137d5761010480548290811061131957fe5b906000526020600020900160005b5054156113745761010360006101048381548110151561134357fe5b906000526020600020900160005b505481526020810191909152604001600090812081815560018101829055600201555b5b600101611302565b6105eb610104600061148f565b5b5050565b600062015180425b0490505b90565b50805460018160011615610100020316600290046000825580601f106113c457506104f5565b601f0160209004906000526020600020908101906104f591906114b1565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106114275782800160ff19823516178555611454565b82800160010185558215611454579182015b82811115611454578235825591602001919060010190611439565b5b506114619291506114b1565b5090565b81548183558181151161048d5760008381526020902061048d9181019083016114b1565b5b505050565b50805460008255906000526020600020908101906104f591906114b1565b5b50565b61139b91905b8082111561146157600081556001016114b7565b5090565b90565b61139b91905b8082111561146157600081556001016114b7565b5090565b905600a165627a7a723058203a7ac7072dc640002704b704af82b742650362cd55debf72fca105c2b916e01d0029'; diff --git a/js/src/contracts/contracts.js b/js/src/contracts/contracts.js deleted file mode 100644 index 59b3bccfc3e69e7c2439ec18487f1c63d058b990..0000000000000000000000000000000000000000 --- a/js/src/contracts/contracts.js +++ /dev/null @@ -1,83 +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 . - -import DappReg from './dappreg'; -import Registry from './registry'; -import SignatureReg from './signaturereg'; -import TokenReg from './tokenreg'; -import GithubHint from './githubhint'; -import * as verification from './verification'; -import BadgeReg from './badgereg'; - -let instance = null; - -export default class Contracts { - constructor (api) { - instance = this; - - this._api = api; - this._registry = new Registry(api); - this._dappreg = new DappReg(api, this._registry); - this._signaturereg = new SignatureReg(api, this._registry); - this._tokenreg = new TokenReg(api, this._registry); - this._githubhint = new GithubHint(api, this._registry); - this._badgeReg = new BadgeReg(api, this._registry); - } - - get registry () { - return this._registry; - } - - get badgeReg () { - return this._badgeReg; - } - - get dappReg () { - return this._dappreg; - } - - get signatureReg () { - return this._signaturereg; - } - - get tokenReg () { - return this._tokenreg; - } - - get githubHint () { - return this._githubhint; - } - - get smsVerification () { - return verification; - } - - get emailVerification () { - return verification; - } - - static create (api) { - if (instance) { - return instance; - } - - return new Contracts(api); - } - - static get () { - return instance; - } -} diff --git a/js/src/contracts/dappreg.js b/js/src/contracts/dappreg.js deleted file mode 100644 index 18af9c1635eb6b9b60e6d4c0e52f38bdd782f168..0000000000000000000000000000000000000000 --- a/js/src/contracts/dappreg.js +++ /dev/null @@ -1,68 +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 . - -export default class DappReg { - constructor (api, registry) { - this._api = api; - this._registry = registry; - - this.getInstance(); - } - - getContract () { - return this._registry.getContract('dappreg'); - } - - getInstance () { - return this.getContract().then((contract) => contract.instance); - } - - count () { - return this.getInstance().then((instance) => { - return instance.count.call(); - }); - } - - at (index) { - return this.getInstance().then((instance) => { - return instance.at.call({}, [index]); - }); - } - - get (id) { - return this.getInstance().then((instance) => { - return instance.get.call({}, [id]); - }); - } - - meta (id, key) { - return this.getInstance().then((instance) => { - return instance.meta.call({}, [id, key]); - }); - } - - getImage (id) { - return this.meta(id, 'IMG'); - } - - getContent (id) { - return this.meta(id, 'CONTENT'); - } - - getManifest (id) { - return this.meta(id, 'MANIFEST'); - } -} diff --git a/js/src/contracts/githubhint.js b/js/src/contracts/githubhint.js deleted file mode 100644 index dfc3d5fb7e866daff48b0d6b495751a393f3b636..0000000000000000000000000000000000000000 --- a/js/src/contracts/githubhint.js +++ /dev/null @@ -1,46 +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 . - -export default class GithubHint { - constructor (api, registry) { - this._api = api; - this._registry = registry; - this._instance = null; - - this.getInstance(); - } - - getContract () { - return this._registry.getContract('githubhint'); - } - - getInstance () { - if (this._instance) { - return Promise.resolve(this._instance); - } - - return this.getContract().then((contract) => { - this._instance = contract.instance; - return this._instance; - }); - } - - getEntry (entryId) { - return this.getInstance().then((instance) => { - return instance.entries.call({}, [entryId]); - }); - } -} diff --git a/js/src/contracts/githubhint.spec.js b/js/src/contracts/githubhint.spec.js deleted file mode 100644 index f3385078237633bd0fdca77cb73f10bc6b188046..0000000000000000000000000000000000000000 --- a/js/src/contracts/githubhint.spec.js +++ /dev/null @@ -1,66 +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 . - -import sinon from 'sinon'; - -import GithubHint from './githubhint'; - -let githubHint; -let instance; -let registry; - -function create () { - instance = { - __id: 'testInstance', - entries: { - call: sinon.stub().resolves('testValue') - } - }; - registry = { - getContract: sinon.stub().resolves({ instance }) - }; - githubHint = new GithubHint({}, registry); - - return githubHint; -} - -describe('contracts/GithubHint', () => { - beforeEach(() => { - create(); - - return githubHint.getInstance(); - }); - - it('instantiates successfully', () => { - expect(githubHint).to.be.ok; - }); - - it('attaches the instance on create', () => { - expect(githubHint._instance.__id).to.equal('testInstance'); - }); - - describe('interface', () => { - describe('getEntry', () => { - beforeEach(() => { - return githubHint.getEntry('testId'); - }); - - it('calls entries on the instance', () => { - expect(instance.entries.call).to.have.been.calledWith({}, ['testId']); - }); - }); - }); -}); diff --git a/js/src/contracts/index.js b/js/src/contracts/index.js deleted file mode 100644 index 8714ff544deb1aa555d2086247c09fc8d99532de..0000000000000000000000000000000000000000 --- a/js/src/contracts/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './contracts'; diff --git a/js/src/contracts/registry.js b/js/src/contracts/registry.js deleted file mode 100644 index cef31785e061210b8094fbee20e827259123eb14..0000000000000000000000000000000000000000 --- a/js/src/contracts/registry.js +++ /dev/null @@ -1,165 +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 . - -import * as abis from './abi'; - -const REGISTRY_V1_HASHES = [ - '0x34f7c51bbb1b1902fbdabfdf04811100f5c9f998f26dd535d2f6f977492c748e', // ropsten - '0x64c3ee34851517a9faecd995c102b339f03e564ad6772dc43a26f993238b20ec' // homestead -]; - -export default class Registry { - _registryContract = null; - - constructor (api) { - this._api = api; - - this._contracts = {}; - this._pendingContracts = {}; - - this._instance = null; - this._fetching = false; - this._queue = []; - - this.getInstance(); - } - - getInstance () { - if (this._instance) { - return Promise.resolve(this._instance); - } - - if (this._fetching) { - return new Promise((resolve) => { - this._queue.push({ resolve }); - }); - } - - this._fetching = true; - - return this.fetchContract() - .then((contract) => { - this._fetching = false; - this._instance = contract.instance; - - this._queue.forEach((queued) => { - queued.resolve(this._instance); - }); - - this._queue = []; - - return this._instance; - }); - } - - getContract (_name) { - const name = _name.toLowerCase(); - - if (this._contracts[name]) { - return Promise.resolve(this._contracts[name]); - } - - if (this._pendingContracts[name]) { - return this._pendingContracts[name]; - } - - const promise = this - .lookupAddress(name) - .then((address) => { - this._contracts[name] = this._api.newContract(abis[name], address); - delete this._pendingContracts[name]; - return this._contracts[name]; - }); - - this._pendingContracts[name] = promise; - - return promise; - } - - getContractInstance (_name) { - return this - .getContract(_name) - .then((contract) => contract.instance); - } - - fetchContract () { - if (this._registryContract) { - return Promise.resolve(this._registryContract); - } - - return this._api.parity - .registryAddress() - .then((address) => Promise.all([ address, this._api.eth.getCode(address) ])) - .then(([ address, code ]) => { - const codeHash = this._api.util.sha3(code); - const version = REGISTRY_V1_HASHES.includes(codeHash) - ? 1 - : 2; - const abi = version === 1 - ? abis.registry - : abis.registry2; - const contract = this._api.newContract(abi, address); - - // Add support for previous `set` and `get` methods - if (!contract.instance.get && contract.instance.getData) { - contract.instance.get = contract.instance.getData; - } - - if (contract.instance.get && !contract.instance.getData) { - contract.instance.getData = contract.instance.get; - } - - if (!contract.instance.set && contract.instance.setData) { - contract.instance.set = contract.instance.setData; - } - - if (contract.instance.set && !contract.instance.setData) { - contract.instance.setData = contract.instance.set; - } - - console.log(`registry at ${address}, code ${codeHash}, version ${version}`); - this._registryContract = contract; - return this._registryContract; - }); - } - - _createGetParams (_name, key) { - const name = _name.toLowerCase(); - const sha3 = this._api.util.sha3.text(name); - - return [sha3, key]; - } - - lookupAddress (name) { - return this - .getInstance() - .then((instance) => { - return instance.getAddress.call({}, this._createGetParams(name, 'A')); - }) - .then((address) => { - console.log('[lookupAddress]', `${name}: ${address}`); - return address; - }); - } - - lookupMeta (name, key) { - return this - .getInstance() - .then((instance) => { - return instance.get.call({}, this._createGetParams(name, key)); - }); - } -} diff --git a/js/src/contracts/registry.spec.js b/js/src/contracts/registry.spec.js deleted file mode 100644 index cf81a2b7210ab9d3b2e29a46147c68df371b8f19..0000000000000000000000000000000000000000 --- a/js/src/contracts/registry.spec.js +++ /dev/null @@ -1,86 +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 . - -import sinon from 'sinon'; - -import apiutil from '~/api/util'; - -import Registry from './registry'; - -const GHH_NAME = 'githubhint'; -const GHH_SHA3 = '0x058740ee9a5a3fb9f1cfa10752baec87e09cc45cd7027fd54708271aca300c75'; - -let api; -let instance; -let registry; - -function create () { - instance = { - __id: 'testInstance', - get: { - call: sinon.stub().resolves('testGet') - } - }; - api = { - eth: { - getCode: sinon.stub().resolves('0x123456') - }, - parity: { - registryAddress: sinon.stub().resolves('testRegistryAddress') - }, - util: apiutil, - newContract: sinon.stub().returns({ instance }) - }; - registry = new Registry(api); - - return registry; -} - -describe('contracts/Registry', () => { - beforeEach(() => { - create(); - - return registry.getInstance(); - }); - - it('instantiates successfully', () => { - expect(registry).to.be.ok; - }); - - it('retrieves the registry on create', () => { - expect(api.parity.registryAddress).to.have.been.called; - }); - - it('attaches the instance on create', () => { - expect(registry._instance.__id).to.equal('testInstance'); - }); - - describe('interface', () => { - describe('lookupMeta', () => { - it('calls get on the contract', () => { - return registry.lookupMeta(GHH_NAME, 'key').then(() => { - expect(instance.get.call).to.have.been.calledWith({}, [GHH_SHA3, 'key']); - }); - }); - - it('converts names to lowercase', () => { - return registry.lookupMeta(GHH_NAME.toUpperCase(), 'key').then(() => { - expect(instance.get.call).to.have.been.calledWith({}, [GHH_SHA3, 'key']); - }); - }); - }); - }); -}); diff --git a/js/src/contracts/signaturereg.js b/js/src/contracts/signaturereg.js deleted file mode 100644 index 9fa3eab069f639194c8bd04b5cf03fdc6aebd1c0..0000000000000000000000000000000000000000 --- a/js/src/contracts/signaturereg.js +++ /dev/null @@ -1,34 +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 . - -export default class SignatureReg { - constructor (api, registry) { - this._api = api; - this._registry = registry; - - this.getInstance(); - } - - getInstance () { - return this._registry.getContractInstance('signaturereg'); - } - - lookup (signature) { - return this.getInstance().then((instance) => { - return instance.entries.call({}, [signature]); - }); - } -} diff --git a/js/src/contracts/snippets/enhanced-wallet.sol b/js/src/contracts/snippets/enhanced-wallet.sol deleted file mode 100644 index 90a15c070ba26db27c4190a6287f6c34446d123f..0000000000000000000000000000000000000000 --- a/js/src/contracts/snippets/enhanced-wallet.sol +++ /dev/null @@ -1,464 +0,0 @@ -//sol Wallet -// Multi-sig, daily-limited account proxy/wallet. -// @authors: -// Gav Wood -// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a -// single, or, crucially, each of a number of, designated owners. -// usage: -// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by -// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the -// interior is executed. - -pragma solidity ^0.4.9; - -contract WalletEvents { - // EVENTS - - // this contract only has six types of events: it can accept a confirmation, in which case - // we record owner and operation (hash) alongside it. - event Confirmation(address owner, bytes32 operation); - event Revoke(address owner, bytes32 operation); - - // some others are in the case of an owner changing. - event OwnerChanged(address oldOwner, address newOwner); - event OwnerAdded(address newOwner); - event OwnerRemoved(address oldOwner); - - // the last one is emitted if the required signatures change - event RequirementChanged(uint newRequirement); - - // Funds has arrived into the wallet (record how much). - event Deposit(address _from, uint value); - // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). - event SingleTransact(address owner, uint value, address to, bytes data, address created); - // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). - event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data, address created); - // Confirmation still needed for a transaction. - event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); -} - -contract WalletAbi { - // Revokes a prior confirmation of the given operation - function revoke(bytes32 _operation) external; - - // Replaces an owner `_from` with another `_to`. - function changeOwner(address _from, address _to) external; - - function addOwner(address _owner) external; - - function removeOwner(address _owner) external; - - function changeRequirement(uint _newRequired) external; - - function isOwner(address _addr) constant returns (bool); - - function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool); - - // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. - function setDailyLimit(uint _newLimit) external; - - function execute(address _to, uint _value, bytes _data) external returns (bytes32 o_hash); - function confirm(bytes32 _h) returns (bool o_success); -} - -contract WalletLibrary is WalletEvents { - // TYPES - - // struct for the status of a pending operation. - struct PendingState { - uint yetNeeded; - uint ownersDone; - uint index; - } - - // Transaction structure to remember details of transaction lest it need be saved for a later call. - struct Transaction { - address to; - uint value; - bytes data; - } - - // MODIFIERS - - // simple single-sig function modifier. - modifier onlyowner { - if (isOwner(msg.sender)) - _; - } - // multi-sig function modifier: the operation must have an intrinsic hash in order - // that later attempts can be realised as the same underlying operation and - // thus count as confirmations. - modifier onlymanyowners(bytes32 _operation) { - if (confirmAndCheck(_operation)) - _; - } - - // METHODS - - // gets called when no other function matches - function() payable { - // just being sent some cash? - if (msg.value > 0) - Deposit(msg.sender, msg.value); - } - - // constructor is given number of sigs required to do protected "onlymanyowners" transactions - // as well as the selection of addresses capable of confirming them. - function initMultiowned(address[] _owners, uint _required) only_uninitialized { - m_numOwners = _owners.length + 1; - m_owners[1] = uint(msg.sender); - m_ownerIndex[uint(msg.sender)] = 1; - for (uint i = 0; i < _owners.length; ++i) - { - m_owners[2 + i] = uint(_owners[i]); - m_ownerIndex[uint(_owners[i])] = 2 + i; - } - m_required = _required; - } - - // Revokes a prior confirmation of the given operation - function revoke(bytes32 _operation) external { - uint ownerIndex = m_ownerIndex[uint(msg.sender)]; - // make sure they're an owner - if (ownerIndex == 0) return; - uint ownerIndexBit = 2**ownerIndex; - var pending = m_pending[_operation]; - if (pending.ownersDone & ownerIndexBit > 0) { - pending.yetNeeded++; - pending.ownersDone -= ownerIndexBit; - Revoke(msg.sender, _operation); - } - } - - // Replaces an owner `_from` with another `_to`. - function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_to)) return; - uint ownerIndex = m_ownerIndex[uint(_from)]; - if (ownerIndex == 0) return; - - clearPending(); - m_owners[ownerIndex] = uint(_to); - m_ownerIndex[uint(_from)] = 0; - m_ownerIndex[uint(_to)] = ownerIndex; - OwnerChanged(_from, _to); - } - - function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_owner)) return; - - clearPending(); - if (m_numOwners >= c_maxOwners) - reorganizeOwners(); - if (m_numOwners >= c_maxOwners) - return; - m_numOwners++; - m_owners[m_numOwners] = uint(_owner); - m_ownerIndex[uint(_owner)] = m_numOwners; - OwnerAdded(_owner); - } - - function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - uint ownerIndex = m_ownerIndex[uint(_owner)]; - if (ownerIndex == 0) return; - if (m_required > m_numOwners - 1) return; - - m_owners[ownerIndex] = 0; - m_ownerIndex[uint(_owner)] = 0; - clearPending(); - reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot - OwnerRemoved(_owner); - } - - function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external { - if (_newRequired > m_numOwners) return; - m_required = _newRequired; - clearPending(); - RequirementChanged(_newRequired); - } - - // Gets an owner by 0-indexed position (using numOwners as the count) - function getOwner(uint ownerIndex) external constant returns (address) { - return address(m_owners[ownerIndex + 1]); - } - - function isOwner(address _addr) constant returns (bool) { - return m_ownerIndex[uint(_addr)] > 0; - } - - function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) { - var pending = m_pending[_operation]; - uint ownerIndex = m_ownerIndex[uint(_owner)]; - - // make sure they're an owner - if (ownerIndex == 0) return false; - - // determine the bit to set for this owner. - uint ownerIndexBit = 2**ownerIndex; - return !(pending.ownersDone & ownerIndexBit == 0); - } - - // constructor - stores initial daily limit and records the present day's index. - function initDaylimit(uint _limit) only_uninitialized { - m_dailyLimit = _limit; - m_lastDay = today(); - } - // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. - function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external { - m_dailyLimit = _newLimit; - } - // resets the amount already spent today. needs many of the owners to confirm. - function resetSpentToday() onlymanyowners(sha3(msg.data)) external { - m_spentToday = 0; - } - - // throw unless the contract is not yet initialized. - modifier only_uninitialized { if (m_numOwners > 0) throw; _; } - - // constructor - just pass on the owner array to the multiowned and - // the limit to daylimit - function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized { - initDaylimit(_daylimit); - initMultiowned(_owners, _required); - } - - // kills the contract sending everything to `_to`. - function kill(address _to) onlymanyowners(sha3(msg.data)) external { - suicide(_to); - } - - // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit. - // If not, goes into multisig process. We provide a hash on return to allow the sender to provide - // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value - // and _data arguments). They still get the option of using them if they want, anyways. - function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 o_hash) { - // first, take the opportunity to check that we're under the daily limit. - if ((_data.length == 0 && underLimit(_value)) || m_required == 1) { - // yes - just execute the call. - address created; - if (_to == 0) { - created = create(_value, _data); - } else { - if (!_to.call.value(_value)(_data)) - throw; - } - SingleTransact(msg.sender, _value, _to, _data, created); - } else { - // determine our operation hash. - o_hash = sha3(msg.data, block.number); - // store if it's new - if (m_txs[o_hash].to == 0 && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) { - m_txs[o_hash].to = _to; - m_txs[o_hash].value = _value; - m_txs[o_hash].data = _data; - } - if (!confirm(o_hash)) { - ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data); - } - } - } - - function create(uint _value, bytes _code) internal returns (address o_addr) { - assembly { - o_addr := create(_value, add(_code, 0x20), mload(_code)) - jumpi(invalidJumpLabel, iszero(extcodesize(o_addr))) - } - } - - // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order - // to determine the body of the transaction from the hash provided. - function confirm(bytes32 _h) onlymanyowners(_h) returns (bool o_success) { - if (m_txs[_h].to != 0 || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) { - address created; - if (m_txs[_h].to == 0) { - created = create(m_txs[_h].value, m_txs[_h].data); - } else { - if (!m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data)) - throw; - } - - MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created); - delete m_txs[_h]; - return true; - } - } - - // INTERNAL METHODS - - function confirmAndCheck(bytes32 _operation) internal returns (bool) { - // determine what index the present sender is: - uint ownerIndex = m_ownerIndex[uint(msg.sender)]; - // make sure they're an owner - if (ownerIndex == 0) return; - - var pending = m_pending[_operation]; - // if we're not yet working on this operation, switch over and reset the confirmation status. - if (pending.yetNeeded == 0) { - // reset count of confirmations needed. - pending.yetNeeded = m_required; - // reset which owners have confirmed (none) - set our bitmap to 0. - pending.ownersDone = 0; - pending.index = m_pendingIndex.length++; - m_pendingIndex[pending.index] = _operation; - } - // determine the bit to set for this owner. - uint ownerIndexBit = 2**ownerIndex; - // make sure we (the message sender) haven't confirmed this operation previously. - if (pending.ownersDone & ownerIndexBit == 0) { - Confirmation(msg.sender, _operation); - // ok - check if count is enough to go ahead. - if (pending.yetNeeded <= 1) { - // enough confirmations: reset and run interior. - delete m_pendingIndex[m_pending[_operation].index]; - delete m_pending[_operation]; - return true; - } - else - { - // not enough: record that this owner in particular confirmed. - pending.yetNeeded--; - pending.ownersDone |= ownerIndexBit; - } - } - } - - function reorganizeOwners() private { - uint free = 1; - while (free < m_numOwners) - { - while (free < m_numOwners && m_owners[free] != 0) free++; - while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--; - if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0) - { - m_owners[free] = m_owners[m_numOwners]; - m_ownerIndex[m_owners[free]] = free; - m_owners[m_numOwners] = 0; - } - } - } - - // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and - // returns true. otherwise just returns false. - function underLimit(uint _value) internal onlyowner returns (bool) { - // reset the spend limit if we're on a different day to last time. - if (today() > m_lastDay) { - m_spentToday = 0; - m_lastDay = today(); - } - // check to see if there's enough left - if so, subtract and return true. - // overflow protection // dailyLimit check - if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) { - m_spentToday += _value; - return true; - } - return false; - } - - // determines today's index. - function today() private constant returns (uint) { return now / 1 days; } - - function clearPending() internal { - uint length = m_pendingIndex.length; - - for (uint i = 0; i < length; ++i) { - delete m_txs[m_pendingIndex[i]]; - - if (m_pendingIndex[i] != 0) - delete m_pending[m_pendingIndex[i]]; - } - - delete m_pendingIndex; - } - - // FIELDS - address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe; - - // the number of owners that must confirm the same operation before it is run. - uint public m_required; - // pointer used to find a free slot in m_owners - uint public m_numOwners; - - uint public m_dailyLimit; - uint public m_spentToday; - uint public m_lastDay; - - // list of owners - uint[256] m_owners; - - uint constant c_maxOwners = 250; - // index on the list of owners to allow reverse lookup - mapping(uint => uint) m_ownerIndex; - // the ongoing operations. - mapping(bytes32 => PendingState) m_pending; - bytes32[] m_pendingIndex; - - // pending transactions we have at present. - mapping (bytes32 => Transaction) m_txs; -} - -contract Wallet is WalletEvents { - - // WALLET CONSTRUCTOR - // calls the `initWallet` method of the Library in this context - function Wallet(address[] _owners, uint _required, uint _daylimit) { - // Signature of the Wallet Library's init function - bytes4 sig = bytes4(sha3("initWallet(address[],uint256,uint256)")); - address target = _walletLibrary; - - // Compute the size of the call data : arrays has 2 - // 32bytes for offset and length, plus 32bytes per element ; - // plus 2 32bytes for each uint - uint argarraysize = (2 + _owners.length); - uint argsize = (2 + argarraysize) * 32; - - assembly { - // Add the signature first to memory - mstore(0x0, sig) - // Add the call data, which is at the end of the - // code - codecopy(0x4, sub(codesize, argsize), argsize) - // Delegate call to the library - delegatecall(sub(gas, 10000), target, 0x0, add(argsize, 0x4), 0x0, 0x0) - } - } - - // METHODS - - // gets called when no other function matches - function() payable { - // just being sent some cash? - if (msg.value > 0) - Deposit(msg.sender, msg.value); - else if (msg.data.length > 0) - _walletLibrary.delegatecall(msg.data); - } - - // Gets an owner by 0-indexed position (using numOwners as the count) - function getOwner(uint ownerIndex) constant returns (address) { - return address(m_owners[ownerIndex + 1]); - } - - // As return statement unavailable in fallback, explicit the method here - - function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) { - return _walletLibrary.delegatecall(msg.data); - } - - function isOwner(address _addr) constant returns (bool) { - return _walletLibrary.delegatecall(msg.data); - } - - // FIELDS - address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe; - - // the number of owners that must confirm the same operation before it is run. - uint public m_required; - // pointer used to find a free slot in m_owners - uint public m_numOwners; - - uint public m_dailyLimit; - uint public m_spentToday; - uint public m_lastDay; - - // list of owners - uint[256] m_owners; -} diff --git a/js/src/contracts/snippets/human-standard-token.sol b/js/src/contracts/snippets/human-standard-token.sol deleted file mode 100644 index db05bbc7df9fdbc78b40629c31a79eae1acf0ba2..0000000000000000000000000000000000000000 --- a/js/src/contracts/snippets/human-standard-token.sol +++ /dev/null @@ -1,60 +0,0 @@ -/* -This Token Contract implements the standard token functionality (https://github.com/ethereum/EIPs/issues/20) as well as the following OPTIONAL extras intended for use by humans. - -In other words. This is intended for deployment in something like a Token Factory or Mist wallet, and then used by humans. -Imagine coins, currencies, shares, voting weight, etc. -Machine-based, rapid creation of many tokens would not necessarily need these extra features or will be minted in other manners. - -1) Initial Finite Supply (upon creation one specifies how much is minted). -2) In the absence of a token registry: Optional Decimal, Symbol & Name. -3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred. - -.*/ - -import "StandardToken.sol"; - -contract HumanStandardToken is StandardToken { - - function () { - //if ether is sent to this address, send it back. - throw; - } - - /* Public variables of the token */ - - /* - NOTE: - The following variables are OPTIONAL vanities. One does not have to include them. - They allow one to customise the token contract & in no way influences the core functionality. - Some wallets/interfaces might not even bother to look at this information. - */ - string public name; //fancy name: eg Simon Bucks - uint8 public decimals; //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether. - string public symbol; //An identifier: eg SBX - string public version = 'H0.1'; //human 0.1 standard. Just an arbitrary versioning scheme. - - function HumanStandardToken( - uint256 _initialAmount, - string _tokenName, - uint8 _decimalUnits, - string _tokenSymbol - ) { - balances[msg.sender] = _initialAmount; // Give the creator all initial tokens - totalSupply = _initialAmount; // Update total supply - name = _tokenName; // Set the name for display purposes - decimals = _decimalUnits; // Amount of decimals for display purposes - symbol = _tokenSymbol; // Set the symbol for display purposes - } - - /* Approves and then calls the receiving contract */ - function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) { - allowed[msg.sender][_spender] = _value; - Approval(msg.sender, _spender, _value); - - //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this. - //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData) - //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead. - if(!_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData)) { throw; } - return true; - } -} diff --git a/js/src/contracts/snippets/standard-token.sol b/js/src/contracts/snippets/standard-token.sol deleted file mode 100644 index 3d91e5510d2956b13bbb46a979fddea53647af2d..0000000000000000000000000000000000000000 --- a/js/src/contracts/snippets/standard-token.sol +++ /dev/null @@ -1,55 +0,0 @@ -/* -You should inherit from StandardToken or, for a token like you would want to -deploy in something like Mist, see HumanStandardToken.sol. -(This implements ONLY the standard functions and NOTHING else. -If you deploy this, you won't have anything useful.) - -Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20 -.*/ - -import "Token.sol"; - -contract StandardToken is Token { - - function transfer(address _to, uint256 _value) returns (bool success) { - //Default assumes totalSupply can't be over max (2^256 - 1). - //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap. - //Replace the if with this one instead. - //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) { - if (balances[msg.sender] >= _value && _value > 0) { - balances[msg.sender] -= _value; - balances[_to] += _value; - Transfer(msg.sender, _to, _value); - return true; - } else { return false; } - } - - function transferFrom(address _from, address _to, uint256 _value) returns (bool success) { - //same as above. Replace this line with the following if you want to protect against wrapping uints. - //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) { - if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) { - balances[_to] += _value; - balances[_from] -= _value; - allowed[_from][msg.sender] -= _value; - Transfer(_from, _to, _value); - return true; - } else { return false; } - } - - function balanceOf(address _owner) constant returns (uint256 balance) { - return balances[_owner]; - } - - function approve(address _spender, uint256 _value) returns (bool success) { - allowed[msg.sender][_spender] = _value; - Approval(msg.sender, _spender, _value); - return true; - } - - function allowance(address _owner, address _spender) constant returns (uint256 remaining) { - return allowed[_owner][_spender]; - } - - mapping (address => uint256) balances; - mapping (address => mapping (address => uint256)) allowed; -} diff --git a/js/src/contracts/snippets/token.sol b/js/src/contracts/snippets/token.sol deleted file mode 100644 index d54c5c42434c10a36bfafc80cf6781b28896a40b..0000000000000000000000000000000000000000 --- a/js/src/contracts/snippets/token.sol +++ /dev/null @@ -1,47 +0,0 @@ -// Abstract contract for the full ERC 20 Token standard -// https://github.com/ethereum/EIPs/issues/20 - -contract Token { - /* This is a slight change to the ERC20 base standard. - function totalSupply() constant returns (uint256 supply); - is replaced with: - uint256 public totalSupply; - This automatically creates a getter function for the totalSupply. - This is moved to the base contract since public getter functions are not - currently recognised as an implementation of the matching abstract - function by the compiler. - */ - /// total amount of tokens - uint256 public totalSupply; - - /// @param _owner The address from which the balance will be retrieved - /// @return The balance - function balanceOf(address _owner) constant returns (uint256 balance); - - /// @notice send `_value` token to `_to` from `msg.sender` - /// @param _to The address of the recipient - /// @param _value The amount of token to be transferred - /// @return Whether the transfer was successful or not - function transfer(address _to, uint256 _value) returns (bool success); - - /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` - /// @param _from The address of the sender - /// @param _to The address of the recipient - /// @param _value The amount of token to be transferred - /// @return Whether the transfer was successful or not - function transferFrom(address _from, address _to, uint256 _value) returns (bool success); - - /// @notice `msg.sender` approves `_addr` to spend `_value` tokens - /// @param _spender The address of the account able to transfer the tokens - /// @param _value The amount of wei to be approved for transfer - /// @return Whether the approval was successful or not - function approve(address _spender, uint256 _value) returns (bool success); - - /// @param _owner The address of the account owning tokens - /// @param _spender The address of the account able to transfer the tokens - /// @return Amount of remaining tokens allowed to spent - function allowance(address _owner, address _spender) constant returns (uint256 remaining); - - event Transfer(address indexed _from, address indexed _to, uint256 _value); - event Approval(address indexed _owner, address indexed _spender, uint256 _value); -} diff --git a/js/src/contracts/snippets/wallet.sol b/js/src/contracts/snippets/wallet.sol deleted file mode 100644 index a8f1ba93872c20c659978347eff0130480ee51d6..0000000000000000000000000000000000000000 --- a/js/src/contracts/snippets/wallet.sol +++ /dev/null @@ -1,403 +0,0 @@ -//sol Wallet -// Multi-sig, daily-limited account proxy/wallet. -// @authors: -// Gav Wood -// inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a -// single, or, crucially, each of a number of, designated owners. -// usage: -// use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by -// some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the -// interior is executed. - -pragma solidity ^0.4.9; - -contract multiowned { - - // TYPES - - // struct for the status of a pending operation. - struct PendingState { - uint yetNeeded; - uint ownersDone; - uint index; - } - - // EVENTS - - // this contract only has six types of events: it can accept a confirmation, in which case - // we record owner and operation (hash) alongside it. - event Confirmation(address owner, bytes32 operation); - event Revoke(address owner, bytes32 operation); - // some others are in the case of an owner changing. - event OwnerChanged(address oldOwner, address newOwner); - event OwnerAdded(address newOwner); - event OwnerRemoved(address oldOwner); - // the last one is emitted if the required signatures change - event RequirementChanged(uint newRequirement); - - // MODIFIERS - - // simple single-sig function modifier. - modifier onlyowner { - if (isOwner(msg.sender)) - _; - } - // multi-sig function modifier: the operation must have an intrinsic hash in order - // that later attempts can be realised as the same underlying operation and - // thus count as confirmations. - modifier onlymanyowners(bytes32 _operation) { - if (confirmAndCheck(_operation)) - _; - } - - // METHODS - - // constructor is given number of sigs required to do protected "onlymanyowners" transactions - // as well as the selection of addresses capable of confirming them. - function multiowned(address[] _owners, uint _required) { - m_numOwners = _owners.length + 1; - m_owners[1] = uint(msg.sender); - m_ownerIndex[uint(msg.sender)] = 1; - for (uint i = 0; i < _owners.length; ++i) - { - m_owners[2 + i] = uint(_owners[i]); - m_ownerIndex[uint(_owners[i])] = 2 + i; - } - m_required = _required; - } - - // Revokes a prior confirmation of the given operation - function revoke(bytes32 _operation) external { - uint ownerIndex = m_ownerIndex[uint(msg.sender)]; - // make sure they're an owner - if (ownerIndex == 0) return; - uint ownerIndexBit = 2**ownerIndex; - var pending = m_pending[_operation]; - if (pending.ownersDone & ownerIndexBit > 0) { - pending.yetNeeded++; - pending.ownersDone -= ownerIndexBit; - Revoke(msg.sender, _operation); - } - } - - // Replaces an owner `_from` with another `_to`. - function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_to)) return; - uint ownerIndex = m_ownerIndex[uint(_from)]; - if (ownerIndex == 0) return; - - clearPending(); - m_owners[ownerIndex] = uint(_to); - m_ownerIndex[uint(_from)] = 0; - m_ownerIndex[uint(_to)] = ownerIndex; - OwnerChanged(_from, _to); - } - - function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - if (isOwner(_owner)) return; - - clearPending(); - if (m_numOwners >= c_maxOwners) - reorganizeOwners(); - if (m_numOwners >= c_maxOwners) - return; - m_numOwners++; - m_owners[m_numOwners] = uint(_owner); - m_ownerIndex[uint(_owner)] = m_numOwners; - OwnerAdded(_owner); - } - - function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external { - uint ownerIndex = m_ownerIndex[uint(_owner)]; - if (ownerIndex == 0) return; - if (m_required > m_numOwners - 1) return; - - m_owners[ownerIndex] = 0; - m_ownerIndex[uint(_owner)] = 0; - clearPending(); - reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot - OwnerRemoved(_owner); - } - - function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external { - if (_newRequired > m_numOwners) return; - m_required = _newRequired; - clearPending(); - RequirementChanged(_newRequired); - } - - // Gets an owner by 0-indexed position (using numOwners as the count) - function getOwner(uint ownerIndex) external constant returns (address) { - return address(m_owners[ownerIndex + 1]); - } - - function isOwner(address _addr) constant returns (bool) { - return m_ownerIndex[uint(_addr)] > 0; - } - - function hasConfirmed(bytes32 _operation, address _owner) constant returns (bool) { - var pending = m_pending[_operation]; - uint ownerIndex = m_ownerIndex[uint(_owner)]; - - // make sure they're an owner - if (ownerIndex == 0) return false; - - // determine the bit to set for this owner. - uint ownerIndexBit = 2**ownerIndex; - return !(pending.ownersDone & ownerIndexBit == 0); - } - - // INTERNAL METHODS - - function confirmAndCheck(bytes32 _operation) internal returns (bool) { - // determine what index the present sender is: - uint ownerIndex = m_ownerIndex[uint(msg.sender)]; - // make sure they're an owner - if (ownerIndex == 0) return; - - var pending = m_pending[_operation]; - // if we're not yet working on this operation, switch over and reset the confirmation status. - if (pending.yetNeeded == 0) { - // reset count of confirmations needed. - pending.yetNeeded = m_required; - // reset which owners have confirmed (none) - set our bitmap to 0. - pending.ownersDone = 0; - pending.index = m_pendingIndex.length++; - m_pendingIndex[pending.index] = _operation; - } - // determine the bit to set for this owner. - uint ownerIndexBit = 2**ownerIndex; - // make sure we (the message sender) haven't confirmed this operation previously. - if (pending.ownersDone & ownerIndexBit == 0) { - Confirmation(msg.sender, _operation); - // ok - check if count is enough to go ahead. - if (pending.yetNeeded <= 1) { - // enough confirmations: reset and run interior. - delete m_pendingIndex[m_pending[_operation].index]; - delete m_pending[_operation]; - return true; - } - else - { - // not enough: record that this owner in particular confirmed. - pending.yetNeeded--; - pending.ownersDone |= ownerIndexBit; - } - } - } - - function reorganizeOwners() private { - uint free = 1; - while (free < m_numOwners) - { - while (free < m_numOwners && m_owners[free] != 0) free++; - while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--; - if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0) - { - m_owners[free] = m_owners[m_numOwners]; - m_ownerIndex[m_owners[free]] = free; - m_owners[m_numOwners] = 0; - } - } - } - - function clearPending() internal { - uint length = m_pendingIndex.length; - for (uint i = 0; i < length; ++i) - if (m_pendingIndex[i] != 0) - delete m_pending[m_pendingIndex[i]]; - delete m_pendingIndex; - } - - // FIELDS - - // the number of owners that must confirm the same operation before it is run. - uint public m_required; - // pointer used to find a free slot in m_owners - uint public m_numOwners; - - // list of owners - uint[256] m_owners; - uint constant c_maxOwners = 250; - // index on the list of owners to allow reverse lookup - mapping(uint => uint) m_ownerIndex; - // the ongoing operations. - mapping(bytes32 => PendingState) m_pending; - bytes32[] m_pendingIndex; -} - -// inheritable "property" contract that enables methods to be protected by placing a linear limit (specifiable) -// on a particular resource per calendar day. is multiowned to allow the limit to be altered. resource that method -// uses is specified in the modifier. -contract daylimit is multiowned { - - // METHODS - - // constructor - stores initial daily limit and records the present day's index. - function daylimit(uint _limit) { - m_dailyLimit = _limit; - m_lastDay = today(); - } - // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. - function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external { - m_dailyLimit = _newLimit; - } - // resets the amount already spent today. needs many of the owners to confirm. - function resetSpentToday() onlymanyowners(sha3(msg.data)) external { - m_spentToday = 0; - } - - // INTERNAL METHODS - - // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and - // returns true. otherwise just returns false. - function underLimit(uint _value) internal onlyowner returns (bool) { - // reset the spend limit if we're on a different day to last time. - if (today() > m_lastDay) { - m_spentToday = 0; - m_lastDay = today(); - } - // check to see if there's enough left - if so, subtract and return true. - // overflow protection // dailyLimit check - if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) { - m_spentToday += _value; - return true; - } - return false; - } - // determines today's index. - function today() private constant returns (uint) { return now / 1 days; } - - // FIELDS - - uint public m_dailyLimit; - uint public m_spentToday; - uint public m_lastDay; -} - -// interface contract for multisig proxy contracts; see below for docs. -contract multisig { - - // EVENTS - - // logged events: - // Funds has arrived into the wallet (record how much). - event Deposit(address _from, uint value); - // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). - event SingleTransact(address owner, uint value, address to, bytes data, address created); - // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). - event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data, address created); - // Confirmation still needed for a transaction. - event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); - - // FUNCTIONS - - // TODO: document - function execute(address _to, uint _value, bytes _data) external returns (bytes32 o_hash); - function confirm(bytes32 _h) returns (bool o_success); -} - -// usage: -// bytes32 h = Wallet(w).from(oneOwner).execute(to, value, data); -// Wallet(w).from(anotherOwner).confirm(h); -contract Wallet is multisig, multiowned, daylimit { - - // TYPES - - // Transaction structure to remember details of transaction lest it need be saved for a later call. - struct Transaction { - address to; - uint value; - bytes data; - } - - // METHODS - - // constructor - just pass on the owner array to the multiowned and - // the limit to daylimit - function Wallet(address[] _owners, uint _required, uint _daylimit) - multiowned(_owners, _required) daylimit(_daylimit) { - } - - // kills the contract sending everything to `_to`. - function kill(address _to) onlymanyowners(sha3(msg.data)) external { - suicide(_to); - } - - // gets called when no other function matches - function() payable { - // just being sent some cash? - if (msg.value > 0) - Deposit(msg.sender, msg.value); - } - - // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit. - // If not, goes into multisig process. We provide a hash on return to allow the sender to provide - // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value - // and _data arguments). They still get the option of using them if they want, anyways. - function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 o_hash) { - // first, take the opportunity to check that we're under the daily limit. - if ((_data.length == 0 && underLimit(_value)) || m_required == 1) { - // yes - just execute the call. - address created; - if (_to == 0) { - created = create(_value, _data); - } else { - if (!_to.call.value(_value)(_data)) - throw; - } - SingleTransact(msg.sender, _value, _to, _data, created); - } else { - // determine our operation hash. - o_hash = sha3(msg.data, block.number); - // store if it's new - if (m_txs[o_hash].to == 0 && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) { - m_txs[o_hash].to = _to; - m_txs[o_hash].value = _value; - m_txs[o_hash].data = _data; - } - if (!confirm(o_hash)) { - ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data); - } - } - } - - function create(uint _value, bytes _code) internal returns (address o_addr) { - assembly { - o_addr := create(_value, add(_code, 0x20), mload(_code)) - jumpi(invalidJumpLabel, iszero(extcodesize(o_addr))) - } - } - - // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order - // to determine the body of the transaction from the hash provided. - function confirm(bytes32 _h) onlymanyowners(_h) returns (bool o_success) { - if (m_txs[_h].to != 0 || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) { - address created; - if (m_txs[_h].to == 0) { - created = create(m_txs[_h].value, m_txs[_h].data); - } else { - if (!m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data)) - throw; - } - - MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created); - delete m_txs[_h]; - return true; - } - } - - // INTERNAL METHODS - - function clearPending() internal { - uint length = m_pendingIndex.length; - for (uint i = 0; i < length; ++i) - delete m_txs[m_pendingIndex[i]]; - super.clearPending(); - } - - // FIELDS - - // pending transactions we have at present. - mapping (bytes32 => Transaction) m_txs; -} diff --git a/js/src/contracts/tokenreg.js b/js/src/contracts/tokenreg.js deleted file mode 100644 index 2bbf639bfd342d1c29739a5e612b9b398853726b..0000000000000000000000000000000000000000 --- a/js/src/contracts/tokenreg.js +++ /dev/null @@ -1,44 +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 . - -export default class TokenReg { - constructor (api, registry) { - this._api = api; - this._registry = registry; - - this.getInstance(); - } - - getContract () { - return this._registry.getContract('tokenreg'); - } - - getInstance () { - return this.getContract().then((contract) => contract.instance); - } - - tokenCount () { - return this.getInstance().then((instance) => { - return instance.tokenCount.call(); - }); - } - - token (index) { - return this.getInstance().then((instance) => { - return instance.token.call({}, [index]); - }); - } -} diff --git a/js/src/contracts/verification.js b/js/src/contracts/verification.js deleted file mode 100644 index 8101565dbdbeb748b4e39065ec7b778e91f7bec6..0000000000000000000000000000000000000000 --- a/js/src/contracts/verification.js +++ /dev/null @@ -1,88 +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 . - -import subscribeToEvents from '../util/subscribe-to-events'; - -export const checkIfVerified = (contract, account) => { - return contract.instance.certified.call({}, [account]); -}; - -export const findLastRequested = (contract, account) => { - let subId = null; - let resolved = false; - - return new Promise((resolve, reject) => { - contract - .subscribe('Requested', { - fromBlock: 0, - toBlock: 'pending', - limit: 1, - topics: [account] - }, (err, logs) => { - if (err) { - return reject(err); - } - - resolve(logs[0] || null); - resolved = true; - - if (subId) { - contract.unsubscribe(subId); - } - }) - .then((_subId) => { - subId = _subId; - - if (resolved) { - contract.unsubscribe(subId); - } - }); - }); -}; - -const blockNumber = (api) => { - return new Promise((resolve, reject) => { - api.subscribe('eth_blockNumber', (err, block) => { - if (err) { - return reject(err); - } - resolve(block); - }) - .then((subscription) => { - api.unsubscribe(subscription); - }) - .catch(reject); - }); -}; - -export const awaitPuzzle = (api, contract, account) => { - return blockNumber(api) - .then((block) => { - return new Promise((resolve, reject) => { - const subscription = subscribeToEvents(contract, ['Puzzled'], { - from: block.toNumber(), - filter: (log) => log.params.who.value === account - }); - - subscription.once('error', reject); - subscription.once('log', subscription.unsubscribe); - subscription.once('log', resolve); - subscription.once('timeout', () => { - reject(new Error('Timed out waiting for the puzzle.')); - }); - }); - }); -}; diff --git a/js/src/dapps/chaindeploy.js b/js/src/dapps/chaindeploy.js deleted file mode 100644 index c3dd420085af151b3623b9f19947b058f88038fa..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy.js +++ /dev/null @@ -1,29 +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 . - -import ReactDOM from 'react-dom'; -import React from 'react'; - -import Application from './chaindeploy/Application'; - -import '../../assets/fonts/Roboto/font.css'; -import '../../assets/fonts/RobotoMono/font.css'; -import './style.css'; - -ReactDOM.render( - , - document.querySelector('#container') -); diff --git a/js/src/dapps/chaindeploy/Application/application.css b/js/src/dapps/chaindeploy/Application/application.css deleted file mode 100644 index f6db5da2919079ca82b17ae52f0487a79aa877bb..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Application/application.css +++ /dev/null @@ -1,78 +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 . -*/ - -.body { - font-size: 0.8em; - - .buttons { - position: fixed; - right: 0.5em; - top: 0.5em; - z-index: 100; - - button { - background: rgb(0, 200, 255); - border: 2px solid rgba(0, 200, 255, 0.5); - border-radius: 0.25em; - color: white; - cursor: pointer; - font-size: 1em; - margin: 0 0 0 0.5em; - outline: none; - padding: 0.75em 1.5em; - white-space: nowrap; - - &:disabled { - background: rgb(230, 230, 230); - border: 2px solid rgba(230, 230, 230, 0.5); - cursor: default; - } - - .icon { - fill: white !important; - margin-right: 0.5em; - } - - .text { - display: inline-block; - line-height: 24px; - vertical-align: top; - } - } - } - - .section { - margin: 0 1em 3em 1em; - - h3 { - background: rgba(0, 0, 0, 0.025); - border-radius: 0.25em; - padding: 0.75em 1em; - margin-bottom: 0.5em; - - small { - vertical-align: middle; - } - } - - .list { - display: flex; - flex-direction: row; - flex-wrap: wrap; - } - } -} diff --git a/js/src/dapps/chaindeploy/Application/application.js b/js/src/dapps/chaindeploy/Application/application.js deleted file mode 100644 index 9e6fa588f6de03da37d62a746b6009735198642d..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Application/application.js +++ /dev/null @@ -1,178 +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 . - -import { observer } from 'mobx-react'; -import React, { Component } from 'react'; - -import Contract from '../Contract'; -import Dapp from '../Dapp'; -import Store from '../store'; - -import styles from './application.css'; - -@observer -export default class Application extends Component { - store = new Store(); - - render () { - return ( -
- { this.renderContracts(false) } - { this.renderContracts(true) } - { this.renderApps() } - { this.renderContracts(false, true) } - { this.renderApps(true) } - { this.renderButtons() } -
- ); - } - - renderButton (text, clickHandler, disabled) { - const onClick = (event) => { - if (!disabled) { - clickHandler(event); - } - }; - - return ( - - ); - } - - renderButtons () { - const { contractBadgereg, contractDappreg, isBadgeDeploying, isContractDeploying, isDappDeploying, haveAllBadges, haveAllContracts, haveAllDapps, registry } = this.store; - const disableRegistry = registry.address || registry.isDeploying; - const disableContracts = !registry.address || isContractDeploying || haveAllContracts; - const disableDapps = !contractDappreg.address || isDappDeploying || haveAllDapps; - const disableBadges = !registry.address || !contractBadgereg.address || isBadgeDeploying || haveAllBadges; - - return ( -
- { this.renderButton('registry', this.deployRegistry, disableRegistry) } - { this.renderButton('contracts', this.deployContracts, disableContracts) } - { this.renderButton('badges', this.deployBadges, disableBadges) } - { this.renderButton('apps', this.deployApps, disableDapps) } -
- ); - } - - renderContracts (isBadges, isExternal) { - const { badges, contracts, contractBadgereg, registry } = this.store; - const regaddress = isBadges - ? contractBadgereg.address - : registry.address; - - return ( -
-

- { - isExternal - ? 'External ' - : '' - }{ - isBadges - ? 'Badges ' - : 'Contracts ' - }(registry { regaddress || 'unknown' }) -

-
- { - isExternal || isBadges - ? null - : ( - - ) - } - { - (isBadges ? badges : contracts) - .filter((contract) => contract.isExternal === isExternal) - .map((contract) => { - return ( - - ); - }) - } -
-
- ); - } - - renderApps (isExternal) { - const { apps, contractDappreg, contractGithubhint } = this.store; - const isDisabled = !contractDappreg.isOnChain || !contractGithubhint.isOnChain; - - return ( -
-

- { - isExternal - ? 'External ' - : '' - }Applications (registry { - contractDappreg.address - ? contractDappreg.address - : 'unknown' - }) -

-
- { - apps - .filter((app) => app.isExternal === isExternal) - .map((app) => { - return ( - - ); - }) - } -
-
- ); - } - - deployApps = () => { - return this.store.deployApps(); - } - - deployBadges = () => { - return this.store.deployBadges(); - } - - deployContracts = () => { - return this.store.deployContracts(); - } - - deployRegistry = () => { - return this.store.deployRegistry(); - } -} diff --git a/js/src/dapps/chaindeploy/Application/index.js b/js/src/dapps/chaindeploy/Application/index.js deleted file mode 100644 index 3d8d1ca3b851e5bfed73373e82eff06b5d9ea46c..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Application/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './application'; diff --git a/js/src/dapps/chaindeploy/Contract/contract.js b/js/src/dapps/chaindeploy/Contract/contract.js deleted file mode 100644 index 1f0b158d2b49ee843a5a415038874b1e4ee29b13..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Contract/contract.js +++ /dev/null @@ -1,132 +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 . - -import React, { Component, PropTypes } from 'react'; - -import ListItem, { Header, Row } from '../ListItem'; - -export default class Contract extends Component { - static propTypes = { - contract: PropTypes.object.isRequired, - disabled: PropTypes.bool - } - - render () { - const { contract, disabled } = this.props; - const location = contract.id === 'registry' - ? 'chain' - : 'registry'; - - return ( - -
- { contract.id } was { - contract.address - ? 'deployed' - : 'not found' - } -
- - { - contract.address - ? contract.address - : 'no address' - } - - - { - contract.hasLatestCode - ? 'has latest available code' - : 'does not have latest code' - } - - - { - contract.isOnChain - ? `registered on ${location}` - : `not registered on ${location}` - } - - { this.renderBadgeInfo() } -
- ); - } - - renderBadgeInfo () { - const { contract } = this.props; - - if (!contract.isBadge) { - return null; - } - - return [ - - { - contract.isBadgeRegistered - ? 'found in badgereg' - : 'not found in badgereg' - } - , - - { - contract.badgeImageHash - ? `badge imageHash ${contract.badgeImageHash}` - : 'has not registered a badge imageHash' - } - , - - { - contract.badgeImageMatch - ? 'has latest badge imageHash' - : 'does not have latest badge imageHash' - } - - ]; - } -} diff --git a/js/src/dapps/chaindeploy/Contract/index.js b/js/src/dapps/chaindeploy/Contract/index.js deleted file mode 100644 index 74c58e942d4f23ba7637a544b403a1e1f88ffb37..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Contract/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './contract'; diff --git a/js/src/dapps/chaindeploy/Dapp/dapp.js b/js/src/dapps/chaindeploy/Dapp/dapp.js deleted file mode 100644 index 5a997c295afd827273421839d6194e45ec5189d8..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Dapp/dapp.js +++ /dev/null @@ -1,98 +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 . - -import React, { Component, PropTypes } from 'react'; - -import ListItem, { Header, Row } from '../ListItem'; - -export default class Dapp extends Component { - static propTypes = { - dapp: PropTypes.object.isRequired, - disabled: PropTypes.bool - } - - render () { - const { dapp, disabled } = this.props; - - return ( - -
- { dapp.name } -
- - { - dapp.isOnChain - ? 'found in dappreg' - : 'not found in dappreg' - } - - { this.renderHash(dapp, 'image') } - { this.renderHash(dapp, 'manifest') } - { this.renderHash(dapp, 'content') } -
- ); - } - - renderHash (dapp, type) { - if (!dapp.source[`${type}Hash`]) { - return null; - } - - const isMatch = dapp[`${type}Match`]; - const hash = dapp[`${type}Hash`]; - - return [ - - { - hash - ? `${type}Hash ${hash}` - : `has not registered an ${type}Hash` - } - , - - { - isMatch - ? `has latest ${type}Hash` - : `does not have latest ${type}Hash` - } - - ]; - } -} diff --git a/js/src/dapps/chaindeploy/Dapp/index.js b/js/src/dapps/chaindeploy/Dapp/index.js deleted file mode 100644 index 3d32813894b4befb9df2b554942ed8998f7bc49b..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/Dapp/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './dapp'; diff --git a/js/src/dapps/chaindeploy/ListItem/Header/header.js b/js/src/dapps/chaindeploy/ListItem/Header/header.js deleted file mode 100644 index e9be01eeab406226b8ef37fcb3762736ffa2f53f..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/Header/header.js +++ /dev/null @@ -1,45 +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 . - -import React, { Component, PropTypes } from 'react'; - -import Icon from '../Icon'; - -import styles from '../listItem.css'; - -export default class Header extends Component { - static propTypes = { - children: PropTypes.node.isRequired, - isBusy: PropTypes.bool, - isOk: PropTypes.bool - } - - render () { - const { children, isBusy, isOk } = this.props; - - return ( -
- -
- { children } -
-
- ); - } -} diff --git a/js/src/dapps/chaindeploy/ListItem/Header/index.js b/js/src/dapps/chaindeploy/ListItem/Header/index.js deleted file mode 100644 index aef90266f940a3c7f8915c7ba910b62bec54317c..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/Header/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './header'; diff --git a/js/src/dapps/chaindeploy/ListItem/Icon/icon.js b/js/src/dapps/chaindeploy/ListItem/Icon/icon.js deleted file mode 100644 index 1f32622e54c4d013edc0e6f26dc4d9a893ab2f03..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/Icon/icon.js +++ /dev/null @@ -1,53 +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 . - -import React, { Component, PropTypes } from 'react'; - -import styles from '../listItem.css'; - -export default class Icon extends Component { - static propTypes = { - isBusy: PropTypes.bool, - isOk: PropTypes.bool - } - - render () { - const { isBusy, isOk } = this.props; - - return ( -
- { - isOk - ? '\u2714' - : ( - isBusy - ? '\u29d6' - : '\u2716' - ) - } -
- ); - } -} diff --git a/js/src/dapps/chaindeploy/ListItem/Icon/index.js b/js/src/dapps/chaindeploy/ListItem/Icon/index.js deleted file mode 100644 index f43e02c49782af1cde49703f410b789d056b29d0..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/Icon/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './icon'; diff --git a/js/src/dapps/chaindeploy/ListItem/Row/index.js b/js/src/dapps/chaindeploy/ListItem/Row/index.js deleted file mode 100644 index 5f2c62dee40946e0794e10be34bbc9374435c2e2..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/Row/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './row'; diff --git a/js/src/dapps/chaindeploy/ListItem/Row/row.js b/js/src/dapps/chaindeploy/ListItem/Row/row.js deleted file mode 100644 index 0982e0321b0c1a1cb2dd49da3945152c9392ebf6..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/Row/row.js +++ /dev/null @@ -1,54 +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 . - -import React, { Component, PropTypes } from 'react'; - -import Icon from '../Icon'; - -import styles from '../listItem.css'; - -export default class Row extends Component { - static propTypes = { - children: PropTypes.node.isRequired, - disabled: PropTypes.bool, - isBusy: PropTypes.bool, - isOk: PropTypes.bool - } - - render () { - const { children, disabled, isBusy, isOk } = this.props; - - return ( -
- -
- { children } -
-
- ); - } -} diff --git a/js/src/dapps/chaindeploy/ListItem/index.js b/js/src/dapps/chaindeploy/ListItem/index.js deleted file mode 100644 index 7c79e3241c49c0215f637097706c87f375616988..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/index.js +++ /dev/null @@ -1,20 +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 . - -export Header from './Header'; -export Row from './Row'; - -export default from './listItem'; diff --git a/js/src/dapps/chaindeploy/ListItem/listItem.css b/js/src/dapps/chaindeploy/ListItem/listItem.css deleted file mode 100644 index 47d6d481d27b69e206eea6e3931043360642a4d0..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/listItem.css +++ /dev/null @@ -1,94 +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 . -*/ - -.listItem { - box-sizing: border-box; - flex: 0 1 33.33%; - max-width: 33.33%; - padding: 0.5em; - position: relative; - - .body { - background: rgba(0, 0, 0, 0.025); - border-radius: 0.25em; - box-sizing: border-box; - display: flex; - flex-direction: column; - flex-wrap: nowrap; - overflow: hidden; - padding: 0.75em; - } - - .status { - background: #f80; - border-radius: 0.25em; - color: white; - font-size: 0.75em; - line-height: 1em; - opacity: 0.9; - padding: 0.5em; - position: absolute; - right: 1em; - top: 1em; - } -} - -.header, -.details { - display: flex; - line-height: 1.5em; - padding: 0.125em 0; - position: relative; - white-space: nowrap; - - .title { - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: top; - } -} - -.details { - margin-left: 2em; -} - -.icon { - border-radius: 0.25em; - display: inline-block; - flex: 0 0 1.5em; - height: 1.5em; - margin-right: 0.5em; - opacity: 0.75; - text-align: center; - vertical-align: middle; - width: 1.5em; - - &.error { - box-shadow: inset 0 0 0 2px rgb(200, 0, 0); - color: rgb(200, 0, 0); - } - - &.ok { - box-shadow: inset 0 0 0 2px rgb(0, 200, 0); - color: rgb(0, 200, 0); - } -} - -.muted { - opacity: 0.25; -} diff --git a/js/src/dapps/chaindeploy/ListItem/listItem.js b/js/src/dapps/chaindeploy/ListItem/listItem.js deleted file mode 100644 index c670123f9241a1c24ea0145857910c89a6ff2459..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/ListItem/listItem.js +++ /dev/null @@ -1,63 +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 . - -import React, { Component, PropTypes } from 'react'; - -import styles from './listItem.css'; - -export default class ListItem extends Component { - static propTypes = { - children: PropTypes.node.isRequired, - disabled: PropTypes.bool, - status: PropTypes.string - } - - render () { - const { children, disabled } = this.props; - - return ( -
-
- { children } -
- { this.renderStatus() } -
- ); - } - - renderStatus () { - const { status } = this.props; - - if (!status) { - return null; - } - - return ( -
- { status } -
- ); - } -} diff --git a/js/src/dapps/chaindeploy/_dapps.js b/js/src/dapps/chaindeploy/_dapps.js deleted file mode 100644 index 4a8da242f680d611ecea7f66324068a3a11ac0ce..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/_dapps.js +++ /dev/null @@ -1,43 +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 . - -import builtinsJson from '~/views/Dapps/builtin.json'; - -const REGISTER_URLS = { - console: 'https://raw.githubusercontent.com/paritytech/console/3ea0dbfefded359ccdbea37bc4cf350c0aa16948/console.jpeg', - dappreg: 'https://raw.githubusercontent.com/paritytech/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/legos-64x64.png', - githubhint: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/link-64x64.jpg', - localtx: 'https://raw.githubusercontent.com/paritytech/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/stack-64x64.png', - registry: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/register-64x64.jpg', - signaturereg: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/hex-64x64.jpg', - tokendeploy: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/interlock-64x64.png', - tokenreg: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/coins-64x64.jpg', - web: 'https://raw.githubusercontent.com/paritytech/dapp-assets/ec6138115d0e1f45258969cd90b3b274e0ff2258/dapps/earth-64x64.jpg' -}; - -const builtins = builtinsJson - .filter((app) => app.id) - .map((app) => { - app.source = { - imageUrl: REGISTER_URLS[app.id] - }; - - return app; - }); - -export { - builtins -}; diff --git a/js/src/dapps/chaindeploy/contracts/abi/jg-voting.json b/js/src/dapps/chaindeploy/contracts/abi/jg-voting.json deleted file mode 100644 index 83a07ef7cbefb4e69d23dee9765dc2dd108229e1..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/abi/jg-voting.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":true,"inputs":[],"name":"count","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalVotes","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"hasSenderVoted","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint256"},{"name":"_answer","type":"uint256"}],"name":"newAnswer","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setQuestionFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"questionFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_index","type":"uint256"}],"name":"get","outputs":[{"name":"closed","type":"bool"},{"name":"owner","type":"address"},{"name":"question","type":"string"},{"name":"balanceNo","type":"uint256"},{"name":"balanceYes","type":"uint256"},{"name":"balanceMaybe","type":"uint256"},{"name":"votesNo","type":"uint256"},{"name":"votesYes","type":"uint256"},{"name":"votesMaybe","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_question","type":"string"}],"name":"newQuestion","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"totalBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"answerFee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_index","type":"uint256"}],"name":"closeQuestion","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setAnswerFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"index","type":"uint256"},{"indexed":false,"name":"question","type":"string"}],"name":"NewQuestion","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"index","type":"uint256"},{"indexed":true,"name":"answer","type":"uint256"},{"indexed":false,"name":"value","type":"uint256"}],"name":"NewAnswer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] diff --git a/js/src/dapps/chaindeploy/contracts/badgereg.js b/js/src/dapps/chaindeploy/contracts/badgereg.js deleted file mode 100644 index ccd6b28c19b32faa0736e352cd78cafb30664af5..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/badgereg.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/badgereg'; -import { compiler, source as sourceUrl, output as byteCode } from './code/badgereg'; - -const id = 'badgereg'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/code/badgereg.json b/js/src/dapps/chaindeploy/contracts/code/badgereg.json deleted file mode 100644 index e7801722a43c1f4e0abb7e58d8da9c7bba223145..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/badgereg.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/BadgeReg.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600455341561003357fe5b5b610a6f806100436000396000f300606060405236156100bf5763ffffffff60e060020a60003504166313af403581146100c15780631e7a505f146100df5780632c0f5f591461010a5780635b8066451461014557806369fe0e2d146101675780637958533a1461017c5780638da5cb5b146101a45780639890220b146101d0578063a02b161e146101e2578063ac4ce2c6146101f7578063b72e717d14610218578063c0f6faed1461025b578063dd93890b14610299578063ddbcb5cb146102b4578063ddca3f43146102e6575bfe5b34156100c957fe5b6100dd600160a060020a0360043516610308565b005b6100f6600160a060020a036004351660243561037c565b604080519115158252519081900360200190f35b341561011257fe5b61011d600435610392565b60408051938452600160a060020a039283166020850152911682820152519081900360600190f35b341561014d57fe5b6101556103ef565b60408051918252519081900360200190f35b341561016f57fe5b6100dd6004356103f6565b005b341561018457fe5b61015560043560243561041b565b60408051918252519081900360200190f35b34156101ac57fe5b6101b461045a565b60408051600160a060020a039092168252519081900360200190f35b34156101d857fe5b6100dd610469565b005b34156101ea57fe5b6100dd6004356104bc565b005b34156101ff57fe5b6100dd600435600160a060020a03602435166105ee565b005b341561022057fe5b610234600160a060020a0360043516610721565b604080519384526020840192909252600160a060020a031682820152519081900360600190f35b341561026357fe5b61026e600435610789565b60408051600160a060020a039485168152602081019390935292168183015290519081900360600190f35b34156102a157fe5b6100dd6004356024356044356107dc565b005b6100f6600160a060020a036004358116906024359060443516610899565b604080519115158252519081900360200190f35b34156102ee57fe5b6101556109cc565b60408051918252519081900360200190f35b60005433600160a060020a0390811691161461032357610378565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b6000610389838333610899565b90505b92915050565b60008181526002602052604081205460038054600019909201929182918291859081106103bb57fe5b906000526020600020906004020160005b5080546002820154600160a060020a03918216955016925090505b509193909250565b6003545b90565b60005433600160a060020a0390811691161461041157610378565b60048190555b5b50565b600060038381548110151561042c57fe5b906000526020600020906004020160005b506000838152600391909101602052604090205490505b92915050565b600054600160a060020a031681565b60005433600160a060020a03908116911614610484576104b8565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156104b857610000565b5b5b565b60005433600160a060020a039081169116146104d757610378565b806003828154811015156104e757fe5b906000526020600020906004020160005b50600101546040517f844e89a9d524dabb877007aa0e9c395e8938fcfee93ece70c2cd0353db79c8e590600090a36001600060038381548110151561053957fe5b906000526020600020906004020160005b5054600160a060020a03168152602081019190915260400160009081208190556003805460029291908490811061057d57fe5b906000526020600020906004020160005b50600101548152602081019190915260400160009081205560038054829081106105b457fe5b906000526020600020906004020160005b508054600160a060020a03199081168255600060018301556002909101805490911690555b5b50565b60008233600160a060020a031660038281548110151561060a57fe5b906000526020600020906004020160005b5060020154600160a060020a0316146106335761071b565b600160a060020a03831660009081526001602052604090205483901561065857610718565b600380548690811061066657fe5b906000526020600020906004020160005b505460038054600160a060020a03909216945085918790811061069657fe5b906000526020600020906004020160005b508054600160a060020a031916600160a060020a039283161790558381166000908152600160209081526040808320839055928716808352918390208890558251918252915187927fa5d871c0e725767cd5aefc99c53aeca35f09dcc268145cbb13b74a7e2f48f196928290030190a25b5b505b50505050565b600160a060020a038116600090815260016020526040812054600380546000199092019291829182918590811061075457fe5b906000526020600020906004020160005b5060018101546002820154909450600160a060020a0316925090505b509193909250565b60006000600060006003858154811015156107a057fe5b906000526020600020906004020160005b50805460018201546002830154600160a060020a03928316975090955016925090505b509193909250565b8233600160a060020a03166003828154811015156107f657fe5b906000526020600020906004020160005b5060020154600160a060020a03161461081f5761071b565b8160038581548110151561082f57fe5b906000526020600020906004020160005b50600085815260039190910160209081526040918290209290925580518481529051859287927f7991c63a749706fd298fc2387764d640be6e714307b6357b1d3c2ce35cba3b52929081900390910190a35b5b50505050565b60006004543410156108aa576109c5565b600160a060020a0384166000908152600160205260409020548490156108cf576109c3565b6000848152600260205260409020548490156108ea576109c0565b60038054600181016108fc83826109d2565b916000526020600020906004020160005b5060408051606081018252600160a060020a03808b1680835260208084018c9052918a169284018390528454600160a060020a03199081168217865560018087018d905560029687018054909216909417905560035460008281529383528484208190558b8452948252918390208490558251918252915160001993909301935088927febbfb6376bef000063e6e33494e4c543a6197091a04eb6a6f55013d85a1c5386929181900390910190a3600192505b5b505b505b9392505050565b60045481565b8154818355818115116109fe576004028160040283600052602060002091820191016109fe9190610a04565b5b505050565b6103f391905b80821115610a3c578054600160a060020a03199081168255600060018301556002820180549091169055600401610a0a565b5090565b905600a165627a7a72305820526fc95faec325cec5dd3e1bb67c165265282c5fc6db21e96197060b823aaa490029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/dappreg.json b/js/src/dapps/chaindeploy/contracts/code/dappreg.json deleted file mode 100644 index 48739a59d282b8aa9397c8a2b677ffa75f223044..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/dappreg.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/225bf022ddd967af2b9ea188e8f611489ca5d7fe/DappReg.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600355341561003357fe5b5b6106ee806100436000396000f300606060405236156100a95763ffffffff60e060020a6000350416630257c48c81146100ab57806306661abd146100d357806313af4035146100f55780631a0919dc1461011357806369fe0e2d146101285780638da5cb5b1461013d5780638eaa6ac01461016957806391cd242d1461019d5780639890220b146101b8578063c52bd836146101ca578063ddca3f43146101eb578063e0886f901461020d578063e1fa8e8414610241575bfe5b34156100b357fe5b6100c160043560243561024e565b60408051918252519081900360200190f35b34156100db57fe5b6100c1610272565b60408051918252519081900360200190f35b34156100fd57fe5b610111600160a060020a0360043516610279565b005b341561011b57fe5b6101116004356102ed565b005b341561013057fe5b610111600435610388565b005b341561014557fe5b61014d6103ad565b60408051600160a060020a039092168252519081900360200190f35b341561017157fe5b61017c6004356103bc565b60408051928352600160a060020a0390911660208301528051918290030190f35b34156101a557fe5b6101116004356024356044356103e4565b005b34156101c057fe5b61011161046d565b005b34156101d257fe5b610111600435600160a060020a03602435166104c0565b005b34156101f357fe5b6100c161054e565b60408051918252519081900360200190f35b341561021557fe5b61017c600435610554565b60408051928352600160a060020a0390911660208301528051918290030190f35b6101116004356105ab565b005b60008281526001602090815260408083208484526002019091529020545b92915050565b6002545b90565b60005433600160a060020a0390811691161461029457610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b60008181526001602081905260409091200154819033600160a060020a0390811691161480159061032d575060005433600160a060020a03908116911614155b1561033757610000565b60008281526001602081905260408083208381559091018054600160a060020a03191690555183917fe17fec26316aebe957e188549d659a89f359c49766bcc0ae2fb7ded274ffe14691a25b5b5050565b60005433600160a060020a039081169116146103a357610000565b60038190555b5b50565b600054600160a060020a031681565b6000818152600160208190526040909120805491810154600160a060020a0316905b50915091565b60008381526001602081905260409091200154839033600160a060020a0390811691161461041157610000565b600084815260016020908152604080832086845260020182529182902084905581518481529151859287927f4dcd4fb147bb133a0da8fbf4e5fc3ddd64f04d4b3f6cbee584374b889d28c78d92918290030190a35b5b50505050565b60005433600160a060020a0390811691161461048857610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156104bc57610000565b5b5b565b60008281526001602081905260409091200154829033600160a060020a039081169116146104ed57610000565b60008381526001602081905260408083209091018054600160a060020a031916600160a060020a0386169081179091559051909185917fd3d10d874a10020c2bce719499d1fd8756d880b128eb2945dd01b3830854e7169190a35b5b505050565b60035481565b6000600060006001600060028681548110151561056d57fe5b906000526020600020900160005b50548152602081019190915260400160002080546001820154909450600160a060020a0316925090505b50915091565b6003543410156105ba57610000565b6000818152600160205260409020548190156105d557610000565b60028054600181016105e78382610677565b916000526020600020900160005b508390555060408051808201825283815233600160a060020a0390811660208084018281526000888152600192839052868120955186559051949091018054600160a060020a0319169490931693909317909155915184917f7d917fcbc9a29a9705ff9936ffa599500e4fd902e4486bae317414fe967b307c91a35b5b505b50565b815481835581811511610548576000838152602090206105489181019083016106a1565b5b505050565b61027691905b808211156106bb57600081556001016106a7565b5090565b905600a165627a7a7230582011d8a45e381635e9de17e14cc4de97a1e17758cfac1fd25e8a5bc1d5f4d1da9d0029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/gavcoin.json b/js/src/dapps/chaindeploy/contracts/code/gavcoin.json deleted file mode 100644 index f0ead4a35d64da94491a929a5e454c3d8e0983ce..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/gavcoin.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/GavCoin.sol", - "output": "0x606060405266038d7ea4c680006002556305f5e100600355341561001f57fe5b5b6108008061002f6000396000f300606060405236156100885763ffffffff60e060020a600035041663095ea7b3811461009f57806318160ddd146100d257806323b872dd146100f457806329cbdc861461012d57806355234ec0146101465780635af36e3e1461016857806370a0823114610192578063a035b1fe146101c0578063a9059cbb146101e2578063dd62ed3e14610215575b61009d5b61009a3360ff60020a610249565b5b565b005b34156100a757fe5b6100be600160a060020a0360043516602435610390565b604080519115158252519081900360200190f35b34156100da57fe5b6100e2610416565b60408051918252519081900360200190f35b34156100fc57fe5b6100be600160a060020a036004358116906024351660443561041c565b604080519115158252519081900360200190f35b61009d600160a060020a036004351660243561052a565b005b341561014e57fe5b6100e2610539565b60408051918252519081900360200190f35b341561017057fe5b6100be60043560243561053f565b604080519115158252519081900360200190f35b341561019a57fe5b6100e2600160a060020a03600435166106d0565b60408051918252519081900360200190f35b34156101c857fe5b6100e26106ef565b60408051918252519081900360200190f35b34156101ea57fe5b6100be600160a060020a03600435166024356106f5565b604080519115158252519081900360200190f35b341561021d57fe5b6100e2600160a060020a03600435811690602435166107a3565b60408051918252519081900360200190f35b34600080805b60008411801561026157508460025411155b1561038757600354600254620f424091025b0492508284116102835783610285565b825b9150600254620f4240830281151561029957fe5b33600160a060020a03166000818152600160208181526040808420805497909604968701865560028054855295830190915280832080548701905584548352808320909101805463ffffffff191662093a80420163ffffffff161790558154850182559254925193945084937f689dcb02b6a65e0e2f1d23ef47c1ec86604ffbed0bcb65f20150cfc7d5e5a9489190a4600380548290039081905593829003931515610382576002805466038d7ea4c6800001908190556305f5e1006003556040517f23c3dae768238f239632b5c4acb89485b440e0fa72481c4aad9f9b4f9b5a0a5f90600090a25b61024f565b5b505050505050565b600082600160a060020a031633600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a350600160a060020a0333811660009081526001602081815260408084209487168452600290940190529190208054830190555b92915050565b60005481565b600160a060020a038316600090815260016020526040812054849083908190101561044657610521565b600160a060020a0380871660009081526001602090815260408083203394851684526002019091529020548791908690819010156104835761051c565b87600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef896040518082815260200191505060405180910390a3600160a060020a03808a166000908152600160208181526040808420338616855260028101835281852080548e900390559183905281548c9003909155928b16825291902080548901905595505b5b5050505b50509392505050565b6105348282610249565b5b5050565b60035481565b600160a060020a0333166000908152600160208181526040808420868552909201905281205483908390819010806105a35750600160a060020a03331660009081526001602081815260408084208685528301909152909120015463ffffffff1642105b156105ad576106c8565b33600160a060020a0381166000908152600160205260409020548590819010156105d6576106c4565b60405186908890600160a060020a033316907f73f04af9dcc582a923ec15d3eea990fe34adabfff2879e28d44572e01a54abb690600090a433600160a060020a0316600090815260016020818152604080842080548b9003815584548b0185558b855290920190529020805487900390819055151561068457600160a060020a03331660009081526001602081815260408084208b85528301909152822091825501805463ffffffff191690555b600160a060020a0333166108fc620f4240888a025b604051919004801590920291906000818181858888f1935050505015156106bf57610000565b600194505b5b50505b505092915050565b600160a060020a0381166000908152600160205260409020545b919050565b60025481565b33600160a060020a038116600090815260016020526040812054909190839081901015610721576106c8565b84600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040518082815260200191505060405180910390a3600160a060020a03338116600090815260016020526040808220805488900390559187168152208054850190555b5b505092915050565b600160a060020a03808316600090815260016020908152604080832093851683526002909301905220545b929150505600a165627a7a72305820ca533a37c92e41888bda66ae0e66415d21a61c60027b269bca633d85b727875c0029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/githubhint.json b/js/src/dapps/chaindeploy/contracts/code/githubhint.json deleted file mode 100644 index 3470ccef0b4f346c233b1280794cfc447b27edd8..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/githubhint.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/GithubHint.sol", - "output": "0x6060604052341561000c57fe5b5b6105868061001c6000396000f300606060405263ffffffff60e060020a60003504166302f2008d81146100425780632196ae0d1461009b578063267b6922146101055780637c8c6643146101c9575bfe5b341561004a57fe5b60408051602060046024803582810135601f810185900485028601850190965285855261009995833595939460449493929092019181908401838280828437509496506101de95505050505050565b005b34156100a357fe5b60408051602060046024803582810135601f81018590048502860185019096528585526100999583359593946044949392909201918190840183828082843750949650505092356bffffffffffffffffffffffff191692506102be915050565b005b341561010d57fe5b6101186004356103b1565b604080516bffffffffffffffffffffffff1984166020820152600160a060020a03831691810191909152606080825284546002600019610100600184161502019091160490820181905281906080820190869080156101b85780601f1061018d576101008083540402835291602001916101b8565b820191906000526020600020905b81548152906001019060200180831161019b57829003601f168201915b505094505050505060405180910390f35b34156101d157fe5b6100996004356103de565b005b6000828152602081905260409020600201548290600160a060020a031615801590610227575060008181526020819052604090206002015433600160a060020a03908116911614155b15610231576102b8565b6040805160608101825283815260006020808301829052600160a060020a0333168385015286825281815292902081518051929391926102749284920190610472565b506020820151600182018054606060020a909204600160a060020a031992831617905560409092015160029091018054600160a060020a0392909216919092161790555b5b505050565b6000838152602081905260409020600201548390600160a060020a031615801590610307575060008181526020819052604090206002015433600160a060020a03908116911614155b15610311576103aa565b604080516060810182528481526bffffffffffffffffffffffff198416602080830191909152600160a060020a0333168284015260008781528082529290922081518051929391926103669284920190610472565b506020820151600182018054606060020a909204600160a060020a031992831617905560409092015160029091018054600160a060020a0392909216919092161790555b5b50505050565b600060208190529081526040902060018101546002820154606060020a90910290600160a060020a031683565b6000818152602081905260409020600201548190600160a060020a031615801590610427575060008181526020819052604090206002015433600160a060020a03908116911614155b156104315761046d565b60008281526020819052604081209061044a82826104f1565b50600181018054600160a060020a03199081169091556002909101805490911690555b5b5050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106104b357805160ff19168380011785556104e0565b828001600101855582156104e0579182015b828111156104e05782518255916020019190600101906104c5565b5b506104ed929150610539565b5090565b50805460018160011615610100020316600290046000825580601f106105175750610535565b601f0160209004906000526020600020908101906105359190610539565b5b50565b61055791905b808211156104ed576000815560010161053f565b5090565b905600a165627a7a72305820a83571409e7b0cc4fe48edd09087f315930ab4e017c62b6d100462285a8f4ae70029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/jg-voting.json b/js/src/dapps/chaindeploy/contracts/code/jg-voting.json deleted file mode 100644 index 08ec4d0ed4b17340d98e9002ccb6be0545d7a637..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/jg-voting.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/jacogr/dapp-voting/blob/9b20754b13b9a387704c0955d88b51d2e0e1896d/src/solidity/Voting.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316178155600281905560038190556004556611c37937e0800060055534156200004057fe5b5b60408051808201909152600781527f48756e6772793f0000000000000000000000000000000000000000000000000060208201526200008e906401000000006200090a6200009682021704565b505b620003af565b60008054819033600160a060020a03908116911614801590620000ba575060055434105b15620000c65762000000565b82600481511080620000d9575060a08151115b15620000e55762000000565b60018054925082810190620000fb908262000244565b50336001838154811015156200010d57fe5b906000526020600020906005020160005b508054600160a060020a03929092166101000261010060a860020a031990921691909117905560018054859190849081106200015657fe5b906000526020600020906005020160005b5060010190805190602001906200018092919062000279565b508133600160a060020a03167f7793f929911ad07e07894a20378f1eccce0fb493486c569d74045731fb583b8e866040518080602001828103825283818151815260200191508051906020019080838360008314620001fc575b805182526020831115620001fc57601f199092019160209182019101620001da565b505050905090810190601f168015620002295780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600192505b5b505b50919050565b8154818355818115116200027357600502816005028360005260206000209182019101620002739190620002ff565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620002bc57805160ff1916838001178555620002ec565b82800160010185558215620002ec579182015b82811115620002ec578251825591602001919060010190620002cf565b5b50620002fb9291506200033f565b5090565b6200033c91905b80821115620002fb578054600160a860020a031916815560006200032e600183018262000363565b5060050162000306565b5090565b90565b6200033c91905b80821115620002fb576000815560010162000346565b5090565b90565b50805460018160011615610100020316600290046000825580601f106200038b5750620003ab565b601f016020900490600052602060002090810190620003ab91906200033f565b5b50565b610d2f80620003bf6000396000f300606060405236156100bf5763ffffffff60e060020a60003504166306661abd81146100c15780630d15fd77146100e357806313af40351461010557806331d3164714610123578063476c494c1461014a5780634df6ca2a1461016c5780638a55b54d146101935780638da5cb5b146101b55780639507d39a146101e15780639890220b146102c7578063a3f66b46146102eb578063ad7a672f1461034d578063bd12b4b51461036f578063c09f32e814610391578063f41c1c93146103b8575bfe5b34156100c957fe5b6100d16103df565b60408051918252519081900360200190f35b34156100eb57fe5b6100d16103e6565b60408051918252519081900360200190f35b341561010d57fe5b610121600160a060020a03600435166103ec565b005b341561012b57fe5b61013660043561046d565b604080519115158252519081900360200190f35b6101366004356024356104b8565b604080519115158252519081900360200190f35b341561017457fe5b6101366004356106c3565b604080519115158252519081900360200190f35b341561019b57fe5b6100d16106ee565b60408051918252519081900360200190f35b34156101bd57fe5b6101c56106f4565b60408051600160a060020a039092168252519081900360200190f35b34156101e957fe5b6101f4600435610703565b604051808a15151515815260200189600160a060020a0316600160a060020a0316815260200180602001888152602001878152602001868152602001858152602001848152602001838152602001828103825289818151815260200191508051906020019080838360008314610285575b80518252602083111561028557601f199092019160209182019101610265565b505050905090810190601f1680156102b15780820380516001836020036101000a031916815260200191505b509a505050505050505050505060405180910390f35b34156102cf57fe5b6101366108b2565b604080519115158252519081900360200190f35b610136600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965061090a95505050505050565b604080519115158252519081900360200190f35b341561035557fe5b6100d1610ab5565b60408051918252519081900360200190f35b341561037757fe5b6100d1610abb565b60408051918252519081900360200190f35b341561039957fe5b610136600435610ac1565b604080519115158252519081900360200190f35b34156103c057fe5b610136600435610b63565b604080519115158252519081900360200190f35b6001545b90565b60035481565b60005433600160a060020a0390811691161461040757610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600060018281548110151561047e57fe5b906000526020600020906005020160005b50600160a060020a0333166000908152600491909101602052604090205460ff1690505b919050565b6000805433600160a060020a039081169116148015906104d9575060045434105b156104e357610000565b600154839081106104f357610000565b8360018181548110151561050357fe5b906000526020600020906005020160005b505460ff1615156001141561052857610000565b8460018181548110151561053857fe5b906000526020600020906005020160005b50600160a060020a0333166000908152600491909101602052604090205460ff1615156001141561057957610000565b84600281111561058857610000565b60038054600190810190915560028054600160a060020a0333163101905580548190899081106105b457fe5b906000526020600020906005020160005b5033600160a060020a031660008181526004929092016020526040909120805460ff191692151592909217909155600180549131918990811061060457fe5b906000526020600020906005020160005b50600088815260029190910160205260409020805490910190556001805481908990811061063f57fe5b906000526020600020906005020160005b506000888152600391909101602090815260409182902080549093019092558051600160a060020a033316318152905188928a927f8b8ed2ef61b90da02f78bd8647287f46833d5b11467db4451e5c4b165485bf46929081900390910190a3600194505b5b505b505b505b505b92915050565b6000805433600160a060020a039081169116146106df57610000565b50600581905560015b5b919050565b60055481565b600054600160a060020a031681565b6000600061070f610b8e565b600060006000600060006000600060018b81548110151561072c57fe5b906000526020600020906005020160005b5090508060000160009054906101000a900460ff1699508060000160019054906101000a9004600160a060020a03169850806001018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108065780601f106107db57610100808354040283529160200191610806565b820191906000526020600020905b8154815290600101906020018083116107e957829003601f168201915b505050505097508060020160006000815260200190815260200160002054965080600201600060018152602001908152602001600020549550806002016000600281526020019081526020016000205494508060030160006000815260200190815260200160002054935080600301600060018152602001908152602001600020549250806003016000600281526020019081526020016000205491505b509193959799909294969850565b6000805433600160a060020a039081169116146108ce57610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f19350505050151561090257610000565b5060015b5b90565b60008054819033600160a060020a0390811691161480159061092d575060055434105b1561093757610000565b82600481511080610949575060a08151115b1561095357610000565b600180549250828101906109679082610ba0565b503360018381548110151561097857fe5b906000526020600020906005020160005b508054600160a060020a03929092166101000274ffffffffffffffffffffffffffffffffffffffff001990921691909117905560018054859190849081106109cd57fe5b906000526020600020906005020160005b5060010190805190602001906109f5929190610bd2565b508133600160a060020a03167f7793f929911ad07e07894a20378f1eccce0fb493486c569d74045731fb583b8e866040518080602001828103825283818151815260200191508051906020019080838360008314610a6e575b805182526020831115610a6e57601f199092019160209182019101610a4e565b505050905090810190601f168015610a9a5780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600192505b5b505b50919050565b60025481565b60045481565b60008133600160a060020a0316600182815481101515610add57fe5b906000526020600020906005020160005b50546101009004600160a060020a031614801590610b1b575060005433600160a060020a03908116911614155b15610b2557610000565b6001600184815481101515610b3657fe5b906000526020600020906005020160005b50805460ff1916911515919091179055600191505b5b50919050565b6000805433600160a060020a03908116911614610b7f57610000565b50600481905560015b5b919050565b60408051602081019091526000815290565b815481835581811511610bcc57600502816005028360005260206000209182019101610bcc9190610c51565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610c1357805160ff1916838001178555610c40565b82800160010185558215610c40579182015b82811115610c40578251825591602001919060010190610c25565b5b50610c4d929150610c9a565b5090565b6103e391905b80821115610c4d57805474ffffffffffffffffffffffffffffffffffffffffff191681556000610c8a6001830182610cbb565b50600501610c57565b5090565b90565b6103e391905b80821115610c4d5760008155600101610ca0565b5090565b90565b50805460018160011615610100020316600290046000825580601f10610ce15750610469565b601f0160209004906000526020600020908101906104699190610c9a565b5b505600a165627a7a72305820b084dcce4e3d78f8a86c925f6c3f2ed689e3674655482541076a1a22f6cdedad0029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/registry.json b/js/src/dapps/chaindeploy/contracts/code/registry.json deleted file mode 100644 index 809e7bcfb3c1e37c2e452a0f13cea7e6ce0e3c97..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/registry.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/b1e0348144793e4ce6f7d6d2c4c7d0bb4ae9765e/SimpleRegistry.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600355341561003357fe5b5b611b2f806100436000396000f300606060405236156101225763ffffffff60e060020a60003504166306b2ff47811461012457806313af40351461015457806319362a28146101725780633f3935d1146101df578063432ced04146102495780634f39ca59146102685780636795dbcd1461028f57806369fe0e2d1461030257806379ce9fac146103295780638da5cb5b1461035c57806390b97fc11461038857806392698814146103f15780639890220b14610418578063ac4e73f91461043c578063ac72c120146104b1578063c3a3582514610388578063ddca3f4314610541578063deb931a214610563578063df57b74214610592578063e30bd740146105c1578063eadf976014610172578063ef5454d6146106ca578063f25eb5c11461073f578063f6d339e414610751575bfe5b341561012c57fe5b610140600160a060020a03600435166107c7565b604080519115158252519081900360200190f35b341561015c57fe5b610170600160a060020a03600435166107fa565b005b341561017a57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526101409583359593946044949392909201918190840183828082843750949650509335935061086e92505050565b604080519115158252519081900360200190f35b34156101e757fe5b610140600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650610a1495505050505050565b604080519115158252519081900360200190f35b610140600435610b6e565b604080519115158252519081900360200190f35b341561027057fe5b610140600435610c03565b604080519115158252519081900360200190f35b341561029757fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102e69583359593946044949392909201918190840183828082843750949650610cc495505050505050565b60408051600160a060020a039092168252519081900360200190f35b341561030a57fe5b610140600435610d40565b604080519115158252519081900360200190f35b341561033157fe5b610140600435600160a060020a0360243516610d9e565b604080519115158252519081900360200190f35b341561036457fe5b6102e6610e2e565b60408051600160a060020a039092168252519081900360200190f35b341561039057fe5b60408051602060046024803582810135601f81018590048502860185019096528585526103df9583359593946044949392909201918190840183828082843750949650610cc495505050505050565b60408051918252519081900360200190f35b34156103f957fe5b610140600435610eb9565b604080519115158252519081900360200190f35b341561042057fe5b610140610ed9565b604080519115158252519081900360200190f35b341561044457fe5b610140600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965050509235600160a060020a03169250610f6e915050565b604080519115158252519081900360200190f35b34156104b957fe5b6101406004356112ac565b604080519115158252519081900360200190f35b341561039057fe5b60408051602060046024803582810135601f81018590048502860185019096528585526103df9583359593946044949392909201918190840183828082843750949650610cc495505050505050565b60408051918252519081900360200190f35b341561054957fe5b6103df61134c565b60408051918252519081900360200190f35b341561056b57fe5b6102e6600435611352565b60408051600160a060020a039092168252519081900360200190f35b341561059a57fe5b6102e6600435611370565b60408051600160a060020a039092168252519081900360200190f35b34156105c957fe5b6105dd600160a060020a0360043516611392565b604080516020808252835181830152835191928392908301918501908083838215610623575b80518252602083111561062357601f199092019160209182019101610603565b505050905090810190601f16801561064f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561017a57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526101409583359593946044949392909201918190840183828082843750949650509335935061086e92505050565b604080519115158252519081900360200190f35b34156106d257fe5b610140600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965050509235600160a060020a031692506115e8915050565b604080519115158252519081900360200190f35b341561074757fe5b6101706116c6565b005b341561075957fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610140958335959394604494939290920191819084018382808284375094965050509235600160a060020a0316925061185a915050565b604080519115158252519081900360200190f35b600160a060020a03811660009081526002602081905260409091205460001961010060018316150201160415155b919050565b60005433600160a060020a039081169116146108155761086a565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b600083815260016020526040812054849033600160a060020a0390811691161461089757610a0b565b6000858152600160209081526040918290209151865186936002019288929182918401908083835b602083106108de5780518252601f1990920191602091820191016108bf565b51815160209384036101000a60001901801990921691161790529201948552506040519384900381018420949094555050855186928291908401908083835b6020831061093c5780518252601f19909201916020918201910161091d565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208183528a51838301528a519096508b95507fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea948b94508392908301919085019080838382156109cd575b8051825260208311156109cd57601f1990920191602091820191016109ad565b505050905090810190601f1680156109f95780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b60008133600160a060020a031660016000836040518082805190602001908083835b60208310610a555780518252601f199092019160209182019101610a36565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912086528501959095529290920160002060010154600160a060020a0316939093149250610aab91505057610b67565b600160a060020a03331660009081526002602090815260409091208451610ad492860190611a09565b5033600160a060020a0316836040518082805190602001908083835b60208310610b0f5780518252601f199092019160209182019101610af0565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192092506000919050a3600191505b5b50919050565b6000818152600160205260408120548290600160a060020a031615610b9257610b67565b600354341015610ba157610b67565b6000838152600160205260408082208054600160a060020a03191633600160a060020a03169081179091559051909185917f4963513eca575aba66fdcd25f267aae85958fe6fb97e75fa25d783f1a091a2219190a3600191505b5b5b50919050565b600081815260016020526040812054829033600160a060020a03908116911614610c2c57610b67565b600083815260016020818152604080842090920154600160a060020a03168352600290528120610c5b91611a88565b60008381526001602081905260408083208054600160a060020a03199081168255920180549092169091555133600160a060020a03169185917fef1961b4d2909dc23643b309bfe5c3e5646842d98c3a58517037ef3871185af39190a3600191505b5b50919050565b600082815260016020908152604080832090518451600290920192859282918401908083835b60208310610d095780518252601f199092019160209182019101610cea565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b6000805433600160a060020a03908116911614610d5c576107f5565b60038290556040805183815290517f6bbc57480a46553fa4d156ce702beef5f3ad66303b0ed1a5d4cb44966c6584c39181900360200190a15060015b5b919050565b600082815260016020526040812054839033600160a060020a03908116911614610dc757610e26565b6000848152600160205260408082208054600160a060020a031916600160a060020a0387811691821790925591519192339091169187917f7b97c62130aa09acbbcbf7482630e756592496f1759eaf702f469cf64dfb779491a4600191505b5b5092915050565b600054600160a060020a031681565b600082815260016020908152604080832090518451600290920192859282918401908083835b60208310610d095780518252601f199092019160209182019101610cea565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b600081815260016020526040902054600160a060020a031615155b919050565b6000805433600160a060020a03908116911614610ef557610f6a565b60408051600160a060020a03301631815290517fdef931299fe61d176f949118058530c1f3f539dcb6950b4e372c9b835c33ca079181900360200190a1604051600160a060020a0333811691309091163180156108fc02916000818181858888f193505050501515610f6657610000565b5060015b5b90565b60006000836040518082805190602001908083835b60208310610fa25780518252601f199092019160209182019101610f83565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060008181526001909252929020549193505033600160a060020a039081169116149050610ff6576112a3565b846040518082805190602001908083835b602083106110265780518252601f199092019160209182019101611007565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600081815260019283905293909320015491955050600160a060020a03161580159250905061111257506000828152600160208181526040808420830154600160a060020a031684526002918290529283902092518354869493919283928592908116156101000260001901160480156110ff5780601f106110dd5761010080835404028352918201916110ff565b820191906000526020600020905b8154815290600101906020018083116110eb575b5050915050604051809103902060001916145b156111eb57600082815260016020818152604080842090920154600160a060020a0316835260029052812061114691611a88565b6000828152600160208181526040928390209091015491518751600160a060020a039093169288928291908401908083835b602083106111975780518252601f199092019160209182019101611178565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd92506000919050a35b6000828152600160208181526040928390209091018054600160a060020a031916600160a060020a0388169081179091559151875188928291908401908083835b6020831061124b5780518252601f19909201916020918201910161122c565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f728435a0031f6a04538fcdd24922a7e06bc7bc945db03e83d22122d1bc5f28df92506000919050a3600192505b5b505092915050565b60008181526001602081905260409091200154600160a060020a031615155b919050565b600082815260016020908152604080832090518451600290920192859282918401908083835b60208310610d095780518252601f199092019160209182019101610cea565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b60035481565b600081815260016020526040902054600160a060020a03165b919050565b60008181526001602081905260409091200154600160a060020a03165b919050565b61139a611ad0565b600160a060020a038216600090815260026020818152604092839020805484516001821615610100026000190190911693909304601f81018390048302840183019094528383529192908301828280156114355780601f1061140a57610100808354040283529160200191611435565b820191906000526020600020905b81548152906001019060200180831161141857829003601f168201915b505050505090505b919050565b600083815260016020526040812054849033600160a060020a0390811691161461089757610a0b565b6000858152600160209081526040918290209151865186936002019288929182918401908083835b602083106108de5780518252601f1990920191602091820191016108bf565b51815160209384036101000a60001901801990921691161790529201948552506040519384900381018420949094555050855186928291908401908083835b6020831061093c5780518252601f19909201916020918201910161091d565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208183528a51838301528a519096508b95507fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea948b94508392908301919085019080838382156109cd575b8051825260208311156109cd57601f1990920191602091820191016109ad565b505050905090810190601f1680156109f95780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b6000805433600160a060020a0390811691161461160457610d3a565b600160a060020a0382166000908152600260209081526040909120845161162d92860190611a09565b5081600160a060020a0316836040518082805190602001908083835b602083106116685780518252601f199092019160209182019101611649565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f098ae8581bb8bd9af1beaf7f2e9f51f31a8e5a8bfada4e303a645d71d9c9192092506000919050a35060015b5b92915050565b33600160a060020a03166002600033600160a060020a0316600160a060020a0316815260200190815260200160002060405180828054600181600116156101000203166002900480156117505780601f1061172e576101008083540402835291820191611750565b820191906000526020600020905b81548152906001019060200180831161173c575b505060405190819003812092507f12491ad95fd945e444d88a894ffad3c21959880a4dcd8af99d4ae4ffc71d4abd9150600090a3600160006002600033600160a060020a0316600160a060020a0316815260200190815260200160002060405180828054600181600116156101000203166002900480156118085780601f106117e6576101008083540402835291820191611808565b820191906000526020600020905b8154815290600101906020018083116117f4575b50506040805191829003909120845260208085019590955292830160009081206001018054600160a060020a031916905533600160a060020a0316815260029094525050812061185791611a88565b5b565b600083815260016020526040812054849033600160a060020a0390811691161461188357610a0b565b60008581526001602090815260409182902091518651600160a060020a038716936002019288929182918401908083835b602083106108de5780518252601f1990920191602091820191016108bf565b51815160209384036101000a60001901801990921691161790529201948552506040519384900381018420949094555050855186928291908401908083835b6020831061093c5780518252601f19909201916020918201910161091d565b51815160209384036101000a6000190180199092169116179052604080519290940182900382208183528a51838301528a519096508b95507fb829c3e412537bbe794c048ccb9e4605bb4aaaa8e4d4c15c1a6e0c2adc1716ea948b94508392908301919085019080838382156109cd575b8051825260208311156109cd57601f1990920191602091820191016109ad565b505050905090810190601f1680156109f95780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b509392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10611a4a57805160ff1916838001178555611a77565b82800160010185558215611a77579182015b82811115611a77578251825591602001919060010190611a5c565b5b50611a84929150611ae2565b5090565b50805460018160011615610100020316600290046000825580601f10611aae575061086a565b601f01602090049060005260206000209081019061086a9190611ae2565b5b50565b60408051602081019091526000815290565b610f6a91905b80821115611a845760008155600101611ae8565b5090565b905600a165627a7a723058202a8f09bd2a20f43dfe4c6adb69bf4bfa211cda23787d972cd6e33eee989cafc50029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/signaturereg.json b/js/src/dapps/chaindeploy/contracts/code/signaturereg.json deleted file mode 100644 index 3dd4fe07d28b3385291bc328d26d500dff694530..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/signaturereg.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/SignatureReg.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316178155600255341561002a57fe5b5b60408051808201909152601081527f726567697374657228737472696e67290000000000000000000000000000000060208201526100759064010000000061036661007c82021704565b505b61031c565b60006100f7826040518082805190602001908083835b602083106100b15780518252601f199092019160209182019101610092565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020836100ff640100000000026103d6176401000000009004565b90505b919050565b7fffffffff000000000000000000000000000000000000000000000000000000008216600090815260016020819052604082205484916002908216156101000260001901909116041561015157610274565b7fffffffff000000000000000000000000000000000000000000000000000000008416600090815260016020908152604090912084516101939286019061027c565b5060028054600101905560408051602080825285518183015285517fffffffff00000000000000000000000000000000000000000000000000000000881693600160a060020a033316937f50e01e16719d6c699e516c57f4c514e77f6bc21a978d33f23980acdddbcbd0b293899391928392908301918501908083838215610236575b80518252602083111561023657601f199092019160209182019101610216565b505050905090810190601f1680156102625780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102bd57805160ff19168380011785556102ea565b828001600101855582156102ea579182015b828111156102ea5782518255916020019190600101906102cf565b5b506102f79291506102fb565b5090565b61031991905b808211156102f75760008155600101610301565b5090565b90565b6105d78061032b6000396000f3006060604052361561005c5763ffffffff60e060020a60003504166313af4035811461005e5780633015a5211461007c5780638da5cb5b1461009e5780639890220b146100ca578063b46bcdaa146100dc578063f2c298be14610179575bfe5b341561006657fe5b61007a600160a060020a03600435166101e3565b005b341561008457fe5b61008c610264565b60408051918252519081900360200190f35b34156100a657fe5b6100ae61026a565b60408051600160a060020a039092168252519081900360200190f35b34156100d257fe5b61007a610279565b005b34156100e457fe5b6100f9600160e060020a0319600435166102cc565b60408051602080825283518183015283519192839290830191850190808383821561013f575b80518252602083111561013f57601f19909201916020918201910161011f565b505050905090810190601f16801561016b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018157fe5b6101cf600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965061036695505050505050565b604080519115158252519081900360200190f35b60005433600160a060020a039081169116146101fe57610260565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b60025481565b600054600160a060020a031681565b60005433600160a060020a03908116911614610294576102c8565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156102c857610000565b5b5b565b60016020818152600092835260409283902080548451600294821615610100026000190190911693909304601f810183900483028401830190945283835291929083018282801561035e5780601f106103335761010080835404028352916020019161035e565b820191906000526020600020905b81548152906001019060200180831161034157829003601f168201915b505050505081565b60006103ce826040518082805190602001908083835b6020831061039b5780518252601f19909201916020918201910161037c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020836103d6565b90505b919050565b600160e060020a03198216600090815260016020819052604082205484916002908216156101000260001901909116041561041057610503565b600160e060020a031984166000908152600160209081526040909120845161043a9286019061050b565b506002805460010190556040805160208082528551818301528551600160e060020a0319881693600160a060020a033316937f50e01e16719d6c699e516c57f4c514e77f6bc21a978d33f23980acdddbcbd0b2938993919283929083019185019080838382156104c5575b8051825260208311156104c557601f1990920191602091820191016104a5565b505050905090810190601f1680156104f15780820380516001836020036101000a031916815260200191505b509250505060405180910390a3600191505b5b5092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061054c57805160ff1916838001178555610579565b82800160010185558215610579579182015b8281111561057957825182559160200191906001019061055e565b5b5061058692915061058a565b5090565b6105a891905b808211156105865760008155600101610590565b5090565b905600a165627a7a723058206830357dde798fafa19dd78a4460c047f76cc132713db13442c5da7485fc0ff40029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/tokendeploy.json b/js/src/dapps/chaindeploy/contracts/code/tokendeploy.json deleted file mode 100644 index 7dd0391b18c88113bf80094e59f236962417379b..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/tokendeploy.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/0ca02d60066202432305c8e9b1cbf33267478ab3/BasicCoin.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055341561002757fe5b5b610f43806100376000396000f3006060604052361561007d5763ffffffff60e060020a600035041663061ea8cc811461007f57806306661abd146100ad57806313af4035146100cf5780635001f3b5146100ed5780638da5cb5b1461010f5780639507d39a1461013b5780639890220b14610179578063acfdfd1c1461018b578063c00ca38314610236575bfe5b341561008757fe5b61009b600160a060020a0360043516610280565b60408051918252519081900360200190f35b34156100b557fe5b61009b61029f565b60408051918252519081900360200190f35b34156100d757fe5b6100eb600160a060020a03600435166102a6565b005b34156100f557fe5b61009b610327565b60408051918252519081900360200190f35b341561011757fe5b61011f61032e565b60408051600160a060020a039092168252519081900360200190f35b341561014357fe5b61014e60043561033d565b60408051600160a060020a039485168152928416602084015292168183015290519081900360600190f35b341561018157fe5b6100eb610392565b005b60408051602060046024803582810135601f8101859004850286018501909652858552610222958335959394604494939290920191819084018382808284375050604080516020601f89358b0180359182018390048302840183019094528083529799988101979196509182019450925082915084018382808284375094965050509235600160a060020a031692506103e5915050565b604080519115158252519081900360200190f35b341561023e57fe5b61014e600160a060020a036004351660243561079b565b60408051600160a060020a039485168152928416602084015292168183015290519081900360600190f35b600160a060020a0381166000908152600260205260409020545b919050565b6001545b90565b60005433600160a060020a039081169116146102c157610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b620f424081565b600054600160a060020a031681565b600060006000600060018581548110151561035457fe5b906000526020600020906003020160005b50805460018201546002830154600160a060020a039283169750908216955016925090505b509193909250565b60005433600160a060020a039081169116146103ad57610000565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156103e157610000565b5b5b565b60008181808088336103f56107eb565b918252600160a060020a03166020820152604080519182900301906000f080151561041c57fe5b925061042733610280565b915083600160a060020a031663ddca3f436000604051602001526040518163ffffffff1660e060020a028152600401809050602060405180830381600087803b151561046f57fe5b60325a03f1151561047c57fe5b50506040805151600160a060020a03331660009081526002602052919091209092506001840191506104ae90826107fb565b50600154600160a060020a03331660009081526002602052604090208054849081106104d657fe5b906000526020600020900160005b5055600180548082016104f78382610825565b916000526020600020906003020160005b60606040519081016040528087600160a060020a0316815260200133600160a060020a0316815260200188600160a060020a0316815250909190915060008201518160000160006101000a815481600160a060020a030219169083600160a060020a0316021790555060208201518160010160006101000a815481600160a060020a030219169083600160a060020a0316021790555060408201518160020160006101000a815481600160a060020a030219169083600160a060020a0316021790555050505083600160a060020a0316637b1a547c82858b620f42408c336000604051602001526040518763ffffffff1660e060020a0281526004018086600160a060020a0316600160a060020a03168152602001806020018581526020018060200184600160a060020a0316600160a060020a03168152602001838103835287818151815260200191508051906020019080838360008314610686575b80518252602083111561068657601f199092019160209182019101610666565b505050905090810190601f1680156106b25780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838382156106f1575b8051825260208311156106f157601f1990920191602091820191016106d1565b505050905090810190601f16801561071d5780820380516001836020036101000a031916815260200191505b509750505050505050506020604051808303818588803b151561073c57fe5b61235a5a03f1151561074a57fe5b5050604051600160a060020a03808716935087811692503316907f454b0172f64812df0cd504c2bd7df7aab8ff328a54d946b4bd0fa7c527adf9cc90600090a4600194505b50505050949350505050565b600160a060020a03821660009081526002602052604081208054829182916107dd9190869081106107c857fe5b906000526020600020900160005b505461033d565b9250925092505b9250925092565b604051610650806108c883390190565b81548183558181151161081f5760008381526020902061081f918101908301610857565b5b505050565b81548183558181151161081f5760030281600302836000526020600020918201910161081f9190610878565b5b505050565b6102a391905b80821115610871576000815560010161085d565b5090565b90565b6102a391905b8082111561087157805473ffffffffffffffffffffffffffffffffffffffff19908116825560018201805482169055600282018054909116905560030161087e565b5090565b905600606060405260008054600160a060020a03191633600160a060020a0316179055341561002757fe5b6040516040806106508339810160405280516020909101515b600034111561004e57610000565b8180151561005b57610000565b600183905560008054600160a060020a031916600160a060020a038416908117825581526002602052604090208390555b5b505b50505b6105af806100a16000396000f3006060604052361561007d5763ffffffff60e060020a600035041663095ea7b3811461009257806313af4035146100c557806318160ddd146100e357806323b872dd146101055780635001f3b51461013e57806370a08231146101605780638da5cb5b1461018e578063a9059cbb146101ba578063dd62ed3e146101ed575b341561008557fe5b6100905b610000565b565b005b341561009a57fe5b6100b1600160a060020a0360043516602435610221565b604080519115158252519081900360200190f35b34156100cd57fe5b610090600160a060020a03600435166102b6565b005b34156100eb57fe5b6100f3610337565b60408051918252519081900360200190f35b341561010d57fe5b6100b1600160a060020a036004358116906024351660443561033d565b604080519115158252519081900360200190f35b341561014657fe5b6100f361045d565b60408051918252519081900360200190f35b341561016857fe5b6100f3600160a060020a0360043516610464565b60408051918252519081900360200190f35b341561019657fe5b61019e610483565b60408051600160a060020a039092168252519081900360200190f35b34156101c257fe5b6100b1600160a060020a0360043516602435610492565b604080519115158252519081900360200190f35b34156101f557fe5b6100f3600160a060020a0360043581169060243516610552565b60408051918252519081900360200190f35b6000600034111561023157610000565b82600160a060020a031633600160a060020a03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a350600160a060020a0333811660009081526002602090815260408083209386168352600193840190915290208054830190555b5b92915050565b60005433600160a060020a039081169116146102d157610000565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b60015481565b6000600034111561034d57610000565b600160a060020a038416600090815260026020526040902054849083908190101561037757610000565b600160a060020a0380871660009081526002602090815260408083203394851684526001019091529020548791908690819010156103b457610000565b87600160a060020a031689600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef896040518082815260200191505060405180910390a3600160a060020a03808a16600090815260026020818152604080842033861685526001808201845282862080548f900390559390925281548c9003909155928b16825291902080548901905595505b5b5050505b50505b9392505050565b620f424081565b600160a060020a0381166000908152600260205260409020545b919050565b600054600160a060020a031681565b600060003411156104a257610000565b33600160a060020a0381166000908152600260205260409020548390819010156104cb57610000565b84600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef866040518082815260200191505060405180910390a3600160a060020a0333811660009081526002602052604080822080548890039055918716815220805485019055600192505b5b50505b92915050565b600160a060020a03808316600090815260026020908152604080832093851683526001909301905220545b929150505600a165627a7a72305820b5bf89a0a85c15df1e9717e49be06fe1a4f9dcc1e0cebf5483dd1c0bcd14a0910029a165627a7a723058207f96b7ad40c02cfaeaf29e65c79456dd3fd9828c9d3fbaf801fb60010456c3880029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/tokenreg.json b/js/src/dapps/chaindeploy/contracts/code/tokenreg.json deleted file mode 100644 index bcba3412738ab5799e8a5e481926ba4e9f6d7b3a..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/tokenreg.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/TokenReg.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316179055670de0b6b3a7640000600455341561003357fe5b5b611473806100436000396000f300606060405236156100b45763ffffffff60e060020a600035041663044215c681146100b657806313af4035146101df57806366b42dcb146101fd57806369fe0e2d146102ab5780637958533a146102c05780637b1a547c146102e8578063891de9ed146103a15780638da5cb5b146104bc5780639890220b146104e85780639f181b5e146104fa578063a02b161e1461051c578063b72e717d14610531578063dd93890b1461066a578063ddca3f4314610685575bfe5b34156100be57fe5b6100c96004356106a7565b60408051600160a060020a038088168252918101859052908216608082015260a060208083018281528751928401929092528651606084019160c0850191908901908083838215610135575b80518252602083111561013557601f199092019160209182019101610115565b505050905090810190601f1680156101615780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838382156101a0575b8051825260208311156101a057601f199092019160209182019101610180565b505050905090810190601f1680156101cc5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b34156101e757fe5b6101fb600160a060020a036004351661083a565b005b60408051602060046024803582810135601f8101859004850286018501909652858552610297958335600160a060020a0316959394604494939290920191819084018382808284375050604080516020601f818a01358b0180359182018390048302840183018552818452989a8a359a9099940197509195509182019350915081908401838280828437509496506108ae95505050505050565b604080519115158252519081900360200190f35b34156102b357fe5b6101fb6004356108c8565b005b34156102c857fe5b6102d66004356024356108ed565b60408051918252519081900360200190f35b60408051602060046024803582810135601f8101859004850286018501909652858552610297958335600160a060020a0316959394604494939290920191819084018382808284375050604080516020601f818a01358b0180359182018390048302840183018552818452989a8a359a90999401975091955091820193509150819084018382808284375094965050509235600160a060020a0316925061092c915050565b604080519115158252519081900360200190f35b34156103a957fe5b6103f7600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843750949650610c6695505050505050565b6040518086815260200185600160a060020a0316600160a060020a031681526020018481526020018060200183600160a060020a0316600160a060020a0316815260200182810382528481815181526020019150805190602001908083836000831461047e575b80518252602083111561047e57601f19909201916020918201910161045e565b505050905090810190601f1680156104aa5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34156104c457fe5b6104cc610dca565b60408051600160a060020a039092168252519081900360200190f35b34156104f057fe5b6101fb610dd9565b005b341561050257fe5b6102d6610e2c565b60408051918252519081900360200190f35b341561052457fe5b6101fb600435610e33565b005b341561053957fe5b61054d600160a060020a0360043516611047565b60405180868152602001806020018581526020018060200184600160a060020a0316600160a060020a03168152602001838103835287818151815260200191508051906020019080838360008314610135575b80518252602083111561013557601f199092019160209182019101610115565b505050905090810190601f1680156101615780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838382156101a0575b8051825260208311156101a057601f199092019160209182019101610180565b505050905090810190601f1680156101cc5780820380516001836020036101000a031916815260200191505b5097505050505050505060405180910390f35b341561067257fe5b6101fb6004356024356044356111f3565b005b341561068d57fe5b6102d66112b0565b60408051918252519081900360200190f35b60006106b16112b6565b60006106bb6112b6565b600060006003878154811015156106ce57fe5b906000526020600020906006020160005b50805460018083018054604080516020601f600260001997861615610100029790970190941695909504928301859004850281018501909152818152600160a060020a039094169a5093945091929083018282801561077f5780601f106107545761010080835404028352916020019161077f565b820191906000526020600020905b81548152906001019060200180831161076257829003601f168201915b505050600280850154600386018054604080516020601f6000196101006001871615020190941696909604928301869004860281018601909152818152969b50919950935091508301828280156108175780601f106107ec57610100808354040283529160200191610817565b820191906000526020600020905b8154815290600101906020018083116107fa57829003601f168201915b50505050600483015491945050600160a060020a031691505b5091939590929450565b60005433600160a060020a03908116911614610855576108aa565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a360008054600160a060020a031916600160a060020a0383161790555b5b50565b60006108bd858585853361092c565b90505b949350505050565b60005433600160a060020a039081169116146108e3576108aa565b60048190555b5b50565b60006003838154811015156108fe57fe5b906000526020600020906006020160005b506000838152600591909101602052604090205490505b92915050565b600060045434101561093d57610c5d565b600160a060020a03861660009081526001602052604090205486901561096257610c5b565b8551869060031461097257610c59565b866002816040518082805190602001908083835b602083106109a55780518252601f199092019160209182019101610986565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220541591506109df905057610c56565b60038054600181016109f183826112c8565b916000526020600020906006020160005b506040805160a081018252600160a060020a03808e1680835260208084018f90529383018d9052606083018c9052908a1660808301528354600160a060020a0319161783558b51909291610a5d9160018401918e01906112fa565b506040820151600282015560608201518051610a839160038401916020909101906112fa565b506080919091015160049091018054600160a060020a031916600160a060020a03928316179055600354908b1660009081526001602090815260409182902083905590518b519293506002928c928291908401908083835b60208310610afa5780518252601f199092019160209182019101610adb565b51815160001960209485036101000a81019182169119929092161790915293909101958652604051958690038101862096909655506003548d519101948d9493508392508401908083835b60208310610b645780518252601f199092019160209182019101610b45565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405180910390207f25074d730da65a10e171fe5589d2182313ef00da38d23a9ae3b78923568bdf2d8b896040518083600160a060020a0316600160a060020a0316815260200180602001828103825283818151815260200191508051906020019080838360008314610c17575b805182526020831115610c1757601f199092019160209182019101610bf7565b505050905090810190601f168015610c435780820380516001836020036101000a031916815260200191505b50935050505060405180910390a3600193505b5b505b505b505b95945050505050565b600060006000610c746112b6565b6000600060016002886040518082805190602001908083835b60208310610cac5780518252601f199092019160209182019101610c8d565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902054039550600386815481101515610cf257fe5b906000526020600020906006020160005b5080546002808301546003840180546040805160206101006001851615026000190190931695909504601f8101839004830286018301909152808552600160a060020a039095169a50919850939450909291908301828280156108175780601f106107ec57610100808354040283529160200191610817565b820191906000526020600020905b8154815290600101906020018083116107fa57829003601f168201915b50505050600483015491945050600160a060020a031691505b5091939590929450565b600054600160a060020a031681565b60005433600160a060020a03908116911614610df457610e28565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f193505050501515610e2857610000565b5b5b565b6003545b90565b60005433600160a060020a03908116911614610e4e576108aa565b80600382815481101515610e5e57fe5b906000526020600020906006020160005b506001016040518082805460018160011615610100020316600290048015610ece5780601f10610eac576101008083540402835291820191610ece565b820191906000526020600020905b815481529060010190602001808311610eba575b505060405190819003812092507f96e76fa77fea85d8abeb7533fdb8288c214bb1dcf1f867c8f36a95f1f509c1759150600090a360016000600383815481101515610f1557fe5b906000526020600020906006020160005b5054600160a060020a031681526020810191909152604001600090812055600380546002919083908110610f5657fe5b906000526020600020906006020160005b506001016040518082805460018160011615610100020316600290048015610fc65780601f10610fa4576101008083540402835291820191610fc6565b820191906000526020600020905b815481529060010190602001808311610fb2575b50509283525050604051908190036020019020600090556003805482908110610feb57fe5b906000526020600020906006020160005b8154600160a060020a0319168255611018600183016000611379565b60028201600090556003820160006110309190611379565b506004018054600160a060020a03191690555b5b50565b60006110516112b6565b600061105b6112b6565b600160a060020a03851660009081526001602052604081205460038054600019909201965082918790811061108c57fe5b906000526020600020906006020160005b509050806001018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561077f5780601f106107545761010080835404028352916020019161077f565b820191906000526020600020905b81548152906001019060200180831161076257829003601f168201915b505050600280850154600386018054604080516020601f6000196101006001871615020190941696909604928301869004860281018601909152818152969b50919950935091508301828280156108175780601f106107ec57610100808354040283529160200191610817565b820191906000526020600020905b8154815290600101906020018083116107fa57829003601f168201915b50505050600483015491945050600160a060020a031691505b5091939590929450565b8233600160a060020a031660038281548110151561120d57fe5b906000526020600020906006020160005b5060040154600160a060020a031614611236576112a9565b8160038581548110151561124657fe5b906000526020600020906006020160005b50600085815260059190910160209081526040918290209290925580518481529051859287927f7991c63a749706fd298fc2387764d640be6e714307b6357b1d3c2ce35cba3b52929081900390910190a35b5b50505050565b60045481565b60408051602081019091526000815290565b8154818355818115116112f4576006028160060283600052602060002091820191016112f491906113c1565b5b505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061133b57805160ff1916838001178555611368565b82800160010185558215611368579182015b8281111561136857825182559160200191906001019061134d565b5b50611375929150611426565b5090565b50805460018160011615610100020316600290046000825580601f1061139f57506108aa565b601f0160209004906000526020600020908101906108aa9190611426565b5b50565b610e3091905b80821115611375578054600160a060020a031916815560006113ec6001830182611379565b60028201600090556003820160006114049190611379565b50600481018054600160a060020a03191690556006016113c7565b5090565b90565b610e3091905b80821115611375576000815560010161142c565b5090565b905600a165627a7a72305820ab1d1a18270ba278cc2f74cd1b7b547cdcd6308a9df1dec1120fa9f6199b1f480029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/verifyEmail.json b/js/src/dapps/chaindeploy/contracts/code/verifyEmail.json deleted file mode 100644 index a87fb0a2284f0e161a19edf84fcf9bfd8eeb8885..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/verifyEmail.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/e5afdacc716ca743ceddf80978d4e6b2b465dbe9/ProofOfEmail.sol", - "output": "0x606060405260008054600160a060020a03191633600160a060020a0316178155600355341561002a57fe5b5b6108a48061003a6000396000f300606060405236156100ca5763ffffffff60e060020a60003504166306b2ff4781146100cc57806313af4035146100fc5780632650b9881461011a5780634b59e8801461018c57806359c87d70146101b05780636795dbcd146101bd57806369fe0e2d1461023057806370c4d5f214610245578063797af627146103255780638da5cb5b1461034c5780639890220b14610378578063ac72c1201461038a578063cc1d4c02146103b1578063ddca3f43146103e1578063df57b74214610403578063e30bd74014610432575bfe5b34156100d457fe5b6100e8600160a060020a03600435166104ce565b604080519115158252519081900360200190f35b341561010457fe5b610118600160a060020a03600435166104d6565b005b341561012257fe5b60408051602060046024803582810135601f810185900485028601850190965285855261017a958335600160a060020a0316959394604494939290920191819084018382808284375094965061055795505050505050565b60408051918252519081900360200190f35b341561019457fe5b610118600160a060020a0360043516602435604435610577565b005b6101186004356105eb565b005b34156101c557fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610214958335959394604494939290920191819084018382808284375094965061063595505050505050565b60408051600160a060020a039092168252519081900360200190f35b341561023857fe5b610118600435610654565b005b341561024d57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102a5958335600160a060020a0316959394604494939290920191819084018382808284375094965061067995505050505050565b6040805160208082528351818301528351919283929083019185019080838382156102eb575b8051825260208311156102eb57601f1990920191602091820191016102cb565b505050905090810190601f1680156103175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561032d57fe5b6100e8600435610688565b604080519115158252519081900360200190f35b341561035457fe5b610214610791565b60408051600160a060020a039092168252519081900360200190f35b341561038057fe5b6101186107a0565b005b341561039257fe5b6100e86004356107f3565b604080519115158252519081900360200190f35b34156103b957fe5b6100e8600160a060020a0360043516610813565b604080519115158252519081900360200190f35b34156103e957fe5b61017a610834565b60408051918252519081900360200190f35b341561040b57fe5b61021460043561083a565b60408051600160a060020a039092168252519081900360200190f35b341561043a57fe5b6102a5600160a060020a0360043516610858565b6040805160208082528351818301528351919283929083019185019080838382156102eb575b8051825260208311156102eb57601f1990920191602091820191016102cb565b505050905090810190601f1680156103175780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60005b919050565b60005433600160a060020a039081169116146104f157610553565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600160a060020a0382166000908152600260205260409020545b92915050565b60005433600160a060020a03908116911614610592576105e5565b600082815260046020908152604091829020839055815184815291518392600160a060020a038716927f76babef7e9f1065118be3f9d7094016a1cc06dd12811501c7712deb22144f37b92918290030190a35b5b505050565b6003543410156105fa57610553565b6040518190600160a060020a033316907f070669e6be82aa9b077a096b0f9617893a4dc5cb05897e27fd7a6112c8e6629e90600090a35b5b50565b600082815260016020526040902054600160a060020a03165b92915050565b60005433600160a060020a0390811691161461066f57610553565b60038190555b5b50565b610571610866565b5b92915050565b6040805182815281516020918190038201902060009081526004909152908120548015156106b55761078b565b6040805184815281516020918190038201902060009081526004825282812081905583815260019091522054600160a060020a031615158061070e5750600160a060020a03331660009081526002602052604090205415155b156107185761078b565b6000818152600160209081526040808320805473ffffffffffffffffffffffffffffffffffffffff191633600160a060020a031690811790915580845260029092528083208490555190917fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f91a2600191505b50919050565b600054600160a060020a031681565b60005433600160a060020a039081169116146107bb576107ef565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f1935050505015156107ef57610000565b5b5b565b600081815260016020526040902054600160a060020a031615155b919050565b600160a060020a03811660009081526002602052604090205415155b919050565b60035481565b600081815260016020526040902054600160a060020a03165b919050565b6104d1610866565b5b919050565b604080516020810190915260008152905600a165627a7a7230582081d03388dd06c78ee4098c4f1e23cd3c25e38d249d5da59962c6b28ec6e20ea70029" -} diff --git a/js/src/dapps/chaindeploy/contracts/code/verifySms.json b/js/src/dapps/chaindeploy/contracts/code/verifySms.json deleted file mode 100644 index 0cfc43f9d6a73897056edb27e97b15b149a07167..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/code/verifySms.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compiler": "v0.4.9+commit.364da425", - "source": "https://github.com/paritytech/contracts/blob/58842b92c00e3c45a84b6d0ac9b842f016dde50a/SMSVerification.sol", - "output": "0x606060405260008054600160a060020a033316600160a060020a03199182168117909255600280549091169091179055666a94d74f430000600455341561004257fe5b5b6109a0806100526000396000f300606060405236156100ca5763ffffffff60e060020a60003504166313af403581146100cc57806314253887146100ea578063338cdca1146101085780633da5c3ce146101125780635283f3391461013357806369fe0e2d146101af57806374a8f103146101c4578063797af627146101e25780638da5cb5b146102095780639890220b14610235578063c89e436114610247578063ca4cbf6714610273578063ca5eb5e1146102e5578063cc1d4c0214610303578063ddca3f4314610333578063fc2525ab14610273575bfe5b34156100d457fe5b6100e8600160a060020a03600435166103c7565b005b34156100f257fe5b6100e8600160a060020a0360043516610448565b005b6100e86104b4565b005b341561011a57fe5b6100e8600160a060020a0360043516602435610521565b005b341561013b57fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610193958335600160a060020a0316959394604494939290920191819084018382808284375094965061059295505050505050565b60408051600160a060020a039092168252519081900360200190f35b34156101b757fe5b6100e8600435610623565b005b34156101cc57fe5b6100e8600160a060020a0360043516610648565b005b34156101ea57fe5b6101f56004356106d9565b604080519115158252519081900360200190f35b341561021157fe5b610193610771565b60408051600160a060020a039092168252519081900360200190f35b341561023d57fe5b6100e8610780565b005b341561024f57fe5b6101936107d3565b60408051600160a060020a039092168252519081900360200190f35b341561027b57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102d3958335600160a060020a0316959394604494939290920191819084018382808284375094965061059295505050505050565b60408051918252519081900360200190f35b34156102ed57fe5b6100e8600160a060020a0360043516610873565b005b341561030b57fe5b6101f5600160a060020a03600435166108bb565b604080519115158252519081900360200190f35b341561033b57fe5b6102d36108dd565b60408051918252519081900360200190f35b341561027b57fe5b60408051602060046024803582810135601f81018590048502860185019096528585526102d3958335600160a060020a0316959394604494939290920191819084018382808284375094965061059295505050505050565b60408051918252519081900360200190f35b60005433600160a060020a039081169116146103e257610444565b60008054604051600160a060020a03808516939216917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b60025433600160a060020a0390811691161461046357610444565b600160a060020a0381166000818152600160208190526040808320805460ff1916909217909155517fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f9190a25b5b50565b6004543410156104c35761051e565b600160a060020a03331660009081526001602052604090205460ff16156104e95761051e565b604051600160a060020a033316907f039f711c9c18dd815b225b1424855e6118e746c6b5d688907f10c4dd29ebe92a90600090a25b5b565b60025433600160a060020a0390811691161461053c5761058d565b600160a060020a038216600081815260036020908152604091829020849055815184815291517fa9a343b39eac85ffb326e93ecd46785b814e72dc9f2b33bb0b4a315ba2859f439281900390910190a25b5b5050565b60006001600084600160a060020a0316600160a060020a03168152602001908152602001600020600101826040518082805190602001908083835b602083106105ec5780518252601f1990920191602091820191016105cd565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b60005433600160a060020a0390811691161461063e57610444565b60048190555b5b50565b60025433600160a060020a0390811691161461066357610444565b600160a060020a038116600090815260016020526040902054819060ff16151561068c5761058d565b600160a060020a038216600081815260016020526040808220805460ff19169055517fb6fa8b8bd5eab60f292eca876e3ef90722275b785309d84b1de113ce0b8c4e749190a25b5b505b50565b6040805182815281516020918190038201902033600160a060020a031660009081526003909252918120549091146107105761076c565b600160a060020a0333166000818152600360209081526040808320839055600191829052808320805460ff1916909217909155517fd415b905d4dd806bfba99a7a0e6351bd0c9db3a9912add21c0e6bef4479f673f9190a25060015b919050565b600054600160a060020a031681565b60005433600160a060020a0390811691161461079b5761051e565b604051600160a060020a0333811691309091163180156108fc02916000818181858888f19350505050151561051e57610000565b5b5b565b600254600160a060020a031681565b60006001600084600160a060020a0316600160a060020a03168152602001908152602001600020600101826040518082805190602001908083835b602083106105ec5780518252601f1990920191602091820191016105cd565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b92915050565b60005433600160a060020a0390811691161461088e57610444565b6002805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b5b50565b600160a060020a03811660009081526001602052604090205460ff165b919050565b60045481565b60006001600084600160a060020a0316600160a060020a03168152602001908152602001600020600101826040518082805190602001908083835b602083106105ec5780518252601f1990920191602091820191016105cd565b51815160209384036101000a6000190180199092169116179052920194855250604051938490030190922054925050505b929150505600a165627a7a72305820f6beb9c0ae3b45609ad6fc26c1b74600cbaa5f0088ca07be3e9c392a12b2c6150029" -} diff --git a/js/src/dapps/chaindeploy/contracts/dappreg.js b/js/src/dapps/chaindeploy/contracts/dappreg.js deleted file mode 100644 index 71379bf8bf873f44f718831b9a351ef21c99130b..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/dappreg.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/dappreg'; -import { compiler, source as sourceUrl, output as byteCode } from './code/dappreg'; - -const id = 'dappreg'; // 7bbc4f1a27628781b96213e781a1b8eec6982c1db8fac739af6e4c5a55862c03 -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/gavcoin.js b/js/src/dapps/chaindeploy/contracts/gavcoin.js deleted file mode 100644 index f7518ef53f01441fef1e343cbc3d9663a00162db..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/gavcoin.js +++ /dev/null @@ -1,32 +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 . - -import abi from '~/contracts/abi/gavcoin'; -import { compiler, source as sourceUrl, output as byteCode } from './code/gavcoin'; - -const isExternal = true; -const id = 'gavcoin'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - isExternal, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/githubhint.js b/js/src/dapps/chaindeploy/contracts/githubhint.js deleted file mode 100644 index 5198e38b5db9e8520ff3870d33c7698dfe74c55c..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/githubhint.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/githubhint'; -import { compiler, source as sourceUrl, output as byteCode } from './code/githubhint'; - -const id = 'githubhint'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/index.js b/js/src/dapps/chaindeploy/contracts/index.js deleted file mode 100644 index 5e066f758c449e08f8a2fad3b0448d7309921824..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/index.js +++ /dev/null @@ -1,52 +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 . - -import * as badgereg from './badgereg'; -import * as dappreg from './dappreg'; -import * as gavcoin from './gavcoin'; -import * as githubhint from './githubhint'; -import * as jgvoting from './jg-voting'; -import * as registry from './registry'; -import * as signaturereg from './signaturereg'; -import * as tokendeployMgr from './tokendeployMgr'; -import * as tokendeployReg from './tokendeployReg'; -import * as tokenreg from './tokenreg'; -import * as verifyEmail from './verifyEmail'; -import * as verifySms from './verifySms'; -import * as wallet from './wallet'; - -const contracts = [ - // builtin - githubhint, - badgereg, - dappreg, - signaturereg, - tokenreg, - tokendeployReg, - tokendeployMgr, - verifyEmail, - verifySms, - wallet, - - // external - gavcoin, - jgvoting -]; - -export { - contracts, - registry -}; diff --git a/js/src/dapps/chaindeploy/contracts/jg-voting.js b/js/src/dapps/chaindeploy/contracts/jg-voting.js deleted file mode 100644 index 8ffbed3c565bb0af593fce9d60ff16b42d58dff8..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/jg-voting.js +++ /dev/null @@ -1,32 +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 . - -import abi from './abi/jg-voting'; -import { compiler, source as sourceUrl, output as byteCode } from './code/jg-voting'; - -const isExternal = true; -const id = 'jg-voting'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - isExternal, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/registry.js b/js/src/dapps/chaindeploy/contracts/registry.js deleted file mode 100644 index 1b44f4245ac737dab241fdf6ca8b26784a2c5bb4..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/registry.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/registry2'; -import { compiler, source as sourceUrl, output as byteCode } from './code/registry'; - -const id = 'registry'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/signaturereg.js b/js/src/dapps/chaindeploy/contracts/signaturereg.js deleted file mode 100644 index 6d9f9bf609cbfd5b8a537fe60a88ed879ffa5417..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/signaturereg.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/signaturereg'; -import { compiler, source as sourceUrl, output as byteCode } from './code/signaturereg'; - -const id = 'signaturereg'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js b/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js deleted file mode 100644 index d07435fdddbda6842c8515dbae2bad5a5c6e01c8..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/tokendeployMgr.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/basiccoinmanager'; -import { compiler, source as sourceUrl, output as byteCode } from './code/tokendeploy'; - -const id = 'basiccoinmgr'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/tokendeployReg.js b/js/src/dapps/chaindeploy/contracts/tokendeployReg.js deleted file mode 100644 index 1db07e91a50d494982e8c081dfcca35476716b71..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/tokendeployReg.js +++ /dev/null @@ -1,28 +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 . - -import { abi, sourceUrl, deployParams, compiler, byteCode } from './tokenreg'; - -const id = 'basiccoinreg'; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/tokenreg.js b/js/src/dapps/chaindeploy/contracts/tokenreg.js deleted file mode 100644 index 11ee29fa1f881c9e3bd7cfae1f77109a3fd8bb5c..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/tokenreg.js +++ /dev/null @@ -1,30 +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 . - -import abi from '~/contracts/abi/tokenreg'; -import { compiler, source as sourceUrl, output as byteCode } from './code/tokenreg'; - -const id = 'tokenreg'; -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/verifyEmail.js b/js/src/dapps/chaindeploy/contracts/verifyEmail.js deleted file mode 100644 index 0176d594954de0b3445c5bbcb95a34d0cd720758..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/verifyEmail.js +++ /dev/null @@ -1,37 +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 . - -import abi from '~/contracts/abi/email-verification'; -import { compiler, source as sourceUrl, output as byteCode } from './code/verifyEmail'; - -const isBadge = true; -const id = 'emailverification'; -const deployParams = []; -const badgeSource = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/c4721a87cb95375da91f8699438d8d7907b3f5e9/certifications/email-verification.svg', - imageHash: '0x5617a14da2a0c210939da6eafb734e60906f64a504c3e107812668860a752dc6' -}; - -export { - abi, - badgeSource, - byteCode, - compiler, - deployParams, - id, - isBadge, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/verifySms.js b/js/src/dapps/chaindeploy/contracts/verifySms.js deleted file mode 100644 index d7ea509022f90e8eddcd0922076f65aab044820e..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/verifySms.js +++ /dev/null @@ -1,37 +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 . - -import abi from '~/contracts/abi/sms-verification'; -import { compiler, source as sourceUrl, output as byteCode } from './code/verifySms'; - -const isBadge = true; -const id = 'smsverification'; -const deployParams = []; -const badgeSource = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/1b1beb57ab1f4d3a93a12711b233b5cded791a2f/certifications/sms-verification.svg', - imageHash: '0x49fa653c35c0a9ce128579883babd673ad4cfc94bf9f1cfe96a2bbc30a7552c6' -}; - -export { - abi, - badgeSource, - byteCode, - compiler, - deployParams, - id, - isBadge, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/contracts/wallet.js b/js/src/dapps/chaindeploy/contracts/wallet.js deleted file mode 100644 index 6639cba801716d00956b1ea689c8239b94425396..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/contracts/wallet.js +++ /dev/null @@ -1,29 +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 . - -import { walletCompiler as compiler, walletLibrary as byteCode, walletLibraryABI as abiJson, walletLibraryRegKey as id, walletSource as sourceUrl } from '~/contracts/code/wallet'; - -const abi = JSON.parse(abiJson); -const deployParams = []; - -export { - abi, - byteCode, - compiler, - deployParams, - id, - sourceUrl -}; diff --git a/js/src/dapps/chaindeploy/dapps/console.js b/js/src/dapps/chaindeploy/dapps/console.js deleted file mode 100644 index 4e599b2faa3e2506d92479beefc7a75b96289d21..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/console.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'console'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/console/3ea0dbfefded359ccdbea37bc4cf350c0aa16948/console.jpeg', - imageHash: '0xc3962e2eab7afaeb9cd11522381723afbafdc41dc7ba31bee472e187c4459e81' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/dappreg.js b/js/src/dapps/chaindeploy/dapps/dappreg.js deleted file mode 100644 index fec35ef763170e0b270ab79f76f0c535ac4cf014..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/dappreg.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'dappreg'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/legos-64x64.png', - imageHash: '0xa8feea35c761cc6c2fe862fe336419f11ca5421f578757720a899b89fc1df154' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/gavcoin.js b/js/src/dapps/chaindeploy/dapps/gavcoin.js deleted file mode 100644 index 148c6fb8ed04866eb6225bd4732030667515597c..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/gavcoin.js +++ /dev/null @@ -1,41 +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 . - -import { api } from '../parity'; - -const isExternal = true; -const id = 'gavcoin'; -const hashId = api.util.sha3(id); -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/9e135f76fe9ba61e2d8ccbd72ed144c26c450780/tokens/gavcoin-64x64.png', - imageHash: '0xd40679a3a234d8421c678d64f4df3308859e8ad07ac95ce4a228aceb96955287', - manifestUrl: 'https://raw.githubusercontent.com/gavofyork/gavcoin/eb2f8dc4d3ad4dd5f4562690525b7cfedc9681ba/manifest.json', - manifestHash: '0xd582c572fbef8015837f2c1a8798f2c3149a1d9d655b4020edb1bbece725371d', - contentUrl: { - repo: 'gavofyork/gavcoin', - commit: '0xeb2f8dc4d3ad4dd5f4562690525b7cfedc9681ba' - }, - contentHash: '0x0b6c7b3fc8dad3edb39fd1465904ce9a11938ef18f08f8115f275047ba249530' -}; -const name = 'GavCoin'; - -export { - hashId, - id, - isExternal, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/githubhint.js b/js/src/dapps/chaindeploy/dapps/githubhint.js deleted file mode 100644 index 49fb4be9cd1351d5af19dfed81db86dafa5aa309..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/githubhint.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'githubhint'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/link-64x64.jpg', - imageHash: '0x6568901e711886e2c61eef1bbc7e2d8d37a27b9eb3e9e270eda8548f2ec796e8' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/index.js b/js/src/dapps/chaindeploy/dapps/index.js deleted file mode 100644 index e95bf5648089806523bdf2e3aaa25aad157987d8..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/index.js +++ /dev/null @@ -1,50 +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 . - -import * as consolejs from './console'; -import * as dappreg from './dappreg'; -import * as gavcoin from './gavcoin'; -import * as githubhint from './githubhint'; -import * as jgvoting from './jg-voting'; -import * as jgwhenblock from './jg-whenblock'; -import * as localtx from './localtx'; -import * as registry from './registry'; -import * as signaturereg from './signaturereg'; -import * as tokendeploy from './tokendeploy'; -import * as tokenreg from './tokenreg'; -import * as web from './web'; - -const apps = [ - // builtin - consolejs, - dappreg, - githubhint, - localtx, - registry, - signaturereg, - tokendeploy, - tokenreg, - web, - - // external - gavcoin, - jgvoting, - jgwhenblock -]; - -export { - apps -}; diff --git a/js/src/dapps/chaindeploy/dapps/jg-voting.js b/js/src/dapps/chaindeploy/dapps/jg-voting.js deleted file mode 100644 index 899e95894d25a38bcee3041b7a0816440359fb3f..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/jg-voting.js +++ /dev/null @@ -1,41 +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 . - -import { api } from '../parity'; - -const isExternal = true; -const id = 'jg-voting'; -const hashId = api.util.sha3(id); -const source = { - imageUrl: 'https://raw.githubusercontent.com/jacogr/dapp-voting/038ff4074544f2babc7aed9c4ac3dc070b85b804/assets/images/vote.jpg', - imageHash: '0x3620828e1a745d2714e9f37dc2d47cdab5ef9982190a845b5e7665b7a7767661', - manifestUrl: 'https://raw.githubusercontent.com/jacogr/dapp-voting/682f0fe4b86508a1a2487de6c7c61f7b100ba5b2/manifest.json', - manifestHash: '0x9b83e01f87d225e7bfdd305c51319504ff9b4cf8d517ca4b64f606762e72f59e', - contentUrl: { - repo: 'jacogr/dapp-voting', - commit: '0x7d941597e862a600a60b9d6ecd3a6f606d96cd7b' - }, - contentHash: '0x9fcc0910f6a8c4e45715d41aea2d287da31bf1d7321003fc66df6a012ce2d753' -}; -const name = 'Yes, No, Maybe'; - -export { - hashId, - id, - isExternal, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/jg-whenblock.js b/js/src/dapps/chaindeploy/dapps/jg-whenblock.js deleted file mode 100644 index 0005ca454a89473bd343efef0f7e63c5d03928d9..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/jg-whenblock.js +++ /dev/null @@ -1,39 +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 . - -const isExternal = true; -const id = 'whenarewethere'; -const hashId = '0xfef3bfded03695e38a9ff476a0999e1fa421e72d1fb3b55a87d6c2bdb6fc18ef'; -const source = { - imageUrl: 'https://raw.githubusercontent.com/jacogr/dapp-when-are-we-there/167aa4d904c5aa6246d0d6d6f41c4ed8a56889cd/assets/images/clock.jpg', - imageHash: '0x2534b44f685b6399bf63f86679128216c43e9a58be1dfb58533923f0bcffeba7', - manifestUrl: 'https://raw.githubusercontent.com/jacogr/dapp-when-are-we-there/bf72dc3033711a3ab41bec3c1249638f70bae768/manifest.json', - manifestHash: '0xfe26f6a19ea9393d69bc5d8c73c5072ccf126f51c10c135b42d6bf162d774fd9', - contentUrl: { - repo: 'jacogr/dapp-when-are-we-there', - commit: '0xbf72dc3033711a3ab41bec3c1249638f70bae768' - }, - contentHash: '0x3505cbbef5c2243eedba07d340d4abccfaa3cfb799f51827e33c9721a5254d13' -}; -const name = 'When are we there'; - -export { - hashId, - id, - isExternal, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/localtx.js b/js/src/dapps/chaindeploy/dapps/localtx.js deleted file mode 100644 index 6fc275a134a6d8d6530787991803faf71bd62437..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/localtx.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'localtx'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/cdd6ac4f1e2f11619bed72a53ae71217dffe19ad/dapps/stack-64x64.png', - imageHash: '0x22b924801e1971659a51956dcdfc5a2d592d8bdd03780dd72d5bc4c84b595b4c' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/registry.js b/js/src/dapps/chaindeploy/dapps/registry.js deleted file mode 100644 index 49ff4757bb73b21ea2bee3a7905962e4764ab36c..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/registry.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'registry'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/register-64x64.jpg', - imageHash: '0xf7100024052cd78b5e043287c05392b5db0bfce5caedd6d39555d40283ef0a1c' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/signaturereg.js b/js/src/dapps/chaindeploy/dapps/signaturereg.js deleted file mode 100644 index 12efcff3622759e63819f386d11db0a7cb6fd6d2..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/signaturereg.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'signaturereg'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/hex-64x64.jpg', - imageHash: '0x26f7f2415cd5cbbffa58e8119fdbdd7181cac79119dd7f6ba6ee99d7f4445640' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/tokendeploy.js b/js/src/dapps/chaindeploy/dapps/tokendeploy.js deleted file mode 100644 index 43ea8f22b0ef6c1353a00f5001f8c4a40ef2f352..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/tokendeploy.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'tokendeploy'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/interlock-64x64.png', - imageHash: '0xde104baf02aec783e0bffc624514ee267dbcb455382375e3ffa715790c1c939f' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/tokenreg.js b/js/src/dapps/chaindeploy/dapps/tokenreg.js deleted file mode 100644 index 784febba05b896604409537dd8177121f87c2baf..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/tokenreg.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'tokenreg'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/b88e983abaa1a6a6345b8d9448c15b117ddb540e/dapps/coins-64x64.jpg', - imageHash: '0xe23d429d15de98c7878d92bc90b79c7afabe1b04c2ad5e3e2c89adc8f439edc9' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/dapps/web.js b/js/src/dapps/chaindeploy/dapps/web.js deleted file mode 100644 index 0726e2bf71e5bab32e9ce2c2dc5e1b24cd0a9e53..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/dapps/web.js +++ /dev/null @@ -1,33 +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 . - -import builtins from '~/views/Dapps/builtin.json'; - -const id = 'web'; -const app = builtins.find((app) => app.url === id); -const hashId = app.id; -const source = { - imageUrl: 'https://raw.githubusercontent.com/paritytech/dapp-assets/ec6138115d0e1f45258969cd90b3b274e0ff2258/dapps/earth-64x64.jpg', - imageHash: '0x0b9b62a9262f75461191d4e8bf686c56528cbc0fe885c1f5878052ca8b2f65bf' -}; -const name = app.name; - -export { - hashId, - id, - name, - source -}; diff --git a/js/src/dapps/chaindeploy/parity.js b/js/src/dapps/chaindeploy/parity.js deleted file mode 100644 index 1dea0d696b4e72b51441b269c560d7316bf64784..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/parity.js +++ /dev/null @@ -1,21 +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 . - -const api = window.parity.api; - -export { - api -}; diff --git a/js/src/dapps/chaindeploy/store.js b/js/src/dapps/chaindeploy/store.js deleted file mode 100644 index 07b6931354555308b91579db947c7d3622da02f1..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/store.js +++ /dev/null @@ -1,714 +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 . - -import { action, computed, observable } from 'mobx'; - -import { contracts as contractsInfo, registry as registryInfo } from './contracts'; -import { apps } from './dapps'; -import { api } from './parity'; -import { executeContract, isValidNumber, validateCode } from './utils'; - -export default class ContractsStore { - @observable apps = null; - @observable badges = null; - @observable contracts = null; - @observable error = null; - @observable registry = null; - - constructor () { - this.apps = apps; - this.badges = contractsInfo.filter((contract) => contract.isBadge); - this.contracts = contractsInfo.filter((contract) => !contract.isBadge); - this.registry = registryInfo; - - api.subscribe('eth_blockNumber', this.onNewBlockNumber); - } - - @computed get contractBadgereg () { - return this.contracts.find((contract) => contract.id === 'badgereg'); - } - - @computed get contractDappreg () { - return this.contracts.find((contract) => contract.id === 'dappreg'); - } - - @computed get contractGithubhint () { - return this.contracts.find((contract) => contract.id === 'githubhint'); - } - - @computed get contractTokenreg () { - return this.contracts.find((contract) => contract.id === 'tokenreg'); - } - - @computed get isBadgeDeploying () { - return this.badges - .filter((contract) => contract.isDeploying) - .length !== 0; - } - - @computed get isContractDeploying () { - return this.contracts - .filter((contract) => contract.isDeploying) - .length !== 0; - } - - @computed get isDappDeploying () { - return this.apps - .filter((app) => app.isDeploying) - .length !== 0; - } - - @computed get haveAllBadges () { - return this.badges - .filter((contract) => !contract.instance || !contract.hasLatestCode || !contract.badgeImageHash || !contract.badgeImageMatch || !contract.isBadgeRegistered) - .length === 0; - } - - @computed get haveAllContracts () { - return this.contracts - .filter((contract) => !contract.instance || !contract.hasLatestCode) - .length === 0; - } - - @computed get haveAllDapps () { - return this.apps - .filter((app) => { - return !app.isOnChain || - !app.imageHash || !app.imageMatch || - (app.source.contentHash && !app.contentMatch) || - (app.source.manifestHash && !app.manifestMatch); - }) - .length === 0; - } - - @action refreshApps = () => { - this.apps = [].concat(this.apps.peek()); - } - - @action refreshContracts = () => { - this.badges = [].concat(this.badges.peek()); - this.contracts = [].concat(this.contracts.peek()); - } - - @action setError = (error) => { - console.error(error); - - this.error = error.message - ? error.message - : error; - } - - @action setRegistryAddress = (address, isOnChain = false) => { - if (this.registry.address !== address || !this.registry.instance) { - console.log(`registry found at ${address}`); - - this.registry = Object.assign({}, this.registry, { - address, - instance: api.newContract(this.registry.abi, address).instance, - isOnChain - }); - } - } - - @action setRegistryCode (byteCode) { - this.registry.hasLatestCode = validateCode(this.registry.byteCode, byteCode); - } - - @action setRegistryDeploying = (isDeploying = false) => { - this.registry = Object.assign({}, this.registry, { - isDeploying, - status: isDeploying - ? 'Deploying contract' - : null - }); - } - - @action setBadgeId = (badge, badgeId) => { - badge.badgeId = badgeId; - badge.isBadgeRegistered = true; - - this.refreshContracts(); - } - - @action setBadgeImageHash = (badge, imageHash) => { - badge.badgeImageHash = imageHash; - badge.badgeImageMatch = badge.badgeSource.imageHash === imageHash; - - this.refreshContracts(); - } - - @action setContractAddress = (contract, address, isOnChain = false) => { - if (contract.address !== address || !contract.instance || contract.isOnChain !== isOnChain) { - console.log(`${contract.id} found at ${address}`); - - contract.address = address; - contract.instance = api.newContract(contract.abi, address).instance; - contract.isOnChain = isOnChain; - - this.refreshContracts(); - } - } - - @action setContractCode (contract, byteCode) { - contract.hasLatestCode = validateCode(contract.byteCode, byteCode); - - this.refreshContracts(); - } - - @action setContractDeploying = (contract, isDeploying = false) => { - contract.isDeploying = isDeploying; - contract.status = isDeploying - ? 'Deploying contract' - : null; - - this.refreshContracts(); - } - - @action setContractStatus = (contract, status) => { - contract.status = status; - - this.refreshContracts(); - } - - @action setAppDeploying = (app, isDeploying = false) => { - app.isDeploying = isDeploying; - app.status = isDeploying - ? 'Registering app' - : null; - - this.refreshApps(); - } - - @action setAppFound = (app, isOnChain = false) => { - if (app.isOnChain !== isOnChain) { - console.log(`${app.name} found on dappreg`); - - app.isOnChain = isOnChain; - - this.refreshApps(); - } - } - - @action setAppContentHash = (app, contentHash) => { - if (app.contentHash !== contentHash) { - console.log(`${app.name} has contentHash ${contentHash}`); - - app.contentHash = contentHash; - app.contentMatch = contentHash === app.source.contentHash; - - this.refreshApps(); - } - } - - @action setAppImageHash = (app, imageHash) => { - if (app.imageHash !== imageHash) { - console.log(`${app.name} has imageHash ${imageHash}`); - - app.imageHash = imageHash; - app.imageMatch = imageHash === app.source.imageHash; - - this.refreshApps(); - } - } - - @action setAppManifestHash = (app, manifestHash) => { - if (app.manifestHash !== manifestHash) { - console.log(`${app.name} has manifestHash ${manifestHash}`); - - app.manifestHash = manifestHash; - app.manifestMatch = manifestHash === app.source.manifestHash; - - this.refreshApps(); - } - } - - @action setAppStatus = (app, status) => { - console.log(app.id, status); - - app.status = status; - - this.refreshApps(); - } - - deployApp = (app) => { - console.log(`Registering application ${app.id}`); - - this.setAppDeploying(app, true); - - const options = {}; - const values = [app.hashId]; - - return api.parity - .defaultAccount() - .then((defaultAccount) => { - options.from = defaultAccount; - - if (app.isOnChain) { - return true; - } - - return this.contractDappreg.instance - .fee.call({}, []) - .then((fee) => { - options.value = fee; - - return executeContract(app.id, this.contractDappreg, 'register', options, values); - }); - }) - .then(() => { - if (app.imageHash && app.imageMatch) { - return true; - } - - this.setAppStatus(app, 'Registering image url'); - - return this - .registerHash(app.source.imageHash, app.source.imageUrl, options.from) - .then(() => this.setAppMeta(app, 'IMG', app.source.imageHash, options.from)); - }) - .then(() => { - if (!app.source.manifestHash || app.manifestMatch) { - return true; - } - - this.setAppStatus(app, 'Registering manifest url'); - - return this - .registerHash(app.source.manifestHash, app.source.manifestUrl, options.from) - .then(() => this.setAppMeta(app, 'MANIFEST', app.source.manifestHash, options.from)); - }) - .then(() => { - if (!app.source.contentHash || app.contentMatch) { - return true; - } - - this.setAppStatus(app, 'Registering content url'); - - return this - .registerRepo(app.source.contentHash, app.source.contentUrl, options.from) - .then(() => this.setAppMeta(app, 'CONTENT', app.source.contentHash, options.from)); - }) - .catch(() => { - return null; - }) - .then(() => { - this.setAppDeploying(app, false); - }); - } - - deployApps = () => { - this.apps - .filter((app) => { - return !app.isDeploying && - ( - !app.isOnChain || - (!app.imageHash || !app.imageMatch) || - (app.source.contentHash && !app.contentMatch) || - (app.source.manifestHash && !app.manifestMatch) - ); - }) - .forEach(this.deployApp); - } - - _deployContract = (contract) => { - console.log(`Deploying contract ${contract.id}`); - - const options = { - data: contract.byteCode - }; - - return api.parity - .defaultAccount() - .then((defaultAccount) => { - options.from = defaultAccount; - - return api - .newContract(contract.abi) - .deploy(options, contract.deployParams, (error, data) => { - if (error) { - console.error(contract.id, error); - } else { - console.log(contract.id, data); - } - }) - .then((contractAddress) => { - return [contractAddress, defaultAccount]; - }); - }); - } - - deployContract = (contract) => { - if (contract.hasLatestCode) { - return Promise.resolve(false); - } - - let defaultAccount = '0x0'; - - this.setContractDeploying(contract, true); - - return this - ._deployContract(contract) - .then(([address, _defaultAccount]) => { - const isOnChain = contract.isOnChain; - - defaultAccount = _defaultAccount; - - this.setContractAddress(contract, address); - - return isOnChain - ? true - : this.reserveAddress(contract, defaultAccount); - }) - .then(() => { - return this.registerAddress(contract, defaultAccount); - }) - .catch(() => { - return null; - }) - .then(() => { - this.setContractDeploying(contract, false); - }); - } - - deployBadge = (badge) => { - let defaultAccount; - - return this - .deployContract(badge) - .then(() => { - this.setContractDeploying(badge, true); - - return api.parity.defaultAccount(); - }) - .then((_defaultAccount) => { - defaultAccount = _defaultAccount; - - if (badge.isBadgeRegistered) { - return true; - } - - this.setContractStatus(badge, 'Registering with badgereg'); - - return this.registerBadge(badge, defaultAccount); - }) - .then(() => { - if (badge.badgeImageMatch) { - return true; - } - - this.setContractStatus(badge, 'Registering image url'); - - return this - .registerHash(badge.badgeSource.imageHash, badge.badgeSource.imageUrl, defaultAccount) - .then(() => this.registerBadgeImage(badge, badge.badgeSource.imageHash, defaultAccount)); - }) - .then(() => { - this.setContractDeploying(badge, false); - }); - } - - deployContracts = () => { - this.contracts - .filter((contract) => !contract.isDeploying && (!contract.instance || !contract.hasLatestCode)) - .forEach(this.deployContract); - } - - deployBadges = () => { - this.badges - .filter((contract) => !contract.isDeploying && (!contract.instance || !contract.hasLatestCode || !contract.badgeImageHash || !contract.badgeImageMatch || !contract.isBadgeRegistered)) - .forEach(this.deployBadge); - } - - deployRegistry = () => { - this.setRegistryDeploying(true); - - return this - ._deployContract(this.registry) - .then(([address]) => { - this.setRegistryDeploying(false); - this.setRegistryAddress(address); - }); - } - - registerBadge = (badge, fromAddress) => { - const options = { - from: fromAddress - }; - const values = [badge.address, api.util.sha3.text(badge.id.toLowerCase())]; - - return this.contractBadgereg.instance - .fee.call({}, []) - .then((fee) => { - options.value = fee; - - return executeContract(badge.id, this.contractBadgereg, 'register', options, values); - }); - } - - registerBadgeImage = (badge, hash, fromAddress) => { - const options = { - from: fromAddress - }; - const values = [badge.badgeId, 'IMG', hash]; - - this.setContractStatus(badge, 'Setting meta IMG'); - - return executeContract(badge.id, this.contractBadgereg, 'setMeta', options, values); - } - - setAppMeta = (app, key, meta, fromAddress) => { - const options = { - from: fromAddress - }; - const values = [app.hashId, key, meta]; - - this.setAppStatus(app, `Setting meta ${key}`); - - return executeContract(app.id, this.contractDappreg, 'setMeta', options, values); - } - - reserveAddress = (contract, fromAddress) => { - const options = { from: fromAddress }; - const values = [api.util.sha3.text(contract.id.toLowerCase())]; - - this.setContractStatus(contract, 'Reserving name'); - - return this.registry.instance - .fee.call({}, []) - .then((value) => { - options.value = value; - - return executeContract(contract.id, this.registry, 'reserve', options, values); - }); - } - - registerAddress = (contract, fromAddress) => { - const options = { from: fromAddress }; - const values = [api.util.sha3.text(contract.id.toLowerCase()), 'A', contract.address]; - - this.setContractStatus(contract, 'Setting lookup address'); - - return executeContract(contract.id, this.registry, 'setAddress', options, values); - } - - registerRepo = (hash, content, fromAddress) => { - const options = { - from: fromAddress - }; - const values = [hash, content.repo || content, content.commit || 0]; - - return this.contractGithubhint.instance - .entries.call({}, [hash]) - .then(([imageUrl, commit, owner]) => { - if (isValidNumber(owner)) { - return true; - } - - return executeContract(hash, this.contractGithubhint, 'hint', options, values); - }) - .catch(() => false); - } - - registerHash = (hash, url, fromAddress) => { - const options = { - from: fromAddress - }; - const values = [hash, url]; - - return this.contractGithubhint.instance - .entries.call({}, [hash]) - .then(([imageUrl, commit, owner]) => { - if (isValidNumber(owner)) { - return true; - } - - return executeContract(hash, this.contractGithubhint, 'hintURL', options, values); - }) - .catch(() => false); - } - - findRegistry = () => { - if (this.registry.address && this.registry.hasLatestCode) { - return Promise.resolve(this.registry); - } - - return api.parity - .registryAddress() - .then((address) => { - if (isValidNumber(address)) { - this.setRegistryAddress(address, true); - } - - return api.eth.getCode(address); - }) - .then((byteCode) => { - this.setRegistryCode(byteCode); - }); - } - - findApps = () => { - if (!this.contractDappreg.instance) { - return Promise.resolve(false); - } - - return Promise - .all( - this.apps.map((app) => { - return app.isOnChain - ? Promise.resolve([[0]]) - : this.contractDappreg.instance.get.call({}, [app.hashId]); - }) - ) - .then((apps) => { - apps.forEach(([_id, owner], index) => { - const id = api.util.bytesToHex(_id); - - if (isValidNumber(id)) { - this.setAppFound(this.apps[index], true); - } - }); - - return Promise.all( - this.apps.map((app) => { - return !app.isOnChain || (app.imageHash && app.imageMatch) - ? Promise.resolve([[0], [0], [0]]) - : Promise.all([ - this.contractDappreg.instance.meta.call({}, [app.hashId, 'CONTENT']), - this.contractDappreg.instance.meta.call({}, [app.hashId, 'IMG']), - this.contractDappreg.instance.meta.call({}, [app.hashId, 'MANIFEST']) - ]); - }) - ); - }) - .then((hashes) => { - hashes.forEach(([content, image, manifest], index) => { - const contentHash = api.util.bytesToHex(content); - const imageHash = api.util.bytesToHex(image); - const manifestHash = api.util.bytesToHex(manifest); - - if (isValidNumber(contentHash)) { - this.setAppContentHash(this.apps[index], contentHash); - } - - if (isValidNumber(imageHash)) { - this.setAppImageHash(this.apps[index], imageHash); - } - - if (isValidNumber(manifestHash)) { - this.setAppManifestHash(this.apps[index], manifestHash); - } - }); - }); - } - - findBadges = () => { - if (!this.contractBadgereg.instance) { - return Promise.resolve(false); - } - - return this - .findContracts(this.badges) - .then(() => { - return Promise.all( - this.badges.map((badge) => { - return badge.isBadgeRegistered - ? Promise.resolve([0, 0, 0]) - : this.contractBadgereg.instance.fromAddress.call({}, [badge.address]); - }) - ); - }) - .then((badgeInfos) => { - badgeInfos.forEach(([id, name, owner], index) => { - if (isValidNumber(owner)) { - this.setBadgeId(this.badges[index], id); - } - }); - - return Promise - .all( - this.badges.map((badge) => { - return !badge.isBadgeRegistered - ? Promise.resolve([0]) - : this.contractBadgereg.instance.meta.call({}, [badge.badgeId, 'IMG']); - }) - ); - }) - .then((images) => { - images.forEach((imageBytes, index) => { - const imageHash = api.util.bytesToHex(imageBytes); - - if (isValidNumber(imageHash)) { - this.setBadgeImageHash(this.badges[index], imageHash); - } - }); - }); - } - - findContracts = (contracts = this.contracts) => { - if (!this.registry.instance) { - return Promise.resolve(false); - } - - return Promise - .all( - contracts.map((contract) => { - const hashId = api.util.sha3.text(contract.id.toLowerCase()); - - return contract.isOnChain - ? Promise.resolve([0, 0]) - : Promise.all([ - this.registry.instance.getAddress.call({}, [hashId, 'A']), - this.registry.instance.getOwner.call({}, [hashId]) - ]); - }) - ) - .then((addresses) => { - addresses.forEach(([address, owner], index) => { - if (isValidNumber(owner) && isValidNumber(address)) { - this.setContractAddress(contracts[index], address, true); - } - }); - - return Promise.all( - contracts.map((contract) => { - return !contract.address || contract.hasLatestCode - ? Promise.resolve(null) - : api.eth.getCode(contract.address); - }) - ); - }) - .then((codes) => { - codes.forEach((byteCode, index) => { - if (byteCode) { - this.setContractCode(contracts[index], byteCode); - } - }); - }); - } - - onNewBlockNumber = (error, blockNumber) => { - if (error) { - return; - } - - return this - .findRegistry() - .then(this.findContracts) - .then(this.findApps) - .then(this.findBadges) - .catch(this.setError); - } -} diff --git a/js/src/dapps/chaindeploy/utils.js b/js/src/dapps/chaindeploy/utils.js deleted file mode 100644 index 87e7279e33fd6d9eab3ca0a82a42fbd0928ee44e..0000000000000000000000000000000000000000 --- a/js/src/dapps/chaindeploy/utils.js +++ /dev/null @@ -1,82 +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 . - -import BigNumber from 'bignumber.js'; - -import { api } from './parity'; - -export function validateCode (source, retrieved) { - const original = source.substr(12); - const bytecode = retrieved.substr(12); - - const knownHash = api.util.sha3(original.slice(-1 * bytecode.length)); - const codeHash = api.util.sha3(bytecode); - - return knownHash === codeHash; -} - -export function isValidNumber (number) { - return number && !(new BigNumber(number)).isZero(); -} - -export function executeContract (logId, contract, funcName, options, values) { - const func = contract.instance[funcName]; - - return func - .estimateGas(options, values) - .then((gasEst) => { - options.gas = gasEst.mul(1.2); - - return trackRequest( - func.postTransaction(options, values), - (error, data) => { - if (error) { - console.error(logId, error); - } else { - console.log(logId, data); - } - } - ); - }); -} - -export function trackRequest (promise, callback) { - return promise - .then((requestId) => { - callback(null, { state: 'checkRequest', requestId }); - - return api.pollMethod('parity_checkRequest', requestId); - }) - .then((txHash) => { - callback(null, { state: 'getTransactionReceipt', txHash }); - - return api.pollMethod('eth_getTransactionReceipt', txHash, (receipt) => { - if (!receipt || !receipt.blockNumber || receipt.blockNumber.eq(0)) { - return false; - } - - return true; - }); - }) - .then((receipt) => { - callback(null, { state: 'hasReceipt', receipt }); - }) - .catch((error) => { - callback(error); - - throw error; - }); -} diff --git a/js/src/dapps/console.js b/js/src/dapps/console.js deleted file mode 100644 index 44b6dcb9c4dd7df4270e03cb8306cb3575c32feb..0000000000000000000000000000000000000000 --- a/js/src/dapps/console.js +++ /dev/null @@ -1,59 +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 . - -import React from 'react'; -import ReactDOM from 'react-dom'; -import { AppContainer } from 'react-hot-loader'; - -import 'codemirror/addon/dialog/dialog'; -import 'codemirror/addon/dialog/dialog.css'; -import 'codemirror/addon/hint/javascript-hint'; -import 'codemirror/addon/hint/show-hint'; -import 'codemirror/addon/hint/show-hint.css'; -import 'codemirror/addon/search/match-highlighter'; -import 'codemirror/addon/search/search'; -import 'codemirror/addon/search/searchcursor'; -import 'codemirror/keymap/sublime'; -import 'codemirror/lib/codemirror.css'; -import 'codemirror/mode/javascript/javascript'; -// Custom codemirror style -import './console/codemirror.css'; - -import Application from './console/Application'; - -import '../../assets/fonts/Roboto/font.css'; -import '../../assets/fonts/RobotoMono/font.css'; -import './style.css'; - -ReactDOM.render( - - - , - document.querySelector('#container') -); - -if (module.hot) { - module.hot.accept('./console/Application/index.js', () => { - require('./console/Application/index.js'); - - ReactDOM.render( - - - , - document.querySelector('#container') - ); - }); -} diff --git a/js/src/dapps/console/Application/application.css b/js/src/dapps/console/Application/application.css deleted file mode 100644 index eea2c030db3db07e19f74482d5202c56b5442954..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Application/application.css +++ /dev/null @@ -1,65 +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 . -*/ - -.app { - display: flex; - flex-direction: column; - font-family: Arial, sans-serif; - font-size: 11px; - height: 100vh; - overflow: hidden; -} - -textarea, -input { - font-family: dejavu sans mono, monospace; - outline: none; -} - -code, -pre { - font-family: dejavu sans mono, monospace; - font-size: 11px; -} - -.header { - flex: 0 0 auto; -} - -.view { - display: flex; - flex: 1; - flex-direction: column; -} - -.eval { - flex: 0 1 auto; - font-family: dejavu sans mono, monospace; - overflow: auto; -} - -.input { - border-top: 1px solid #eee; - display: flex; - flex: 1 1 auto; - min-height: 50px; -} - -.status { - flex: 0 0 auto; - font-family: dejavu sans mono, monospace; -} diff --git a/js/src/dapps/console/Application/application.js b/js/src/dapps/console/Application/application.js deleted file mode 100644 index 5a591e710a882c0c60e8ec3f2b21703266abcba3..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Application/application.js +++ /dev/null @@ -1,94 +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 . - -import { observer } from 'mobx-react'; -import React, { Component } from 'react'; - -import { api } from '../parity'; - -import Console from '../Console'; -import Header from '../Header'; -import Input from '../Input'; -import Settings from '../Settings'; -import Snippets from '../Snippets'; -import Watches from '../Watches'; - -import ApplicationStore from './application.store'; -import WatchesStore from '../Watches/watches.store'; - -import styles from './application.css'; - -@observer -export default class Application extends Component { - application = ApplicationStore.get(); - watches = WatchesStore.get(); - - componentWillMount () { - this.watches.add('time', () => new Date()); - this.watches.add('blockNumber', api.eth.blockNumber, api); - } - - render () { - return ( -
-
-
-
- - { this.renderView() } - -
- -
-
- ); - } - - renderView () { - const { view } = this.application; - - if (view === 'console') { - return ( -
-
- -
-
- -
-
- ); - } - - if (view === 'settings') { - return ( -
- -
- ); - } - - if (view === 'snippets') { - return ( -
- -
- ); - } - - return null; - } -} diff --git a/js/src/dapps/console/Application/application.store.js b/js/src/dapps/console/Application/application.store.js deleted file mode 100644 index c10be46c66404d1dd96361c6d0fa1cf5174ce2c5..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Application/application.store.js +++ /dev/null @@ -1,42 +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 . - -import { action, observable } from 'mobx'; - -let instance; - -export default class ApplicationStore { - @observable view = this.views[0].id; - - views = [ - { label: 'Console', id: 'console' }, - { label: 'Snippets', id: 'snippets' }, - { label: 'Settings', id: 'settings' } - ]; - - static get () { - if (!instance) { - instance = new ApplicationStore(); - } - - return instance; - } - - @action - setView (view) { - this.view = view; - } -} diff --git a/js/src/dapps/console/Application/index.js b/js/src/dapps/console/Application/index.js deleted file mode 100644 index 3d8d1ca3b851e5bfed73373e82eff06b5d9ea46c..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Application/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './application'; diff --git a/js/src/dapps/console/Autocomplete/autocomplete.css b/js/src/dapps/console/Autocomplete/autocomplete.css deleted file mode 100644 index 8d4585e7a7ca86800e6f531d7598995960fe3c48..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Autocomplete/autocomplete.css +++ /dev/null @@ -1,55 +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 . -*/ - -.container { - background: #f8f8f8; - box-shadow: 0 0.125em 0.25em rgba(0, 0, 0, 0.5); - font-family: dejavu sans mono, monospace; - left: 20px; - position: absolute; - max-height: 300px; - overflow: auto; -} - -.item { - background-color: white; - padding: 0.25em 0.25em 0.25em 0.35em; - display: flex; - justify-content: space-between; - - &.selected { - background-color: rgb(64, 115, 244); - - &, - .proto { - color: white; - } - } - - &:hover { - cursor: default; - } - - &:hover:not(.selected) { - background-color: rgb(230, 236, 255); - } - - .proto { - color: gray; - margin-left: 1em; - } -} diff --git a/js/src/dapps/console/Autocomplete/autocomplete.js b/js/src/dapps/console/Autocomplete/autocomplete.js deleted file mode 100644 index e2938f23dc457ef9fe87d8a5b60dd097c14254d4..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Autocomplete/autocomplete.js +++ /dev/null @@ -1,96 +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 . - -import { observer } from 'mobx-react'; -import React, { Component } from 'react'; -import ReactDOM from 'react-dom'; - -import AutocompleteStore from './autocomplete.store'; - -import styles from './autocomplete.css'; - -@observer -export default class Autocomplete extends Component { - autocompleteStore = AutocompleteStore.get(); - - render () { - if (!this.autocompleteStore.show) { - return null; - } - - return ( -
- { this.renderAutocompletes() } -
- ); - } - - renderAutocompletes () { - const { selected, values } = this.autocompleteStore; - const displayedProto = {}; - - return values.map((autocomplete, index) => { - const { name, prototypeName } = autocomplete; - const onClick = () => this.handleClick(index); - const setRef = (node) => this.setRef(index, node); - - const proto = !displayedProto[prototypeName] - ? ( - - { prototypeName } - - ) - : null; - - if (!displayedProto[prototypeName]) { - displayedProto[prototypeName] = true; - } - - const classes = [ styles.item ]; - - if (index === selected) { - classes.push(styles.selected); - } - - return ( -
- - { name } - - { proto } -
- ); - }); - } - - handleClick = (index) => { - this.autocompleteStore.select(index); - }; - - setRef = (index, node) => { - const element = ReactDOM.findDOMNode(node); - - this.autocompleteStore.setElement(index, element); - }; -} diff --git a/js/src/dapps/console/Autocomplete/autocomplete.store.js b/js/src/dapps/console/Autocomplete/autocomplete.store.js deleted file mode 100644 index 82ff2f24dc8e1c27312ce0bedb32e0d79e620e8d..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Autocomplete/autocomplete.store.js +++ /dev/null @@ -1,234 +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 . - -import { action, observable } from 'mobx'; - -import { evaluate } from '../utils'; - -let instance; - -export default class AutocompleteStore { - @observable values = []; - @observable position = {}; - @observable show = false; - @observable selected = null; - - elements = {}; - inputNode = null; - lastObject = null; - lastObjectPropertyNames = []; - - static get () { - if (!instance) { - instance = new AutocompleteStore(); - } - - return instance; - } - - get hasSelected () { - return this.selected !== null; - } - - clearCache () { - this.lastObject = null; - this.lastObjectPropertyNames = null; - } - - @action - focus (offset = 1) { - if (this.values.length === 0) { - this.selected = null; - return; - } - - this.selected = this.selected === null - ? ( - offset === 1 - ? 0 - : this.values.length - 1 - ) - : (this.values.length + this.selected + offset) % (this.values.length); - - if (this.isVisible(this.selected)) { - return; - } - - const element = this.elements[this.selected]; - - if (!element) { - return; - } - - element.scrollIntoView(offset === -1); - } - - focusOnInput () { - if (!this.inputNode) { - return; - } - - this.inputNode.focus(); - } - - @action - hide () { - this.show = false; - this.selected = null; - } - - isVisible (index) { - const element = this.elements[index]; - - if (!element) { - return false; - } - - const eBoundings = element.getBoundingClientRect(); - const pBoundings = element.parentElement.getBoundingClientRect(); - - if (eBoundings.top < pBoundings.top || eBoundings.bottom > pBoundings.bottom) { - return false; - } - - return true; - } - - select (inputStore, _index = this.selected) { - const index = _index === null - ? 0 - : _index; - - if (!this.values[index]) { - console.warn(`autocomplete::select has been called on AutocompleteStore with wrong value ${index}`); - return; - } - - const { name } = this.values[index]; - const { input } = inputStore; - const objects = input.split('.'); - - objects[objects.length - 1] = name; - const nextInput = objects.join('.'); - - this.hide(); - this.focusOnInput(); - return inputStore.updateInput(nextInput, false); - } - - setElement (index, element) { - this.elements[index] = element; - } - - setInputNode (node) { - this.inputNode = node; - } - - @action - setPosition () { - if (!this.inputNode) { - return; - } - - const inputBoundings = this.inputNode.getBoundingClientRect(); - const bodyBoundings = document.body.getBoundingClientRect(); - - // display on bottom of input - if (inputBoundings.top < bodyBoundings.height / 2) { - const nextPosition = { - top: 20 - }; - - this.position = nextPosition; - return; - } - - // display on top of input - const nextPosition = { - bottom: inputBoundings.height - }; - - this.position = nextPosition; - return; - } - - @action - setValues (values) { - this.values = values; - this.selected = null; - const show = values.length > 0; - - // Reveal autocomplete - if (!this.show && show) { - this.setPosition(); - } - - this.show = show; - } - - update (input) { - if (input.length === 0) { - return this.setValues([]); - } - - const objects = input.split('.'); - const suffix = objects.pop().toLowerCase(); - const prefix = objects.join('.'); - const object = prefix.length > 0 - ? prefix - : 'window'; - - if (object !== this.lastObject) { - const evalResult = evaluate(object); - - if (evalResult.error) { - this.lastObjectProperties = []; - } else { - this.lastObjectProperties = getAllProperties(evalResult.result); - } - - this.lastObject = object; - } - - const autocompletes = this.lastObjectProperties.filter((property) => { - return property.name.toLowerCase().includes(suffix); - }); - - return this.setValues(autocompletes); - } -} - -function getAllProperties (object) { - const propertyNames = {}; - - while (object) { - const prototypeName = object && object.constructor && object.constructor.name || ''; - - Object.getOwnPropertyNames(object) - .sort() - .forEach((name) => { - if (Object.prototype.hasOwnProperty.call(propertyNames, name)) { - return; - } - - propertyNames[name] = { name, prototypeName }; - }); - - object = Object.getPrototypeOf(object); - } - - return Object.values(propertyNames); -} diff --git a/js/src/dapps/console/Autocomplete/index.js b/js/src/dapps/console/Autocomplete/index.js deleted file mode 100644 index 5761be0e3ed50cb72fa427bf953c240a2de1bf80..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Autocomplete/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './autocomplete'; diff --git a/js/src/dapps/console/Console/console.css b/js/src/dapps/console/Console/console.css deleted file mode 100644 index a0b3db4ff36d9a2e2cb26e6268aadacdfa4e53a6..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Console/console.css +++ /dev/null @@ -1,58 +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 . -*/ - -.result { - border-top: 1px solid #eee; - display: flex; - font-family: dejavu sans mono, monospace; - padding: 0.35em 0.25em; - - &.error { - background-color: hsl(0, 100%, 97%); - - .text { - color: red; - } - } - - &.warn { - background-color: hsl(50, 100%, 95%); - } -} - -.type { - font-weight: bold !important; - font-size: 8pt; - padding: 0 0.5em 0 0.25em; -} - -.time { - color: gray; - padding: 0 1em 0 0.5em; -} - -.token { - white-space: pre-wrap; -} - -.text { - display: flex; -} - -.text .token:not(:first-child) { - margin-left: 0.5em; -} diff --git a/js/src/dapps/console/Console/console.js b/js/src/dapps/console/Console/console.js deleted file mode 100644 index 75f9713a6661248f5b8ead2211a2a9d4453477c1..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Console/console.js +++ /dev/null @@ -1,118 +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 . - -import { observer } from 'mobx-react'; -import React, { Component } from 'react'; -import ReactDOM from 'react-dom'; -import { ObjectInspector } from 'react-inspector'; - -import ConsoleStore from './console.store'; -import SettingsStore from '../Settings/settings.store'; - -import styles from './console.css'; - -const ICONS = { - debug: ' ', - error: '✖', - info: 'ℹ', - input: '>', - log: ' ', - result: '<', - warn: '⚠' -}; - -@observer -export default class Console extends Component { - consoleStore = ConsoleStore.get(); - settingsStore = SettingsStore.get(); - - render () { - return ( -
- { this.renderResults() } -
- ); - } - - renderResults () { - const { logs } = this.consoleStore; - - return logs.map((data, index) => { - const { type, timestamp } = data; - const values = this.consoleStore.logValues[index]; - const classes = [ styles.result, styles[type] ]; - - return ( -
- - { this.renderTimestamp(timestamp) } - - { - values.map((value, valueIndex) => ( - - { this.toString(value) } - - )) - } - -
- ); - }); - } - - renderTimestamp (timestamp) { - const { displayTimestamps } = this.settingsStore; - - if (!displayTimestamps) { - return null; - } - - return ( - - { new Date(timestamp).toISOString().slice(11, 23) } - - ); - } - - setRef = (node) => { - const element = ReactDOM.findDOMNode(node); - - this.consoleStore.setNode(element); - }; - - toString (value) { - if (typeof value === 'string') { - return value; - } - - if (value instanceof Error) { - return value.toString(); - } - - return ( - - ); - } -} diff --git a/js/src/dapps/console/Console/console.store.js b/js/src/dapps/console/Console/console.store.js deleted file mode 100644 index dc2fc6db4cac53fd26c31abc67e82f52559d3556..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Console/console.store.js +++ /dev/null @@ -1,126 +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 . - -import { action, observable } from 'mobx'; - -import AutocompleteStore from '../Autocomplete/autocomplete.store'; -import { evaluate } from '../utils'; - -let instance; - -export default class ConsoleStore { - @observable logs = []; - - autocompleteStore = AutocompleteStore.get(); - logValues = []; - node = null; - - constructor () { - this.attachConsole(); - } - - static get () { - if (!instance) { - instance = new ConsoleStore(); - } - - return instance; - } - - attachConsole () { - ['debug', 'error', 'info', 'log', 'warn'].forEach((level) => { - const old = window.console[level].bind(window.console); - - window.console[level] = (...args) => { - old(...args); - this.log({ type: level, values: args }); - }; - }); - } - - @action - clear () { - this.logs = []; - this.logValues = []; - } - - evaluate (input) { - this.log({ type: 'input', value: input }); - - setTimeout(() => { - const { result, error } = evaluate(input); - let value = error || result; - const type = error - ? 'error' - : 'result'; - - if (typeof value === 'string') { - value = `"${value}"`; - } - - if (value && typeof value === 'object' && typeof value.then === 'function') { - return value - .then((result) => { - this.log({ type: 'result', value: result }); - }) - .catch((error) => { - this.log({ type: 'error', value: error }); - }); - } - - this.log({ type, value }); - }); - } - - @action - log ({ type, value, values }) { - this.logs.push({ - type, - timestamp: Date.now() - }); - - if (values) { - this.logValues.push(values); - } else { - this.logValues.push([ value ]); - } - - this.autocompleteStore.setPosition(); - this.scroll(); - } - - setNode (node) { - this.node = node; - this.scroll(); - } - - scroll () { - if (!this.node) { - return; - } - - setTimeout(() => { - if (this.node.children.length === 0) { - return; - } - - // Scroll to the last child - this.node - .children[this.node.children.length - 1] - .scrollIntoView(false); - }, 50); - } -} diff --git a/js/src/dapps/console/Console/index.js b/js/src/dapps/console/Console/index.js deleted file mode 100644 index 2956b330fe4e777e1a44304040d6b6b1324c8f16..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Console/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './console'; diff --git a/js/src/dapps/console/Header/header.css b/js/src/dapps/console/Header/header.css deleted file mode 100644 index 116de6b8c91c8c4d285a1bf56ba5ec0cf8c107e9..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Header/header.css +++ /dev/null @@ -1,51 +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 . -*/ - -.container { - background-color: #f3f3f3; - border-bottom: 1px solid #ccc; - font-size: 12px; - padding: 0 0.5em; -} - -.tabs { - display: flex; -} - -.tab { - align-items: center; - box-sizing: border-box; - border: 1px solid transparent; - color: #333; - cursor: default; - display: flex; - height: 24px; - line-height: 15px; - margin-top: 2px; - padding: 2px 6px 2px 4px; - - &:hover, - &.active:hover { - background-color: #e5e5e5; - } - - &.active { - background-color: white; - border: 1px solid #ccc; - border-bottom: none; - } -} diff --git a/js/src/dapps/console/Header/header.js b/js/src/dapps/console/Header/header.js deleted file mode 100644 index c422b825604f9381d9797cac505e734107dbe693..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Header/header.js +++ /dev/null @@ -1,65 +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 . - -import { observer } from 'mobx-react'; -import React, { Component } from 'react'; - -import ApplicationStore from '../Application/application.store'; - -import styles from './header.css'; - -@observer -export default class Header extends Component { - application = ApplicationStore.get(); - - render () { - return ( -
-
- { this.renderTabs() } -
-
- ); - } - - renderTabs () { - const { view } = this.application; - - return this.application.views.map((tab) => { - const { label, id } = tab; - const classes = [ styles.tab ]; - const onClick = () => this.handleClickTab(id); - - if (id === view) { - classes.push(styles.active); - } - - return ( -
- { label } -
- ); - }); - } - - handleClickTab = (id) => { - this.application.setView(id); - }; -} diff --git a/js/src/dapps/console/Header/index.js b/js/src/dapps/console/Header/index.js deleted file mode 100644 index aef90266f940a3c7f8915c7ba910b62bec54317c..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Header/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './header'; diff --git a/js/src/dapps/console/Input/index.js b/js/src/dapps/console/Input/index.js deleted file mode 100644 index 29e00f72b19f9481ced013481cbec51dc551898c..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Input/index.js +++ /dev/null @@ -1,17 +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 . - -export default from './input'; diff --git a/js/src/dapps/console/Input/input.css b/js/src/dapps/console/Input/input.css deleted file mode 100644 index 7b0c2306e48610966ee5a07638c1ad0fc9c45c51..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Input/input.css +++ /dev/null @@ -1,46 +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 . -*/ - -.type { - color: #59f; - font-weight: bold !important; - font-size: 11px; - padding: 0 0.5em 0 0.25em; -} - -.inputContainer { - flex: 1; -} - -.input { - border: 0; - margin: 0; - padding: 0; - color: black; - height: 100%; - font-size: 11px; - resize: none; - width: 100%; -} - -.container { - border-top: 1px solid lightgray; - display: flex; - flex: 1; - padding: 0.25em; - position: relative; -} diff --git a/js/src/dapps/console/Input/input.js b/js/src/dapps/console/Input/input.js deleted file mode 100644 index 3263aff38487ef50c0fd84fe456611c2e981ff6f..0000000000000000000000000000000000000000 --- a/js/src/dapps/console/Input/input.js +++ /dev/null @@ -1,145 +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 . - -import keycode from 'keycode'; -import { observer } from 'mobx-react'; -import React, { Component } from 'react'; -import ReactDOM from 'react-dom'; - -import Autocomplete from '../Autocomplete'; - -import AutocompleteStore from '../Autocomplete/autocomplete.store'; -import ConsoleStore from '../Console/console.store'; -import InputStore from './input.store'; -import SettingsStore from '../Settings/settings.store'; - -import styles from './input.css'; - -@observer -export default class Input extends Component { - autocompleteStore = AutocompleteStore.get(); - consoleStore = ConsoleStore.get(); - inputStore = InputStore.get(); - settingsStore = SettingsStore.get(); - - render () { - const { input } = this.inputStore; - - return ( -
- - > -
-