Compare commits
362 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2662d1925e | ||
|
|
d961010f63 | ||
|
|
6885be06a4 | ||
|
|
aa0a703e7c | ||
|
|
748eda2aac | ||
|
|
fabec3e3f1 | ||
|
|
d688869035 | ||
|
|
90fccf9651 | ||
|
|
1b3787040b | ||
|
|
c253e1f33e | ||
|
|
5923146210 | ||
|
|
9e28241b29 | ||
|
|
f22326ef81 | ||
|
|
46f995ceb2 | ||
|
|
713fc9ff94 | ||
|
|
a9214081c0 | ||
|
|
d8a0d38229 | ||
|
|
ea8e7fcf73 | ||
|
|
73354d8d93 | ||
|
|
87e1080581 | ||
|
|
e95bbe36cb | ||
|
|
b6afc81d69 | ||
|
|
b8d9b6f826 | ||
|
|
424b38a8d7 | ||
|
|
5bd6b208af | ||
|
|
23a23e7a18 | ||
|
|
9d8e6ee4c9 | ||
|
|
280894691e | ||
|
|
b9f9d11929 | ||
|
|
860ef19e95 | ||
|
|
f8f22245ec | ||
|
|
e14d68e559 | ||
|
|
2b1d148ceb | ||
|
|
f6909d8243 | ||
|
|
fd29926a21 | ||
|
|
63535860bc | ||
|
|
6e76be7fad | ||
|
|
ae74e8df78 | ||
|
|
4fa78e0537 | ||
|
|
f1f64930cf | ||
|
|
4c6b282bee | ||
|
|
07e3a7f3d4 | ||
|
|
64295fde62 | ||
|
|
a6350c65aa | ||
|
|
36c917eb7a | ||
|
|
cfe57633fa | ||
|
|
80a83c95d3 | ||
|
|
f6c3d4c695 | ||
|
|
2895e3b2ab | ||
|
|
f2f4217e3c | ||
|
|
4c3be46f93 | ||
|
|
71f4f61146 | ||
|
|
a016dc5c6c | ||
|
|
cf2cb58e1d | ||
|
|
dcb69ba353 | ||
|
|
1b0948d9d1 | ||
|
|
6e34ee6837 | ||
|
|
1986c4ee79 | ||
|
|
df1c5ac616 | ||
|
|
c7219aae30 | ||
|
|
ee01612768 | ||
|
|
e0091c672a | ||
|
|
82c3265858 | ||
|
|
93f700d961 | ||
|
|
eb565a7e2b | ||
|
|
e194a2c6e3 | ||
|
|
db1ea1dcd8 | ||
|
|
9d55f0b4ab | ||
|
|
887aa62fdb | ||
|
|
8adde605e9 | ||
|
|
5fdf6be798 | ||
|
|
1b4d23fd20 | ||
|
|
43dc9af03b | ||
|
|
13729a0f7f | ||
|
|
80754c3426 | ||
|
|
8c2199dd2a | ||
|
|
6b17e321df | ||
|
|
f743829759 | ||
|
|
29c364be43 | ||
|
|
6993ec9531 | ||
|
|
0d3423cbe0 | ||
|
|
293e06e0f4 | ||
|
|
e0e79fdee0 | ||
|
|
2c97bcc1a4 | ||
|
|
c4ca84cdf3 | ||
|
|
ffeaee778c | ||
|
|
acf7c48d7e | ||
|
|
834585d61b | ||
|
|
81ca599f2a | ||
|
|
20bd1fa789 | ||
|
|
6960d35abb | ||
|
|
c8b4373e13 | ||
|
|
2d2513b35a | ||
|
|
3696f68626 | ||
|
|
ff697b64b3 | ||
|
|
9c8b7c23d1 | ||
|
|
f99819d326 | ||
|
|
6b57429d72 | ||
|
|
f59ed47b1b | ||
|
|
aefa8d5f59 | ||
|
|
f3015ce0c6 | ||
|
|
4f25d43516 | ||
|
|
9d313e31e6 | ||
|
|
330cdc1a4d | ||
|
|
93fbbb9aaf | ||
|
|
a404dd5415 | ||
|
|
11c447dfbe | ||
|
|
f48780c29b | ||
|
|
35513b14de | ||
|
|
63c7ae9a89 | ||
|
|
b31bff5ce2 | ||
|
|
4fd1ec643f | ||
|
|
79aeb95272 | ||
|
|
ca329078f5 | ||
|
|
acc5bdfc35 | ||
|
|
79a17dedd0 | ||
|
|
0c0f965354 | ||
|
|
0bd2979c04 | ||
|
|
f24bff5998 | ||
|
|
ad633de6d9 | ||
|
|
d243b15ae0 | ||
|
|
fcd042a487 | ||
|
|
1b1b44bb20 | ||
|
|
8471b91002 | ||
|
|
4979c62bb5 | ||
|
|
2b8b8851ab | ||
|
|
7c5fd042f3 | ||
|
|
d9201aa6f2 | ||
|
|
7f5ac8ba7a | ||
|
|
fc22c58408 | ||
|
|
2627288311 | ||
|
|
19184e8529 | ||
|
|
b6415c6196 | ||
|
|
acad59b300 | ||
|
|
0051c26acf | ||
|
|
bceb1d5691 | ||
|
|
61a7c30ed5 | ||
|
|
0659cb8592 | ||
|
|
a665116eb1 | ||
|
|
0bd2348ca1 | ||
|
|
eb81168674 | ||
|
|
ad9a53f486 | ||
|
|
5e2def1b23 | ||
|
|
240ef46c72 | ||
|
|
f4d14e271f | ||
|
|
48629c2bd4 | ||
|
|
d311bebaee | ||
|
|
fc9a2933af | ||
|
|
feb87c901e | ||
|
|
d8d7abc848 | ||
|
|
80f0e4b58f | ||
|
|
53e590f54b | ||
|
|
a4969ca498 | ||
|
|
680807e601 | ||
|
|
a89bbfe366 | ||
|
|
44c00b1f74 | ||
|
|
11d3cb3f08 | ||
|
|
8c286125e6 | ||
|
|
d193ddde19 | ||
|
|
396ccdbcc1 | ||
|
|
a9cb572238 | ||
|
|
05f9606bf2 | ||
|
|
00124b5a4b | ||
|
|
dabfa2c663 | ||
|
|
3420c2bac0 | ||
|
|
4f12d7ad12 | ||
|
|
5ce249ac64 | ||
|
|
cd26526868 | ||
|
|
974b24549b | ||
|
|
dab2a6bd4b | ||
|
|
505e284932 | ||
|
|
b1e3acaf0c | ||
|
|
fbf425c4e2 | ||
|
|
79b671f6c7 | ||
|
|
2af3140a26 | ||
|
|
efb390eb60 | ||
|
|
175051bac7 | ||
|
|
0a654afecc | ||
|
|
66e4410be7 | ||
|
|
bd1a578f93 | ||
|
|
6a9de9b11e | ||
|
|
1ba4df08f9 | ||
|
|
abb2a8c5a2 | ||
|
|
fd75491103 | ||
|
|
ef47426a93 | ||
|
|
5807402a0b | ||
|
|
e50eafe6e1 | ||
|
|
a23f5b8fd9 | ||
|
|
bd2e4f9c13 | ||
|
|
e551122ab9 | ||
|
|
73f4564b66 | ||
|
|
509fda727b | ||
|
|
ffc066e5a4 | ||
|
|
cafdfa8107 | ||
|
|
49f219451b | ||
|
|
45978bc2bd | ||
|
|
c689495826 | ||
|
|
46954527e7 | ||
|
|
72279856cd | ||
|
|
13ccb9f827 | ||
|
|
1503348782 | ||
|
|
5de32a70da | ||
|
|
8e0c522931 | ||
|
|
6c7d0fef4e | ||
|
|
12256a1e97 | ||
|
|
ec90fc47bc | ||
|
|
ee9bfac625 | ||
|
|
27786f014c | ||
|
|
8099efe215 | ||
|
|
cc796a232a | ||
|
|
d1b28bf57e | ||
|
|
acb1243214 | ||
|
|
fa1f81b5a3 | ||
|
|
1ef9d5b52f | ||
|
|
7f707fa524 | ||
|
|
c62e97d3c4 | ||
|
|
27d1c2d7d1 | ||
|
|
e3665ed9e3 | ||
|
|
14e7641835 | ||
|
|
5baa7e8fb5 | ||
|
|
cfe826fae9 | ||
|
|
5a131175e8 | ||
|
|
d850eb0dd5 | ||
|
|
34cdeac2a6 | ||
|
|
f53c3e582c | ||
|
|
fdc7b0fdaa | ||
|
|
0f337171bf | ||
|
|
073d242d1e | ||
|
|
44cc442d12 | ||
|
|
d5c19bae1c | ||
|
|
88e0cfe5ca | ||
|
|
141f6a047e | ||
|
|
fe7bc545bf | ||
|
|
c4c5d79a0f | ||
|
|
0a9095626d | ||
|
|
a6e96b052e | ||
|
|
86ef490a94 | ||
|
|
b97bf81adf | ||
|
|
d5584a01c7 | ||
|
|
d83798db62 | ||
|
|
4bb517ec94 | ||
|
|
de906d4afd | ||
|
|
fafb534cd3 | ||
|
|
a5a06e49ba | ||
|
|
9f96fa0a73 | ||
|
|
bbae075c60 | ||
|
|
bacc0f0b9a | ||
|
|
582a4ea339 | ||
|
|
09edb94d53 | ||
|
|
02e33c4f91 | ||
|
|
8d24b4e804 | ||
|
|
895574b774 | ||
|
|
b4af8df535 | ||
|
|
5f064a9076 | ||
|
|
5b30f22011 | ||
|
|
9d9e2b43f2 | ||
|
|
5dc5be1e58 | ||
|
|
306c1764eb | ||
|
|
f6a390849b | ||
|
|
cd088a4345 | ||
|
|
bd9a8aa22b | ||
|
|
8fc504eb1a | ||
|
|
c1b3d5fe1a | ||
|
|
e53bf9a95e | ||
|
|
decc9eaa85 | ||
|
|
3f61f2d8d9 | ||
|
|
7f02a08741 | ||
|
|
cff1bc88fa | ||
|
|
59f0eb7e6b | ||
|
|
a729ca3223 | ||
|
|
afe14b42e2 | ||
|
|
62832c93b0 | ||
|
|
1887080990 | ||
|
|
edc38c2cee | ||
|
|
16e0ad1288 | ||
|
|
5a561997cf | ||
|
|
413442d7be | ||
|
|
4489ca0a38 | ||
|
|
3a2c173fe1 | ||
|
|
9c051ab756 | ||
|
|
63221c5152 | ||
|
|
8714a40d84 | ||
|
|
825c7990f2 | ||
|
|
d743df549b | ||
|
|
6022c47b53 | ||
|
|
02eb046774 | ||
|
|
f2dd032884 | ||
|
|
55c046cb88 | ||
|
|
7701f73cdf | ||
|
|
213e007a4b | ||
|
|
78d0a8696f | ||
|
|
e1333ea1e9 | ||
|
|
4ee217ba7c | ||
|
|
6fc5014b4d | ||
|
|
859a41308c | ||
|
|
d2120ded56 | ||
|
|
be5db14160 | ||
|
|
1786b6eedd | ||
|
|
2d693be735 | ||
|
|
35c607f6be | ||
|
|
20248c443b | ||
|
|
bf55db4c7e | ||
|
|
dbdb57a8c0 | ||
|
|
78a1d8b7b4 | ||
|
|
1c076af5ee | ||
|
|
bf4fa658f3 | ||
|
|
5da8da68cc | ||
|
|
083dcc369b | ||
|
|
7827cc048e | ||
|
|
9de1afeeb6 | ||
|
|
eed630a002 | ||
|
|
6be45367e9 | ||
|
|
f7dae48c17 | ||
|
|
44161874ff | ||
|
|
faf6f1f9ea | ||
|
|
425dcd45c2 | ||
|
|
dae5d75dd6 | ||
|
|
33d3bfae8b | ||
|
|
7e89bab4aa | ||
|
|
9584faee55 | ||
|
|
9bbf8b6c0f | ||
|
|
bf242552f3 | ||
|
|
752031a657 | ||
|
|
d250f348a3 | ||
|
|
26d1303034 | ||
|
|
89987745f6 | ||
|
|
c31ffab22e | ||
|
|
21a27fee9f | ||
|
|
10c121a299 | ||
|
|
67e75e1da1 | ||
|
|
412e2ce3a0 | ||
|
|
73f2ff38ec | ||
|
|
981ad0bc53 | ||
|
|
5a581c1c90 | ||
|
|
87699f8de0 | ||
|
|
42268fd1ef | ||
|
|
2cf0d7d775 | ||
|
|
de91a5532d | ||
|
|
e91eb337c9 | ||
|
|
8dfa46f4f0 | ||
|
|
e04a2f926a | ||
|
|
98b89c8e4f | ||
|
|
b30b54e446 | ||
|
|
4723ea69a1 | ||
|
|
64fd64fd6b | ||
|
|
28eb05f032 | ||
|
|
969a9815e4 | ||
|
|
4cc274e75f | ||
|
|
c5fa7aab43 | ||
|
|
e7cdad6146 | ||
|
|
92e770e916 | ||
|
|
6fcd775d48 | ||
|
|
944bf6a59e | ||
|
|
90a7ca9d10 | ||
|
|
9e2b2b361c | ||
|
|
08f0573fb5 | ||
|
|
8132d38b50 | ||
|
|
10e1787ad1 | ||
|
|
69085aa282 | ||
|
|
fba63de974 | ||
|
|
288d73789a | ||
|
|
002496603c |
@@ -1,3 +1,27 @@
|
||||
# NOTE: if you make changes here, remember to also update:
|
||||
# scripts/test-linux.sh
|
||||
# scripts/build-linux.sh
|
||||
# scripts/build-windows.sh
|
||||
|
||||
# Using 'cfg` is broken, see https://github.com/rust-lang/cargo/issues/6858
|
||||
#[target.'cfg(target_arch = "x86_64")']
|
||||
#rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
# …so instead we list all target triples (Tier 1 64-bit platforms)
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
[target.x86_64-pc-windows-msvc]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
# Link the C runtime statically ; https://github.com/paritytech/parity-ethereum/issues/6643
|
||||
rustflags = ["-Ctarget-feature=+crt-static"]
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3", "-Ctarget-feature=+crt-static"]
|
||||
|
||||
[target.x86_64-apple-darwin]
|
||||
# Enables the aes-ni instructions for RustCrypto dependency.
|
||||
rustflags = ["-Ctarget-feature=+aes,+sse2,+ssse3"]
|
||||
|
||||
|
||||
6
.github/ISSUE_TEMPLATE.md
vendored
6
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,10 +1,14 @@
|
||||
_Before filing a new issue, please **provide the following information**._
|
||||
|
||||
_If you think that your issue is an exploitable security vulnerability, please mail your bugreport to security@parity.io instead; your submission might be eligible for our Bug Bounty._
|
||||
_You can find mode info on the reporting process in [SECURITY.md](https://github.com/paritytech/parity-ethereum/blob/master/SECURITY.md)_
|
||||
|
||||
|
||||
- **Parity Ethereum version**: 0.0.0
|
||||
- **Operating system**: Windows / MacOS / Linux
|
||||
- **Installation**: homebrew / one-line installer / built from source
|
||||
- **Fully synchronized**: no / yes
|
||||
- **Network**: ethereum / ropsten / kovan / ...
|
||||
- **Network**: ethereum / ropsten / goerli / ...
|
||||
- **Restarted**: no / yes
|
||||
|
||||
_Your issue description goes here below. Try to include **actual** vs. **expected behavior** and **steps to reproduce** the issue._
|
||||
|
||||
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
21
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
Thank you for your Pull Request!
|
||||
|
||||
Before you submitting, please check that:
|
||||
|
||||
- [ ] You added a brief description of the PR, e.g.:
|
||||
- What does it do?
|
||||
- What important points reviewers should know?
|
||||
- Is there something left for follow-up PRs?
|
||||
- [ ] You labeled the PR with appropriate labels if you have permissions to do so.
|
||||
- [ ] You mentioned a related issue if this PR related to it, e.g. `Fixes #228` or `Related #1337`.
|
||||
- [ ] You asked any particular reviewers to review. If you aren't sure, start with GH suggestions.
|
||||
- [ ] Your PR adheres [the style guide](https://wiki.parity.io/Coding-guide)
|
||||
- In particular, mind the maximal line length.
|
||||
- There is no commented code checked in unless necessary.
|
||||
- Any panickers have a proof or removed.
|
||||
- [ ] You updated any rustdocs which may have changed
|
||||
|
||||
After you've read this notice feel free to remove it.
|
||||
Thank you!
|
||||
|
||||
✄ -----------------------------------------------------------------------------
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -43,6 +43,3 @@ parity-clib-examples/cpp/build/
|
||||
.vscode
|
||||
rls/
|
||||
/parity.*
|
||||
|
||||
# cargo remote artifacts
|
||||
remote-target
|
||||
|
||||
@@ -9,15 +9,16 @@ image: ${REGISTRY}/parity-ci-linux:latest
|
||||
variables:
|
||||
GIT_STRATEGY: fetch
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
GIT_DEPTH: 3
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
CARGO_HOME: "/ci-cache/${CI_PROJECT_NAME}/cargo/${CI_JOB_NAME}"
|
||||
CARGO_TARGET: x86_64-unknown-linux-gnu
|
||||
CARGO_INCREMENTAL: 0
|
||||
REGISTRY: registry.parity.io/parity/infrastructure/scripts
|
||||
|
||||
.releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries")
|
||||
only: &releaseable_branches
|
||||
- stable
|
||||
- beta
|
||||
- tags
|
||||
- schedules
|
||||
|
||||
@@ -31,9 +32,8 @@ variables:
|
||||
- tools/
|
||||
|
||||
.docker-cache-status: &docker-cache-status
|
||||
variables:
|
||||
CARGO_HOME: "/ci-cache/parity-ethereum/cargo/${CI_JOB_NAME}"
|
||||
dependencies: []
|
||||
interruptible: true
|
||||
before_script:
|
||||
- rustup show
|
||||
- cargo --version
|
||||
@@ -112,12 +112,6 @@ validate-chainspecs:
|
||||
script:
|
||||
- ./scripts/gitlab/validate-chainspecs.sh
|
||||
|
||||
test-cpp:
|
||||
stage: build
|
||||
<<: *docker-cache-status
|
||||
script:
|
||||
- ./scripts/gitlab/test-cpp.sh
|
||||
|
||||
test-linux:
|
||||
stage: build
|
||||
<<: *docker-cache-status
|
||||
@@ -139,12 +133,6 @@ test-linux-nightly:
|
||||
- ./scripts/gitlab/test-linux.sh nightly
|
||||
allow_failure: true
|
||||
|
||||
build-android:
|
||||
<<: *build-on-linux
|
||||
image: ${REGISTRY}/parity-ci-android:stretch
|
||||
variables:
|
||||
CARGO_TARGET: armv7-linux-androideabi
|
||||
|
||||
build-linux:
|
||||
<<: *build-on-linux
|
||||
only: *releaseable_branches
|
||||
@@ -177,8 +165,6 @@ build-darwin:
|
||||
variables:
|
||||
CARGO_TARGET: x86_64-apple-darwin
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
script:
|
||||
- scripts/gitlab/build-linux.sh
|
||||
tags:
|
||||
@@ -319,7 +305,7 @@ publish-release-awss3-nightly: &publish-release-awss3
|
||||
script:
|
||||
- echo "__________Push binaries to AWS S3____________"
|
||||
- case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in
|
||||
(beta|stable|nightly)
|
||||
(stable|nightly)
|
||||
export BUCKET=releases.parity.io/ethereum;
|
||||
;;
|
||||
(*)
|
||||
|
||||
546
CHANGELOG.md
546
CHANGELOG.md
@@ -1,213 +1,397 @@
|
||||
## Parity-Ethereum [v2.5.12](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.12)
|
||||
|
||||
Parity Ethereum v2.5.12-stable is a patch release that adds Istanbul hardfork
|
||||
block numbers for POA and xDai networks, implements ECIP-1056 and implements
|
||||
EIP-2384/2387 - Muir Glacier.
|
||||
## Parity-Ethereum [v2.7.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.7.1)
|
||||
Parity Ethereum v2.7.2-stable is a patch version release of parity-ethereum.
|
||||
Starting in the 2.7.x series of releases, parity-ethereum is switching to a single `stable` release
|
||||
track. As a result, any clients that currently receive updates from the `beta`
|
||||
track should switch to the `stable` track.
|
||||
Due to database format changes, upgrading from 2.5.x or 2.6.x is one-way only.
|
||||
|
||||
The full list of included changes:
|
||||
* Enable EIP-2384 for ice age hard fork (#11281)
|
||||
|
||||
* backwards compatible call_type creation_method (#11450 + #11455)
|
||||
* chore: remove unused dependencies (#11432)
|
||||
* Cargo.lock: new lockfile format (#11448)
|
||||
* rlp_derive: cleanup (#11446)
|
||||
* Avoid long state queries when serving GetNodeData requests (#11444)
|
||||
* update kvdb-rocksdb to 0.4 (#11442)
|
||||
* Remove dead bootnodes, add new geth bootnodes (#11441)
|
||||
* goerli: replace foundation bootnode (#11433)
|
||||
* fix: export hardcoded sync format (#11416)
|
||||
* verification: fix race same block + misc (#11400)
|
||||
* update classic testnet bootnodes (#11398)
|
||||
* gcc to clang (#11453)
|
||||
|
||||
## Parity-Ethereum [v2.7.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.7.1)
|
||||
Parity Ethereum v2.7.1-stable is a patch version release of parity-ethereum.
|
||||
Starting in the 2.7.x series of releases, parity-ethereum is switching to a single `stable` release
|
||||
track. As a result, any clients that currently receive updates from the `beta`
|
||||
track should switch to the `stable` track.
|
||||
Due to database format changes, upgrading from 2.5.x or 2.6.x is one-way only.
|
||||
|
||||
The full list of included changes from `v2.7.0` to `v2.7.1`:
|
||||
|
||||
* Revert "Distinguish between `create` and `create2` (#11311)" (#11427)
|
||||
|
||||
## Parity-Ethereum [v2.7.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.7.0)
|
||||
|
||||
Parity Ethereum v2.7.0-stable is a minor version release of parity-ethereum. As
|
||||
of this release, parity-ethereum is switching to a single `stable` release
|
||||
track. As a result, any clients that currently receive updates from the `beta`
|
||||
track should switch to the `stable` track.
|
||||
|
||||
The full list of included changes from `v2.5-stable` to `v2.7-stable` (the
|
||||
`v2.6-beta` branch will already include some of these changes):
|
||||
|
||||
* Update POA bootnodes (#11411)
|
||||
* Update ProgPoW to 0.9.3 (#11407)
|
||||
* Add EtherCore support (#11402)
|
||||
* json-tests: Fix compile error (#11384)
|
||||
* ethcore/res: fix ethereum classic chainspec blake2_f activation block num (#11391)
|
||||
* Switching to stable-track (#11377)
|
||||
* Update copyright notice 2020 (#11386)
|
||||
* miner: fix deprecation warning Error::description (#11380)
|
||||
* Fix Aztlan hard fork issues (#11347)
|
||||
* authority_round: Fix next_step_time_duration. (#11379)
|
||||
* Set the block gas limit to the value returned by a contract call (#10928)
|
||||
* [Trace] Distinguish between `create` and `create2` (#11311)
|
||||
* fix cargo audit (#11378)
|
||||
* Fix esoteric test config variable (#11292)
|
||||
* Rip out the C and Java bindings (#11346)
|
||||
* Encapsulate access to the client for secret store (#11232)
|
||||
* Forward-port #11356 (#11359)
|
||||
* Fix error message typo (#11363)
|
||||
* [util/migration]: remove needless `static` bounds (#11348)
|
||||
* Replace stale boot nodes with latest list (#11351)
|
||||
* Update to latest `kvdb-*`: no default column, DBValue is Vec (#11312)
|
||||
* we do not profit from incremental now (#11302)
|
||||
* update autoupdate fork blocks for nightly (#11308)
|
||||
* Add Nat PMP method to P2P module (#11210)
|
||||
* Add randomness contract support to AuthorityRound. (#10946)
|
||||
* ethcore/res: activate ecip-1061 on kotti and mordor (#11338)
|
||||
* tx-q: enable basic verification of local transactions (#11332)
|
||||
* remove null signatures (#11335)
|
||||
* ethcore/res: activate agharta on classic 9573000 (#11331)
|
||||
* Istanbul HF in xDai (2019-12-12) (#11299)
|
||||
* Istanbul HF in POA Core (2019-12-19) (#11298)
|
||||
* Istanbul HF in POA Sokol (2019-12-05) (#11282)
|
||||
* Activate ecip-1061 on kotti and mordor (#11338)
|
||||
* Enable basic verification of local transactions (#11332)
|
||||
* Disallow EIP-86 style null signatures for transactions outside tests (#11335)
|
||||
|
||||
|
||||
## Parity-Ethereum [v2.5.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.11)
|
||||
|
||||
Parity Ethereum v2.5.11-stable is an emergency patch release that adds the missing
|
||||
eip1344_transition for mainnet - Users are advised to update as soon as possible
|
||||
to prevent any issues with the imminent Istanbul hardfork
|
||||
|
||||
The full list of included changes:
|
||||
- [chainspec]: add `eip1344_transition` for istanbul (#11301)
|
||||
|
||||
## Parity-Ethereum [v2.5.10](https://github.com/paritytech/parity-ethereum/releases/tag/2.5.10)
|
||||
|
||||
Parity Ethereum v2.5.10-stable is a patch release that adds block numbers for
|
||||
activating the Istanbul hardfork on mainnet, as well as a large number of
|
||||
various bugfixes, QoL changes, some code cleanup/refactoring and other
|
||||
miscellaneous changes.
|
||||
|
||||
This release removes legacy aliases for the mainnet. If you specify `--chain homestead`, `--chain frontier` or `--chain byzantium`, this will need to be changed to one of: `--chain eth`, `--chain ethereum`, `--chain foundation` or `--chain mainnet`.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [secretstore] migrate to version 4 (#11322)
|
||||
* Enable EIP-2384 for ice age hard fork (#11281)
|
||||
* Fix atomicity violation in network-devp2p (#11277)
|
||||
* Istanbul activation on xDai (#11299)
|
||||
* Istanbul activation on POA Core (#11298)
|
||||
* Adds support for ipc socket permissions (#11273)
|
||||
* Add check for deserialising hex values over U256 limit (#11309)
|
||||
* validate-chainspecs: check istanbul eips are in the foundation spec (#11305)
|
||||
* [chainspec]: add `eip1344_transition` for istanbul (#11301)
|
||||
* only add transactions to signing-queue if it is enabled (#11272)
|
||||
* Use upstream rocksdb (#11248)
|
||||
* Treat only blocks in queue as synced (#11264)
|
||||
* add support for evan.network chains (#11289)
|
||||
* Add benchmarks and tests for RlpNodeCodec decoding (#11287)
|
||||
* upgrade vergen to 3.0 (#11293)
|
||||
* interruptible test and build jobs (#11294)
|
||||
* Istanbul HF on POA Sokol (#11282)
|
||||
* [ethcore]: apply filter when `PendingSet::AlwaysQueue` in `ready_transactions_filtered` (#11227)
|
||||
* Update lib.rs (#11286)
|
||||
* Don't prune ancient state when instantiating a Client (#11270)
|
||||
* fixed verify_uncles error type (#11276)
|
||||
* ethcore: fix rlp deprecation warnings (#11280)
|
||||
* Upgrade trie-db to 0.16.0. (#11274)
|
||||
* Clarify what first_block `None` means (#11269)
|
||||
* removed redundant VMType enum with one variant (#11266)
|
||||
* Ensure jsonrpc threading settings are sane (#11267)
|
||||
* Return Ok(None) when the registrar contract returns empty slice (#11257)
|
||||
* Add a benchmark for snapshot::account::to_fat_rlps() (#11185)
|
||||
* Fix misc compile warnings (#11258)
|
||||
* simplify verification (#11249)
|
||||
* update ropsten forkCanonHash, forkBlock (#11247)
|
||||
* Make InstantSeal Instant again (#11186)
|
||||
* ropsten #6631425 foundation #8798209 (#11201)
|
||||
* [stable] builtin, istanbul and mordor testnet backports (#11234)
|
||||
* ethcore-builtin (#10850)
|
||||
* [builtin]: support `multiple prices and activations` in chain spec (#11039)
|
||||
* [chain specs]: activate `Istanbul` on mainnet (#11228)
|
||||
* ethcore/res: add mordor testnet configuration (#11200)
|
||||
* Update list of bootnodes for xDai chain (#11236)
|
||||
* ethcore: remove `test-helper feat` from build (#11047)
|
||||
* Secret store: fix Instant::now() related race in net_keep_alive (#11155) (#11159)
|
||||
* [stable]: backport #10691 and #10683 (#11143)
|
||||
* Fix compiler warning (that will become an error) (#10683)
|
||||
* Refactor Clique stepping (#10691)
|
||||
* Add Constantinople eips to the dev (instant_seal) config (#10809)
|
||||
* Add cargo-remote dir to .gitignore (?)
|
||||
* ethcore/res: add mordor testnet configuration (#11200)
|
||||
* [chain specs]: activate `Istanbul` on mainnet (#11228)
|
||||
* [builtin]: support `multiple prices and activations` in chain spec (#11039)
|
||||
* Insert explicit warning into the panic hook (#11225)
|
||||
* Snapshot restoration overhaul (#11219)
|
||||
* Fix docker centos build (#11226)
|
||||
* Update MIX bootnodes. (#11203)
|
||||
* retry on gitlab system failures (#11222)
|
||||
* Update bootnodes. (#11203)
|
||||
* Use provided usd-per-eth value if an endpoint is specified (#11209)
|
||||
* Add new line after writing block to hex file. (#10984)
|
||||
* Type annotation for next_key() matching of json filter options (#11192) (but no `FilterOption` in 2.5 so…)
|
||||
* Use a lock instead of atomics for snapshot Progress (#11197)
|
||||
* [informant]: `MillisecondDuration` -> `as_millis()` (#11211)
|
||||
* Step duration map configuration parameter ported from the POA Network fork (#10902)
|
||||
* Upgrade jsonrpc to latest (#11206)
|
||||
* [CI] check evmbin build (#11096)
|
||||
* Correct EIP-712 encoding (#11092)
|
||||
* [client]: Fix for incorrectly dropped consensus messages (#11086)
|
||||
* Fix block detail updating (#11015)
|
||||
* Switching sccache from local to Redis (#10971)
|
||||
* [export hardcoded sync]: use debug for `H256` (#11204)
|
||||
* Pause pruning while snapshotting (#11178)
|
||||
* Type annotation for next_key() matching of json filter options (#11192)
|
||||
* Crypto primitives removed from ethkey (#11174)
|
||||
* Made ecrecover implementation trait public (#11188)
|
||||
* Remove unused macro_use. (#11191)
|
||||
* [dependencies]: jsonrpc `14.0.1` (#11183)
|
||||
* [receipt]: add `sender` & `receiver` to `RichReceipts` (#11179)
|
||||
* [dependencies] bump rand 0.7 (#11022)
|
||||
* [ethcore/builtin]: do not panic in blake2pricer on short input (#11180)
|
||||
* TxPermissions ver 3: gas price & data (#11170)
|
||||
* [ethash] chainspec validate `ecip1017EraRounds` non-zero (#11123)
|
||||
* util Host: fix a double Read Lock bug in fn Host::session_readable() (#11175)
|
||||
* ethcore client: fix a double Read Lock bug in fn Client::logs() (#11172)
|
||||
* Aura: Report malice on sibling blocks from the same validator (#11160)
|
||||
* Change how RPCs eth_call and eth_estimateGas handle "Pending" (#11127)
|
||||
* Cleanup stratum a bit (#11161)
|
||||
* [keccak-hasher]: rust2018 (#11163)
|
||||
* Upgrade to jsonrpc v14 (#11151)
|
||||
* SecretStore: expose restore_key_public in HTTP API (#10241)
|
||||
|
||||
## Parity-Ethereum [v2.5.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.9)
|
||||
|
||||
Parity Ethereum v2.5.9-stable is a patch release that adds the block numbers for activating the Istanbul hardfork on test networks: Ropsten, Görli, Rinkeby and Kovan.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* Secret store: fix Instant::now() related race in net_keep_alive (#11155)
|
||||
* RPC method for clearing the engine signer (#10920)
|
||||
* Use TryFrom instead of From+panic for Builtin (#11140)
|
||||
* Fix sccache statistics (#11145)
|
||||
* Update ethereum types to 0.8.0 version (#11139)
|
||||
* [json]: add docs to `hardfork specification` (#11138)
|
||||
* ServiceTransactionChecker::refresh_cache: allow registrar unavailable (#11126)
|
||||
* Fix some random typos, formatting/whitespace (#11128)
|
||||
* Refactor parity_listStorageKeys with count parameter optional (#11124)
|
||||
* Make EIP712Domain Fields Optional (#11103)
|
||||
* EIP-712: bump version in prep for publishing (#11106)
|
||||
* move StateResult to `common-types` (#11121)
|
||||
* Deduplicate registrar contract & calling logic (#11110)
|
||||
* Refactor return type of `BlockChainClient::code` #7098 (#11102)
|
||||
* Switching sccache from local to Redis (#10971)
|
||||
* SIMD Implementation for EIP-152 (#11056)
|
||||
* Fix deprecated trait objects without an explicit `dyn` (#11112)
|
||||
* [spec] fix rinkeby spec (#11108)
|
||||
* Update to latest jsonrpc (#11111)
|
||||
* use images from our registry (#11105)
|
||||
* Correct EIP-712 encoding (#11092)
|
||||
* [CI] check evmbin build (#11096)
|
||||
* Update `kvdb`, `kvdb-rocksdb` and `h2` (#11091)
|
||||
* [client]: Fix for incorrectly dropped consensus messages (#11082) (#11086)
|
||||
* Update JSON tests to d4f86ecf4aa7c (#11054)
|
||||
* fix(network): typo (#11088)
|
||||
* [ethash] remove manual unrolling (#11069)
|
||||
* ethcore/res: activate Istanbul on Ropsten, Görli, Rinkeby, Kovan (#11068)
|
||||
* [json-spec] make blake2 pricing spec more readable (#11034)
|
||||
|
||||
## Parity-Ethereum [v2.5.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.8)
|
||||
|
||||
Parity Ethereum v2.5.8-stable is a patch release that improves security, stability and performance.
|
||||
|
||||
* The most noteworthy improvement in this release is incorporating all the EIPs required for the Istanbul hard fork.
|
||||
* This release also fixes certain security and performance issues, one of which was suspected to be consensus-threatening but turned out to be benign. Thanks to Martin Holst Swende and Felix Lange from the Ethereum Foundation for bringing the suspicious issue to our attention.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [sync]: rust 2018 (#11067)
|
||||
* [ethcore]: move client test types to test-helpers (#11062)
|
||||
* [sync]: remove unused dependencies or make dev (#11061)
|
||||
* [ethcore]: reduce re-exports (#11059)
|
||||
* [evmbin] fix time formatting (#11060)
|
||||
* Update hardcoded headers (foundation, classic, kovan, xdai, ewc, ...) (#11053)
|
||||
* cargo update -p eth-secp256k1 (#11052)
|
||||
* ethcore: remove `test-helper feat` from build (#11047)
|
||||
* Include test-helpers from ethjson (#11045)
|
||||
* [ethcore]: cleanup dependencies (#11043)
|
||||
* add more tx tests (#11038)
|
||||
* Fix parallel transactions race-condition (#10995)
|
||||
* [ethcore]: make it compile without `test-helpers` feature (#11036)
|
||||
* Benchmarks for block verification (#11035)
|
||||
* Move snapshot related traits to their proper place (#11012)
|
||||
* cleanup json crate (#11027)
|
||||
* [spec] add istanbul test spec (#11033)
|
||||
* [json-spec] make blake2 pricing spec more readable (#11034)
|
||||
* Add blake2_f precompile (#11017)
|
||||
* Add new line after writing block to hex file. (#10984)
|
||||
* fix: remove unused error-chain (#11028)
|
||||
* fix: remove needless use of itertools (#11029)
|
||||
* Convert `std::test` benchmarks to use Criterion (#10999)
|
||||
* Fix block detail updating (#11015)
|
||||
* [trace] introduce trace failed to Ext (#11019)
|
||||
* cli: update usage and version headers (#10924)
|
||||
* [private-tx] remove unused rand (#11024)
|
||||
* Extract snapshot to own crate (#11010)
|
||||
* Edit publish-onchain.sh to use https (#11016)
|
||||
* Fix deadlock in network-devp2p (#11013)
|
||||
* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
|
||||
* Fix deadlock in `network-devp2p` (#11013)
|
||||
* Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191)
|
||||
* EIP 1884 Re-pricing of trie-size dependent operations (#10992)
|
||||
* xDai chain support and nodes list update (#10989)
|
||||
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
|
||||
* [trace] check mem diff within range (#11002)
|
||||
* EIP-1344 Add CHAINID op-code (#10983)
|
||||
* manual publish jobs for releases, no changes for nightlies (#10977)
|
||||
* [blooms-db] Fix benchmarks (#10974)
|
||||
* Verify transaction against its block during import (#10954)
|
||||
* Better error message for rpc gas price errors (#10931)
|
||||
* tx-pool: accept local tx with higher gas price when pool full (#10901)
|
||||
* Fix fork choice (#10837)
|
||||
* Cleanup unused vm dependencies (#10787)
|
||||
* Make ClientIoMessage generic over the Client (#10981)
|
||||
* bump spin to 0.5.2 (#10996)
|
||||
* fix compile warnings (#10993)
|
||||
* Fix compilation on recent nightlies (#10991)
|
||||
* Don't build rpc with ethcore test-helpers (#11048)
|
||||
* EIP 1884 Re-pricing of trie-size dependent operations (#10992)
|
||||
* Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191)
|
||||
|
||||
## Parity-Ethereum [v2.5.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.7)
|
||||
|
||||
Parity Ethereum v2.5.7-stable is a bugfix release that fixes a potential DoS attack in the trace_call RPC method. This is a critical upgrade for anyone running Parity nodes with RPC exposed to the public internet (and highly recommended for anyone else). For details see this blog post.
|
||||
|
||||
## Parity-Ethereum [v2.5.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.6)
|
||||
|
||||
Parity-Ethereum v2.5.6-stable is a bugfix release that improves stability.
|
||||
|
||||
* Allow specifying hostnames for node URLs
|
||||
* Fix a bug where archive nodes were losing peers
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [ipfs] Convert to edition 2018 (#10979)
|
||||
* Extract spec to own crate (#10978)
|
||||
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
|
||||
* Extract engines to own crates (#10966)
|
||||
* Configuration map of block reward contract addresses (#10875)
|
||||
* Add a 2/3 quorum option to Authority Round. (#10909)
|
||||
* Fix rlp decode for inline trie nodes. (#10980)
|
||||
* Private contract migration and offchain state sync (#10748)
|
||||
* manual publish jobs for releases, no changes for nightlies (#10977)
|
||||
* Extract the Engine trait (#10958)
|
||||
* Better error message for rpc gas price errors (#10931)
|
||||
* [.gitlab.yml] cargo check ethcore benches (#10965)
|
||||
* Verify transaction against its block during import (#10954)
|
||||
* [evmbin] fix compilation (#10976)
|
||||
* Update to latest trie version. (#10972)
|
||||
* [blooms-db] Fix benchmarks (#10974)
|
||||
* Fix ethcore/benches build. (#10964)
|
||||
* tx-pool: accept local tx with higher gas price when pool full (#10901)
|
||||
* Disable unsyncable expanse chain (#10926)
|
||||
* Extract Machine from ethcore (#10949)
|
||||
* removed redundant state_root function from spec, improve spec error types (#10955)
|
||||
* Add support for Energy Web Foundation's new chains (#10957)
|
||||
* [evmbin] add more tests to main.rs (#10956)
|
||||
* Fix compiler warnings in util/io and upgrade to edition 2018 Upgrade mio to latest (#10953)
|
||||
* unify loading spec && further spec cleanups (#10948)
|
||||
* refactor: Refactor evmbin CLI (#10742)
|
||||
* journaldb changes (#10929)
|
||||
* Allow default block parameter to be blockHash (#10932)
|
||||
* Enable sealing when engine is ready (#10938)
|
||||
* Fix some warnings and typos. (#10941)
|
||||
* Updated security@parity.io key (#10939)
|
||||
* Change the return type of step_inner function. (#10940)
|
||||
* get rid of hidden mutability of Spec (#10904)
|
||||
* simplify BlockReward::reward implementation (#10906)
|
||||
* Kaspersky AV whitelisting (#10919)
|
||||
* Avast whitelist script (#10900)
|
||||
* Docker images renaming (#10863)
|
||||
* Remove excessive warning (#10831)
|
||||
* Allow --nat extip:your.host.here.org (#10830)
|
||||
* additional arithmetic EVM opcode benchmarks (#10916)
|
||||
* [Cargo.lock] cargo update -p crossbeam-epoch (#10921)
|
||||
* Fixes incorrect comment. (#10913)
|
||||
* Add file path to disk map write/read warnings (#10911)
|
||||
* remove verify_transaction_unordered from engine (#10891)
|
||||
* Avast whitelist script (#10900)
|
||||
* cleanup ethcore ethereum module (#10899)
|
||||
* Move more types out of ethcore (#10880)
|
||||
* return block nonce when engine is clique (#10892)
|
||||
* TransactionQueue::import accepts iterator (#10889)
|
||||
* rename is_pruned to is_prunable (#10888)
|
||||
* simplify create_address_scheme (#10890)
|
||||
* Move DatabaseExtras back to trace (#10868)
|
||||
* Update README.md and Changelogs (#10866)
|
||||
* whisper is no longer a part of parity-ethereum repo (#10855)
|
||||
* [ethash] remove mem::uninitialized (#10861)
|
||||
* Docker images renaming (#10863)
|
||||
* Move the substate module into ethcore/executive (#10867)
|
||||
* Run cargo fix on a few of the worst offenders (#10854)
|
||||
* removed redundant fork choice abstraction (#10849)
|
||||
* Extract state-db from ethcore (#10858)
|
||||
* Fix fork choice (#10837)
|
||||
* Move more code into state-account (#10840)
|
||||
* Remove compiler warning (#10865)
|
||||
* [ethash] use static_assertions crate (#10860)
|
||||
* EIP-1702: Generalized Account Versioning Scheme (#10771)
|
||||
* ethcore-builtin (#10850)
|
||||
* removed QueueError type (#10852)
|
||||
* removed unused macros (#10851)
|
||||
* bump crossbeam (#10848)
|
||||
* removed unused trait PrivateNotify and unused Error types (#10847)
|
||||
* make fn submit_seal more idiomatic (#10843)
|
||||
* update parking-lot to 0.8 (#10845)
|
||||
* Update version to 2.7.0 (#10846)
|
||||
* update jsonrpc to 12.0 (#10841)
|
||||
* Improve logging and cleanup in miner around block sealing (#10745)
|
||||
* Extract AccountDB to account-db (#10839)
|
||||
* test: Update Whisper test for invalid pool size (#10811)
|
||||
* Extricate PodAccount and state Account to own crates (#10838)
|
||||
* logs (#10817)
|
||||
* refactor: whisper: Add type aliases and update rustdocs in message.rs (#10812)
|
||||
* Break circular dependency between Client and Engine (part 1) (#10833)
|
||||
* tests: Relates to #10655: Test instructions for Readme (#10835)
|
||||
* refactor: Related #9459 - evmbin: replace untyped json! macro with fully typed serde serialization using Rust structs (#10657)
|
||||
* idiomatic changes to PodState (#10834)
|
||||
* Allow --nat extip:your.host.here.org (#10830)
|
||||
* When updating the client or when called from RPC, sleep should mean sleep (#10814)
|
||||
* added new ropsten-bootnode and removed old one (#10794)
|
||||
* ethkey no longer uses byteorder (#10786)
|
||||
* Remove excessive warning (#10831)
|
||||
* Fix typo in README.md (#10828)
|
||||
* ethcore does not use byteorder (#10829)
|
||||
* Better logging when backfilling ancient blocks fail (#10796)
|
||||
* depends: Update wordlist to v1.3 (#10823)
|
||||
* cargo update -p smallvec (#10822)
|
||||
* replace memzero with zeroize crate (#10816)
|
||||
* Don't repeat the logic from Default impl (#10813)
|
||||
* removed additional_params method (#10818)
|
||||
* Add Constantinople eips to the dev (instant_seal) config (#10809)
|
||||
* removed redundant fmt::Display implementations (#10806)
|
||||
* revert changes to .gitlab-ci.yml (#10807)
|
||||
* Add filtering capability to `parity_pendingTransactions` (issue 8269) (#10506)
|
||||
* removed EthEngine alias (#10805)
|
||||
* wait a bit longer in should_check_status_of_request_when_its_resolved (#10808)
|
||||
* Do not drop the peer with None difficulty (#10772)
|
||||
* ethcore-bloom-journal updated to 2018 (#10804)
|
||||
* ethcore-light uses bincode 1.1 (#10798)
|
||||
* Fix a few typos and unused warnings. (#10803)
|
||||
* updated project to ansi_term 0.11 (#10799)
|
||||
* added new ropsten-bootnode and removed old one (#10794)
|
||||
* updated price-info to edition 2018 (#10801)
|
||||
* ethcore-network-devp2p uses igd 0.9 (#10797)
|
||||
* updated parity-local-store to edition 2018 and removed redundant Error type (#10800)
|
||||
* Cleanup unused vm dependencies (#10787)
|
||||
* Removed redundant ethcore-service error type (#10788)
|
||||
* Removed machine abstraction from ethcore (#10791)
|
||||
* Updated blooms-db to rust 2018 and removed redundant deps (#10785)
|
||||
* ethkey no longer uses byteorder (#10786)
|
||||
* Log validator set changes in EpochManager (#10734)
|
||||
* Treat empty account the same as non-exist accounts in EIP-1052 (#10775)
|
||||
* docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652)
|
||||
|
||||
## Parity-Ethereum [v2.5.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.5)
|
||||
|
||||
Parity-Ethereum v2.5.5-stable is a minor release that improves performance and stability.
|
||||
This release stabilises the 2.5 branch.
|
||||
|
||||
As of today, Parity-Ethereum 2.4 reaches end of life and everyone is
|
||||
encouraged to upgrade.
|
||||
|
||||
## Parity-Ethereum [v2.5.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.4)
|
||||
|
||||
Parity Ethereum v2.5.4-beta is a security update that addresses servo/rust-smallvec#148
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* cargo update -p smallvec ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822))
|
||||
|
||||
## Parity-Ethereum [v2.5.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.3)
|
||||
|
||||
Parity-Ethereum 2.5.3-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
* EthereumClassic: activate the Atlantis Hardfork
|
||||
* Clique: fix time overflow
|
||||
* State tests: treat empty accounts the same as non-existant accounts (EIP 1052)
|
||||
* Networking: support discovery-only peers (geth bootnodes)
|
||||
* Snapshotting: fix unclean shutdown while snappshotting is under way
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/paritytech/parity-ethereum/pull/10766))
|
||||
* fix docker tags for publishing ([#10741](https://github.com/paritytech/parity-ethereum/pull/10741))
|
||||
* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720))
|
||||
* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/paritytech/parity-ethereum/pull/10775))
|
||||
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/paritytech/parity-ethereum/pull/10705))
|
||||
* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/paritytech/parity-ethereum/pull/10744))
|
||||
|
||||
## Parity-Ethereum [v2.5.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.2)
|
||||
|
||||
Parity-Ethereum 2.5.2-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
Among others, it enables the _Atlantis_ hardfork on **Morden** and **Kotti** Classic networks.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [CI] allow cargo audit to fail ([#10676](https://github.com/paritytech/parity-ethereum/pull/10676))
|
||||
* Reset blockchain properly ([#10669](https://github.com/paritytech/parity-ethereum/pull/10669))
|
||||
* new image ([#10673](https://github.com/paritytech/parity-ethereum/pull/10673))
|
||||
* Update publishing ([#10644](https://github.com/paritytech/parity-ethereum/pull/10644))
|
||||
* enable lto for release builds ([#10717](https://github.com/paritytech/parity-ethereum/pull/10717))
|
||||
* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/paritytech/parity-ethereum/pull/10719))
|
||||
* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/paritytech/parity-ethereum/pull/10731))
|
||||
|
||||
## Parity-Ethereum [v2.5.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.1)
|
||||
|
||||
Parity-Ethereum 2.5.1-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
Among others, it enables the Petersburg hardfork on **Rinkeby** and **POA-Core** Network, as well as the **Kovan** Network community hardfork.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638))
|
||||
|
||||
## Parity-Ethereum [v2.5.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.0)
|
||||
|
||||
Parity-Ethereum 2.5.0-beta is a minor release that improves performance and stabilizes the 2.5 branch by marking it as beta release.
|
||||
|
||||
- This release adds support for the Clique consensus engine ([#9981](https://github.com/paritytech/parity-ethereum/pull/9981))
|
||||
- This enables Parity-Ethereum users to use the Görli, the Kotti Classic, and the legacy Rinkeby testnet. To get started try `parity --chain goerli`; note that light client support is currently not yet fully functional.
|
||||
- This release removes the dead chain configs for Easthub and Ethereum Social ([#10531](https://github.com/paritytech/parity-ethereum/pull/10531))
|
||||
|
||||
As of today, Parity-Ethereum 2.3 reaches end of life and everyone is encouraged to upgrade.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* fix(light cull): poll light cull instead of timer ([#10559](https://github.com/paritytech/parity-ethereum/pull/10559))
|
||||
|
||||
* Move Engine::register_client to be before other I/O handler registration (#10767)
|
||||
* Print warnings when using dangerous settings for ValidatorSet (#10733)
|
||||
* ethcore/res: activate atlantis classic hf on block 8772000 (#10766)
|
||||
* refactor: Fix indentation (#10740)
|
||||
* Updated Bn128PairingImpl to use optimized batch pairing (#10765)
|
||||
* fix: aura don't add `SystemTime::now()` (#10720)
|
||||
* Initialize private tx logger only if private tx functionality is enabled (#10758)
|
||||
* Remove unused code (#10762)
|
||||
* Remove calls to heapsize (#10432)
|
||||
* [devp2p] Update to 2018 edition (#10716)
|
||||
* Add a way to signal shutdown to snapshotting threads (#10744)
|
||||
* Enable aesni (#10756)
|
||||
* remove support of old SS db formats (#10757)
|
||||
* [devp2p] Don't use `rust-crypto` (#10714)
|
||||
* updater: fix static id hashes initialization (#10755)
|
||||
* Use fewer threads for snapshotting (#10752)
|
||||
* Die error_chain, die (#10747)
|
||||
* Fix deprectation warnings on nightly (#10746)
|
||||
* fix docker tags for publishing (#10741)
|
||||
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet (#10705)
|
||||
* ethcore: enable ECIP-1054 for classic (#10731)
|
||||
* Stop breaking out of loop if a non-canonical hash is found (#10729)
|
||||
* Refactor Clique stepping (#10691)
|
||||
* Use RUSTFLAGS to set the optimization level (#10719)
|
||||
* SecretStore: non-blocking wait of session completion (#10303)
|
||||
* removed secret_store folder (#10722)
|
||||
* SecretStore: expose restore_key_public in HTTP API (#10241)
|
||||
* Revert "enable lto for release builds (#10717)" (#10721)
|
||||
* enable lto for release builds (#10717)
|
||||
* Merge `Notifier` and `TransactionsPoolNotifier` (#10591)
|
||||
* [devp2p] Fix warnings and re-org imports (#10710)
|
||||
* Upgrade ethereum types (#10670)
|
||||
* introduce MissingParent Error, fixes #10699 (#10700)
|
||||
* Update publishing (#10644)
|
||||
* Upgrade to parity-crypto 0.4 (#10650)
|
||||
* new image (#10673)
|
||||
* Add SealingState; don't prepare block when not ready. (#10529)
|
||||
* Fix compiler warning (that will become an error) (#10683)
|
||||
* add_sync_notifier in EthPubSubClient holds on to a Client for too long (#10689)
|
||||
* Don't panic if extra_data is longer than VANITY_LENGTH (#10682)
|
||||
* docs: evmbin - Update Rust docs (#10658)
|
||||
* Remove annoying compiler warnings (#10679)
|
||||
* Reset blockchain properly (#10669)
|
||||
* Remove support for hardware wallets (#10678)
|
||||
* [CI] allow cargo audit to fail (#10676)
|
||||
* docs: Add ProgPoW Rust docs to ethash module (#10653)
|
||||
* fix: Move PR template into .github/ folder (#10663)
|
||||
* docs: Add PR template (#10654)
|
||||
* Trivial journal for private transactions (#10056)
|
||||
* fix(compilation warnings) (#10649)
|
||||
* [whisper] Move needed aes_gcm crypto in-crate (#10647)
|
||||
* Adds parity_getRawBlockByNumber, parity_submitRawBlock (#10609)
|
||||
* Fix rinkeby petersburg fork (#10632)
|
||||
* ci: publish docs debug (#10638)
|
||||
* Fix publish docs (#10635)
|
||||
* Update kovan.json to switch validator set to POA Consensus Contracts (#10628)
|
||||
* [ethcore] remove error_chain (#10616)
|
||||
* Remove unused import (#10615)
|
||||
* evm: add some mulmod benches (#10600)
|
||||
* Clique: zero-fill extradata when the supplied value is less than 32 bytes in length (#10605)
|
||||
* Constantinople HF on POA Core (#10606)
|
||||
* adds rpc error message for --no-ancient-blocks (#10608)
|
||||
* Allow CORS requests in Secret Store API (#10584)
|
||||
* update bootnodes (#10595)
|
||||
* sccache logs to stdout (#10596)
|
||||
* fix(whisper expiry): current time + work + ttl (#10587)
|
||||
* CI improvements (#10579)
|
||||
* Watch transactions pool (#10558)
|
||||
* fix(evmbin): make benches compile again (#10586)
|
||||
* fix issue with compilation when 'slow-blocks' feature enabled (#10585)
|
||||
* Reject crazy timestamps instead of truncating. (#10574)
|
||||
* Node table limiting and cache for node filter (#10288)
|
||||
* fix(light cull): poll light cull instead of timer (#10559)
|
||||
* Update Issue Template to direct security issue to email (#10562)
|
||||
* RPC: Implements eth_subscribe("syncing") (#10311)
|
||||
* Explicitly enable or disable Stratum in config file (Issue 9785) (#10521)
|
||||
* version: bump master to 2.6 (#10560)
|
||||
|
||||
6264
Cargo.lock
generated
6264
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
109
Cargo.toml
109
Cargo.toml
@@ -2,40 +2,27 @@
|
||||
description = "Parity Ethereum client"
|
||||
name = "parity-ethereum"
|
||||
# NOTE Make sure to update util/version/Cargo.toml as well
|
||||
version = "2.5.12"
|
||||
version = "2.7.2"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
blooms-db = { path = "util/blooms-db" }
|
||||
log = "0.4"
|
||||
rustc-hex = "1.0"
|
||||
docopt = "1.0"
|
||||
clap = "2"
|
||||
term_size = "0.3"
|
||||
textwrap = "0.9"
|
||||
num_cpus = "1.2"
|
||||
number_prefix = "0.2"
|
||||
rpassword = "1.0"
|
||||
semver = "0.9"
|
||||
ansi_term = "0.10"
|
||||
parking_lot = "0.7"
|
||||
regex = "1.0"
|
||||
ansi_term = "0.11"
|
||||
atty = "0.2.8"
|
||||
toml = "0.4"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
serde_derive = "1.0"
|
||||
futures = "0.1"
|
||||
fdlimit = "0.1"
|
||||
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
|
||||
jsonrpc-core = "14.0.0"
|
||||
parity-bytes = "0.1"
|
||||
blooms-db = { path = "util/blooms-db" }
|
||||
clap = "2"
|
||||
cli-signer= { path = "cli-signer" }
|
||||
client-traits = { path = "ethcore/client-traits" }
|
||||
common-types = { path = "ethcore/types" }
|
||||
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
|
||||
dir = { path = "util/dir" }
|
||||
docopt = "1.0"
|
||||
engine = { path = "ethcore/engine" }
|
||||
ethabi = { version = "9.0.1", optional = true }
|
||||
ethcore = { path = "ethcore", features = ["parity"] }
|
||||
ethcore-accounts = { path = "accounts", optional = true }
|
||||
ethcore-blockchain = { path = "ethcore/blockchain" }
|
||||
ethcore-call-contract = { path = "ethcore/call-contract"}
|
||||
ethcore-call-contract = { path = "ethcore/call-contract", optional = true }
|
||||
ethcore-db = { path = "ethcore/db" }
|
||||
ethcore-io = { path = "util/io" }
|
||||
ethcore-light = { path = "ethcore/light" }
|
||||
@@ -43,35 +30,53 @@ ethcore-logger = { path = "parity/logger" }
|
||||
ethcore-miner = { path = "miner" }
|
||||
ethcore-network = { path = "util/network" }
|
||||
ethcore-private-tx = { path = "ethcore/private-tx" }
|
||||
ethcore-secretstore = { path = "secret-store", optional = true }
|
||||
ethcore-service = { path = "ethcore/service" }
|
||||
ethcore-sync = { path = "ethcore/sync" }
|
||||
ethereum-types = "0.4"
|
||||
ethereum-types = "0.8.0"
|
||||
ethkey = { path = "accounts/ethkey" }
|
||||
ethstore = { path = "accounts/ethstore" }
|
||||
fdlimit = "0.1"
|
||||
futures = "0.1"
|
||||
journaldb = { path = "util/journaldb" }
|
||||
jsonrpc-core = "14.0.3"
|
||||
keccak-hash = "0.4.0"
|
||||
kvdb = "0.3.1"
|
||||
kvdb-rocksdb = "0.4.1"
|
||||
log = "0.4"
|
||||
migration-rocksdb = { path = "util/migration-rocksdb" }
|
||||
node-filter = { path = "ethcore/node-filter" }
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
cli-signer= { path = "cli-signer" }
|
||||
num_cpus = "1.2"
|
||||
number_prefix = "0.2"
|
||||
panic_hook = { path = "util/panic-hook" }
|
||||
parity-bytes = "0.1"
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
parity-daemonize = "0.3"
|
||||
parity-hash-fetch = { path = "updater/hash-fetch" }
|
||||
parity-ipfs-api = { path = "ipfs" }
|
||||
parity-local-store = { path = "miner/local-store" }
|
||||
parity-runtime = { path = "util/runtime" }
|
||||
parity-rpc = { path = "rpc" }
|
||||
parity-updater = { path = "updater" }
|
||||
parity-version = { path = "util/version" }
|
||||
parity-whisper = { path = "whisper" }
|
||||
parity-path = "0.1"
|
||||
dir = { path = "util/dir" }
|
||||
panic_hook = { path = "util/panic-hook" }
|
||||
keccak-hash = "0.1"
|
||||
migration-rocksdb = { path = "util/migration-rocksdb" }
|
||||
kvdb = "0.1"
|
||||
kvdb-rocksdb = "0.1.3"
|
||||
journaldb = { path = "util/journaldb" }
|
||||
|
||||
ethcore-secretstore = { path = "secret-store", optional = true }
|
||||
|
||||
parity-rpc = { path = "rpc" }
|
||||
parity-runtime = { path = "util/runtime" }
|
||||
parity-updater = { path = "updater" }
|
||||
parity-util-mem = { version = "0.3.0", features = ["jemalloc-global"] }
|
||||
parity-version = { path = "util/version" }
|
||||
parking_lot = "0.9"
|
||||
regex = "1.0"
|
||||
registrar = { path = "util/registrar" }
|
||||
rlp = "0.4.0"
|
||||
rpassword = "1.0"
|
||||
rustc-hex = "1.0"
|
||||
semver = "0.9"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
snapshot = { path = "ethcore/snapshot" }
|
||||
spec = { path = "ethcore/spec" }
|
||||
term_size = "0.3"
|
||||
textwrap = "0.9"
|
||||
toml = "0.4"
|
||||
verification = { path = "ethcore/verification" }
|
||||
|
||||
[build-dependencies]
|
||||
rustc_version = "0.2"
|
||||
@@ -81,7 +86,6 @@ pretty_assertions = "0.1"
|
||||
ipnetwork = "0.12.6"
|
||||
tempdir = "0.3"
|
||||
fake-fetch = { path = "util/fake-fetch" }
|
||||
lazy_static = "1.2.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
|
||||
@@ -91,12 +95,11 @@ default = ["accounts"]
|
||||
accounts = ["ethcore-accounts", "parity-rpc/accounts"]
|
||||
miner-debug = ["ethcore/miner-debug"]
|
||||
json-tests = ["ethcore/json-tests"]
|
||||
ci-skip-tests = ["ethcore/ci-skip-tests"]
|
||||
test-heavy = ["ethcore/test-heavy"]
|
||||
evm-debug = ["ethcore/evm-debug"]
|
||||
evm-debug-tests = ["ethcore/evm-debug-tests"]
|
||||
slow-blocks = ["ethcore/slow-blocks"]
|
||||
secretstore = ["ethcore-secretstore", "ethcore-secretstore/accounts"]
|
||||
secretstore = ["ethcore-secretstore", "accounts", "ethabi", "ethcore-call-contract"]
|
||||
final = ["parity-version/final"]
|
||||
deadlock_detection = ["parking_lot/deadlock_detection"]
|
||||
# to create a memory profile (requires nightly rust), use e.g.
|
||||
@@ -118,10 +121,6 @@ path = "parity/lib.rs"
|
||||
path = "parity/main.rs"
|
||||
name = "parity"
|
||||
|
||||
[profile.test]
|
||||
lto = false
|
||||
opt-level = 3 # makes tests slower to compile, but faster to run
|
||||
|
||||
[profile.release]
|
||||
debug = false
|
||||
lto = true
|
||||
@@ -136,14 +135,4 @@ members = [
|
||||
"chainspec",
|
||||
"ethcore/wasm/run",
|
||||
"evmbin",
|
||||
"parity-clib",
|
||||
"whisper/cli",
|
||||
"util/triehash-ethereum",
|
||||
"util/keccak-hasher",
|
||||
"util/patricia-trie-ethereum",
|
||||
"util/fastmap",
|
||||
"util/time-utils"
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
heapsize = { git = "https://github.com/cheme/heapsize.git", branch = "ec-macfix" }
|
||||
|
||||
@@ -57,7 +57,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
|
||||
$ curl https://sh.rustup.rs -sSf | sh
|
||||
```
|
||||
|
||||
Parity Ethereum also requires `gcc`, `g++`, `libudev-dev`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
|
||||
Parity Ethereum also requires `gcc`, `g++`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
|
||||
|
||||
- OSX:
|
||||
```bash
|
||||
@@ -320,10 +320,6 @@ Caching, Importing Blocks, and Block Information
|
||||
patricia-trie-ethereum registrar rlp_compress rlp_derive parity-runtime stats
|
||||
time-utils triehash-ethereum unexpected parity-version
|
||||
```
|
||||
* Parity Whisper Protocol Implementation
|
||||
```bash
|
||||
parity-whisper whisper-cli
|
||||
```
|
||||
|
||||
</p></details>
|
||||
|
||||
@@ -360,10 +356,10 @@ In addition to the Parity Ethereum client, there are additional tools in this re
|
||||
- [evmbin](./evmbin) - Parity Ethereum EVM Implementation.
|
||||
- [ethstore](./accounts/ethstore) - Parity Ethereum Key Management.
|
||||
- [ethkey](./accounts/ethkey) - Parity Ethereum Keys Generator.
|
||||
- [whisper](./whisper) - Parity Ethereum Whisper-v2 PoC Implementation.
|
||||
|
||||
The following tool is available in a separate repository:
|
||||
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi)
|
||||
- [whisper](https://github.com/paritytech/whisper) - Parity Ethereum Whisper-v2 PoC Implementation.
|
||||
|
||||
## 7. Community <a id="chapter-007"></a>
|
||||
|
||||
|
||||
77
SECURITY.md
77
SECURITY.md
@@ -48,33 +48,54 @@ Our Bug Bounty Program allows us to recognise and reward members of the Parity c
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFlyIAwBCACe0keNPjgYzZ1Oy/8t3zj/Qw9bHHqrzx7FWy8NbXnYBM19NqOZ
|
||||
DIP7Oe0DvCaf/uruBskCS0iVstHlEFQ2AYe0Ei0REt9lQdy61GylU/DEB3879IG+
|
||||
6FO0SnFeYeerv1/hFI2K6uv8v7PyyVDiiJSW0I1KIs2OBwJicTKmWxLAeQsRgx9G
|
||||
yRGalrVk4KP+6pWTA7k3DxmDZKZyfYV/Ej10NtuzmsemwDbv98HKeomp/kgFOfSy
|
||||
3AZjeCpctlsNqpjUuXa0/HudmH2WLxZ0fz8XeoRh8XM9UudNIecjrDqmAFrt/btQ
|
||||
/3guvlzhFCdhYPVGsUusKMECk/JG+Xx1/1ZjABEBAAG0LFBhcml0eSBTZWN1cml0
|
||||
eSBDb250YWN0IDxzZWN1cml0eUBwYXJpdHkuaW8+iQFUBBMBCAA+FiEE2uUVYCjP
|
||||
N6B8aTiDXQ8DAY0H3nMFAllyIAwCGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYCAwEC
|
||||
HgECF4AACgkQXQ8DAY0H3nM60wgAkS3A36Zc+upiaxU7tumcGv+an17j7gin0sif
|
||||
+0ELSjVfrXInM6ovai+NhUdcLkJ7tCrKS90fvlaELK5Sg9CXBWCTFccKN4A/B7ey
|
||||
rOg2NPXUecnyBB/XqQgKYH7ujYlOlqBDXMfz6z8Hj6WToxg9PPMGGomyMGh8AWxM
|
||||
3yRPFs5RKt0VKgN++5N00oly5Y8ri5pgCidDvCLYMGTVDHFKwkuc9w6BlWlu1R1e
|
||||
/hXFWUFAP1ffTAul3QwyKhjPn2iotCdxXjvt48KaU8DN4iL7aMBN/ZBKqGS7yRdF
|
||||
D/JbJyaaJ0ZRvFSTSXy/sWY3z1B5mtCPBxco8hqqNfRkCwuZ6LkBDQRZciAMAQgA
|
||||
8BP8xrwe12TOUTqL/Vrbxv/FLdhKh53J6TrPKvC2TEEKOrTNo5ahRq+XOS5E7G2N
|
||||
x3b+fq8gR9BzFcldAx0XWUtGs/Wv++ulaSNqTBxj13J3G3WGsUfMKxRgj//piCUD
|
||||
bCFLQfGZdKk0M1o9QkPVARwwmvCNiNB/l++xGqPtfc44H5jWj3GoGvL2MkShPzrN
|
||||
yN/bJ+m+R5gtFGdInqa5KXBuxxuW25eDKJ+LzjbgUgeC76wNcfOiQHTdMkcupjdO
|
||||
bbGFwo10hcbRAOcZEv6//Zrlmk/6nPxEd2hN20St2bSN0+FqfZ267mWEu3ejsgF8
|
||||
ArdCpv5h4fBvJyNwiTZwIQARAQABiQE8BBgBCAAmFiEE2uUVYCjPN6B8aTiDXQ8D
|
||||
AY0H3nMFAllyIAwCGwwFCQPCZwAACgkQXQ8DAY0H3nNisggAl4fqhRlA34wIb190
|
||||
sqXHVxiCuzPaqS6krE9xAa1+gncX485OtcJNqnjugHm2rFE48lv7oasviuPXuInE
|
||||
/OgVFnXYv9d/Xx2JUeDs+bFTLouCDRY2Unh7KJZasfqnMcCHWcxHx5FvRNZRssaB
|
||||
WTZVo6sizPurGUtbpYe4/OLFhadBqAE0EUmVRFEUMc1YTnu4eLaRBzoWN4d2UWwi
|
||||
LN25RSrVSke7LTSFbgn9ntQrQ2smXSR+cdNkkfRCjFcpUaecvFl9HwIqoyVbT4Ym
|
||||
0hbpbbX/cJdc91tKa+psa29uMeGL/cgL9fAu19yNFRyOTMxjZnvql1X/WE1pLmoP
|
||||
ETBD1Q==
|
||||
=K9Qw
|
||||
mQINBF0vHwQBEADKui4qAo4bzdzRhMm+uhUpYGf8jjjmET3zJ8kKQIpp6JTsV+HJ
|
||||
6m1We0QYeMRXoOYH1xVHBf2zNCuHS0nSQdUCQA7SHWsPB05STa2hvlR7fSdQnCCp
|
||||
gnLOJWXvvedlRDIAhvqI6cwLdUlXgVSKEwrwmrpiBhh4NxI3qX+LyIa+Ovkchu2S
|
||||
d/YCnE4GqojSGRfJYiGwe2N+sF7OfaoKhQuTrtdDExHrMU4cWnTXW2wyxTr4xkj9
|
||||
jS2WeLVZWflvkDHT8JD9N6jNxBVEF/Qvjk83zI0kCOzkhek8x+YUgfLq3/rHOYbX
|
||||
3pW21ccHYPacHjHWvKE+xRebjeEhJ4KxKHfCVjQcxybwDBqDka1AniZt4CQ7UORf
|
||||
MU/ue2oSZ9nNg0uMdb/0AbQPZ04OlMcYPAPWzFL08nVPox9wT9uqlL6JtcOeC90h
|
||||
oOeDmfgwmjMmdwWTRgt9qQjcbgXzVvuAzIGbzj1X3MdLspWdHs/d2+US4nji1TkN
|
||||
oYIW7vE+xkd3aB+NZunIlm9Rwd/0mSgDg+DaNa5KceOLhq0/qKgcXC/RRU29I8II
|
||||
tusRoR/oesGJGYTjh4k6PJkG+nvDPsoQrwYT44bhnniS1xYkxWYXF99JFI7LgMdD
|
||||
e1SgKeIDVpvm873k82E6arp5655Wod1XOjaXBggCwFp84eKcEZEN+1qEWwARAQAB
|
||||
tClQYXJpdHkgU2VjdXJpdHkgVGVhbSA8c2VjdXJpdHlAcGFyaXR5LmlvPokCVAQT
|
||||
AQoAPhYhBJ1LK264+XFW0ZZpqf8IEtSRuWeYBQJdLx8EAhsDBQkDwmcABQsJCAcC
|
||||
BhUKCQgLAgQWAgMBAh4BAheAAAoJEP8IEtSRuWeYL84QAI6NwnwS561DWYYRAd4y
|
||||
ocGPr3CnwFSt1GjkSkRy3B+tMhzexBg1y7EbLRUefIrO4LwOlywtRk8tTRGgEI4i
|
||||
5xRLHbOkeolfgCFSpOj5d8cMKCt5HEIv18hsv6dkrzlSYA5NLX/GRBEh3F/0sGny
|
||||
vCXapfxa1cx72sU7631JBK7t2Tf+MfwxdfyFZ9TI9WdtP5AfVjgTkIVkEDFcZPTc
|
||||
n3CYXqTYFIBCNUD8LP4iTi3xUt7pTGJQQoFT8l15nJCgzRYQ+tXpoTRlf+/LtXmw
|
||||
6iidPV87E06jHdK9666rBouIabAtx7i0/4kwo+bSZ8DiSKRUaehiHGd212HSEmdF
|
||||
jxquWE4pEzoUowYznhSIfR+WWIqRBHxEYarP4m98Hi+VXZ7Fw1ytzO8+BAKnLXnj
|
||||
2W2+T9qJks5gqVEoaWNnqpvya6JA11QZvZ0w7Om2carDc2ILNm2Xx9J0mRUye8P0
|
||||
KxcgqJuKNGFtugebQAsXagkxOKsdKna1PlDlxEfTf6AgI3ST8qSiMAwaaIMB/REF
|
||||
VKUapGoslQX4tOCjibI2pzEgE//D8NAaSVu2A9+BUcFERdZRxsI7fydIXNeZ2R46
|
||||
N2qfW+DP3YR/14QgdRxDItEavUoE1vByRXwIufKAkVemOZzIoFXKFsDeXwqTVW5i
|
||||
6CXu6OddZ3QHDiT9TEbRny4QuQINBF0vKCwBEACnP5J7LEGbpxNBrPvGdxZUo0YA
|
||||
U8RgeKDRPxJTvMo27V1IPZGaKRCRq8LBfg/eHhqZhQ7SLJBjBljd8kuT5dHDBTRe
|
||||
jE1UIOhmnlSlrEJjAmpVO08irlGpq1o+8mGcvkBsR0poCVjeNeSnwYfRnR+c3GK5
|
||||
Er6/JRqfN4mJvnEC9/Pbm6C7ql6YLKxC3yqzF97JL5brbbuozrW7nixY/yAI8619
|
||||
VlBIMP7PAUbGcnSQyuV5b/Wr2Sgr6NJclnNSLjh2U9/Du6w/0tDGlMBts8HjRnWJ
|
||||
BXbkTdQKCTaqgK68kTKSiN1/x+lynxHC2AavMpH/08Kopg2ZCzJowMKIgcB+4Z/I
|
||||
DJKZWHWKumhaZMGXcWgzgcByog9IpamuROEZFJNEUAFf7YIncEckPSif4looiOdS
|
||||
VurKZGvYXXaGSsZbGgHxI5CWu7ZxMdLBLvtOcCYmRQrG+g/h+PGU5BT0bNAfNTkm
|
||||
V3/n1B/TWbpWRmB3AwT2emQivXHkaubGI0VivhaO43AuI9JWoqiMqFtxbuTeoxwD
|
||||
xlu2Dzcp0v+AR4T5cIG9D5/+yiPc25aIY7cIKxuNFHIDL4td5fwSGC7vU6998PIG
|
||||
2Y48TGBnw7zpEfDfMayqAeBjX0YU6PTNsvS5O6bP3j4ojTOUYD7Z8QdCvgISDID3
|
||||
WMGAdmSwmCRvsQ/OJwARAQABiQI8BBgBCgAmFiEEnUsrbrj5cVbRlmmp/wgS1JG5
|
||||
Z5gFAl0vKCwCGwwFCQB2pwAACgkQ/wgS1JG5Z5hdbw//ZqR+JcWm59NUIHjauETJ
|
||||
sYDYhcAfa3txTacRn5uPz/TQiTd7wZ82+G8Et0ZnpEHy6eWyBqHpG0hiPhFBzxjY
|
||||
nhjHl8jJeyo2mQIVJhzkL58BHBZk8WM2TlaU7VxZ6TYOmP2y3qf6FD6mCcrQ4Fml
|
||||
E9f0lyVUoI/5Zs9oF0izRk8vkwaY3UvLM7XEY6nM8GnFG8kaiZMYmx26Zo7Uz31G
|
||||
7EGGZFsrVDXfNhSJyz79Gyn+Lx9jOTdoR0sH/THYIIosE83awMGE6jKeuDYTbVWu
|
||||
+ZtHQef+pRteki3wvNLJK+kC1y3BtHqDJS9Lqx0s8SCiVozlC+fZfC9hCtU7bXJK
|
||||
0UJZ4qjSvj6whzfaNgOZAqJpmwgOnd8W/3YJk1DwUeX98FcU38MR23SOkx2EDdDE
|
||||
77Kdu62vTs/tLmOTuyKBvYPaHaYulYjQTxurG+o8vhHtaL87ARvuq+83dj+nO5z3
|
||||
5O9vkcVJYWjOEnJe7ZvCTxeLJehpCmHIbyUuDx5P24MWVbyXOxIlxNxTqlub5GlW
|
||||
rQF6Qsa/0k9TRk7Htbct6fAA0/VahJS0g096MrTH8AxBXDNE8lIoNeGikVlaxK9Z
|
||||
S+aannlWYIJymZ4FygIPPaRlzhAoXBuJd8OaR5giC7dS1xquxKOiQEXTGsLeGFaI
|
||||
BZYiIhW7GG4ozvKDqyNm4eg=
|
||||
=yKcB
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
||||
@@ -8,21 +8,15 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
common-types = { path = "../ethcore/types" }
|
||||
ethkey = { path = "ethkey" }
|
||||
ethstore = { path = "ethstore" }
|
||||
log = "0.4"
|
||||
parking_lot = "0.7"
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
parking_lot = "0.9"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))'.dependencies]
|
||||
hardware-wallet = { path = "hw" }
|
||||
|
||||
[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))'.dependencies]
|
||||
fake-hardware-wallet = { path = "fake-hardware-wallet" }
|
||||
|
||||
[dev-dependencies]
|
||||
ethereum-types = "0.4"
|
||||
ethereum-types = "0.8.0"
|
||||
tempdir = "0.3"
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
[package]
|
||||
description = "Parity Ethereum Keys Generator"
|
||||
name = "ethkey"
|
||||
version = "0.3.0"
|
||||
version = "0.4.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
edit-distance = "2.0"
|
||||
parity-crypto = "0.3.0"
|
||||
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "ccc06e7480148b723eb44ac56cf4d20eec380b6f" }
|
||||
ethereum-types = "0.4"
|
||||
lazy_static = "1.0"
|
||||
log = "0.4"
|
||||
memzero = { path = "../../util/memzero" }
|
||||
parity-wordlist = "1.3"
|
||||
quick-error = "1.2.2"
|
||||
rand = "0.4"
|
||||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
tiny-keccak = "1.4"
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
parity-wordlist = "1.3"
|
||||
|
||||
@@ -6,7 +6,7 @@ Parity Ethereum keys generator.
|
||||
|
||||
```
|
||||
Parity Ethereum Keys Generator.
|
||||
Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
|
||||
Usage:
|
||||
ethkey info <secret-or-phrase> [options]
|
||||
@@ -218,4 +218,4 @@ _This project is a part of the Parity Ethereum toolchain._
|
||||
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding.
|
||||
- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/accounts/ethstore) - Parity Ethereum key management.
|
||||
- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/accounts/ethkey) - Parity Ethereum keys generator.
|
||||
- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC.
|
||||
- [whisper](https://github.com/paritytech/whisper) - Implementation of Whisper-v2 PoC.
|
||||
|
||||
@@ -9,7 +9,8 @@ docopt = "1.0"
|
||||
env_logger = "0.5"
|
||||
ethkey = { path = "../" }
|
||||
panic_hook = { path = "../../../util/panic-hook" }
|
||||
parity-wordlist="1.3"
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
parity-wordlist="1.2"
|
||||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -19,6 +19,7 @@ extern crate env_logger;
|
||||
extern crate ethkey;
|
||||
extern crate panic_hook;
|
||||
extern crate parity_wordlist;
|
||||
extern crate parity_crypto;
|
||||
extern crate rustc_hex;
|
||||
extern crate serde;
|
||||
extern crate threadpool;
|
||||
@@ -30,12 +31,13 @@ use std::num::ParseIntError;
|
||||
use std::{env, fmt, process, io, sync};
|
||||
|
||||
use docopt::Docopt;
|
||||
use ethkey::{KeyPair, Random, Brain, BrainPrefix, Prefix, Error as EthkeyError, Generator, sign, verify_public, verify_address, brain_recover};
|
||||
use ethkey::{Brain, BrainPrefix, Prefix, brain_recover};
|
||||
use parity_crypto::publickey::{KeyPair, Random, Error as EthkeyError, Generator, sign, verify_public, verify_address};
|
||||
use rustc_hex::{FromHex, FromHexError};
|
||||
|
||||
const USAGE: &'static str = r#"
|
||||
Parity Ethereum keys generator.
|
||||
Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
|
||||
Usage:
|
||||
ethkey info <secret-or-phrase> [options]
|
||||
@@ -200,7 +202,7 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
|
||||
let keypair = Brain::new(phrase).generate().expect("Brain wallet generator is infallible; qed");
|
||||
(keypair, Some(phrase_info))
|
||||
} else {
|
||||
let secret = args.arg_secret_or_phrase.parse().map_err(|_| EthkeyError::InvalidSecret)?;
|
||||
let secret = args.arg_secret_or_phrase.parse().map_err(|_| EthkeyError::InvalidSecretKey)?;
|
||||
(KeyPair::from_secret(secret)?, None)
|
||||
};
|
||||
Ok(display(result, display_mode))
|
||||
@@ -241,7 +243,7 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
|
||||
};
|
||||
Ok(display(result, display_mode))
|
||||
} else if args.cmd_sign {
|
||||
let secret = args.arg_secret.parse().map_err(|_| EthkeyError::InvalidSecret)?;
|
||||
let secret = args.arg_secret.parse().map_err(|_| EthkeyError::InvalidSecretKey)?;
|
||||
let message = args.arg_message.parse().map_err(|_| EthkeyError::InvalidMessage)?;
|
||||
let signature = sign(&secret, &message)?;
|
||||
Ok(format!("{}", signature))
|
||||
@@ -249,7 +251,7 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
|
||||
let signature = args.arg_signature.parse().map_err(|_| EthkeyError::InvalidSignature)?;
|
||||
let message = args.arg_message.parse().map_err(|_| EthkeyError::InvalidMessage)?;
|
||||
let ok = if args.cmd_public {
|
||||
let public = args.arg_public.parse().map_err(|_| EthkeyError::InvalidPublic)?;
|
||||
let public = args.arg_public.parse().map_err(|_| EthkeyError::InvalidPublicKey)?;
|
||||
verify_public(&public, &signature, &message)?
|
||||
} else if args.cmd_address {
|
||||
let address = args.arg_address.parse().map_err(|_| EthkeyError::InvalidAddress)?;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -14,8 +14,9 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use keccak::Keccak256;
|
||||
use super::{KeyPair, Generator, Secret};
|
||||
use std::convert::Infallible;
|
||||
use parity_crypto::publickey::{KeyPair, Generator, Secret};
|
||||
use parity_crypto::Keccak256;
|
||||
use parity_wordlist;
|
||||
|
||||
/// Simple brainwallet.
|
||||
@@ -32,7 +33,7 @@ impl Brain {
|
||||
}
|
||||
|
||||
impl Generator for Brain {
|
||||
type Error = ::Void;
|
||||
type Error = Infallible;
|
||||
|
||||
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
|
||||
let seed = self.0.clone();
|
||||
@@ -45,7 +46,7 @@ impl Generator for Brain {
|
||||
match i > 16384 {
|
||||
false => i += 1,
|
||||
true => {
|
||||
if let Ok(pair) = Secret::from_unsafe_slice(&secret)
|
||||
if let Ok(pair) = Secret::import_key(&secret)
|
||||
.and_then(KeyPair::from_secret)
|
||||
{
|
||||
if pair.address()[0] == 0 {
|
||||
@@ -61,7 +62,8 @@ impl Generator for Brain {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {Brain, Generator};
|
||||
use Brain;
|
||||
use parity_crypto::publickey::Generator;
|
||||
|
||||
#[test]
|
||||
fn test_brain() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -14,7 +14,8 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{Generator, KeyPair, Error, Brain};
|
||||
use super::Brain;
|
||||
use parity_crypto::publickey::{Generator, KeyPair, Error};
|
||||
use parity_wordlist as wordlist;
|
||||
|
||||
/// Tries to find brain-seed keypair with address starting with given prefix.
|
||||
@@ -47,7 +48,7 @@ impl Generator for BrainPrefix {
|
||||
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) {
|
||||
if keypair.address().as_ref().starts_with(&self.prefix) {
|
||||
self.last_phrase = phrase;
|
||||
return Ok(keypair)
|
||||
}
|
||||
@@ -59,12 +60,13 @@ impl Generator for BrainPrefix {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {Generator, BrainPrefix};
|
||||
use BrainPrefix;
|
||||
use parity_crypto::publickey::Generator;
|
||||
|
||||
#[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));
|
||||
assert!(keypair.address().as_bytes().starts_with(&prefix));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -19,7 +19,8 @@ use std::collections::HashSet;
|
||||
use edit_distance::edit_distance;
|
||||
use parity_wordlist;
|
||||
|
||||
use super::{Address, Brain, Generator};
|
||||
use super::Brain;
|
||||
use parity_crypto::publickey::{Address, Generator};
|
||||
|
||||
/// Tries to find a phrase for address, given the number
|
||||
/// of expected words and a partial phrase.
|
||||
|
||||
@@ -1,189 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use secp256k1;
|
||||
use std::io;
|
||||
use parity_crypto::error::SymmError;
|
||||
|
||||
quick_error! {
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
Secp(e: secp256k1::Error) {
|
||||
display("secp256k1 error: {}", e)
|
||||
cause(e)
|
||||
from()
|
||||
}
|
||||
Io(e: io::Error) {
|
||||
display("i/o error: {}", e)
|
||||
cause(e)
|
||||
from()
|
||||
}
|
||||
InvalidMessage {
|
||||
display("invalid message")
|
||||
}
|
||||
Symm(e: SymmError) {
|
||||
cause(e)
|
||||
from()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ECDH functions
|
||||
pub mod ecdh {
|
||||
use secp256k1::{self, ecdh, key};
|
||||
use super::Error;
|
||||
use {Secret, Public, SECP256K1};
|
||||
|
||||
/// Agree on a shared secret
|
||||
pub fn agree(secret: &Secret, public: &Public) -> Result<Secret, Error> {
|
||||
let context = &SECP256K1;
|
||||
let pdata = {
|
||||
let mut temp = [4u8; 65];
|
||||
(&mut temp[1..65]).copy_from_slice(&public[0..64]);
|
||||
temp
|
||||
};
|
||||
|
||||
let publ = key::PublicKey::from_slice(context, &pdata)?;
|
||||
let sec = key::SecretKey::from_slice(context, &secret)?;
|
||||
let shared = ecdh::SharedSecret::new_raw(context, &publ, &sec);
|
||||
|
||||
Secret::from_unsafe_slice(&shared[0..32])
|
||||
.map_err(|_| Error::Secp(secp256k1::Error::InvalidSecretKey))
|
||||
}
|
||||
}
|
||||
|
||||
/// ECIES function
|
||||
pub mod ecies {
|
||||
use parity_crypto::{aes, digest, hmac, is_equal};
|
||||
use ethereum_types::H128;
|
||||
use super::{ecdh, Error};
|
||||
use {Random, Generator, Public, Secret};
|
||||
|
||||
/// Encrypt a message with a public key, writing an HMAC covering both
|
||||
/// the plaintext and authenticated data.
|
||||
///
|
||||
/// Authenticated data may be empty.
|
||||
pub fn encrypt(public: &Public, auth_data: &[u8], plain: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let r = Random.generate()?;
|
||||
let z = ecdh::agree(r.secret(), public)?;
|
||||
let mut key = [0u8; 32];
|
||||
kdf(&z, &[0u8; 0], &mut key);
|
||||
|
||||
let ekey = &key[0..16];
|
||||
let mkey = hmac::SigKey::sha256(&digest::sha256(&key[16..32]));
|
||||
|
||||
let mut msg = vec![0u8; 1 + 64 + 16 + plain.len() + 32];
|
||||
msg[0] = 0x04u8;
|
||||
{
|
||||
let msgd = &mut msg[1..];
|
||||
msgd[0..64].copy_from_slice(r.public());
|
||||
let iv = H128::random();
|
||||
msgd[64..80].copy_from_slice(&iv);
|
||||
{
|
||||
let cipher = &mut msgd[(64 + 16)..(64 + 16 + plain.len())];
|
||||
aes::encrypt_128_ctr(ekey, &iv, plain, cipher)?;
|
||||
}
|
||||
let mut hmac = hmac::Signer::with(&mkey);
|
||||
{
|
||||
let cipher_iv = &msgd[64..(64 + 16 + plain.len())];
|
||||
hmac.update(cipher_iv);
|
||||
}
|
||||
hmac.update(auth_data);
|
||||
let sig = hmac.sign();
|
||||
msgd[(64 + 16 + plain.len())..].copy_from_slice(&sig);
|
||||
}
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
/// 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<Vec<u8>, Error> {
|
||||
let meta_len = 1 + 64 + 16 + 32;
|
||||
if encrypted.len() < meta_len || encrypted[0] < 2 || encrypted[0] > 4 {
|
||||
return Err(Error::InvalidMessage); //invalid message: publickey
|
||||
}
|
||||
|
||||
let e = &encrypted[1..];
|
||||
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 = hmac::SigKey::sha256(&digest::sha256(&key[16..32]));
|
||||
|
||||
let clen = encrypted.len() - meta_len;
|
||||
let cipher_with_iv = &e[64..(64+16+clen)];
|
||||
let cipher_iv = &cipher_with_iv[0..16];
|
||||
let cipher_no_iv = &cipher_with_iv[16..];
|
||||
let msg_mac = &e[(64+16+clen)..];
|
||||
|
||||
// Verify tag
|
||||
let mut hmac = hmac::Signer::with(&mkey);
|
||||
hmac.update(cipher_with_iv);
|
||||
hmac.update(auth_data);
|
||||
let mac = hmac.sign();
|
||||
|
||||
if !is_equal(&mac.as_ref()[..], msg_mac) {
|
||||
return Err(Error::InvalidMessage);
|
||||
}
|
||||
|
||||
let mut msg = vec![0u8; clen];
|
||||
aes::decrypt_128_ctr(ekey, cipher_iv, cipher_no_iv, &mut msg[..])?;
|
||||
Ok(msg)
|
||||
}
|
||||
|
||||
fn kdf(secret: &Secret, s1: &[u8], dest: &mut [u8]) {
|
||||
// SEC/ISO/Shoup specify counter size SHOULD be equivalent
|
||||
// to size of hash output, however, it also notes that
|
||||
// the 4 bytes is okay. NIST specifies 4 bytes.
|
||||
let mut ctr = 1u32;
|
||||
let mut written = 0usize;
|
||||
while written < dest.len() {
|
||||
let mut hasher = digest::Hasher::sha256();
|
||||
let ctrs = [(ctr >> 24) as u8, (ctr >> 16) as u8, (ctr >> 8) as u8, ctr as u8];
|
||||
hasher.update(&ctrs);
|
||||
hasher.update(secret);
|
||||
hasher.update(s1);
|
||||
let d = hasher.finish();
|
||||
&mut dest[written..(written + 32)].copy_from_slice(&d);
|
||||
written += 32;
|
||||
ctr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::ecies;
|
||||
use {Random, Generator};
|
||||
|
||||
#[test]
|
||||
fn ecies_shared() {
|
||||
let kp = Random.generate().unwrap();
|
||||
let message = b"So many books, so little time";
|
||||
|
||||
let shared = b"shared";
|
||||
let wrong_shared = b"incorrect";
|
||||
let encrypted = ecies::encrypt(kp.public(), shared, message).unwrap();
|
||||
assert!(encrypted[..] != message[..]);
|
||||
assert_eq!(encrypted[0], 0x04);
|
||||
|
||||
assert!(ecies::decrypt(kp.secret(), wrong_shared, &encrypted).is_err());
|
||||
let decrypted = ecies::decrypt(kp.secret(), shared, &encrypted).unwrap();
|
||||
assert_eq!(decrypted[..message.len()], message[..]);
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::{fmt, error};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Crypto error
|
||||
pub enum Error {
|
||||
/// Invalid secret key
|
||||
InvalidSecret,
|
||||
/// Invalid public key
|
||||
InvalidPublic,
|
||||
/// Invalid address
|
||||
InvalidAddress,
|
||||
/// Invalid EC signature
|
||||
InvalidSignature,
|
||||
/// Invalid AES message
|
||||
InvalidMessage,
|
||||
/// IO Error
|
||||
Io(::std::io::Error),
|
||||
/// Custom
|
||||
Custom(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let msg = match *self {
|
||||
Error::InvalidSecret => "Invalid secret".into(),
|
||||
Error::InvalidPublic => "Invalid public".into(),
|
||||
Error::InvalidAddress => "Invalid address".into(),
|
||||
Error::InvalidSignature => "Invalid EC signature".into(),
|
||||
Error::InvalidMessage => "Invalid AES message".into(),
|
||||
Error::Io(ref err) => format!("I/O error: {}", err),
|
||||
Error::Custom(ref s) => s.clone(),
|
||||
};
|
||||
|
||||
f.write_fmt(format_args!("Crypto error ({})", msg))
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn description(&self) -> &str {
|
||||
"Crypto error"
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for Error {
|
||||
fn into(self) -> String {
|
||||
format!("{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::secp256k1::Error> for Error {
|
||||
fn from(e: ::secp256k1::Error) -> Error {
|
||||
match e {
|
||||
::secp256k1::Error::InvalidMessage => Error::InvalidMessage,
|
||||
::secp256k1::Error::InvalidPublicKey => Error::InvalidPublic,
|
||||
::secp256k1::Error::InvalidSecretKey => Error::InvalidSecret,
|
||||
_ => Error::InvalidSignature,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<::std::io::Error> for Error {
|
||||
fn from(err: ::std::io::Error) -> Error {
|
||||
Error::Io(err)
|
||||
}
|
||||
}
|
||||
@@ -1,500 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Extended keys
|
||||
|
||||
use secret::Secret;
|
||||
use Public;
|
||||
use ethereum_types::H256;
|
||||
pub use self::derivation::Error as DerivationError;
|
||||
|
||||
/// Represents label that can be stored as a part of key derivation
|
||||
pub trait Label {
|
||||
/// Length of the data that label occupies
|
||||
fn len() -> usize;
|
||||
|
||||
/// Store label data to the key derivation sequence
|
||||
/// Must not use more than `len()` bytes from slice
|
||||
fn store(&self, target: &mut [u8]);
|
||||
}
|
||||
|
||||
impl Label for u32 {
|
||||
fn len() -> usize { 4 }
|
||||
|
||||
fn store(&self, target: &mut [u8]) {
|
||||
let bytes = self.to_be_bytes();
|
||||
target[0..4].copy_from_slice(&bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/// Key derivation over generic label `T`
|
||||
pub enum Derivation<T: Label> {
|
||||
/// Soft key derivation (allow proof of parent)
|
||||
Soft(T),
|
||||
/// Hard key derivation (does not allow proof of parent)
|
||||
Hard(T),
|
||||
}
|
||||
|
||||
impl From<u32> for Derivation<u32> {
|
||||
fn from(index: u32) -> Self {
|
||||
if index < (2 << 30) {
|
||||
Derivation::Soft(index)
|
||||
}
|
||||
else {
|
||||
Derivation::Hard(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Label for H256 {
|
||||
fn len() -> usize { 32 }
|
||||
|
||||
fn store(&self, target: &mut [u8]) {
|
||||
self.copy_to(&mut target[0..32]);
|
||||
}
|
||||
}
|
||||
|
||||
/// Extended secret key, allows deterministic derivation of subsequent keys.
|
||||
pub struct ExtendedSecret {
|
||||
secret: Secret,
|
||||
chain_code: H256,
|
||||
}
|
||||
|
||||
impl ExtendedSecret {
|
||||
/// New extended key from given secret and chain code.
|
||||
pub fn with_code(secret: Secret, chain_code: H256) -> ExtendedSecret {
|
||||
ExtendedSecret {
|
||||
secret: secret,
|
||||
chain_code: chain_code,
|
||||
}
|
||||
}
|
||||
|
||||
/// New extended key from given secret with the random chain code.
|
||||
pub fn new_random(secret: Secret) -> ExtendedSecret {
|
||||
ExtendedSecret::with_code(secret, H256::random())
|
||||
}
|
||||
|
||||
/// New extended key from given secret.
|
||||
/// Chain code will be derived from the secret itself (in a deterministic way).
|
||||
pub fn new(secret: Secret) -> ExtendedSecret {
|
||||
let chain_code = derivation::chain_code(*secret);
|
||||
ExtendedSecret::with_code(secret, chain_code)
|
||||
}
|
||||
|
||||
/// Derive new private key
|
||||
pub fn derive<T>(&self, index: Derivation<T>) -> ExtendedSecret where T: Label {
|
||||
let (derived_key, next_chain_code) = derivation::private(*self.secret, self.chain_code, index);
|
||||
|
||||
let derived_secret = Secret::from(derived_key.0);
|
||||
|
||||
ExtendedSecret::with_code(derived_secret, next_chain_code)
|
||||
}
|
||||
|
||||
/// Private key component of the extended key.
|
||||
pub fn as_raw(&self) -> &Secret {
|
||||
&self.secret
|
||||
}
|
||||
}
|
||||
|
||||
/// Extended public key, allows deterministic derivation of subsequent keys.
|
||||
pub struct ExtendedPublic {
|
||||
public: Public,
|
||||
chain_code: H256,
|
||||
}
|
||||
|
||||
impl ExtendedPublic {
|
||||
/// New extended public key from known parent and chain code
|
||||
pub fn new(public: Public, chain_code: H256) -> Self {
|
||||
ExtendedPublic { public: public, chain_code: chain_code }
|
||||
}
|
||||
|
||||
/// Create new extended public key from known secret
|
||||
pub fn from_secret(secret: &ExtendedSecret) -> Result<Self, DerivationError> {
|
||||
Ok(
|
||||
ExtendedPublic::new(
|
||||
derivation::point(**secret.as_raw())?,
|
||||
secret.chain_code.clone(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Derive new public key
|
||||
/// Operation is defined only for index belongs [0..2^31)
|
||||
pub fn derive<T>(&self, index: Derivation<T>) -> Result<Self, DerivationError> where T: Label {
|
||||
let (derived_key, next_chain_code) = derivation::public(self.public, self.chain_code, index)?;
|
||||
Ok(ExtendedPublic::new(derived_key, next_chain_code))
|
||||
}
|
||||
|
||||
pub fn public(&self) -> &Public {
|
||||
&self.public
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExtendedKeyPair {
|
||||
secret: ExtendedSecret,
|
||||
public: ExtendedPublic,
|
||||
}
|
||||
|
||||
impl ExtendedKeyPair {
|
||||
pub fn new(secret: Secret) -> Self {
|
||||
let extended_secret = ExtendedSecret::new(secret);
|
||||
let extended_public = ExtendedPublic::from_secret(&extended_secret)
|
||||
.expect("Valid `Secret` always produces valid public; qed");
|
||||
ExtendedKeyPair {
|
||||
secret: extended_secret,
|
||||
public: extended_public,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_code(secret: Secret, public: Public, chain_code: H256) -> Self {
|
||||
ExtendedKeyPair {
|
||||
secret: ExtendedSecret::with_code(secret, chain_code.clone()),
|
||||
public: ExtendedPublic::new(public, chain_code),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_secret(secret: Secret, chain_code: H256) -> Self {
|
||||
let extended_secret = ExtendedSecret::with_code(secret, chain_code);
|
||||
let extended_public = ExtendedPublic::from_secret(&extended_secret)
|
||||
.expect("Valid `Secret` always produces valid public; qed");
|
||||
ExtendedKeyPair {
|
||||
secret: extended_secret,
|
||||
public: extended_public,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_seed(seed: &[u8]) -> Result<ExtendedKeyPair, DerivationError> {
|
||||
let (master_key, chain_code) = derivation::seed_pair(seed);
|
||||
Ok(ExtendedKeyPair::with_secret(
|
||||
Secret::from_unsafe_slice(&*master_key).map_err(|_| DerivationError::InvalidSeed)?,
|
||||
chain_code,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn secret(&self) -> &ExtendedSecret {
|
||||
&self.secret
|
||||
}
|
||||
|
||||
pub fn public(&self) -> &ExtendedPublic {
|
||||
&self.public
|
||||
}
|
||||
|
||||
pub fn derive<T>(&self, index: Derivation<T>) -> Result<Self, DerivationError> where T: Label {
|
||||
let derived = self.secret.derive(index);
|
||||
|
||||
Ok(ExtendedKeyPair {
|
||||
public: ExtendedPublic::from_secret(&derived)?,
|
||||
secret: derived,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Derivation functions for private and public keys
|
||||
// Work is based on BIP0032
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
|
||||
mod derivation {
|
||||
use parity_crypto::hmac;
|
||||
use ethereum_types::{U256, U512, H512, H256};
|
||||
use secp256k1::key::{SecretKey, PublicKey};
|
||||
use SECP256K1;
|
||||
use keccak;
|
||||
use math::curve_order;
|
||||
use super::{Label, Derivation};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
InvalidHardenedUse,
|
||||
InvalidPoint,
|
||||
MissingIndex,
|
||||
InvalidSeed,
|
||||
}
|
||||
|
||||
// Deterministic derivation of the key using secp256k1 elliptic curve.
|
||||
// Derivation can be either hardened or not.
|
||||
// For hardened derivation, pass u32 index at least 2^31 or custom Derivation::Hard(T) enum
|
||||
//
|
||||
// Can panic if passed `private_key` is not a valid secp256k1 private key
|
||||
// (outside of (0..curve_order()]) field
|
||||
pub fn private<T>(private_key: H256, chain_code: H256, index: Derivation<T>) -> (H256, H256) where T: Label {
|
||||
match index {
|
||||
Derivation::Soft(index) => private_soft(private_key, chain_code, index),
|
||||
Derivation::Hard(index) => private_hard(private_key, chain_code, index),
|
||||
}
|
||||
}
|
||||
|
||||
fn hmac_pair(data: &[u8], private_key: H256, chain_code: H256) -> (H256, H256) {
|
||||
let private: U256 = private_key.into();
|
||||
|
||||
// produces 512-bit derived hmac (I)
|
||||
let skey = hmac::SigKey::sha512(&*chain_code);
|
||||
let i_512 = hmac::sign(&skey, &data[..]);
|
||||
|
||||
// left most 256 bits are later added to original private key
|
||||
let hmac_key: U256 = H256::from_slice(&i_512[0..32]).into();
|
||||
// right most 256 bits are new chain code for later derivations
|
||||
let next_chain_code = H256::from(&i_512[32..64]);
|
||||
|
||||
let child_key = private_add(hmac_key, private).into();
|
||||
(child_key, next_chain_code)
|
||||
}
|
||||
|
||||
// Can panic if passed `private_key` is not a valid secp256k1 private key
|
||||
// (outside of (0..curve_order()]) field
|
||||
fn private_soft<T>(private_key: H256, chain_code: H256, index: T) -> (H256, H256) where T: Label {
|
||||
let mut data = vec![0u8; 33 + T::len()];
|
||||
|
||||
let sec_private = SecretKey::from_slice(&SECP256K1, &*private_key)
|
||||
.expect("Caller should provide valid private key");
|
||||
let sec_public = PublicKey::from_secret_key(&SECP256K1, &sec_private)
|
||||
.expect("Caller should provide valid private key");
|
||||
let public_serialized = sec_public.serialize_vec(&SECP256K1, true);
|
||||
|
||||
// curve point (compressed public key) -- index
|
||||
// 0.33 -- 33..end
|
||||
data[0..33].copy_from_slice(&public_serialized);
|
||||
index.store(&mut data[33..]);
|
||||
|
||||
hmac_pair(&data, private_key, chain_code)
|
||||
}
|
||||
|
||||
// Deterministic derivation of the key using secp256k1 elliptic curve
|
||||
// This is hardened derivation and does not allow to associate
|
||||
// corresponding public keys of the original and derived private keys
|
||||
fn private_hard<T>(private_key: H256, chain_code: H256, index: T) -> (H256, H256) where T: Label {
|
||||
let mut data: Vec<u8> = vec![0u8; 33 + T::len()];
|
||||
let private: U256 = private_key.into();
|
||||
|
||||
// 0x00 (padding) -- private_key -- index
|
||||
// 0 -- 1..33 -- 33..end
|
||||
private.to_big_endian(&mut data[1..33]);
|
||||
index.store(&mut data[33..(33 + T::len())]);
|
||||
|
||||
hmac_pair(&data, private_key, chain_code)
|
||||
}
|
||||
|
||||
fn private_add(k1: U256, k2: U256) -> U256 {
|
||||
let sum = U512::from(k1) + U512::from(k2);
|
||||
modulo(sum, curve_order())
|
||||
}
|
||||
|
||||
// todo: surely can be optimized
|
||||
fn modulo(u1: U512, u2: U256) -> U256 {
|
||||
let dv = u1 / U512::from(u2);
|
||||
let md = u1 - (dv * U512::from(u2));
|
||||
md.into()
|
||||
}
|
||||
|
||||
pub fn public<T>(public_key: H512, chain_code: H256, derivation: Derivation<T>) -> Result<(H512, H256), Error> where T: Label {
|
||||
let index = match derivation {
|
||||
Derivation::Soft(index) => index,
|
||||
Derivation::Hard(_) => { return Err(Error::InvalidHardenedUse); }
|
||||
};
|
||||
|
||||
let mut public_sec_raw = [0u8; 65];
|
||||
public_sec_raw[0] = 4;
|
||||
public_sec_raw[1..65].copy_from_slice(&*public_key);
|
||||
let public_sec = PublicKey::from_slice(&SECP256K1, &public_sec_raw).map_err(|_| Error::InvalidPoint)?;
|
||||
let public_serialized = public_sec.serialize_vec(&SECP256K1, true);
|
||||
|
||||
let mut data = vec![0u8; 33 + T::len()];
|
||||
// curve point (compressed public key) -- index
|
||||
// 0.33 -- 33..end
|
||||
data[0..33].copy_from_slice(&public_serialized);
|
||||
index.store(&mut data[33..(33 + T::len())]);
|
||||
|
||||
// HMAC512SHA produces [derived private(256); new chain code(256)]
|
||||
let skey = hmac::SigKey::sha512(&*chain_code);
|
||||
let i_512 = hmac::sign(&skey, &data[..]);
|
||||
|
||||
let new_private = H256::from(&i_512[0..32]);
|
||||
let new_chain_code = H256::from(&i_512[32..64]);
|
||||
|
||||
// Generated private key can (extremely rarely) be out of secp256k1 key field
|
||||
if curve_order() <= new_private.clone().into() { return Err(Error::MissingIndex); }
|
||||
let new_private_sec = SecretKey::from_slice(&SECP256K1, &*new_private)
|
||||
.expect("Private key belongs to the field [0..CURVE_ORDER) (checked above); So initializing can never fail; qed");
|
||||
let mut new_public = PublicKey::from_secret_key(&SECP256K1, &new_private_sec)
|
||||
.expect("Valid private key produces valid public key");
|
||||
|
||||
// Adding two points on the elliptic curves (combining two public keys)
|
||||
new_public.add_assign(&SECP256K1, &public_sec)
|
||||
.expect("Addition of two valid points produce valid point");
|
||||
|
||||
let serialized = new_public.serialize_vec(&SECP256K1, false);
|
||||
|
||||
Ok((
|
||||
H512::from(&serialized[1..65]),
|
||||
new_chain_code,
|
||||
))
|
||||
}
|
||||
|
||||
fn sha3(slc: &[u8]) -> H256 {
|
||||
keccak::Keccak256::keccak256(slc).into()
|
||||
}
|
||||
|
||||
pub fn chain_code(secret: H256) -> H256 {
|
||||
// 10,000 rounds of sha3
|
||||
let mut running_sha3 = sha3(&*secret);
|
||||
for _ in 0..99999 { running_sha3 = sha3(&*running_sha3); }
|
||||
running_sha3
|
||||
}
|
||||
|
||||
pub fn point(secret: H256) -> Result<H512, Error> {
|
||||
let sec = SecretKey::from_slice(&SECP256K1, &*secret)
|
||||
.map_err(|_| Error::InvalidPoint)?;
|
||||
let public_sec = PublicKey::from_secret_key(&SECP256K1, &sec)
|
||||
.map_err(|_| Error::InvalidPoint)?;
|
||||
let serialized = public_sec.serialize_vec(&SECP256K1, false);
|
||||
Ok(H512::from(&serialized[1..65]))
|
||||
}
|
||||
|
||||
pub fn seed_pair(seed: &[u8]) -> (H256, H256) {
|
||||
let skey = hmac::SigKey::sha512(b"Bitcoin seed");
|
||||
let i_512 = hmac::sign(&skey, seed);
|
||||
|
||||
let master_key = H256::from_slice(&i_512[0..32]);
|
||||
let chain_code = H256::from_slice(&i_512[32..64]);
|
||||
|
||||
(master_key, chain_code)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{ExtendedSecret, ExtendedPublic, ExtendedKeyPair};
|
||||
use secret::Secret;
|
||||
use std::str::FromStr;
|
||||
use ethereum_types::{H128, H256};
|
||||
use super::{derivation, Derivation};
|
||||
|
||||
fn master_chain_basic() -> (H256, H256) {
|
||||
let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
|
||||
.expect("Seed should be valid H128")
|
||||
.to_vec();
|
||||
|
||||
derivation::seed_pair(&*seed)
|
||||
}
|
||||
|
||||
fn test_extended<F>(f: F, test_private: H256) where F: Fn(ExtendedSecret) -> ExtendedSecret {
|
||||
let (private_seed, chain_code) = master_chain_basic();
|
||||
let extended_secret = ExtendedSecret::with_code(Secret::from(private_seed.0), chain_code);
|
||||
let derived = f(extended_secret);
|
||||
assert_eq!(**derived.as_raw(), test_private);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn smoky() {
|
||||
let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
|
||||
let extended_secret = ExtendedSecret::with_code(secret.clone(), 0u64.into());
|
||||
|
||||
// hardened
|
||||
assert_eq!(&**extended_secret.as_raw(), &*secret);
|
||||
assert_eq!(&**extended_secret.derive(2147483648.into()).as_raw(), &"0927453daed47839608e414a3738dfad10aed17c459bbd9ab53f89b026c834b6".into());
|
||||
assert_eq!(&**extended_secret.derive(2147483649.into()).as_raw(), &"44238b6a29c6dcbe9b401364141ba11e2198c289a5fed243a1c11af35c19dc0f".into());
|
||||
|
||||
// normal
|
||||
assert_eq!(&**extended_secret.derive(0.into()).as_raw(), &"bf6a74e3f7b36fc4c96a1e12f31abc817f9f5904f5a8fc27713163d1f0b713f6".into());
|
||||
assert_eq!(&**extended_secret.derive(1.into()).as_raw(), &"bd4fca9eb1f9c201e9448c1eecd66e302d68d4d313ce895b8c134f512205c1bc".into());
|
||||
assert_eq!(&**extended_secret.derive(2.into()).as_raw(), &"86932b542d6cab4d9c65490c7ef502d89ecc0e2a5f4852157649e3251e2a3268".into());
|
||||
|
||||
let extended_public = ExtendedPublic::from_secret(&extended_secret).expect("Extended public should be created");
|
||||
let derived_public = extended_public.derive(0.into()).expect("First derivation of public should succeed");
|
||||
assert_eq!(&*derived_public.public(), &"f7b3244c96688f92372bfd4def26dc4151529747bab9f188a4ad34e141d47bd66522ff048bc6f19a0a4429b04318b1a8796c000265b4fa200dae5f6dda92dd94".into());
|
||||
|
||||
let keypair = ExtendedKeyPair::with_secret(
|
||||
Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap(),
|
||||
064.into(),
|
||||
);
|
||||
assert_eq!(&**keypair.derive(2147483648u32.into()).expect("Derivation of keypair should succeed").secret().as_raw(), &"edef54414c03196557cf73774bc97a645c9a1df2164ed34f0c2a78d1375a930c".into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn h256_soft_match() {
|
||||
let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
|
||||
let derivation_secret = H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015").unwrap();
|
||||
|
||||
let extended_secret = ExtendedSecret::with_code(secret.clone(), 0u64.into());
|
||||
let extended_public = ExtendedPublic::from_secret(&extended_secret).expect("Extended public should be created");
|
||||
|
||||
let derived_secret0 = extended_secret.derive(Derivation::Soft(derivation_secret));
|
||||
let derived_public0 = extended_public.derive(Derivation::Soft(derivation_secret)).expect("First derivation of public should succeed");
|
||||
|
||||
let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0).expect("Extended public should be created");
|
||||
|
||||
assert_eq!(public_from_secret0.public(), derived_public0.public());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn h256_hard() {
|
||||
let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
|
||||
let derivation_secret = H256::from_str("51eaf04f9dbbc1417dc97e789edd0c37ecda88bac490434e367ea81b71b7b015").unwrap();
|
||||
let extended_secret = ExtendedSecret::with_code(secret.clone(), 1u64.into());
|
||||
|
||||
assert_eq!(&**extended_secret.derive(Derivation::Hard(derivation_secret)).as_raw(), &"2bc2d696fb744d77ff813b4a1ef0ad64e1e5188b622c54ba917acc5ebc7c5486".into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn match_() {
|
||||
let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
|
||||
let extended_secret = ExtendedSecret::with_code(secret.clone(), 1.into());
|
||||
let extended_public = ExtendedPublic::from_secret(&extended_secret).expect("Extended public should be created");
|
||||
|
||||
let derived_secret0 = extended_secret.derive(0.into());
|
||||
let derived_public0 = extended_public.derive(0.into()).expect("First derivation of public should succeed");
|
||||
|
||||
let public_from_secret0 = ExtendedPublic::from_secret(&derived_secret0).expect("Extended public should be created");
|
||||
|
||||
assert_eq!(public_from_secret0.public(), derived_public0.public());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seeds() {
|
||||
let seed = H128::from_str("000102030405060708090a0b0c0d0e0f")
|
||||
.expect("Seed should be valid H128")
|
||||
.to_vec();
|
||||
|
||||
// private key from bitcoin test vector
|
||||
// xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs
|
||||
let test_private = H256::from_str("e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35")
|
||||
.expect("Private should be decoded ok");
|
||||
|
||||
let (private_seed, _) = derivation::seed_pair(&*seed);
|
||||
|
||||
assert_eq!(private_seed, test_private);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vector_1() {
|
||||
// xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7
|
||||
// H(0)
|
||||
test_extended(
|
||||
|secret| secret.derive(2147483648.into()),
|
||||
H256::from_str("edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea")
|
||||
.expect("Private should be decoded ok")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vector_2() {
|
||||
// xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs
|
||||
// H(0)/1
|
||||
test_extended(
|
||||
|secret| secret.derive(2147483648.into()).derive(1.into()),
|
||||
H256::from_str("3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368")
|
||||
.expect("Private should be decoded ok")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
use secp256k1::key;
|
||||
use rustc_hex::ToHex;
|
||||
use keccak::Keccak256;
|
||||
use super::{Secret, Public, Address, SECP256K1, Error};
|
||||
|
||||
pub fn public_to_address(public: &Public) -> Address {
|
||||
let hash = public.keccak256();
|
||||
let mut result = Address::default();
|
||||
result.copy_from_slice(&hash[12..]);
|
||||
result
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
/// secp256k1 key pair
|
||||
pub struct KeyPair {
|
||||
secret: Secret,
|
||||
public: Public,
|
||||
}
|
||||
|
||||
impl fmt::Display for KeyPair {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
writeln!(f, "secret: {}", self.secret.to_hex())?;
|
||||
writeln!(f, "public: {}", self.public.to_hex())?;
|
||||
write!(f, "address: {}", self.address().to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyPair {
|
||||
/// Create a pair from secret key
|
||||
pub fn from_secret(secret: Secret) -> Result<KeyPair, Error> {
|
||||
let context = &SECP256K1;
|
||||
let s: key::SecretKey = key::SecretKey::from_slice(context, &secret[..])?;
|
||||
let pub_key = key::PublicKey::from_secret_key(context, &s)?;
|
||||
let serialized = pub_key.serialize_vec(context, false);
|
||||
|
||||
let mut public = Public::default();
|
||||
public.copy_from_slice(&serialized[1..65]);
|
||||
|
||||
let keypair = KeyPair {
|
||||
secret: secret,
|
||||
public: public,
|
||||
};
|
||||
|
||||
Ok(keypair)
|
||||
}
|
||||
|
||||
pub fn from_secret_slice(slice: &[u8]) -> Result<KeyPair, Error> {
|
||||
Self::from_secret(Secret::from_unsafe_slice(slice)?)
|
||||
}
|
||||
|
||||
pub fn from_keypair(sec: key::SecretKey, publ: key::PublicKey) -> Self {
|
||||
let context = &SECP256K1;
|
||||
let serialized = publ.serialize_vec(context, false);
|
||||
let secret = Secret::from(sec);
|
||||
let mut public = Public::default();
|
||||
public.copy_from_slice(&serialized[1..65]);
|
||||
|
||||
KeyPair {
|
||||
secret: secret,
|
||||
public: public,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn secret(&self) -> &Secret {
|
||||
&self.secret
|
||||
}
|
||||
|
||||
pub fn public(&self) -> &Public {
|
||||
&self.public
|
||||
}
|
||||
|
||||
pub fn address(&self) -> Address {
|
||||
public_to_address(&self.public)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
use {KeyPair, Secret};
|
||||
|
||||
#[test]
|
||||
fn from_secret() {
|
||||
let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
|
||||
let _ = KeyPair::from_secret(secret).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keypair_display() {
|
||||
let expected =
|
||||
"secret: a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65
|
||||
public: 8ce0db0b0359ffc5866ba61903cc2518c3675ef2cf380a7e54bde7ea20e6fa1ab45b7617346cd11b7610001ee6ae5b0155c41cad9527cbcdff44ec67848943a4
|
||||
address: 5b073e9233944b5e729e46d618f0d8edf3d9c34a".to_owned();
|
||||
let secret = Secret::from_str("a100df7a048e50ed308ea696dc600215098141cb391e9527329df289f9383f65").unwrap();
|
||||
let kp = KeyPair::from_secret(secret).unwrap();
|
||||
assert_eq!(format!("{}", kp), expected);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -18,19 +18,9 @@
|
||||
|
||||
extern crate edit_distance;
|
||||
extern crate parity_crypto;
|
||||
extern crate ethereum_types;
|
||||
extern crate memzero;
|
||||
extern crate parity_wordlist;
|
||||
#[macro_use]
|
||||
extern crate quick_error;
|
||||
extern crate rand;
|
||||
extern crate rustc_hex;
|
||||
extern crate secp256k1;
|
||||
extern crate serde;
|
||||
extern crate tiny_keccak;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
@@ -38,50 +28,13 @@ extern crate serde_derive;
|
||||
|
||||
mod brain;
|
||||
mod brain_prefix;
|
||||
mod error;
|
||||
mod keypair;
|
||||
mod keccak;
|
||||
mod password;
|
||||
mod prefix;
|
||||
mod random;
|
||||
mod signature;
|
||||
mod secret;
|
||||
mod extended;
|
||||
|
||||
pub mod brain_recover;
|
||||
pub mod crypto;
|
||||
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;
|
||||
pub use self::password::Password;
|
||||
pub use self::prefix::Prefix;
|
||||
pub use self::random::Random;
|
||||
pub use self::signature::{sign, verify_public, verify_address, recover, Signature};
|
||||
pub use self::secret::Secret;
|
||||
pub use self::extended::{ExtendedPublic, ExtendedSecret, ExtendedKeyPair, DerivationError, Derivation};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/// Uninstantiatable error type for infallible generators.
|
||||
#[derive(Debug)]
|
||||
pub enum Void {}
|
||||
|
||||
/// Generates new keypair.
|
||||
pub trait Generator {
|
||||
type Error;
|
||||
|
||||
/// Should be called to generate new keypair.
|
||||
fn generate(&mut self) -> Result<KeyPair, Self::Error>;
|
||||
}
|
||||
pub use self::prefix::Prefix;
|
||||
@@ -1,129 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{SECP256K1, Public, Secret, Error};
|
||||
use secp256k1::key;
|
||||
use secp256k1::constants::{GENERATOR_X, GENERATOR_Y, CURVE_ORDER};
|
||||
use ethereum_types::{U256, H256};
|
||||
|
||||
/// Whether the public key is valid.
|
||||
pub fn public_is_valid(public: &Public) -> bool {
|
||||
to_secp256k1_public(public).ok()
|
||||
.map_or(false, |p| p.is_valid())
|
||||
}
|
||||
|
||||
/// Inplace multiply public key by secret key (EC point * scalar)
|
||||
pub fn public_mul_secret(public: &mut Public, secret: &Secret) -> Result<(), Error> {
|
||||
let key_secret = secret.to_secp256k1_secret()?;
|
||||
let mut key_public = to_secp256k1_public(public)?;
|
||||
key_public.mul_assign(&SECP256K1, &key_secret)?;
|
||||
set_public(public, &key_public);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inplace add one public key to another (EC point + EC point)
|
||||
pub fn public_add(public: &mut Public, other: &Public) -> Result<(), Error> {
|
||||
let mut key_public = to_secp256k1_public(public)?;
|
||||
let other_public = to_secp256k1_public(other)?;
|
||||
key_public.add_assign(&SECP256K1, &other_public)?;
|
||||
set_public(public, &key_public);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inplace sub one public key from another (EC point - EC point)
|
||||
pub fn public_sub(public: &mut Public, other: &Public) -> Result<(), Error> {
|
||||
let mut key_neg_other = to_secp256k1_public(other)?;
|
||||
key_neg_other.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
|
||||
|
||||
let mut key_public = to_secp256k1_public(public)?;
|
||||
key_public.add_assign(&SECP256K1, &key_neg_other)?;
|
||||
set_public(public, &key_public);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Replace public key with its negation (EC point = - EC point)
|
||||
pub fn public_negate(public: &mut Public) -> Result<(), Error> {
|
||||
let mut key_public = to_secp256k1_public(public)?;
|
||||
key_public.mul_assign(&SECP256K1, &key::MINUS_ONE_KEY)?;
|
||||
set_public(public, &key_public);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return base point of secp256k1
|
||||
pub fn generation_point() -> Public {
|
||||
let mut public_sec_raw = [0u8; 65];
|
||||
public_sec_raw[0] = 4;
|
||||
public_sec_raw[1..33].copy_from_slice(&GENERATOR_X);
|
||||
public_sec_raw[33..65].copy_from_slice(&GENERATOR_Y);
|
||||
|
||||
let public_key = key::PublicKey::from_slice(&SECP256K1, &public_sec_raw)
|
||||
.expect("constructing using predefined constants; qed");
|
||||
let mut public = Public::default();
|
||||
set_public(&mut public, &public_key);
|
||||
public
|
||||
}
|
||||
|
||||
/// Return secp256k1 elliptic curve order
|
||||
pub fn curve_order() -> U256 {
|
||||
H256::from_slice(&CURVE_ORDER).into()
|
||||
}
|
||||
|
||||
fn to_secp256k1_public(public: &Public) -> Result<key::PublicKey, Error> {
|
||||
let public_data = {
|
||||
let mut temp = [4u8; 65];
|
||||
(&mut temp[1..65]).copy_from_slice(&public[0..64]);
|
||||
temp
|
||||
};
|
||||
|
||||
Ok(key::PublicKey::from_slice(&SECP256K1, &public_data)?)
|
||||
}
|
||||
|
||||
fn set_public(public: &mut Public, key_public: &key::PublicKey) {
|
||||
let key_public_serialized = key_public.serialize_vec(&SECP256K1, false);
|
||||
public.copy_from_slice(&key_public_serialized[1..65]);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{Random, Generator};
|
||||
use super::{public_add, public_sub};
|
||||
|
||||
#[test]
|
||||
fn public_addition_is_commutative() {
|
||||
let public1 = Random.generate().unwrap().public().clone();
|
||||
let public2 = Random.generate().unwrap().public().clone();
|
||||
|
||||
let mut left = public1.clone();
|
||||
public_add(&mut left, &public2).unwrap();
|
||||
|
||||
let mut right = public2.clone();
|
||||
public_add(&mut right, &public1).unwrap();
|
||||
|
||||
assert_eq!(left, right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn public_addition_is_reversible_with_subtraction() {
|
||||
let public1 = Random.generate().unwrap().public().clone();
|
||||
let public2 = Random.generate().unwrap().public().clone();
|
||||
|
||||
let mut sum = public1.clone();
|
||||
public_add(&mut sum, &public2).unwrap();
|
||||
public_sub(&mut sum, &public2).unwrap();
|
||||
|
||||
assert_eq!(sum, public1);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::{Random, Generator, KeyPair, Error};
|
||||
use parity_crypto::publickey::{Random, Generator, KeyPair, Error};
|
||||
|
||||
/// Tries to find keypair with address starting with given prefix.
|
||||
pub struct Prefix {
|
||||
@@ -37,7 +37,7 @@ impl Generator for Prefix {
|
||||
fn generate(&mut self) -> Result<KeyPair, Error> {
|
||||
for _ in 0..self.iterations {
|
||||
let keypair = Random.generate()?;
|
||||
if keypair.address().starts_with(&self.prefix) {
|
||||
if keypair.address().as_ref().starts_with(&self.prefix) {
|
||||
return Ok(keypair)
|
||||
}
|
||||
}
|
||||
@@ -48,12 +48,13 @@ impl Generator for Prefix {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use {Generator, Prefix};
|
||||
use Prefix;
|
||||
use parity_crypto::publickey::Generator;
|
||||
|
||||
#[test]
|
||||
fn prefix_generator() {
|
||||
let prefix = vec![0xffu8];
|
||||
let keypair = Prefix::new(prefix.clone(), usize::max_value()).generate().unwrap();
|
||||
assert!(keypair.address().starts_with(&prefix));
|
||||
assert!(keypair.address().as_bytes().starts_with(&prefix));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use rand::os::OsRng;
|
||||
use super::{Generator, KeyPair, SECP256K1};
|
||||
|
||||
/// Randomly generates new keypair, instantiating the RNG each time.
|
||||
pub struct Random;
|
||||
|
||||
impl Generator for Random {
|
||||
type Error = ::std::io::Error;
|
||||
|
||||
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
|
||||
let mut rng = OsRng::new()?;
|
||||
match rng.generate() {
|
||||
Ok(pair) => Ok(pair),
|
||||
Err(void) => match void {}, // LLVM unreachable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Generator for OsRng {
|
||||
type Error = ::Void;
|
||||
|
||||
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
|
||||
let (sec, publ) = SECP256K1.generate_keypair(self)
|
||||
.expect("context always created with full capabilities; qed");
|
||||
|
||||
Ok(KeyPair::from_keypair(sec, publ))
|
||||
}
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::str::FromStr;
|
||||
use rustc_hex::ToHex;
|
||||
use secp256k1::constants::{SECRET_KEY_SIZE as SECP256K1_SECRET_KEY_SIZE};
|
||||
use secp256k1::key;
|
||||
use ethereum_types::H256;
|
||||
use memzero::Memzero;
|
||||
use {Error, SECP256K1};
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct Secret {
|
||||
inner: Memzero<H256>,
|
||||
}
|
||||
|
||||
impl ToHex for Secret {
|
||||
fn to_hex(&self) -> String {
|
||||
format!("{:x}", *self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::LowerHex for Secret {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.inner.fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Secret {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.inner.fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
impl Secret {
|
||||
/// Creates a `Secret` from the given slice, returning `None` if the slice length != 32.
|
||||
pub fn from_slice(key: &[u8]) -> Option<Self> {
|
||||
if key.len() != 32 {
|
||||
return None
|
||||
}
|
||||
let mut h = H256::default();
|
||||
h.copy_from_slice(&key[0..32]);
|
||||
Some(Secret { inner: Memzero::from(h) })
|
||||
}
|
||||
|
||||
/// Creates zero key, which is invalid for crypto operations, but valid for math operation.
|
||||
pub fn zero() -> Self {
|
||||
Secret { inner: Memzero::from(H256::default()) }
|
||||
}
|
||||
|
||||
/// Imports and validates the key.
|
||||
pub fn from_unsafe_slice(key: &[u8]) -> Result<Self, Error> {
|
||||
let secret = key::SecretKey::from_slice(&super::SECP256K1, key)?;
|
||||
Ok(secret.into())
|
||||
}
|
||||
|
||||
/// Checks validity of this key.
|
||||
pub fn check_validity(&self) -> Result<(), Error> {
|
||||
self.to_secp256k1_secret().map(|_| ())
|
||||
}
|
||||
|
||||
/// Inplace add one secret key to another (scalar + scalar)
|
||||
pub fn add(&mut self, other: &Secret) -> Result<(), Error> {
|
||||
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(())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Inplace subtract one secret key from another (scalar - scalar)
|
||||
pub fn sub(&mut self, other: &Secret) -> Result<(), Error> {
|
||||
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> {
|
||||
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(())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Inplace multiply one secret key to another (scalar * scalar)
|
||||
pub fn mul(&mut self, other: &Secret) -> Result<(), Error> {
|
||||
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(())
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Inplace negate secret key (-scalar)
|
||||
pub fn neg(&mut self) -> Result<(), Error> {
|
||||
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)
|
||||
pub fn inv(&mut self) -> Result<(), Error> {
|
||||
let mut key_secret = self.to_secp256k1_secret()?;
|
||||
key_secret.inv_assign(&SECP256K1)?;
|
||||
|
||||
*self = key_secret.into();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 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 => (),
|
||||
_ => {
|
||||
let c = self.clone();
|
||||
for _ in 1..pow {
|
||||
self.mul(&c)?;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create `secp256k1::key::SecretKey` based on this secret
|
||||
pub fn to_secp256k1_secret(&self) -> Result<key::SecretKey, Error> {
|
||||
Ok(key::SecretKey::from_slice(&SECP256K1, &self[..])?)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Secret {
|
||||
type Err = Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(H256::from_str(s).map_err(|e| Error::Custom(format!("{:?}", e)))?.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 32]> for Secret {
|
||||
fn from(k: [u8; 32]) -> Self {
|
||||
Secret { inner: Memzero::from(H256(k)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<H256> for Secret {
|
||||
fn from(s: H256) -> Self {
|
||||
s.0.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&'static str> for Secret {
|
||||
fn from(s: &'static str) -> Self {
|
||||
s.parse().expect(&format!("invalid string literal for {}: '{}'", stringify!(Self), s))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<key::SecretKey> for Secret {
|
||||
fn from(key: key::SecretKey) -> Self {
|
||||
let mut a = [0; SECP256K1_SECRET_KEY_SIZE];
|
||||
a.copy_from_slice(&key[0 .. SECP256K1_SECRET_KEY_SIZE]);
|
||||
a.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Secret {
|
||||
type Target = H256;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
use super::super::{Random, Generator};
|
||||
use super::Secret;
|
||||
|
||||
#[test]
|
||||
fn multiplicating_secret_inversion_with_secret_gives_one() {
|
||||
let secret = Random.generate().unwrap().secret().clone();
|
||||
let mut inversion = secret.clone();
|
||||
inversion.inv().unwrap();
|
||||
inversion.mul(&secret).unwrap();
|
||||
assert_eq!(inversion, Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secret_inversion_is_reversible_with_inversion() {
|
||||
let secret = Random.generate().unwrap().secret().clone();
|
||||
let mut inversion = secret.clone();
|
||||
inversion.inv().unwrap();
|
||||
inversion.inv().unwrap();
|
||||
assert_eq!(inversion, secret);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn secret_pow() {
|
||||
let secret = Random.generate().unwrap().secret().clone();
|
||||
|
||||
let mut pow0 = secret.clone();
|
||||
pow0.pow(0).unwrap();
|
||||
assert_eq!(pow0, Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap());
|
||||
|
||||
let mut pow1 = secret.clone();
|
||||
pow1.pow(1).unwrap();
|
||||
assert_eq!(pow1, secret);
|
||||
|
||||
let mut pow2 = secret.clone();
|
||||
pow2.pow(2).unwrap();
|
||||
let mut pow2_expected = secret.clone();
|
||||
pow2_expected.mul(&secret).unwrap();
|
||||
assert_eq!(pow2, pow2_expected);
|
||||
|
||||
let mut pow3 = secret.clone();
|
||||
pow3.pow(3).unwrap();
|
||||
let mut pow3_expected = secret.clone();
|
||||
pow3_expected.mul(&secret).unwrap();
|
||||
pow3_expected.mul(&secret).unwrap();
|
||||
assert_eq!(pow3, pow3_expected);
|
||||
}
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::cmp::PartialEq;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
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 ethereum_types::{H520, H256};
|
||||
use {Secret, Public, SECP256K1, Error, Message, public_to_address, Address};
|
||||
|
||||
/// Signature encoded as RSV components
|
||||
#[repr(C)]
|
||||
pub struct Signature([u8; 65]);
|
||||
|
||||
impl Signature {
|
||||
/// Get a slice into the 'r' portion of the data.
|
||||
pub fn r(&self) -> &[u8] {
|
||||
&self.0[0..32]
|
||||
}
|
||||
|
||||
/// Get a slice into the 's' portion of the data.
|
||||
pub fn s(&self) -> &[u8] {
|
||||
&self.0[32..64]
|
||||
}
|
||||
|
||||
/// Get the recovery byte.
|
||||
pub fn v(&self) -> u8 {
|
||||
self.0[64]
|
||||
}
|
||||
|
||||
/// Encode the signature into RSV array (V altered to be in "Electrum" notation).
|
||||
pub fn into_electrum(mut self) -> [u8; 65] {
|
||||
self.0[64] += 27;
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Parse bytes as a signature encoded as RSV (V in "Electrum" notation).
|
||||
/// May return empty (invalid) signature if given data has invalid length.
|
||||
pub fn from_electrum(data: &[u8]) -> Self {
|
||||
if data.len() != 65 || data[64] < 27 {
|
||||
// fallback to empty (invalid) signature
|
||||
return Signature::default();
|
||||
}
|
||||
|
||||
let mut sig = [0u8; 65];
|
||||
sig.copy_from_slice(data);
|
||||
sig[64] -= 27;
|
||||
Signature(sig)
|
||||
}
|
||||
|
||||
/// Create a signature object from the sig.
|
||||
pub fn from_rsv(r: &H256, s: &H256, v: u8) -> Self {
|
||||
let mut sig = [0u8; 65];
|
||||
sig[0..32].copy_from_slice(&r);
|
||||
sig[32..64].copy_from_slice(&s);
|
||||
sig[64] = v;
|
||||
Signature(sig)
|
||||
}
|
||||
|
||||
/// Check if this is a "low" signature.
|
||||
pub fn is_low_s(&self) -> bool {
|
||||
H256::from_slice(self.s()) <= "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0".into()
|
||||
}
|
||||
|
||||
/// Check if each component of the signature is in range.
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.v() <= 1 &&
|
||||
H256::from_slice(self.r()) < "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into() &&
|
||||
H256::from_slice(self.r()) >= 1.into() &&
|
||||
H256::from_slice(self.s()) < "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141".into() &&
|
||||
H256::from_slice(self.s()) >= 1.into()
|
||||
}
|
||||
}
|
||||
|
||||
// manual implementation large arrays don't have trait impls by default.
|
||||
// remove when integer generics exist
|
||||
impl PartialEq for Signature {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
&self.0[..] == &other.0[..]
|
||||
}
|
||||
}
|
||||
|
||||
// manual implementation required in Rust 1.13+, see `std::cmp::AssertParamIsEq`.
|
||||
impl Eq for Signature { }
|
||||
|
||||
// also manual for the same reason, but the pretty printing might be useful.
|
||||
impl fmt::Debug for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("Signature")
|
||||
.field("r", &self.0[0..32].to_hex())
|
||||
.field("s", &self.0[32..64].to_hex())
|
||||
.field("v", &self.0[64..65].to_hex())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "{}", self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Signature {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.from_hex() {
|
||||
Ok(ref hex) if hex.len() == 65 => {
|
||||
let mut data = [0; 65];
|
||||
data.copy_from_slice(&hex[0..65]);
|
||||
Ok(Signature(data))
|
||||
},
|
||||
_ => Err(Error::InvalidSignature)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Signature {
|
||||
fn default() -> Self {
|
||||
Signature([0; 65])
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Signature {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
H520::from(self.0).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Signature {
|
||||
fn clone(&self) -> Self {
|
||||
Signature(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 65]> for Signature {
|
||||
fn from(s: [u8; 65]) -> Self {
|
||||
Signature(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[u8; 65]> for Signature {
|
||||
fn into(self) -> [u8; 65] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Signature> for H520 {
|
||||
fn from(s: Signature) -> Self {
|
||||
H520::from(s.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<H520> for Signature {
|
||||
fn from(bytes: H520) -> Self {
|
||||
Signature(bytes.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Signature {
|
||||
type Target = [u8; 65];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Signature {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sign(secret: &Secret, message: &Message) -> Result<Signature, Error> {
|
||||
let context = &SECP256K1;
|
||||
let sec = SecretKey::from_slice(context, &secret)?;
|
||||
let s = context.sign_recoverable(&SecpMessage::from_slice(&message[..])?, &sec)?;
|
||||
let (rec_id, data) = s.serialize_compact(context);
|
||||
let mut data_arr = [0; 65];
|
||||
|
||||
// no need to check if s is low, it always is
|
||||
data_arr[0..64].copy_from_slice(&data[0..64]);
|
||||
data_arr[64] = rec_id.to_i32() as u8;
|
||||
Ok(Signature(data_arr))
|
||||
}
|
||||
|
||||
pub fn verify_public(public: &Public, signature: &Signature, message: &Message) -> Result<bool, Error> {
|
||||
let context = &SECP256K1;
|
||||
let rsig = RecoverableSignature::from_compact(context, &signature[0..64], RecoveryId::from_i32(signature[64] as i32)?)?;
|
||||
let sig = rsig.to_standard(context);
|
||||
|
||||
let pdata: [u8; 65] = {
|
||||
let mut temp = [4u8; 65];
|
||||
temp[1..65].copy_from_slice(&**public);
|
||||
temp
|
||||
};
|
||||
|
||||
let publ = PublicKey::from_slice(context, &pdata)?;
|
||||
match context.verify(&SecpMessage::from_slice(&message[..])?, &sig, &publ) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(SecpError::IncorrectSignature) => Ok(false),
|
||||
Err(x) => Err(Error::from(x))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_address(address: &Address, signature: &Signature, message: &Message) -> Result<bool, Error> {
|
||||
let public = recover(signature, message)?;
|
||||
let recovered_address = public_to_address(&public);
|
||||
Ok(address == &recovered_address)
|
||||
}
|
||||
|
||||
pub fn recover(signature: &Signature, message: &Message) -> Result<Public, Error> {
|
||||
let context = &SECP256K1;
|
||||
let rsig = RecoverableSignature::from_compact(context, &signature[0..64], RecoveryId::from_i32(signature[64] as i32)?)?;
|
||||
let pubkey = context.recover(&SecpMessage::from_slice(&message[..])?, &rsig)?;
|
||||
let serialized = pubkey.serialize_vec(context, false);
|
||||
|
||||
let mut public = Public::default();
|
||||
public.copy_from_slice(&serialized[1..65]);
|
||||
Ok(public)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::str::FromStr;
|
||||
use {Generator, Random, Message};
|
||||
use super::{sign, verify_public, verify_address, recover, Signature};
|
||||
|
||||
#[test]
|
||||
fn vrs_conversion() {
|
||||
// given
|
||||
let keypair = Random.generate().unwrap();
|
||||
let message = Message::default();
|
||||
let signature = sign(keypair.secret(), &message).unwrap();
|
||||
|
||||
// when
|
||||
let vrs = signature.clone().into_electrum();
|
||||
let from_vrs = Signature::from_electrum(&vrs);
|
||||
|
||||
// then
|
||||
assert_eq!(signature, from_vrs);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signature_to_and_from_str() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let message = Message::default();
|
||||
let signature = sign(keypair.secret(), &message).unwrap();
|
||||
let string = format!("{}", signature);
|
||||
let deserialized = Signature::from_str(&string).unwrap();
|
||||
assert_eq!(signature, deserialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_and_recover_public() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let message = Message::default();
|
||||
let signature = sign(keypair.secret(), &message).unwrap();
|
||||
assert_eq!(keypair.public(), &recover(&signature, &message).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_and_verify_public() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let message = Message::default();
|
||||
let signature = sign(keypair.secret(), &message).unwrap();
|
||||
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_and_verify_address() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let message = Message::default();
|
||||
let signature = sign(keypair.secret(), &message).unwrap();
|
||||
assert!(verify_address(&keypair.address(), &signature, &message).unwrap());
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
libc = "0.2"
|
||||
rand = "0.4"
|
||||
rand = "0.7"
|
||||
ethkey = { path = "../ethkey" }
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
@@ -16,14 +16,13 @@ rustc-hex = "1.0"
|
||||
tiny-keccak = "1.4"
|
||||
time = "0.1.34"
|
||||
itertools = "0.5"
|
||||
parking_lot = "0.7"
|
||||
parity-crypto = "0.3.0"
|
||||
ethereum-types = "0.4"
|
||||
parking_lot = "0.9"
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
ethereum-types = "0.8.0"
|
||||
dir = { path = "../../util/dir" }
|
||||
smallvec = "0.6"
|
||||
parity-wordlist = "1.3"
|
||||
parity-wordlist = "1.0"
|
||||
tempdir = "0.3"
|
||||
lazy_static = "1.2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
matches = "0.1"
|
||||
|
||||
@@ -6,7 +6,7 @@ Parity Ethereum key management.
|
||||
|
||||
```
|
||||
Parity Ethereum key management tool.
|
||||
Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
|
||||
Usage:
|
||||
ethstore insert <secret> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
|
||||
@@ -337,4 +337,4 @@ _This project is a part of the Parity Ethereum toolchain._
|
||||
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding.
|
||||
- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/accounts/ethstore) - Parity Ethereum key management.
|
||||
- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/accounts/ethkey) - Parity Ethereum keys generator.
|
||||
- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC.
|
||||
- [whisper](https://github.com/paritytech/whisper) - Implementation of Whisper-v2 PoC.
|
||||
|
||||
@@ -11,8 +11,10 @@ num_cpus = "1.6"
|
||||
rustc-hex = "1.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.9"
|
||||
ethstore = { path = "../" }
|
||||
ethkey = { path = "../../ethkey" }
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
dir = { path = '../../../util/dir' }
|
||||
panic_hook = { path = "../../../util/panic-hook" }
|
||||
|
||||
@@ -22,4 +24,4 @@ path = "src/main.rs"
|
||||
doc = false
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3.5"
|
||||
tempdir = "0.3"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -19,7 +19,8 @@ use std::sync::Arc;
|
||||
use std::collections::VecDeque;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use ethstore::{ethkey::Password, PresaleWallet, Error};
|
||||
use ethstore::{PresaleWallet, Error};
|
||||
use ethkey::Password;
|
||||
use num_cpus;
|
||||
|
||||
pub fn run(passwords: VecDeque<Password>, wallet_path: &str) -> Result<(), Error> {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -17,9 +17,11 @@
|
||||
extern crate dir;
|
||||
extern crate docopt;
|
||||
extern crate ethstore;
|
||||
extern crate ethkey;
|
||||
extern crate num_cpus;
|
||||
extern crate panic_hook;
|
||||
extern crate parking_lot;
|
||||
extern crate parity_crypto;
|
||||
extern crate rustc_hex;
|
||||
extern crate serde;
|
||||
|
||||
@@ -34,14 +36,15 @@ use std::{env, process, fs, fmt};
|
||||
|
||||
use docopt::Docopt;
|
||||
use ethstore::accounts_dir::{KeyDirectory, RootDiskDirectory};
|
||||
use ethstore::ethkey::{Address, Password};
|
||||
use ethkey::Password;
|
||||
use parity_crypto::publickey::Address;
|
||||
use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, PresaleWallet, SecretVaultRef, StoreAccountRef};
|
||||
|
||||
mod crack;
|
||||
|
||||
pub const USAGE: &'static str = r#"
|
||||
Parity Ethereum key management tool.
|
||||
Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
|
||||
Usage:
|
||||
ethstore insert <secret> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
|
||||
@@ -163,7 +166,7 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
fn key_dir(location: &str, password: Option<Password>) -> Result<Box<KeyDirectory>, Error> {
|
||||
fn key_dir(location: &str, password: Option<Password>) -> Result<Box<dyn KeyDirectory>, Error> {
|
||||
let dir: RootDiskDirectory = match location {
|
||||
"geth" => RootDiskDirectory::create(dir::geth(false))?,
|
||||
"geth-test" => RootDiskDirectory::create(dir::geth(true))?,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -15,8 +15,8 @@
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::str;
|
||||
use std::num::NonZeroU32;
|
||||
use ethkey::{Password, Secret};
|
||||
use crypto::publickey::Secret;
|
||||
use ethkey::Password;
|
||||
use {json, Error, crypto};
|
||||
use crypto::Keccak256;
|
||||
use random::Random;
|
||||
@@ -74,12 +74,12 @@ impl From<Crypto> for String {
|
||||
|
||||
impl Crypto {
|
||||
/// Encrypt account secret
|
||||
pub fn with_secret(secret: &Secret, password: &Password, iterations: NonZeroU32) -> Result<Self, crypto::Error> {
|
||||
Crypto::with_plain(&*secret, password, iterations)
|
||||
pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
|
||||
Crypto::with_plain(secret.as_ref(), password, iterations)
|
||||
}
|
||||
|
||||
/// Encrypt custom plain data
|
||||
pub fn with_plain(plain: &[u8], password: &Password, iterations: NonZeroU32) -> Result<Self, crypto::Error> {
|
||||
pub fn with_plain(plain: &[u8], password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
|
||||
let salt: [u8; 32] = Random::random();
|
||||
let iv: [u8; 16] = Random::random();
|
||||
|
||||
@@ -121,7 +121,7 @@ impl Crypto {
|
||||
}
|
||||
|
||||
let secret = self.do_decrypt(password, 32)?;
|
||||
Ok(Secret::from_unsafe_slice(&secret)?)
|
||||
Ok(Secret::import_key(&secret)?)
|
||||
}
|
||||
|
||||
/// Try to decrypt and return result as is
|
||||
@@ -159,18 +159,14 @@ impl Crypto {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ethkey::{Generator, Random};
|
||||
use super::{Crypto, Error, NonZeroU32};
|
||||
|
||||
lazy_static! {
|
||||
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
|
||||
}
|
||||
use crypto::publickey::{Generator, Random};
|
||||
use super::{Crypto, Error};
|
||||
|
||||
#[test]
|
||||
fn crypto_with_secret_create() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let passwd = "this is sparta".into();
|
||||
let crypto = Crypto::with_secret(keypair.secret(), &passwd, *ITERATIONS).unwrap();
|
||||
let crypto = Crypto::with_secret(keypair.secret(), &passwd, 10240).unwrap();
|
||||
let secret = crypto.secret(&passwd).unwrap();
|
||||
assert_eq!(keypair.secret(), &secret);
|
||||
}
|
||||
@@ -178,7 +174,7 @@ mod tests {
|
||||
#[test]
|
||||
fn crypto_with_secret_invalid_password() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), *ITERATIONS).unwrap();
|
||||
let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), 10240).unwrap();
|
||||
assert_matches!(crypto.secret(&"this is sparta!".into()), Err(Error::InvalidPassword))
|
||||
}
|
||||
|
||||
@@ -186,7 +182,7 @@ mod tests {
|
||||
fn crypto_with_null_plain_data() {
|
||||
let original_data = b"";
|
||||
let passwd = "this is sparta".into();
|
||||
let crypto = Crypto::with_plain(&original_data[..], &passwd, *ITERATIONS).unwrap();
|
||||
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
|
||||
let decrypted_data = crypto.decrypt(&passwd).unwrap();
|
||||
assert_eq!(original_data[..], *decrypted_data);
|
||||
}
|
||||
@@ -195,7 +191,7 @@ mod tests {
|
||||
fn crypto_with_tiny_plain_data() {
|
||||
let original_data = b"{}";
|
||||
let passwd = "this is sparta".into();
|
||||
let crypto = Crypto::with_plain(&original_data[..], &passwd, *ITERATIONS).unwrap();
|
||||
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
|
||||
let decrypted_data = crypto.decrypt(&passwd).unwrap();
|
||||
assert_eq!(original_data[..], *decrypted_data);
|
||||
}
|
||||
@@ -204,7 +200,7 @@ mod tests {
|
||||
fn crypto_with_huge_plain_data() {
|
||||
let original_data: Vec<_> = (1..65536).map(|i| (i % 256) as u8).collect();
|
||||
let passwd = "this is sparta".into();
|
||||
let crypto = Crypto::with_plain(&original_data, &passwd, *ITERATIONS).unwrap();
|
||||
let crypto = Crypto::with_plain(&original_data, &passwd, 10240).unwrap();
|
||||
let decrypted_data = crypto.decrypt(&passwd).unwrap();
|
||||
assert_eq!(&original_data, &decrypted_data);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -15,7 +15,6 @@
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use json;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Prf {
|
||||
@@ -24,7 +23,7 @@ pub enum Prf {
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Pbkdf2 {
|
||||
pub c: NonZeroU32,
|
||||
pub c: u32,
|
||||
pub dklen: u32,
|
||||
pub prf: Prf,
|
||||
pub salt: Vec<u8>,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -14,13 +14,13 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use ethkey::{self, KeyPair, sign, Address, Password, Signature, Message, Public, Secret};
|
||||
use ethkey::crypto::ecdh::agree;
|
||||
use crypto::publickey::{KeyPair, sign, Address, Signature, Message, Public, Secret};
|
||||
use ethkey::Password;
|
||||
use crypto::publickey::ecdh::agree;
|
||||
use {json, Error};
|
||||
use account::Version;
|
||||
use crypto;
|
||||
use super::crypto::Crypto;
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
/// Account representation.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
@@ -60,7 +60,7 @@ impl SafeAccount {
|
||||
keypair: &KeyPair,
|
||||
id: [u8; 16],
|
||||
password: &Password,
|
||||
iterations: NonZeroU32,
|
||||
iterations: u32,
|
||||
name: String,
|
||||
meta: String
|
||||
) -> Result<Self, crypto::Error> {
|
||||
@@ -136,7 +136,7 @@ impl SafeAccount {
|
||||
}
|
||||
|
||||
/// Create a new `VaultKeyFile` from the given `self`
|
||||
pub fn into_vault_file(self, iterations: NonZeroU32, password: &Password) -> Result<json::VaultKeyFile, Error> {
|
||||
pub fn into_vault_file(self, iterations: u32, password: &Password) -> Result<json::VaultKeyFile, Error> {
|
||||
let meta_plain = json::VaultKeyMeta {
|
||||
address: self.address.into(),
|
||||
name: Some(self.name),
|
||||
@@ -162,7 +162,7 @@ impl SafeAccount {
|
||||
/// Decrypt a message.
|
||||
pub fn decrypt(&self, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
|
||||
let secret = self.crypto.secret(password)?;
|
||||
ethkey::crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
|
||||
crypto::publickey::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
|
||||
}
|
||||
|
||||
/// Agree on shared key.
|
||||
@@ -178,7 +178,7 @@ impl SafeAccount {
|
||||
}
|
||||
|
||||
/// Change account's password.
|
||||
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: NonZeroU32) -> Result<Self, Error> {
|
||||
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result<Self, Error> {
|
||||
let secret = self.crypto.secret(old_password)?;
|
||||
let result = SafeAccount {
|
||||
id: self.id.clone(),
|
||||
@@ -200,20 +200,15 @@ impl SafeAccount {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ethkey::{Generator, Random, verify_public, Message};
|
||||
use super::{SafeAccount, NonZeroU32};
|
||||
|
||||
lazy_static! {
|
||||
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
|
||||
}
|
||||
|
||||
use crypto::publickey::{Generator, Random, verify_public, Message};
|
||||
use super::SafeAccount;
|
||||
|
||||
#[test]
|
||||
fn sign_and_verify_public() {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let password = "hello world".into();
|
||||
let message = Message::default();
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned());
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned());
|
||||
let signature = account.unwrap().sign(&password, &message).unwrap();
|
||||
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
|
||||
}
|
||||
@@ -223,9 +218,10 @@ mod tests {
|
||||
let keypair = Random.generate().unwrap();
|
||||
let first_password = "hello world".into();
|
||||
let sec_password = "this is sparta".into();
|
||||
let i = 10240;
|
||||
let message = Message::default();
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap();
|
||||
let new_account = account.change_password(&first_password, &sec_password, *ITERATIONS).unwrap();
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap();
|
||||
let new_account = account.change_password(&first_password, &sec_password, i).unwrap();
|
||||
assert!(account.sign(&first_password, &message).is_ok());
|
||||
assert!(account.sign(&sec_password, &message).is_err());
|
||||
assert!(new_account.sign(&first_password, &message).is_err());
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -61,7 +61,6 @@ pub fn find_unique_filename_using_random_suffix(parent_path: &Path, original_fil
|
||||
/// Create a new file and restrict permissions to owner only. It errors if the file already exists.
|
||||
#[cfg(unix)]
|
||||
pub fn create_new_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
|
||||
use libc;
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
|
||||
fs::OpenOptions::new()
|
||||
@@ -83,7 +82,6 @@ pub fn create_new_file_with_permissions_to_owner(file_path: &Path) -> io::Result
|
||||
/// Create a new file and restrict permissions to owner only. It replaces the existing file if it already exists.
|
||||
#[cfg(unix)]
|
||||
pub fn replace_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
|
||||
use libc;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let file = fs::File::create(file_path)?;
|
||||
@@ -286,7 +284,7 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
|
||||
|
||||
fn path(&self) -> Option<&PathBuf> { Some(&self.path) }
|
||||
|
||||
fn as_vault_provider(&self) -> Option<&VaultKeyDirectoryProvider> {
|
||||
fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
@@ -296,12 +294,12 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
|
||||
}
|
||||
|
||||
impl<T> VaultKeyDirectoryProvider for DiskDirectory<T> where T: KeyFileManager {
|
||||
fn create(&self, name: &str, key: VaultKey) -> Result<Box<VaultKeyDirectory>, Error> {
|
||||
fn create(&self, name: &str, key: VaultKey) -> Result<Box<dyn VaultKeyDirectory>, Error> {
|
||||
let vault_dir = VaultDiskDirectory::create(&self.path, name, key)?;
|
||||
Ok(Box::new(vault_dir))
|
||||
}
|
||||
|
||||
fn open(&self, name: &str, key: VaultKey) -> Result<Box<VaultKeyDirectory>, Error> {
|
||||
fn open(&self, name: &str, key: VaultKey) -> Result<Box<dyn VaultKeyDirectory>, Error> {
|
||||
let vault_dir = VaultDiskDirectory::at(&self.path, name, key)?;
|
||||
Ok(Box::new(vault_dir))
|
||||
}
|
||||
@@ -356,16 +354,11 @@ mod test {
|
||||
extern crate tempdir;
|
||||
|
||||
use std::{env, fs};
|
||||
use std::num::NonZeroU32;
|
||||
use super::{KeyDirectory, RootDiskDirectory, VaultKey};
|
||||
use account::SafeAccount;
|
||||
use ethkey::{Random, Generator};
|
||||
use crypto::publickey::{Random, Generator};
|
||||
use self::tempdir::TempDir;
|
||||
|
||||
lazy_static! {
|
||||
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_create_new_account() {
|
||||
// given
|
||||
@@ -376,7 +369,7 @@ mod test {
|
||||
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
|
||||
|
||||
// when
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned());
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned());
|
||||
let res = directory.insert(account.unwrap());
|
||||
|
||||
// then
|
||||
@@ -397,7 +390,7 @@ mod test {
|
||||
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
|
||||
|
||||
// when
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap();
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap();
|
||||
let filename = "test".to_string();
|
||||
let dedup = true;
|
||||
|
||||
@@ -433,7 +426,7 @@ mod test {
|
||||
|
||||
// and when
|
||||
let before_root_items_count = fs::read_dir(&dir).unwrap().count();
|
||||
let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, *ITERATIONS));
|
||||
let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, 1024));
|
||||
|
||||
// then
|
||||
assert!(vault.is_ok());
|
||||
@@ -441,7 +434,7 @@ mod test {
|
||||
assert!(after_root_items_count > before_root_items_count);
|
||||
|
||||
// and when
|
||||
let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, *ITERATIONS));
|
||||
let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, 1024));
|
||||
|
||||
// then
|
||||
assert!(vault.is_ok());
|
||||
@@ -458,9 +451,8 @@ mod test {
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let directory = RootDiskDirectory::create(&temp_path).unwrap();
|
||||
let vault_provider = directory.as_vault_provider().unwrap();
|
||||
let iter = NonZeroU32::new(1).expect("1 > 0; qed");
|
||||
vault_provider.create("vault1", VaultKey::new(&"password1".into(), iter)).unwrap();
|
||||
vault_provider.create("vault2", VaultKey::new(&"password2".into(), iter)).unwrap();
|
||||
vault_provider.create("vault1", VaultKey::new(&"password1".into(), 1)).unwrap();
|
||||
vault_provider.create("vault2", VaultKey::new(&"password2".into(), 1)).unwrap();
|
||||
|
||||
// then
|
||||
let vaults = vault_provider.list_vaults().unwrap();
|
||||
@@ -482,7 +474,7 @@ mod test {
|
||||
|
||||
let keypair = Random.generate().unwrap();
|
||||
let password = "test pass".into();
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, *ITERATIONS, "Test".to_owned(), "{}".to_owned());
|
||||
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned());
|
||||
directory.insert(account.unwrap()).expect("Account should be inserted ok");
|
||||
|
||||
let new_hash = directory.files_hash().expect("New files hash should be calculated ok");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -17,7 +17,7 @@
|
||||
use std::collections::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
use itertools;
|
||||
use ethkey::Address;
|
||||
use crypto::publickey::Address;
|
||||
|
||||
use {SafeAccount, Error};
|
||||
use super::KeyDirectory;
|
||||
@@ -68,7 +68,7 @@ impl KeyDirectory for MemoryDirectory {
|
||||
fn unique_repr(&self) -> Result<u64, Error> {
|
||||
let mut val = 0u64;
|
||||
let accounts = self.accounts.read();
|
||||
for acc in accounts.keys() { val = val ^ acc.low_u64() }
|
||||
for acc in accounts.keys() { val = val ^ acc.to_low_u64_be() }
|
||||
Ok(val)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -17,7 +17,6 @@
|
||||
//! Accounts Directory
|
||||
|
||||
use ethkey::Password;
|
||||
use std::num::NonZeroU32;
|
||||
use std::path::{PathBuf};
|
||||
use {SafeAccount, Error};
|
||||
|
||||
@@ -42,7 +41,7 @@ pub struct VaultKey {
|
||||
/// Vault password
|
||||
pub password: Password,
|
||||
/// Number of iterations to produce a derived key from password
|
||||
pub iterations: NonZeroU32,
|
||||
pub iterations: u32,
|
||||
}
|
||||
|
||||
/// Keys directory
|
||||
@@ -58,7 +57,7 @@ pub trait KeyDirectory: Send + Sync {
|
||||
/// Get directory filesystem path, if available
|
||||
fn path(&self) -> Option<&PathBuf> { None }
|
||||
/// Return vault provider, if available
|
||||
fn as_vault_provider(&self) -> Option<&VaultKeyDirectoryProvider> { None }
|
||||
fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> { None }
|
||||
/// Unique representation of directory account collection
|
||||
fn unique_repr(&self) -> Result<u64, Error>;
|
||||
}
|
||||
@@ -66,9 +65,9 @@ pub trait KeyDirectory: Send + Sync {
|
||||
/// Vaults provider
|
||||
pub trait VaultKeyDirectoryProvider {
|
||||
/// Create new vault with given key
|
||||
fn create(&self, name: &str, key: VaultKey) -> Result<Box<VaultKeyDirectory>, Error>;
|
||||
fn create(&self, name: &str, key: VaultKey) -> Result<Box<dyn VaultKeyDirectory>, Error>;
|
||||
/// Open existing vault with given key
|
||||
fn open(&self, name: &str, key: VaultKey) -> Result<Box<VaultKeyDirectory>, Error>;
|
||||
fn open(&self, name: &str, key: VaultKey) -> Result<Box<dyn VaultKeyDirectory>, Error>;
|
||||
/// List all vaults
|
||||
fn list_vaults(&self) -> Result<Vec<String>, Error>;
|
||||
/// Get vault meta
|
||||
@@ -78,7 +77,7 @@ pub trait VaultKeyDirectoryProvider {
|
||||
/// Vault directory
|
||||
pub trait VaultKeyDirectory: KeyDirectory {
|
||||
/// Cast to `KeyDirectory`
|
||||
fn as_key_directory(&self) -> &KeyDirectory;
|
||||
fn as_key_directory(&self) -> &dyn KeyDirectory;
|
||||
/// Vault name
|
||||
fn name(&self) -> &str;
|
||||
/// Get vault key
|
||||
@@ -97,7 +96,7 @@ pub use self::vault::VaultDiskDirectory;
|
||||
|
||||
impl VaultKey {
|
||||
/// Create new vault key
|
||||
pub fn new(password: &Password, iterations: NonZeroU32) -> Self {
|
||||
pub fn new(password: &Password, iterations: u32) -> Self {
|
||||
VaultKey {
|
||||
password: password.clone(),
|
||||
iterations: iterations,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -119,7 +119,7 @@ impl VaultDiskDirectory {
|
||||
}
|
||||
|
||||
impl VaultKeyDirectory for VaultDiskDirectory {
|
||||
fn as_key_directory(&self) -> &KeyDirectory {
|
||||
fn as_key_directory(&self) -> &dyn KeyDirectory {
|
||||
self
|
||||
}
|
||||
|
||||
@@ -282,17 +282,11 @@ mod test {
|
||||
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::num::NonZeroU32;
|
||||
use std::path::PathBuf;
|
||||
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;
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_vault_name_succeeds() {
|
||||
assert!(check_vault_name("vault"));
|
||||
@@ -331,7 +325,7 @@ mod test {
|
||||
fn create_vault_file_succeeds() {
|
||||
// given
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new(&"password".into(), *ITERATIONS);
|
||||
let key = VaultKey::new(&"password".into(), 1024);
|
||||
let mut vault_dir: PathBuf = temp_path.path().into();
|
||||
vault_dir.push("vault");
|
||||
fs::create_dir_all(&vault_dir).unwrap();
|
||||
@@ -350,7 +344,7 @@ mod test {
|
||||
fn read_vault_file_succeeds() {
|
||||
// given
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new(&"password".into(), *ITERATIONS);
|
||||
let key = VaultKey::new(&"password".into(), 1024);
|
||||
let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"758696c8dc6378ab9b25bb42790da2f5"},"ciphertext":"54eb50683717d41caaeb12ea969f2c159daada5907383f26f327606a37dc7168","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"3c320fa566a1a7963ac8df68a19548d27c8f40bf92ef87c84594dcd5bbc402b6"},"mac":"9e5c2314c2a0781962db85611417c614bd6756666b6b1e93840f5b6ed895f003"}}"#;
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
let mut vault_file_path: PathBuf = dir.clone();
|
||||
@@ -371,7 +365,7 @@ mod test {
|
||||
fn read_vault_file_fails() {
|
||||
// given
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new(&"password1".into(), *ITERATIONS);
|
||||
let key = VaultKey::new(&"password1".into(), 1024);
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
let mut vault_file_path: PathBuf = dir.clone();
|
||||
vault_file_path.push(VAULT_FILE_NAME);
|
||||
@@ -400,7 +394,7 @@ mod test {
|
||||
fn vault_directory_can_be_created() {
|
||||
// given
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new(&"password".into(), *ITERATIONS);
|
||||
let key = VaultKey::new(&"password".into(), 1024);
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
|
||||
// when
|
||||
@@ -420,7 +414,7 @@ mod test {
|
||||
fn vault_directory_cannot_be_created_if_already_exists() {
|
||||
// given
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new(&"password".into(), *ITERATIONS);
|
||||
let key = VaultKey::new(&"password".into(), 1024);
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
let mut vault_dir = dir.clone();
|
||||
vault_dir.push("vault");
|
||||
@@ -437,7 +431,7 @@ mod test {
|
||||
fn vault_directory_cannot_be_opened_if_not_exists() {
|
||||
// given
|
||||
let temp_path = TempDir::new("").unwrap();
|
||||
let key = VaultKey::new(&"password".into(), *ITERATIONS);
|
||||
let key = VaultKey::new(&"password".into(), 1024);
|
||||
let dir: PathBuf = temp_path.path().into();
|
||||
|
||||
// when
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::io::Error as IoError;
|
||||
use ethkey::{self, Error as EthKeyError};
|
||||
use crypto::{self, Error as EthCryptoError};
|
||||
use ethkey::DerivationError;
|
||||
use crypto::publickey::{Error as EthPublicKeyCryptoError, DerivationError};
|
||||
|
||||
/// Account-related errors.
|
||||
#[derive(Debug)]
|
||||
@@ -47,12 +46,10 @@ pub enum Error {
|
||||
VaultNotFound,
|
||||
/// Account creation failed.
|
||||
CreationFailed,
|
||||
/// `EthKey` error
|
||||
EthKey(EthKeyError),
|
||||
/// `ethkey::crypto::Error`
|
||||
EthKeyCrypto(ethkey::crypto::Error),
|
||||
/// `EthCrypto` error
|
||||
EthCrypto(EthCryptoError),
|
||||
/// `EthPublicKeyCryptoError` error
|
||||
EthPublicKeyCrypto(EthPublicKeyCryptoError),
|
||||
/// Derivation error
|
||||
Derivation(DerivationError),
|
||||
/// Custom error
|
||||
@@ -74,9 +71,8 @@ impl fmt::Display for Error {
|
||||
Error::InvalidVaultName => "Invalid vault name".into(),
|
||||
Error::VaultNotFound => "Vault not found".into(),
|
||||
Error::CreationFailed => "Account creation failed".into(),
|
||||
Error::EthKey(ref err) => err.to_string(),
|
||||
Error::EthKeyCrypto(ref err) => err.to_string(),
|
||||
Error::EthCrypto(ref err) => err.to_string(),
|
||||
Error::EthPublicKeyCrypto(ref err) => err.to_string(),
|
||||
Error::Derivation(ref err) => format!("Derivation error: {:?}", err),
|
||||
Error::Custom(ref s) => s.clone(),
|
||||
};
|
||||
@@ -91,15 +87,9 @@ impl From<IoError> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EthKeyError> for Error {
|
||||
fn from(err: EthKeyError) -> Self {
|
||||
Error::EthKey(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ethkey::crypto::Error> for Error {
|
||||
fn from(err: ethkey::crypto::Error) -> Self {
|
||||
Error::EthKeyCrypto(err)
|
||||
impl From<EthPublicKeyCryptoError> for Error {
|
||||
fn from(err: EthPublicKeyCryptoError) -> Self {
|
||||
Error::EthPublicKeyCrypto(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! ethkey reexport to make documentation look pretty.
|
||||
pub use _ethkey::*;
|
||||
use json;
|
||||
|
||||
impl Into<json::H160> for Address {
|
||||
fn into(self) -> json::H160 {
|
||||
let a: [u8; 20] = self.into();
|
||||
From::from(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<json::H160> for Address {
|
||||
fn from(json: json::H160) -> Self {
|
||||
let a: [u8; 20] = json.into();
|
||||
From::from(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a json::H160> for Address {
|
||||
fn from(json: &'a json::H160) -> Self {
|
||||
let mut a = [0u8; 20];
|
||||
a.copy_from_slice(json);
|
||||
From::from(a)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -15,26 +15,21 @@
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::num::NonZeroU32;
|
||||
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, Password, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair};
|
||||
use crypto::publickey::{Signature, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair};
|
||||
use ethkey::Password;
|
||||
use accounts_dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError};
|
||||
use account::SafeAccount;
|
||||
use presale::PresaleWallet;
|
||||
use json::{self, Uuid, OpaqueKeyFile};
|
||||
use {import, Error, SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation, OpaqueSecret};
|
||||
|
||||
|
||||
lazy_static! {
|
||||
static ref KEY_ITERATIONS: NonZeroU32 =
|
||||
NonZeroU32::new(crypto::KEY_ITERATIONS as u32).expect("KEY_ITERATIONS > 0; qed");
|
||||
}
|
||||
|
||||
/// Accounts store.
|
||||
pub struct EthStore {
|
||||
store: EthMultiStore,
|
||||
@@ -42,12 +37,12 @@ pub struct EthStore {
|
||||
|
||||
impl EthStore {
|
||||
/// Open a new accounts store with given key directory backend.
|
||||
pub fn open(directory: Box<KeyDirectory>) -> Result<Self, Error> {
|
||||
Self::open_with_iterations(directory, *KEY_ITERATIONS)
|
||||
pub fn open(directory: Box<dyn KeyDirectory>) -> Result<Self, Error> {
|
||||
Self::open_with_iterations(directory, KEY_ITERATIONS as u32)
|
||||
}
|
||||
|
||||
/// Open a new account store with given key directory backend and custom number of iterations.
|
||||
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: NonZeroU32) -> Result<Self, Error> {
|
||||
pub fn open_with_iterations(directory: Box<dyn KeyDirectory>, iterations: u32) -> Result<Self, Error> {
|
||||
Ok(EthStore {
|
||||
store: EthMultiStore::open_with_iterations(directory, iterations)?,
|
||||
})
|
||||
@@ -190,7 +185,7 @@ impl SecretStore for EthStore {
|
||||
Ok(account.check_password(password))
|
||||
}
|
||||
|
||||
fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &Password, new_password: &Password) -> Result<(), Error> {
|
||||
fn copy_account(&self, new_store: &dyn SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &Password, new_password: &Password) -> Result<(), Error> {
|
||||
let account = self.get(account)?;
|
||||
let secret = account.crypto.secret(password)?;
|
||||
new_store.insert_account(new_vault, secret, new_password)?;
|
||||
@@ -262,11 +257,11 @@ impl SecretStore for EthStore {
|
||||
|
||||
/// Similar to `EthStore` but may store many accounts (with different passwords) for the same `Address`
|
||||
pub struct EthMultiStore {
|
||||
dir: Box<KeyDirectory>,
|
||||
iterations: NonZeroU32,
|
||||
dir: Box<dyn KeyDirectory>,
|
||||
iterations: u32,
|
||||
// order lock: cache, then vaults
|
||||
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
|
||||
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>,
|
||||
vaults: Mutex<HashMap<String, Box<dyn VaultKeyDirectory>>>,
|
||||
timestamp: Mutex<Timestamp>,
|
||||
}
|
||||
|
||||
@@ -278,12 +273,12 @@ struct Timestamp {
|
||||
|
||||
impl EthMultiStore {
|
||||
/// Open new multi-accounts store with given key directory backend.
|
||||
pub fn open(directory: Box<KeyDirectory>) -> Result<Self, Error> {
|
||||
Self::open_with_iterations(directory, *KEY_ITERATIONS)
|
||||
pub fn open(directory: Box<dyn KeyDirectory>) -> Result<Self, Error> {
|
||||
Self::open_with_iterations(directory, KEY_ITERATIONS as u32)
|
||||
}
|
||||
|
||||
/// Open new multi-accounts store with given key directory backend and custom number of iterations for new keys.
|
||||
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: NonZeroU32) -> Result<Self, Error> {
|
||||
pub fn open_with_iterations(directory: Box<dyn KeyDirectory>, iterations: u32) -> Result<Self, Error> {
|
||||
let store = EthMultiStore {
|
||||
dir: directory,
|
||||
vaults: Mutex::new(HashMap::new()),
|
||||
@@ -448,13 +443,13 @@ impl EthMultiStore {
|
||||
Derivation::Hierarchical(path) => {
|
||||
for path_item in path {
|
||||
extended = extended.derive(
|
||||
if path_item.soft { ethkey::Derivation::Soft(path_item.index) }
|
||||
else { ethkey::Derivation::Hard(path_item.index) }
|
||||
if path_item.soft { crypto::publickey::Derivation::Soft(path_item.index) }
|
||||
else { crypto::publickey::Derivation::Hard(path_item.index) }
|
||||
)?;
|
||||
}
|
||||
},
|
||||
Derivation::SoftHash(h256) => { extended = extended.derive(ethkey::Derivation::Soft(h256))?; }
|
||||
Derivation::HardHash(h256) => { extended = extended.derive(ethkey::Derivation::Hard(h256))?; }
|
||||
Derivation::SoftHash(h256) => { extended = extended.derive(crypto::publickey::Derivation::Soft(h256))?; }
|
||||
Derivation::HardHash(h256) => { extended = extended.derive(crypto::publickey::Derivation::Hard(h256))?; }
|
||||
}
|
||||
Ok(extended)
|
||||
}
|
||||
@@ -485,7 +480,7 @@ impl SimpleSecretStore for EthMultiStore {
|
||||
let accounts = self.get_matching(&account_ref, password)?;
|
||||
for account in accounts {
|
||||
let extended = self.generate(account.crypto.secret(password)?, derivation)?;
|
||||
return Ok(ethkey::public_to_address(extended.public().public()));
|
||||
return Ok(crypto::publickey::public_to_address(extended.public().public()));
|
||||
}
|
||||
Err(Error::InvalidPassword)
|
||||
}
|
||||
@@ -497,7 +492,7 @@ impl SimpleSecretStore for EthMultiStore {
|
||||
for account in accounts {
|
||||
let extended = self.generate(account.crypto.secret(password)?, derivation)?;
|
||||
let secret = extended.secret().as_raw();
|
||||
return Ok(ethkey::sign(&secret, message)?)
|
||||
return Ok(crypto::publickey::sign(&secret, message)?)
|
||||
}
|
||||
Err(Error::InvalidPassword)
|
||||
}
|
||||
@@ -696,7 +691,7 @@ mod tests {
|
||||
extern crate tempdir;
|
||||
|
||||
use accounts_dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory};
|
||||
use ethkey::{Random, Generator, KeyPair};
|
||||
use crypto::publickey::{Random, Generator, KeyPair};
|
||||
use secret_store::{SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation};
|
||||
use super::{EthStore, EthMultiStore};
|
||||
use self::tempdir::TempDir;
|
||||
@@ -715,7 +710,7 @@ mod tests {
|
||||
}
|
||||
|
||||
struct RootDiskDirectoryGuard {
|
||||
pub key_dir: Option<Box<KeyDirectory>>,
|
||||
pub key_dir: Option<Box<dyn KeyDirectory>>,
|
||||
_path: TempDir,
|
||||
}
|
||||
|
||||
@@ -1090,7 +1085,7 @@ mod tests {
|
||||
SecretVaultRef::Root,
|
||||
&address,
|
||||
&"test".into(),
|
||||
Derivation::HardHash(H256::from(0)),
|
||||
Derivation::HardHash(H256::zero()),
|
||||
).unwrap();
|
||||
|
||||
// there should be 2 accounts in the store
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -18,13 +18,13 @@ use std::collections::HashSet;
|
||||
use std::path::Path;
|
||||
use std::fs;
|
||||
|
||||
use ethkey::Address;
|
||||
use crypto::publickey::Address;
|
||||
use accounts_dir::{KeyDirectory, RootDiskDirectory, DiskKeyFileManager, KeyFileManager};
|
||||
use dir;
|
||||
use Error;
|
||||
|
||||
/// Import an account from a file.
|
||||
pub fn import_account(path: &Path, dst: &KeyDirectory) -> Result<Address, Error> {
|
||||
pub fn import_account(path: &Path, dst: &dyn KeyDirectory) -> Result<Address, Error> {
|
||||
let key_manager = DiskKeyFileManager::default();
|
||||
let existing_accounts = dst.load()?.into_iter().map(|a| a.address).collect::<HashSet<_>>();
|
||||
let filename = path.file_name().and_then(|n| n.to_str()).map(|f| f.to_owned());
|
||||
@@ -40,7 +40,7 @@ pub fn import_account(path: &Path, dst: &KeyDirectory) -> Result<Address, Error>
|
||||
}
|
||||
|
||||
/// Import all accounts from one directory to the other.
|
||||
pub fn import_accounts(src: &KeyDirectory, dst: &KeyDirectory) -> Result<Vec<Address>, Error> {
|
||||
pub fn import_accounts(src: &dyn KeyDirectory, dst: &dyn KeyDirectory) -> Result<Vec<Address>, Error> {
|
||||
let accounts = src.load()?;
|
||||
let existing_accounts = dst.load()?.into_iter()
|
||||
.map(|a| a.address)
|
||||
@@ -64,7 +64,7 @@ pub fn read_geth_accounts(testnet: bool) -> Vec<Address> {
|
||||
}
|
||||
|
||||
/// Import specific `desired` accounts from the Geth keystore into `dst`.
|
||||
pub fn import_geth_accounts(dst: &KeyDirectory, desired: HashSet<Address>, testnet: bool) -> Result<Vec<Address>, Error> {
|
||||
pub fn import_geth_accounts(dst: &dyn KeyDirectory, desired: HashSet<Address>, testnet: bool) -> Result<Vec<Address>, Error> {
|
||||
let src = RootDiskDirectory::at(dir::geth(testnet));
|
||||
let accounts = src.load()?;
|
||||
let existing_accounts = dst.load()?.into_iter().map(|a| a.address).collect::<HashSet<_>>();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -41,7 +41,7 @@ impl str::FromStr for Crypto {
|
||||
|
||||
impl From<Crypto> for String {
|
||||
fn from(c: Crypto) -> Self {
|
||||
serde_json::to_string(&c).expect("serialization cannot fail, cause all crypto keys are strings")
|
||||
serde_json::to_string(&c).expect("Serialization cannot fail, because all crypto keys are strings")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -38,7 +38,7 @@ impl<'a> Into<String> for &'a Uuid {
|
||||
let d3 = &self.0[6..8];
|
||||
let d4 = &self.0[8..10];
|
||||
let d5 = &self.0[10..16];
|
||||
[d1, d2, d3, d4, d5].into_iter().map(|d| d.to_hex()).collect::<Vec<String>>().join("-")
|
||||
[d1, d2, d3, d4, d5].iter().map(|d| d.to_hex()).collect::<Vec<String>>().join("-")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -15,7 +15,6 @@
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fmt;
|
||||
use std::num::NonZeroU32;
|
||||
use serde::{Serialize, Serializer, Deserialize, Deserializer};
|
||||
use serde::de::{Visitor, Error as SerdeError};
|
||||
use super::{Error, Bytes};
|
||||
@@ -109,7 +108,7 @@ impl<'a> Visitor<'a> for PrfVisitor {
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Pbkdf2 {
|
||||
pub c: NonZeroU32,
|
||||
pub c: u32,
|
||||
pub dklen: u32,
|
||||
pub prf: Prf,
|
||||
pub salt: Bytes,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -41,11 +41,6 @@ impl VaultFile {
|
||||
mod test {
|
||||
use serde_json;
|
||||
use json::{VaultFile, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
lazy_static! {
|
||||
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_and_from_json() {
|
||||
@@ -56,7 +51,7 @@ mod test {
|
||||
}),
|
||||
ciphertext: "4d6938a1f49b7782".into(),
|
||||
kdf: Kdf::Pbkdf2(Pbkdf2 {
|
||||
c: *ITERATIONS,
|
||||
c: 1024,
|
||||
dklen: 32,
|
||||
prf: Prf::HmacSha256,
|
||||
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
|
||||
@@ -81,7 +76,7 @@ mod test {
|
||||
}),
|
||||
ciphertext: "4d6938a1f49b7782".into(),
|
||||
kdf: Kdf::Pbkdf2(Pbkdf2 {
|
||||
c: *ITERATIONS,
|
||||
c: 1024,
|
||||
dklen: 32,
|
||||
prf: Prf::HmacSha256,
|
||||
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -106,11 +106,6 @@ mod test {
|
||||
use serde_json;
|
||||
use json::{VaultKeyFile, Version, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf,
|
||||
insert_vault_name_to_json_meta, remove_vault_name_from_json_meta};
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
lazy_static! {
|
||||
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_and_from_json() {
|
||||
@@ -123,7 +118,7 @@ mod test {
|
||||
}),
|
||||
ciphertext: "4befe0a66d9a4b6fec8e39eb5c90ac5dafdeaab005fff1af665fd1f9af925c91".into(),
|
||||
kdf: Kdf::Pbkdf2(Pbkdf2 {
|
||||
c: *ITERATIONS,
|
||||
c: 10240,
|
||||
dklen: 32,
|
||||
prf: Prf::HmacSha256,
|
||||
salt: "f17731e84ecac390546692dbd4ccf6a3a2720dc9652984978381e61c28a471b2".into(),
|
||||
@@ -136,7 +131,7 @@ mod test {
|
||||
}),
|
||||
ciphertext: "fef0d113d7576c1702daf380ad6f4c5408389e57991cae2a174facd74bd549338e1014850bddbab7eb486ff5f5c9c5532800c6a6d4db2be2212cd5cd3769244ab230e1f369e8382a9e6d7c0a".into(),
|
||||
kdf: Kdf::Pbkdf2(Pbkdf2 {
|
||||
c: *ITERATIONS,
|
||||
c: 10240,
|
||||
dklen: 32,
|
||||
prf: Prf::HmacSha256,
|
||||
salt: "aca82865174a82249a198814b263f43a631f272cbf7ed329d0f0839d259c652a".into(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -33,11 +33,9 @@ extern crate tempdir;
|
||||
|
||||
extern crate parity_crypto as crypto;
|
||||
extern crate ethereum_types;
|
||||
extern crate ethkey as _ethkey;
|
||||
extern crate ethkey as ethkey;
|
||||
extern crate parity_wordlist;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
@@ -48,7 +46,6 @@ extern crate serde_derive;
|
||||
extern crate matches;
|
||||
|
||||
pub mod accounts_dir;
|
||||
pub mod ethkey;
|
||||
|
||||
mod account;
|
||||
mod json;
|
||||
@@ -74,4 +71,30 @@ pub use self::random::random_string;
|
||||
pub use self::parity_wordlist::random_phrase;
|
||||
|
||||
/// An opaque wrapper for secret.
|
||||
pub struct OpaqueSecret(::ethkey::Secret);
|
||||
pub struct OpaqueSecret(crypto::publickey::Secret);
|
||||
|
||||
// Additional converters for Address
|
||||
use crypto::publickey::Address;
|
||||
|
||||
impl Into<json::H160> for Address {
|
||||
fn into(self) -> json::H160 {
|
||||
let a: [u8; 20] = self.into();
|
||||
From::from(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<json::H160> for Address {
|
||||
fn from(json: json::H160) -> Self {
|
||||
let a: [u8; 20] = json.into();
|
||||
From::from(a)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a json::H160> for Address {
|
||||
fn from(json: &'a json::H160) -> Self {
|
||||
let mut a = [0u8; 20];
|
||||
a.copy_from_slice(json);
|
||||
From::from(a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -15,10 +15,10 @@
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::fs;
|
||||
use std::num::NonZeroU32;
|
||||
use std::path::Path;
|
||||
use json;
|
||||
use ethkey::{Address, Secret, KeyPair, Password};
|
||||
use crypto::publickey::{Address, Secret, KeyPair};
|
||||
use ethkey::Password;
|
||||
use crypto::{Keccak256, pbkdf2};
|
||||
use {crypto, Error};
|
||||
|
||||
@@ -59,15 +59,14 @@ impl PresaleWallet {
|
||||
let mut derived_key = [0u8; 32];
|
||||
let salt = pbkdf2::Salt(password.as_bytes());
|
||||
let sec = pbkdf2::Secret(password.as_bytes());
|
||||
let iter = NonZeroU32::new(2000).expect("2000 > 0; qed");
|
||||
pbkdf2::sha256(iter, salt, sec, &mut derived_key);
|
||||
pbkdf2::sha256(2000, salt, sec, &mut derived_key);
|
||||
|
||||
let mut key = vec![0; self.ciphertext.len()];
|
||||
let len = crypto::aes::decrypt_128_cbc(&derived_key[0..16], &self.iv, &self.ciphertext, &mut key)
|
||||
.map_err(|_| Error::InvalidPassword)?;
|
||||
let unpadded = &key[..len];
|
||||
|
||||
let secret = Secret::from_unsafe_slice(&unpadded.keccak256())?;
|
||||
let secret = Secret::import_key(&unpadded.keccak256())?;
|
||||
if let Ok(kp) = KeyPair::from_secret(secret) {
|
||||
if kp.address() == self.address {
|
||||
return Ok(kp)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use rand::{Rng, OsRng};
|
||||
use rand::{Rng, RngCore, rngs::OsRng, distributions::Alphanumeric};
|
||||
|
||||
pub trait Random {
|
||||
fn random() -> Self where Self: Sized;
|
||||
@@ -23,7 +23,7 @@ pub trait Random {
|
||||
impl Random for [u8; 16] {
|
||||
fn random() -> Self {
|
||||
let mut result = [0u8; 16];
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut rng = OsRng;
|
||||
rng.fill_bytes(&mut result);
|
||||
result
|
||||
}
|
||||
@@ -32,7 +32,7 @@ impl Random for [u8; 16] {
|
||||
impl Random for [u8; 32] {
|
||||
fn random() -> Self {
|
||||
let mut result = [0u8; 32];
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut rng = OsRng;
|
||||
rng.fill_bytes(&mut result);
|
||||
result
|
||||
}
|
||||
@@ -40,6 +40,6 @@ impl Random for [u8; 32] {
|
||||
|
||||
/// Generate a random string of given length.
|
||||
pub fn random_string(length: usize) -> String {
|
||||
let mut rng = OsRng::new().expect("Not able to operate without random source.");
|
||||
rng.gen_ascii_chars().take(length).collect()
|
||||
let rng = OsRng;
|
||||
rng.sample_iter(&Alphanumeric).take(length).collect()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -17,7 +17,8 @@
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::path::PathBuf;
|
||||
use std::cmp::Ordering;
|
||||
use ethkey::{Address, Message, Signature, Secret, Password, Public};
|
||||
use crypto::publickey::{Address, Message, Signature, Secret, Public};
|
||||
use ethkey::Password;
|
||||
use Error;
|
||||
use json::{Uuid, OpaqueKeyFile};
|
||||
use ethereum_types::H256;
|
||||
@@ -110,7 +111,7 @@ pub trait SecretStore: SimpleSecretStore {
|
||||
|
||||
/// Signs a message with raw secret.
|
||||
fn sign_with_secret(&self, secret: &OpaqueSecret, message: &Message) -> Result<Signature, Error> {
|
||||
Ok(::ethkey::sign(&secret.0, message)?)
|
||||
Ok(crypto::publickey::sign(&secret.0, message)?)
|
||||
}
|
||||
|
||||
/// Imports presale wallet
|
||||
@@ -118,7 +119,7 @@ pub trait SecretStore: SimpleSecretStore {
|
||||
/// Imports existing JSON wallet
|
||||
fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &Password, gen_id: bool) -> Result<StoreAccountRef, Error>;
|
||||
/// Copies account between stores and vaults.
|
||||
fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &Password, new_password: &Password) -> Result<(), Error>;
|
||||
fn copy_account(&self, new_store: &dyn SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &Password, new_password: &Password) -> Result<(), Error>;
|
||||
/// Checks if password matches given account.
|
||||
fn test_password(&self, account: &StoreAccountRef, password: &Password) -> Result<bool, Error>;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -16,13 +16,17 @@
|
||||
|
||||
extern crate rand;
|
||||
extern crate ethstore;
|
||||
extern crate ethereum_types;
|
||||
extern crate parity_crypto;
|
||||
|
||||
mod util;
|
||||
|
||||
use ethstore::{EthStore, SimpleSecretStore, SecretVaultRef, StoreAccountRef};
|
||||
use ethstore::ethkey::{Random, Generator, Secret, KeyPair, verify_address};
|
||||
use parity_crypto::publickey::{Random, Generator, Secret, KeyPair, verify_address};
|
||||
use ethstore::accounts_dir::RootDiskDirectory;
|
||||
use util::TransientDir;
|
||||
use ethereum_types::Address;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn secret_store_create() {
|
||||
@@ -114,9 +118,9 @@ fn secret_store_laod_geth_files() {
|
||||
let dir = RootDiskDirectory::at(test_path());
|
||||
let store = EthStore::open(Box::new(dir)).unwrap();
|
||||
assert_eq!(store.accounts().unwrap(), vec![
|
||||
StoreAccountRef::root("3f49624084b67849c7b4e805c5988c21a430f9d9".into()),
|
||||
StoreAccountRef::root("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf".into()),
|
||||
StoreAccountRef::root("63121b431a52f8043c16fcf0d1df9cb7b5f66649".into()),
|
||||
StoreAccountRef::root(Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()),
|
||||
StoreAccountRef::root(Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()),
|
||||
StoreAccountRef::root(Address::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap()),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -125,8 +129,8 @@ fn secret_store_load_pat_files() {
|
||||
let dir = RootDiskDirectory::at(pat_path());
|
||||
let store = EthStore::open(Box::new(dir)).unwrap();
|
||||
assert_eq!(store.accounts().unwrap(), vec![
|
||||
StoreAccountRef::root("3f49624084b67849c7b4e805c5988c21a430f9d9".into()),
|
||||
StoreAccountRef::root("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf".into()),
|
||||
StoreAccountRef::root(Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()),
|
||||
StoreAccountRef::root(Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -140,8 +144,8 @@ fn test_decrypting_files_with_short_ciphertext() {
|
||||
let store = EthStore::open(Box::new(dir)).unwrap();
|
||||
let accounts = store.accounts().unwrap();
|
||||
assert_eq!(accounts, vec![
|
||||
StoreAccountRef::root("31e9d1e6d844bd3a536800ef8d8be6a9975db509".into()),
|
||||
StoreAccountRef::root("d1e64e5480bfaf733ba7d48712decb8227797a4e".into()),
|
||||
StoreAccountRef::root(Address::from_str("31e9d1e6d844bd3a536800ef8d8be6a9975db509").unwrap()),
|
||||
StoreAccountRef::root(Address::from_str("d1e64e5480bfaf733ba7d48712decb8227797a4e").unwrap()),
|
||||
]);
|
||||
|
||||
let message = Default::default();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::{env, fs};
|
||||
use rand::{Rng, OsRng};
|
||||
use rand::{RngCore, rngs::OsRng};
|
||||
use ethstore::accounts_dir::{KeyDirectory, RootDiskDirectory};
|
||||
use ethstore::{Error, SafeAccount};
|
||||
|
||||
pub fn random_dir() -> PathBuf {
|
||||
let mut rng = OsRng::new().unwrap();
|
||||
let mut rng = OsRng;
|
||||
let mut dir = env::temp_dir();
|
||||
dir.push(format!("{:x}-{:x}", rng.next_u64(), rng.next_u64()));
|
||||
dir
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
[package]
|
||||
description = "Fake hardware-wallet, for OS' that don't support libusb"
|
||||
name = "fake-hardware-wallet"
|
||||
version = "0.0.1"
|
||||
license = "GPL-3.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.4"
|
||||
ethkey = { path = "../../accounts/ethkey" }
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Dummy module for platforms that does not provide support for hardware wallets (libusb)
|
||||
|
||||
extern crate ethereum_types;
|
||||
extern crate ethkey;
|
||||
|
||||
use std::fmt;
|
||||
use ethereum_types::U256;
|
||||
use ethkey::{Address, Signature};
|
||||
|
||||
pub struct WalletInfo {
|
||||
pub address: Address,
|
||||
pub name: String,
|
||||
pub manufacturer: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// `ErrorType` for devices with no `hardware wallet`
|
||||
pub enum Error {
|
||||
NoWallet,
|
||||
KeyNotFound,
|
||||
}
|
||||
|
||||
pub struct TransactionInfo {
|
||||
/// Nonce
|
||||
pub nonce: U256,
|
||||
/// Gas price
|
||||
pub gas_price: U256,
|
||||
/// Gas limit
|
||||
pub gas_limit: U256,
|
||||
/// Receiver
|
||||
pub to: Option<Address>,
|
||||
/// Value
|
||||
pub value: U256,
|
||||
/// Data
|
||||
pub data: Vec<u8>,
|
||||
/// Chain ID
|
||||
pub chain_id: Option<u64>,
|
||||
}
|
||||
|
||||
pub enum KeyPath {
|
||||
/// Ethereum.
|
||||
Ethereum,
|
||||
/// Ethereum classic.
|
||||
EthereumClassic,
|
||||
}
|
||||
|
||||
/// `HardwareWalletManager` for devices with no `hardware wallet`
|
||||
pub struct HardwareWalletManager;
|
||||
|
||||
impl HardwareWalletManager {
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
Err(Error::NoWallet)
|
||||
}
|
||||
|
||||
pub fn set_key_path(&self, _key_path: KeyPath) {}
|
||||
|
||||
pub fn wallet_info(&self, _: &Address) -> Option<WalletInfo> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn list_wallets(&self) -> Vec<WalletInfo> {
|
||||
Vec::with_capacity(0)
|
||||
}
|
||||
|
||||
pub fn list_locked_wallets(&self) -> Result<Vec<String>, Error> {
|
||||
Err(Error::NoWallet)
|
||||
}
|
||||
|
||||
pub fn pin_matrix_ack(&self, _: &str, _: &str) -> Result<bool, Error> {
|
||||
Err(Error::NoWallet)
|
||||
}
|
||||
|
||||
pub fn sign_transaction(&self, _address: &Address, _transaction: &TransactionInfo, _rlp_transaction: &[u8]) -> Result<Signature, Error> {
|
||||
Err(Error::NoWallet) }
|
||||
|
||||
pub fn sign_message(&self, _address: &Address, _msg: &[u8]) -> Result<Signature, Error> {
|
||||
Err(Error::NoWallet)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "No hardware wallet!!")
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
[package]
|
||||
description = "Hardware wallet support."
|
||||
homepage = "http://parity.io"
|
||||
license = "GPL-3.0"
|
||||
name = "hardware-wallet"
|
||||
version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
parking_lot = "0.7"
|
||||
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" }
|
||||
ethereum-types = "0.4"
|
||||
semver = "0.9"
|
||||
|
||||
[dev-dependencies]
|
||||
rustc-hex = "1.0"
|
||||
File diff suppressed because one or more lines are too long
@@ -1,402 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Hardware wallet management.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![warn(warnings)]
|
||||
|
||||
extern crate ethereum_types;
|
||||
extern crate ethkey;
|
||||
extern crate hidapi;
|
||||
extern crate libusb;
|
||||
extern crate parking_lot;
|
||||
extern crate protobuf;
|
||||
extern crate semver;
|
||||
extern crate trezor_sys;
|
||||
|
||||
#[macro_use] extern crate log;
|
||||
#[cfg(test)] extern crate rustc_hex;
|
||||
|
||||
mod ledger;
|
||||
mod trezor;
|
||||
|
||||
use std::sync::{Arc, atomic, atomic::AtomicBool, Weak};
|
||||
use std::{fmt, time::Duration};
|
||||
use std::thread;
|
||||
|
||||
use ethereum_types::U256;
|
||||
use ethkey::{Address, Signature};
|
||||
use parking_lot::Mutex;
|
||||
|
||||
const HID_GLOBAL_USAGE_PAGE: u16 = 0xFF00;
|
||||
const HID_USB_DEVICE_CLASS: u8 = 0;
|
||||
const MAX_POLLING_DURATION: Duration = Duration::from_millis(500);
|
||||
const USB_EVENT_POLLING_INTERVAL: Duration = Duration::from_millis(500);
|
||||
|
||||
/// `HardwareWallet` device
|
||||
#[derive(Debug)]
|
||||
pub struct Device {
|
||||
path: String,
|
||||
info: WalletInfo,
|
||||
}
|
||||
|
||||
/// `Wallet` trait
|
||||
pub trait Wallet<'a> {
|
||||
/// Error
|
||||
type Error;
|
||||
/// Transaction data format
|
||||
type Transaction;
|
||||
|
||||
/// Sign transaction data with wallet managing `address`.
|
||||
fn sign_transaction(&self, address: &Address, transaction: Self::Transaction) -> Result<Signature, Self::Error>;
|
||||
|
||||
/// Set key derivation path for a chain.
|
||||
fn set_key_path(&self, key_path: KeyPath);
|
||||
|
||||
/// Re-populate device list
|
||||
/// Note, this assumes all devices are iterated over and updated
|
||||
fn update_devices(&self, device_direction: DeviceDirection) -> Result<usize, Self::Error>;
|
||||
|
||||
/// Read device info
|
||||
fn read_device(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result<Device, Self::Error>;
|
||||
|
||||
/// List connected and acknowledged wallets
|
||||
fn list_devices(&self) -> Vec<WalletInfo>;
|
||||
|
||||
/// List locked wallets
|
||||
/// This may be moved if it is the wrong assumption, for example this is not supported by Ledger
|
||||
/// Then this method return a empty vector
|
||||
fn list_locked_devices(&self) -> Vec<String>;
|
||||
|
||||
/// Get wallet info.
|
||||
fn get_wallet(&self, address: &Address) -> Option<WalletInfo>;
|
||||
|
||||
/// Generate ethereum address for a Wallet
|
||||
fn get_address(&self, device: &hidapi::HidDevice) -> Result<Option<Address>, Self::Error>;
|
||||
|
||||
/// Open a device using `device path`
|
||||
/// Note, f - is a closure that borrows HidResult<HidDevice>
|
||||
/// HidDevice is in turn a type alias for a `c_void function pointer`
|
||||
/// For further information see:
|
||||
/// * <https://github.com/paritytech/hidapi-rs>
|
||||
/// * <https://github.com/rust-lang/libc>
|
||||
fn open_path<R, F>(&self, f: F) -> Result<R, Self::Error>
|
||||
where F: Fn() -> Result<R, &'static str>;
|
||||
}
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/// 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<Address>,
|
||||
/// Value
|
||||
pub value: U256,
|
||||
/// Data
|
||||
pub data: Vec<u8>,
|
||||
/// Chain ID
|
||||
pub chain_id: Option<u64>,
|
||||
}
|
||||
|
||||
/// Hardware wallet information.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WalletInfo {
|
||||
/// Wallet device name.
|
||||
pub name: String,
|
||||
/// Wallet device manufacturer.
|
||||
pub manufacturer: String,
|
||||
/// Wallet device serial number.
|
||||
pub serial: String,
|
||||
/// Ethereum address.
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ledger::Error> for Error {
|
||||
fn from(err: ledger::Error) -> Self {
|
||||
match err {
|
||||
ledger::Error::KeyNotFound => Error::KeyNotFound,
|
||||
_ => Error::LedgerDevice(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<trezor::Error> for Error {
|
||||
fn from(err: trezor::Error) -> Self {
|
||||
match err {
|
||||
trezor::Error::KeyNotFound => Error::KeyNotFound,
|
||||
_ => Error::TrezorDevice(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<libusb::Error> for Error {
|
||||
fn from(err: libusb::Error) -> Self {
|
||||
Error::Usb(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the direction of the `HardwareWallet` i.e, whether it arrived or left
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum DeviceDirection {
|
||||
/// Device arrived
|
||||
Arrived,
|
||||
/// Device left
|
||||
Left,
|
||||
}
|
||||
|
||||
impl fmt::Display for DeviceDirection {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
DeviceDirection::Arrived => write!(f, "arrived"),
|
||||
DeviceDirection::Left => write!(f, "left"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Hardware wallet management interface.
|
||||
pub struct HardwareWalletManager {
|
||||
exiting: Arc<AtomicBool>,
|
||||
ledger: Arc<ledger::Manager>,
|
||||
trezor: Arc<trezor::Manager>,
|
||||
}
|
||||
|
||||
impl HardwareWalletManager {
|
||||
/// Hardware wallet constructor
|
||||
pub fn new() -> Result<Self, Error> {
|
||||
let exiting = Arc::new(AtomicBool::new(false));
|
||||
let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().map_err(|e| Error::Hid(e.to_string().clone()))?));
|
||||
let ledger = ledger::Manager::new(hidapi.clone());
|
||||
let trezor = trezor::Manager::new(hidapi.clone());
|
||||
let usb_context = Arc::new(libusb::Context::new()?);
|
||||
|
||||
let l = ledger.clone();
|
||||
let t = trezor.clone();
|
||||
let exit = exiting.clone();
|
||||
|
||||
// Subscribe to all vendor IDs (VIDs) and product IDs (PIDs)
|
||||
// This means that the `HardwareWalletManager` is responsible to validate the detected device
|
||||
usb_context.register_callback(
|
||||
None, None, Some(HID_USB_DEVICE_CLASS),
|
||||
Box::new(EventHandler::new(
|
||||
Arc::downgrade(&ledger),
|
||||
Arc::downgrade(&trezor)
|
||||
))
|
||||
)?;
|
||||
|
||||
// Hardware event subscriber thread
|
||||
thread::Builder::new()
|
||||
.name("hw_wallet_manager".to_string())
|
||||
.spawn(move || {
|
||||
if let Err(e) = l.update_devices(DeviceDirection::Arrived) {
|
||||
debug!(target: "hw", "Ledger couldn't connect at startup, error: {}", e);
|
||||
}
|
||||
if let Err(e) = t.update_devices(DeviceDirection::Arrived) {
|
||||
debug!(target: "hw", "Trezor couldn't connect at startup, error: {}", e);
|
||||
}
|
||||
|
||||
while !exit.load(atomic::Ordering::Acquire) {
|
||||
if let Err(e) = usb_context.handle_events(Some(USB_EVENT_POLLING_INTERVAL)) {
|
||||
debug!(target: "hw", "HardwareWalletManager event handler error: {}", e);
|
||||
}
|
||||
}
|
||||
})
|
||||
.ok();
|
||||
|
||||
Ok(Self {
|
||||
exiting,
|
||||
trezor,
|
||||
ledger,
|
||||
})
|
||||
}
|
||||
|
||||
/// Select key derivation path for a chain.
|
||||
/// Currently, only one hard-coded keypath is supported
|
||||
/// It is managed by `ethcore/account_provider`
|
||||
pub fn set_key_path(&self, key_path: KeyPath) {
|
||||
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<WalletInfo> {
|
||||
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
|
||||
/// This is only applicable to Trezor because Ledger only appears as
|
||||
/// a device when it is unlocked
|
||||
pub fn list_locked_wallets(&self) -> Result<Vec<String>, Error> {
|
||||
Ok(self.trezor.list_locked_devices())
|
||||
}
|
||||
|
||||
/// Get connected wallet info.
|
||||
pub fn wallet_info(&self, address: &Address) -> Option<WalletInfo> {
|
||||
if let Some(info) = self.ledger.get_wallet(address) {
|
||||
Some(info)
|
||||
} else {
|
||||
self.trezor.get_wallet(address)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign a message with the wallet (only supported by Ledger)
|
||||
pub fn sign_message(&self, address: &Address, msg: &[u8]) -> Result<Signature, Error> {
|
||||
if self.ledger.get_wallet(address).is_some() {
|
||||
Ok(self.ledger.sign_message(address, msg)?)
|
||||
} else if self.trezor.get_wallet(address).is_some() {
|
||||
Err(Error::TrezorDevice(trezor::Error::NoSigningMessage))
|
||||
} else {
|
||||
Err(Error::KeyNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign transaction data with wallet managing `address`.
|
||||
pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo, encoded_transaction: &[u8]) -> Result<Signature, Error> {
|
||||
if self.ledger.get_wallet(address).is_some() {
|
||||
Ok(self.ledger.sign_transaction(address, encoded_transaction)?)
|
||||
} else if self.trezor.get_wallet(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
|
||||
/// This is only applicable to Trezor because Ledger only appears as
|
||||
/// a device when it is unlocked
|
||||
pub fn pin_matrix_ack(&self, path: &str, pin: &str) -> Result<bool, Error> {
|
||||
self.trezor.pin_matrix_ack(path, pin).map_err(Error::TrezorDevice)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for HardwareWalletManager {
|
||||
fn drop(&mut self) {
|
||||
// Indicate to the USB Hotplug handler that it
|
||||
// shall terminate but don't wait for it to terminate.
|
||||
// If it doesn'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);
|
||||
}
|
||||
}
|
||||
|
||||
/// Hardware wallet event handler
|
||||
///
|
||||
/// Note, that this runs to completion and race-conditions can't occur but it can
|
||||
/// stop other events for being processed with an infinite loop or similar
|
||||
struct EventHandler {
|
||||
ledger: Weak<ledger::Manager>,
|
||||
trezor: Weak<trezor::Manager>,
|
||||
}
|
||||
|
||||
impl EventHandler {
|
||||
/// Trezor event handler constructor
|
||||
pub fn new(ledger: Weak<ledger::Manager>, trezor: Weak<trezor::Manager>) -> Self {
|
||||
Self { ledger, trezor }
|
||||
}
|
||||
|
||||
fn extract_device_info(device: &libusb::Device) -> Result<(u16, u16), Error> {
|
||||
let desc = device.device_descriptor()?;
|
||||
Ok((desc.vendor_id(), desc.product_id()))
|
||||
}
|
||||
}
|
||||
|
||||
impl libusb::Hotplug for EventHandler {
|
||||
fn device_arrived(&mut self, device: libusb::Device) {
|
||||
// Upgrade reference to an Arc
|
||||
if let (Some(ledger), Some(trezor)) = (self.ledger.upgrade(), self.trezor.upgrade()) {
|
||||
// Version ID and Product ID are available
|
||||
if let Ok((vid, pid)) = Self::extract_device_info(&device) {
|
||||
if trezor::is_valid_trezor(vid, pid) {
|
||||
if !trezor::try_connect_polling(&trezor, &MAX_POLLING_DURATION, DeviceDirection::Arrived) {
|
||||
trace!(target: "hw", "Trezor device was detected but connection failed");
|
||||
}
|
||||
} else if ledger::is_valid_ledger(vid, pid) {
|
||||
if !ledger::try_connect_polling(&ledger, &MAX_POLLING_DURATION, DeviceDirection::Arrived) {
|
||||
trace!(target: "hw", "Ledger device was detected but connection failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn device_left(&mut self, device: libusb::Device) {
|
||||
// Upgrade reference to an Arc
|
||||
if let (Some(ledger), Some(trezor)) = (self.ledger.upgrade(), self.trezor.upgrade()) {
|
||||
// Version ID and Product ID are available
|
||||
if let Ok((vid, pid)) = Self::extract_device_info(&device) {
|
||||
if trezor::is_valid_trezor(vid, pid) {
|
||||
if !trezor::try_connect_polling(&trezor, &MAX_POLLING_DURATION, DeviceDirection::Left) {
|
||||
trace!(target: "hw", "Trezor device was detected but disconnection failed");
|
||||
}
|
||||
} else if ledger::is_valid_ledger(vid, pid) {
|
||||
if !ledger::try_connect_polling(&ledger, &MAX_POLLING_DURATION, DeviceDirection::Left) {
|
||||
trace!(target: "hw", "Ledger device was detected but disconnection failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper to determine if a device is a valid HID
|
||||
pub fn is_valid_hid_device(usage_page: u16, interface_number: i32) -> bool {
|
||||
usage_page == HID_GLOBAL_USAGE_PAGE || interface_number == HID_USB_DEVICE_CLASS as i32
|
||||
}
|
||||
@@ -1,463 +0,0 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity Ethereum is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! 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 std::cmp::{min, max};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::fmt;
|
||||
|
||||
use ethereum_types::{U256, H256, Address};
|
||||
use ethkey::Signature;
|
||||
use hidapi;
|
||||
use libusb;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use protobuf::{self, Message, ProtobufEnum};
|
||||
use super::{DeviceDirection, WalletInfo, TransactionInfo, KeyPath, Wallet, Device, is_valid_hid_device};
|
||||
use trezor_sys::messages::{EthereumAddress, PinMatrixAck, MessageType, EthereumTxRequest, EthereumSignTx, EthereumGetAddress, EthereumTxAck, ButtonAck};
|
||||
|
||||
/// Trezor v1 vendor ID
|
||||
const TREZOR_VID: u16 = 0x534c;
|
||||
/// Trezor product IDs
|
||||
const TREZOR_PIDS: [u16; 1] = [0x0001];
|
||||
|
||||
const ETH_DERIVATION_PATH: [u32; 5] = [0x8000_002C, 0x8000_003C, 0x8000_0000, 0, 0]; // m/44'/60'/0'/0/0
|
||||
const ETC_DERIVATION_PATH: [u32; 5] = [0x8000_002C, 0x8000_003D, 0x8000_0000, 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),
|
||||
/// Libusb error
|
||||
LibUsb(libusb::Error),
|
||||
/// 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),
|
||||
/// Signing messages are not supported by Trezor
|
||||
NoSigningMessage,
|
||||
/// No device arrived
|
||||
NoDeviceArrived,
|
||||
/// No device left
|
||||
NoDeviceLeft,
|
||||
/// Invalid PID or VID
|
||||
InvalidDevice,
|
||||
}
|
||||
|
||||
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::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::BadMessageType => write!(f, "Bad Message Type in RPC call"),
|
||||
Error::LockedDevice(ref s) => write!(f, "Device is locked, needs PIN to perform operations: {}", s),
|
||||
Error::NoSigningMessage=> write!(f, "Signing messages are not supported by Trezor"),
|
||||
Error::NoDeviceArrived => write!(f, "No device arrived"),
|
||||
Error::NoDeviceLeft => write!(f, "No device left"),
|
||||
Error::InvalidDevice => write!(f, "Device with non-supported product ID or vendor ID was detected"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<hidapi::HidError> for Error {
|
||||
fn from(err: hidapi::HidError) -> Self {
|
||||
Error::Usb(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<libusb::Error> for Error {
|
||||
fn from(err: libusb::Error) -> Self {
|
||||
Error::LibUsb(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<protobuf::ProtobufError> for Error {
|
||||
fn from(_: protobuf::ProtobufError) -> Self {
|
||||
Error::Protocol(&"Could not read response from Trezor Device")
|
||||
}
|
||||
}
|
||||
|
||||
/// Trezor device manager
|
||||
pub struct Manager {
|
||||
usb: Arc<Mutex<hidapi::HidApi>>,
|
||||
devices: RwLock<Vec<Device>>,
|
||||
locked_devices: RwLock<Vec<String>>,
|
||||
key_path: RwLock<KeyPath>,
|
||||
}
|
||||
|
||||
/// HID Version used for the Trezor device
|
||||
enum HidVersion {
|
||||
V1,
|
||||
V2,
|
||||
}
|
||||
|
||||
impl Manager {
|
||||
/// Create a new instance.
|
||||
pub fn new(usb: Arc<Mutex<hidapi::HidApi>>) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
usb,
|
||||
devices: RwLock::new(Vec::new()),
|
||||
locked_devices: RwLock::new(Vec::new()),
|
||||
key_path: RwLock::new(KeyPath::Ethereum),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pin_matrix_ack(&self, device_path: &str, pin: &str) -> Result<bool, Error> {
|
||||
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(DeviceDirection::Arrived)?;
|
||||
unlocked
|
||||
}
|
||||
|
||||
fn u256_to_be_vec(&self, val: &U256) -> Vec<u8> {
|
||||
let mut buf = [0_u8; 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<u64>, data: &[u8]) -> Result<Signature, Error> {
|
||||
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<usize, Error> {
|
||||
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(b'#');
|
||||
data.push(b'#');
|
||||
// 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![b'?'],
|
||||
HidVersion::V2 => vec![0, b'?'],
|
||||
};
|
||||
padded_chunk.extend_from_slice(&chunk);
|
||||
total_written += device.write(&padded_chunk)?;
|
||||
}
|
||||
Ok(total_written)
|
||||
}
|
||||
|
||||
fn probe_hid_version(&self, device: &hidapi::HidDevice) -> Result<HidVersion, Error> {
|
||||
let mut buf2 = [0xFF_u8; 65];
|
||||
buf2[0] = 0;
|
||||
buf2[1] = 63;
|
||||
let mut buf1 = [0xFF_u8; 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<u8>), 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] != b'?' || buf[1] != b'#' || buf[2] != b'#' {
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Wallet<'a> for Manager {
|
||||
type Error = Error;
|
||||
type Transaction = &'a TransactionInfo;
|
||||
|
||||
fn sign_transaction(&self, address: &Address, t_info: Self::Transaction) ->
|
||||
Result<Signature, Error> {
|
||||
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));
|
||||
|
||||
if let Some(addr) = t_info.to {
|
||||
message.set_to(addr.to_vec())
|
||||
}
|
||||
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 set_key_path(&self, key_path: KeyPath) {
|
||||
*self.key_path.write() = key_path;
|
||||
}
|
||||
|
||||
fn update_devices(&self, device_direction: DeviceDirection) -> Result<usize, Error> {
|
||||
let mut usb = self.usb.lock();
|
||||
usb.refresh_devices();
|
||||
let devices = usb.devices();
|
||||
let num_prev_devices = self.devices.read().len();
|
||||
|
||||
let detected_devices = devices.iter()
|
||||
.filter(|&d| is_valid_trezor(d.vendor_id, d.product_id) &&
|
||||
is_valid_hid_device(d.usage_page, d.interface_number)
|
||||
)
|
||||
.fold(Vec::new(), |mut v, d| {
|
||||
match self.read_device(&usb, &d) {
|
||||
Ok(info) => {
|
||||
trace!(target: "hw", "Found device: {:?}", info);
|
||||
v.push(info);
|
||||
}
|
||||
Err(e) => trace!(target: "hw", "Error reading device info: {}", e),
|
||||
};
|
||||
v
|
||||
});
|
||||
|
||||
let num_curr_devices = detected_devices.len();
|
||||
*self.devices.write() = detected_devices;
|
||||
|
||||
match device_direction {
|
||||
DeviceDirection::Arrived => {
|
||||
if num_curr_devices > num_prev_devices {
|
||||
Ok(num_curr_devices - num_prev_devices)
|
||||
} else {
|
||||
Err(Error::NoDeviceArrived)
|
||||
}
|
||||
}
|
||||
DeviceDirection::Left => {
|
||||
if num_prev_devices > num_curr_devices {
|
||||
Ok(num_prev_devices - num_curr_devices)
|
||||
} else {
|
||||
Err(Error::NoDeviceLeft)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_device(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result<Device, Error> {
|
||||
let handle = self.open_path(|| usb.open_path(&dev_info.path))?;
|
||||
let manufacturer = dev_info.manufacturer_string.clone().unwrap_or_else(|| "Unknown".to_owned());
|
||||
let name = dev_info.product_string.clone().unwrap_or_else(|| "Unknown".to_owned());
|
||||
let serial = dev_info.serial_number.clone().unwrap_or_else(|| "Unknown".to_owned());
|
||||
match self.get_address(&handle) {
|
||||
Ok(Some(addr)) => {
|
||||
Ok(Device {
|
||||
path: dev_info.path.clone(),
|
||||
info: WalletInfo {
|
||||
name,
|
||||
manufacturer,
|
||||
serial,
|
||||
address: addr,
|
||||
},
|
||||
})
|
||||
}
|
||||
Ok(None) => Err(Error::LockedDevice(dev_info.path.clone())),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
fn list_devices(&self) -> Vec<WalletInfo> {
|
||||
self.devices.read().iter().map(|d| d.info.clone()).collect()
|
||||
}
|
||||
|
||||
fn list_locked_devices(&self) -> Vec<String> {
|
||||
(*self.locked_devices.read()).clone()
|
||||
}
|
||||
|
||||
fn get_wallet(&self, address: &Address) -> Option<WalletInfo> {
|
||||
self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone())
|
||||
}
|
||||
|
||||
fn get_address(&self, device: &hidapi::HidDevice) -> Result<Option<Address>, 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),
|
||||
}
|
||||
}
|
||||
|
||||
fn open_path<R, F>(&self, f: F) -> Result<R, Error>
|
||||
where F: Fn() -> Result<R, &'static str>
|
||||
{
|
||||
f().map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
/// Poll the device in maximum `max_polling_duration` if it doesn't succeed
|
||||
pub fn try_connect_polling(trezor: &Manager, duration: &Duration, dir: DeviceDirection) -> bool {
|
||||
let start_time = Instant::now();
|
||||
while start_time.elapsed() <= *duration {
|
||||
if let Ok(num_devices) = trezor.update_devices(dir) {
|
||||
trace!(target: "hw", "{} Trezor devices {}", num_devices, dir);
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Check if the detected device is a Trezor device by checking both the product ID and the vendor ID
|
||||
pub fn is_valid_trezor(vid: u16, pid: u16) -> bool {
|
||||
vid == TREZOR_VID && TREZOR_PIDS.contains(&pid)
|
||||
}
|
||||
|
||||
#[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::Address;
|
||||
use MAX_POLLING_DURATION;
|
||||
use super::HardwareWalletManager;
|
||||
|
||||
let manager = HardwareWalletManager::new().unwrap();
|
||||
|
||||
assert_eq!(try_connect_polling(&manager.trezor, &MAX_POLLING_DURATION, DeviceDirection::Arrived), true);
|
||||
|
||||
let addr: Address = manager.list_wallets()
|
||||
.iter()
|
||||
.filter(|d| d.name == "TREZOR".to_string() && d.manufacturer == "SatoshiLabs".to_string())
|
||||
.nth(0)
|
||||
.map(|d| d.address)
|
||||
.unwrap();
|
||||
|
||||
let t_info = TransactionInfo {
|
||||
nonce: U256::from(1),
|
||||
gas_price: U256::from(100),
|
||||
gas_limit: U256::from(21_000),
|
||||
to: Some(Address::from(1337)),
|
||||
chain_id: Some(1),
|
||||
value: U256::from(1_000_000),
|
||||
data: (&[1u8; 3000]).to_vec(),
|
||||
};
|
||||
|
||||
let signature = manager.trezor.sign_transaction(&addr, &t_info);
|
||||
assert!(signature.is_ok());
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -21,7 +21,8 @@ use std::{
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use ethkey::{Address, Password};
|
||||
use parity_crypto::publickey::Address;
|
||||
use ethkey::Password;
|
||||
use serde_derive::{Serialize, Deserialize};
|
||||
use serde_json;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
@@ -17,7 +17,6 @@
|
||||
use std::fmt;
|
||||
|
||||
use ethstore::{Error as SSError};
|
||||
use hardware_wallet::{Error as HardwareError};
|
||||
|
||||
/// Signing error
|
||||
#[derive(Debug)]
|
||||
@@ -26,8 +25,6 @@ pub enum SignError {
|
||||
NotUnlocked,
|
||||
/// Account does not exist.
|
||||
NotFound,
|
||||
/// Low-level hardware device error.
|
||||
Hardware(HardwareError),
|
||||
/// Low-level error from store
|
||||
SStore(SSError),
|
||||
}
|
||||
@@ -37,18 +34,11 @@ impl fmt::Display for SignError {
|
||||
match *self {
|
||||
SignError::NotUnlocked => write!(f, "Account is locked"),
|
||||
SignError::NotFound => write!(f, "Account does not exist"),
|
||||
SignError::Hardware(ref e) => write!(f, "{}", e),
|
||||
SignError::SStore(ref e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HardwareError> for SignError {
|
||||
fn from(e: HardwareError) -> Self {
|
||||
SignError::Hardware(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SSError> for SignError {
|
||||
fn from(e: SSError) -> Self {
|
||||
SignError::SStore(e)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -22,28 +22,23 @@ mod account_data;
|
||||
mod error;
|
||||
mod stores;
|
||||
|
||||
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
|
||||
extern crate fake_hardware_wallet as hardware_wallet;
|
||||
|
||||
use self::account_data::{Unlock, AccountData};
|
||||
use self::stores::AddressBook;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
use common_types::transaction::{Action, Transaction};
|
||||
use ethkey::{Address, Message, Public, Secret, Password, Random, Generator};
|
||||
use ethkey::Password;
|
||||
use parity_crypto::publickey::{Address, Message, Public, Secret, Random, Generator, Signature};
|
||||
use ethstore::accounts_dir::MemoryDirectory;
|
||||
use ethstore::{
|
||||
SimpleSecretStore, SecretStore, EthStore, EthMultiStore,
|
||||
random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret,
|
||||
};
|
||||
use log::{warn, debug};
|
||||
use log::warn;
|
||||
use parking_lot::RwLock;
|
||||
|
||||
pub use ethkey::Signature;
|
||||
pub use ethstore::{Derivation, IndexDerivation, KeyFile, Error};
|
||||
pub use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo};
|
||||
|
||||
pub use self::account_data::AccountMeta;
|
||||
pub use self::error::SignError;
|
||||
@@ -53,10 +48,6 @@ type AccountToken = Password;
|
||||
/// Account management settings.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct AccountProviderSettings {
|
||||
/// Enable hardware wallet support.
|
||||
pub enable_hardware_wallets: bool,
|
||||
/// Use the classic chain key on the hardware wallet.
|
||||
pub hardware_wallet_classic_key: bool,
|
||||
/// Store raw account secret when unlocking the account permanently.
|
||||
pub unlock_keep_secret: bool,
|
||||
/// Disallowed accounts.
|
||||
@@ -73,11 +64,9 @@ pub struct AccountProvider {
|
||||
/// Address book.
|
||||
address_book: RwLock<AddressBook>,
|
||||
/// Accounts on disk
|
||||
sstore: Box<SecretStore>,
|
||||
sstore: Box<dyn SecretStore>,
|
||||
/// Accounts unlocked with rolling tokens
|
||||
transient_sstore: EthMultiStore,
|
||||
/// Accounts in hardware wallets.
|
||||
hardware_store: Option<HardwareWalletManager>,
|
||||
/// When unlocking account permanently we additionally keep a raw secret in memory
|
||||
/// to increase the performance of transaction signing.
|
||||
unlock_keep_secret: bool,
|
||||
@@ -91,19 +80,7 @@ fn transient_sstore() -> EthMultiStore {
|
||||
|
||||
impl AccountProvider {
|
||||
/// Creates new account provider.
|
||||
pub fn new(sstore: Box<SecretStore>, settings: AccountProviderSettings) -> Self {
|
||||
let mut hardware_store = None;
|
||||
|
||||
if settings.enable_hardware_wallets {
|
||||
match HardwareWalletManager::new() {
|
||||
Ok(manager) => {
|
||||
manager.set_key_path(if settings.hardware_wallet_classic_key { KeyPath::EthereumClassic } else { KeyPath::Ethereum });
|
||||
hardware_store = Some(manager)
|
||||
},
|
||||
Err(e) => debug!("Error initializing hardware wallets: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(sstore: Box<dyn SecretStore>, settings: AccountProviderSettings) -> Self {
|
||||
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",
|
||||
@@ -121,9 +98,8 @@ impl AccountProvider {
|
||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||
unlocked: RwLock::new(HashMap::new()),
|
||||
address_book: RwLock::new(address_book),
|
||||
sstore: sstore,
|
||||
sstore,
|
||||
transient_sstore: transient_sstore(),
|
||||
hardware_store: hardware_store,
|
||||
unlock_keep_secret: settings.unlock_keep_secret,
|
||||
blacklisted_accounts: settings.blacklisted_accounts,
|
||||
}
|
||||
@@ -137,7 +113,6 @@ impl AccountProvider {
|
||||
address_book: RwLock::new(AddressBook::transient()),
|
||||
sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
|
||||
transient_sstore: transient_sstore(),
|
||||
hardware_store: None,
|
||||
unlock_keep_secret: false,
|
||||
blacklisted_accounts: vec![],
|
||||
}
|
||||
@@ -219,34 +194,6 @@ impl AccountProvider {
|
||||
Ok(self.accounts()?.first().cloned().unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Returns addresses of hardware accounts.
|
||||
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
|
||||
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
|
||||
if !accounts.is_empty() {
|
||||
return Ok(accounts.into_iter().map(|a| a.address).collect());
|
||||
}
|
||||
}
|
||||
Err(Error::Custom("No hardware wallet accounts were found".into()))
|
||||
}
|
||||
|
||||
/// Get a list of paths to locked hardware wallets
|
||||
pub fn locked_hardware_accounts(&self) -> Result<Vec<String>, 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<bool, SignError> {
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns each address along with metadata.
|
||||
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
|
||||
self.address_book.read().get()
|
||||
@@ -277,36 +224,14 @@ impl AccountProvider {
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
/// Returns each hardware account along with name and meta.
|
||||
pub fn hardware_accounts_info(&self) -> Result<HashMap<Address, AccountMeta>, Error> {
|
||||
let r = self.hardware_accounts()?
|
||||
.into_iter()
|
||||
.map(|address| (address.clone(), self.account_meta(address).ok().unwrap_or_default()))
|
||||
.collect();
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
|
||||
/// Returns each account along with name and meta.
|
||||
pub fn account_meta(&self, address: Address) -> Result<AccountMeta, Error> {
|
||||
if let Some(info) = self.hardware_store.as_ref().and_then(|s| s.wallet_info(&address)) {
|
||||
Ok(AccountMeta {
|
||||
name: info.name,
|
||||
meta: info.manufacturer,
|
||||
uuid: None,
|
||||
})
|
||||
} else {
|
||||
let account = self.sstore.account_ref(&address)?;
|
||||
Ok(AccountMeta {
|
||||
name: self.sstore.name(&account)?,
|
||||
meta: self.sstore.meta(&account)?,
|
||||
uuid: self.sstore.uuid(&account).ok().map(Into::into), // allowed to not have a Uuid
|
||||
})
|
||||
}
|
||||
let account = self.sstore.account_ref(&address)?;
|
||||
Ok(AccountMeta {
|
||||
name: self.sstore.name(&account)?,
|
||||
meta: self.sstore.meta(&account)?,
|
||||
uuid: self.sstore.uuid(&account).ok().map(Into::into), // allowed to not have a Uuid
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns account public key.
|
||||
@@ -370,10 +295,7 @@ impl AccountProvider {
|
||||
let _ = self.sstore.sign(&account, &password, &Default::default())?;
|
||||
}
|
||||
|
||||
let data = AccountData {
|
||||
unlock: unlock,
|
||||
password: password,
|
||||
};
|
||||
let data = AccountData { unlock, password };
|
||||
|
||||
unlocked.insert(account, data);
|
||||
Ok(())
|
||||
@@ -575,43 +497,13 @@ impl AccountProvider {
|
||||
self.sstore.set_vault_meta(name, meta)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
/// Sign message with hardware wallet.
|
||||
pub fn sign_message_with_hardware(&self, address: &Address, message: &[u8]) -> Result<Signature, SignError> {
|
||||
match self.hardware_store.as_ref().map(|s| s.sign_message(address, message)) {
|
||||
None | Some(Err(HardwareError::KeyNotFound)) => Err(SignError::NotFound),
|
||||
Some(Err(e)) => Err(From::from(e)),
|
||||
Some(Ok(s)) => Ok(s),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sign transaction with hardware wallet.
|
||||
pub fn sign_transaction_with_hardware(&self, address: &Address, transaction: &Transaction, chain_id: Option<u64>, rlp_encoded_transaction: &[u8]) -> Result<Signature, SignError> {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AccountProvider, Unlock};
|
||||
use std::time::{Duration, Instant};
|
||||
use ethkey::{Generator, Random, Address};
|
||||
use parity_crypto::publickey::{Generator, Random, Address};
|
||||
use ethstore::{StoreAccountRef, Derivation};
|
||||
use ethereum_types::H256;
|
||||
|
||||
@@ -636,7 +528,7 @@ mod tests {
|
||||
let derived_addr = ap.derive_account(
|
||||
&kp.address(),
|
||||
None,
|
||||
Derivation::SoftHash(H256::from(999)),
|
||||
Derivation::SoftHash(H256::from_low_u64_be(999)),
|
||||
false,
|
||||
).expect("Derivation should not fail");
|
||||
|
||||
@@ -654,7 +546,7 @@ mod tests {
|
||||
let derived_addr = ap.derive_account(
|
||||
&kp.address(),
|
||||
None,
|
||||
Derivation::SoftHash(H256::from(999)),
|
||||
Derivation::SoftHash(H256::from_low_u64_be(999)),
|
||||
true,
|
||||
).expect("Derivation should not fail");
|
||||
|
||||
@@ -675,7 +567,7 @@ mod tests {
|
||||
let derived_addr = ap.derive_account(
|
||||
&kp.address(),
|
||||
None,
|
||||
Derivation::SoftHash(H256::from(1999)),
|
||||
Derivation::SoftHash(H256::from_low_u64_be(1999)),
|
||||
true,
|
||||
).expect("Derivation should not fail");
|
||||
ap.unlock_account_permanently(derived_addr, "base".into())
|
||||
@@ -687,7 +579,7 @@ mod tests {
|
||||
let signed_msg2 = ap.sign_derived(
|
||||
&kp.address(),
|
||||
None,
|
||||
Derivation::SoftHash(H256::from(1999)),
|
||||
Derivation::SoftHash(H256::from_low_u64_be(1999)),
|
||||
msg,
|
||||
).expect("Derived signing with existing unlocked account should not fail");
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -20,7 +20,7 @@ use std::{fs, fmt, hash, ops};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use ethkey::Address;
|
||||
use parity_crypto::publickey::Address;
|
||||
use log::{trace, warn};
|
||||
|
||||
use crate::AccountMeta;
|
||||
@@ -130,7 +130,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
|
||||
trace!(target: "diskmap", "revert {:?}", self.path);
|
||||
let _ = fs::File::open(self.path.clone())
|
||||
.map_err(|e| trace!(target: "diskmap", "Couldn't open disk map: {}", e))
|
||||
.and_then(|f| read(f).map_err(|e| warn!(target: "diskmap", "Couldn't read disk map: {}", e)))
|
||||
.and_then(|f| read(f).map_err(|e| warn!(target: "diskmap", "Couldn't read disk map at: {:?} {}", self.path, e)))
|
||||
.and_then(|m| {
|
||||
self.cache = m;
|
||||
Ok(())
|
||||
@@ -144,16 +144,16 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
|
||||
if self.transient { return; }
|
||||
trace!(target: "diskmap", "save {:?}", self.path);
|
||||
let _ = fs::File::create(self.path.clone())
|
||||
.map_err(|e| warn!(target: "diskmap", "Couldn't open disk map for writing: {}", e))
|
||||
.map_err(|e| warn!(target: "diskmap", "Couldn't open disk map for writing at: {:?} {}", self.path, e))
|
||||
.and_then(|mut f| {
|
||||
write(&self.cache, &mut f).map_err(|e| warn!(target: "diskmap", "Couldn't write to disk map: {}", e))
|
||||
write(&self.cache, &mut f).map_err(|e| warn!(target: "diskmap", "Couldn't write to disk map at: {:?} {}", self.path, e))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::AddressBook;
|
||||
use super::{AddressBook, Address};
|
||||
use std::collections::HashMap;
|
||||
use tempdir::TempDir;
|
||||
use crate::account_data::AccountMeta;
|
||||
@@ -162,12 +162,12 @@ mod tests {
|
||||
fn should_save_and_reload_address_book() {
|
||||
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());
|
||||
b.set_name(Address::from_low_u64_be(1), "One".to_owned());
|
||||
b.set_meta(Address::from_low_u64_be(1), "{1:1}".to_owned());
|
||||
let b = AddressBook::new(tempdir.path());
|
||||
assert_eq!(b.get(), vec![
|
||||
(1, AccountMeta {name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None})
|
||||
].into_iter().map(|(a, b)| (a.into(), b)).collect::<HashMap<_, _>>());
|
||||
(Address::from_low_u64_be(1), AccountMeta {name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None})
|
||||
].into_iter().collect::<HashMap<_, _>>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -175,15 +175,15 @@ mod tests {
|
||||
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());
|
||||
b.set_name(Address::from_low_u64_be(1), "One".to_owned());
|
||||
b.set_name(Address::from_low_u64_be(2), "Two".to_owned());
|
||||
b.set_name(Address::from_low_u64_be(3), "Three".to_owned());
|
||||
b.remove(Address::from_low_u64_be(2).into());
|
||||
|
||||
let b = AddressBook::new(tempdir.path());
|
||||
assert_eq!(b.get(), vec![
|
||||
(1, AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None}),
|
||||
(3, AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}),
|
||||
].into_iter().map(|(a, b)| (a.into(), b)).collect::<HashMap<_, _>>());
|
||||
(Address::from_low_u64_be(1), AccountMeta{name: "One".to_owned(), meta: "{}".to_owned(), uuid: None}),
|
||||
(Address::from_low_u64_be(3), AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}),
|
||||
].into_iter().collect::<HashMap<_, _>>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -7,7 +7,7 @@ version = "1.4.0"
|
||||
authors = ["Parity <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.4"
|
||||
ethereum-types = "0.8.0"
|
||||
futures = "0.1"
|
||||
rpassword = "1.0"
|
||||
parity-rpc = { path = "../rpc" }
|
||||
|
||||
@@ -7,15 +7,15 @@ version = "1.4.0"
|
||||
authors = ["Parity <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
ethereum-types = "0.4"
|
||||
ethereum-types = "0.8.0"
|
||||
futures = "0.1"
|
||||
log = "0.4"
|
||||
serde = "1.0"
|
||||
serde_json = "1.0"
|
||||
url = "2"
|
||||
url = "2.1.0"
|
||||
matches = "0.1"
|
||||
parking_lot = "0.9"
|
||||
jsonrpc-core = "14.0.3"
|
||||
jsonrpc-ws-server = "14.0.3"
|
||||
parity-rpc = { path = "../../rpc" }
|
||||
keccak-hash = "0.1"
|
||||
keccak-hash = "0.4.0"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -36,7 +36,7 @@ extern crate log;
|
||||
extern crate matches;
|
||||
|
||||
/// Boxed future response.
|
||||
pub type BoxFuture<T, E> = Box<futures::Future<Item=T, Error=E> + Send>;
|
||||
pub type BoxFuture<T, E> = Box<dyn futures::Future<Item=T, Error=E> + Send>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
220
docs/CHANGELOG-2.5.md
Normal file
220
docs/CHANGELOG-2.5.md
Normal file
@@ -0,0 +1,220 @@
|
||||
## Parity-Ethereum [v2.5.13](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.13)
|
||||
|
||||
Parity Ethereum v2.5.13-stable is a security release. Valid blocks with manipulated transactions (added/replaced) cause the client to stall.
|
||||
|
||||
The full list of included changes:
|
||||
* Make sure to not mark block header hash as invalid if only the body is wrong (#11356)
|
||||
|
||||
## Parity-Ethereum [v2.5.12](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.12)
|
||||
|
||||
Parity Ethereum v2.5.12-stable is a patch release that adds Istanbul hardfork
|
||||
block numbers for POA and xDai networks, implements ECIP-1056 and implements
|
||||
EIP-2384/2387 - Muir Glacier.
|
||||
|
||||
The full list of included changes:
|
||||
* Enable EIP-2384 for ice age hard fork (#11281)
|
||||
* ethcore/res: activate agharta on classic 9573000 (#11331)
|
||||
* Istanbul HF in xDai (2019-12-12) (#11299)
|
||||
* Istanbul HF in POA Core (2019-12-19) (#11298)
|
||||
* Istanbul HF in POA Sokol (2019-12-05) (#11282)
|
||||
* Activate ecip-1061 on kotti and mordor (#11338)
|
||||
* Enable basic verification of local transactions (#11332)
|
||||
* Disallow EIP-86 style null signatures for transactions outside tests (#11335)
|
||||
|
||||
|
||||
## Parity-Ethereum [v2.5.11](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.11)
|
||||
|
||||
Parity Ethereum v2.5.11-stable is an emergency patch release that adds the missing
|
||||
eip1344_transition for mainnet - Users are advised to update as soon as possible
|
||||
to prevent any issues with the imminent Istanbul hardfork
|
||||
|
||||
The full list of included changes:
|
||||
- [chainspec]: add `eip1344_transition` for istanbul (#11301)
|
||||
|
||||
## Parity-Ethereum [v2.5.10](https://github.com/paritytech/parity-ethereum/releases/tag/2.5.10)
|
||||
|
||||
Parity Ethereum v2.5.10-stable is a patch release that adds block numbers for
|
||||
activating the Istanbul hardfork on mainnet, as well as a large number of
|
||||
various bugfixes, QoL changes, some code cleanup/refactoring and other
|
||||
miscellaneous changes.
|
||||
|
||||
This release removes legacy aliases for the mainnet. If you specify `--chain homestead`, `--chain frontier` or `--chain byzantium`, this will need to be changed to one of: `--chain eth`, `--chain ethereum`, `--chain foundation` or `--chain mainnet`.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ropsten #6631425 foundation #8798209 (#11201)
|
||||
* [stable] builtin, istanbul and mordor testnet backports (#11234)
|
||||
* ethcore-builtin (#10850)
|
||||
* [builtin]: support `multiple prices and activations` in chain spec (#11039)
|
||||
* [chain specs]: activate `Istanbul` on mainnet (#11228)
|
||||
* ethcore/res: add mordor testnet configuration (#11200)
|
||||
* Update list of bootnodes for xDai chain (#11236)
|
||||
* ethcore: remove `test-helper feat` from build (#11047)
|
||||
* Secret store: fix Instant::now() related race in net_keep_alive (#11155) (#11159)
|
||||
* [stable]: backport #10691 and #10683 (#11143)
|
||||
* Fix compiler warning (that will become an error) (#10683)
|
||||
* Refactor Clique stepping (#10691)
|
||||
* Add Constantinople eips to the dev (instant_seal) config (#10809)
|
||||
* Add cargo-remote dir to .gitignore (?)
|
||||
* Insert explicit warning into the panic hook (#11225)
|
||||
* Fix docker centos build (#11226)
|
||||
* Update MIX bootnodes. (#11203)
|
||||
* Use provided usd-per-eth value if an endpoint is specified (#11209)
|
||||
* Add new line after writing block to hex file. (#10984)
|
||||
* Type annotation for next_key() matching of json filter options (#11192) (but no `FilterOption` in 2.5 so…)
|
||||
* Upgrade jsonrpc to latest (#11206)
|
||||
* [CI] check evmbin build (#11096)
|
||||
* Correct EIP-712 encoding (#11092)
|
||||
* [client]: Fix for incorrectly dropped consensus messages (#11086)
|
||||
* Fix block detail updating (#11015)
|
||||
* Switching sccache from local to Redis (#10971)
|
||||
* Made ecrecover implementation trait public (#11188)
|
||||
* [dependencies]: jsonrpc `14.0.1` (#11183)
|
||||
* [receipt]: add `sender` & `receiver` to `RichReceipts` (#11179)
|
||||
* [ethcore/builtin]: do not panic in blake2pricer on short input (#11180)
|
||||
* util Host: fix a double Read Lock bug in fn Host::session_readable() (#11175)
|
||||
* ethcore client: fix a double Read Lock bug in fn Client::logs() (#11172)
|
||||
* Change how RPCs eth_call and eth_estimateGas handle "Pending" (#11127)
|
||||
* Cleanup stratum a bit (#11161)
|
||||
* Upgrade to jsonrpc v14 (#11151)
|
||||
* SecretStore: expose restore_key_public in HTTP API (#10241)
|
||||
|
||||
## Parity-Ethereum [v2.5.9](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.9)
|
||||
|
||||
Parity Ethereum v2.5.9-stable is a patch release that adds the block numbers for activating the Istanbul hardfork on test networks: Ropsten, Görli, Rinkeby and Kovan.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ethcore/res: activate Istanbul on Ropsten, Görli, Rinkeby, Kovan (#11068)
|
||||
* [json-spec] make blake2 pricing spec more readable (#11034)
|
||||
|
||||
## Parity-Ethereum [v2.5.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.8)
|
||||
|
||||
Parity Ethereum v2.5.8-stable is a patch release that improves security, stability and performance.
|
||||
|
||||
* The most noteworthy improvement in this release is incorporating all the EIPs required for the Istanbul hard fork.
|
||||
* This release also fixes certain security and performance issues, one of which was suspected to be consensus-threatening but turned out to be benign. Thanks to Martin Holst Swende and Felix Lange from the Ethereum Foundation for bringing the suspicious issue to our attention.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* add more tx tests (#11038)
|
||||
* Fix parallel transactions race-condition (#10995)
|
||||
* Add blake2_f precompile (#11017)
|
||||
* [trace] introduce trace failed to Ext (#11019)
|
||||
* Edit publish-onchain.sh to use https (#11016)
|
||||
* Fix deadlock in network-devp2p (#11013)
|
||||
* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
|
||||
* xDai chain support and nodes list update (#10989)
|
||||
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
|
||||
* EIP-1344 Add CHAINID op-code (#10983)
|
||||
* manual publish jobs for releases, no changes for nightlies (#10977)
|
||||
* [blooms-db] Fix benchmarks (#10974)
|
||||
* Verify transaction against its block during import (#10954)
|
||||
* Better error message for rpc gas price errors (#10931)
|
||||
* tx-pool: accept local tx with higher gas price when pool full (#10901)
|
||||
* Fix fork choice (#10837)
|
||||
* Cleanup unused vm dependencies (#10787)
|
||||
* Fix compilation on recent nightlies (#10991)
|
||||
* Don't build rpc with ethcore test-helpers (#11048)
|
||||
* EIP 1884 Re-pricing of trie-size dependent operations (#10992)
|
||||
* Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191)
|
||||
|
||||
## Parity-Ethereum [v2.5.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.7)
|
||||
|
||||
Parity Ethereum v2.5.7-stable is a bugfix release that fixes a potential DoS attack in the trace_call RPC method. This is a critical upgrade for anyone running Parity nodes with RPC exposed to the public internet (and highly recommended for anyone else). For details see this blog post.
|
||||
|
||||
## Parity-Ethereum [v2.5.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.6)
|
||||
|
||||
Parity-Ethereum v2.5.6-stable is a bugfix release that improves stability.
|
||||
|
||||
* Allow specifying hostnames for node URLs
|
||||
* Fix a bug where archive nodes were losing peers
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* Kaspersky AV whitelisting (#10919)
|
||||
* Avast whitelist script (#10900)
|
||||
* Docker images renaming (#10863)
|
||||
* Remove excessive warning (#10831)
|
||||
* Allow --nat extip:your.host.here.org (#10830)
|
||||
* When updating the client or when called from RPC, sleep should mean sleep (#10814)
|
||||
* added new ropsten-bootnode and removed old one (#10794)
|
||||
* ethkey no longer uses byteorder (#10786)
|
||||
* Do not drop the peer with None difficulty (#10772)
|
||||
* docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652)
|
||||
|
||||
## Parity-Ethereum [v2.5.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.5)
|
||||
|
||||
Parity-Ethereum v2.5.5-stable is a minor release that improves performance and stability.
|
||||
This release stabilises the 2.5 branch.
|
||||
|
||||
As of today, Parity-Ethereum 2.4 reaches end of life and everyone is
|
||||
encouraged to upgrade.
|
||||
|
||||
## Parity-Ethereum [v2.5.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.4)
|
||||
|
||||
Parity Ethereum v2.5.4-beta is a security update that addresses servo/rust-smallvec#148
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* cargo update -p smallvec ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822))
|
||||
|
||||
## Parity-Ethereum [v2.5.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.3)
|
||||
|
||||
Parity-Ethereum 2.5.3-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
* EthereumClassic: activate the Atlantis Hardfork
|
||||
* Clique: fix time overflow
|
||||
* State tests: treat empty accounts the same as non-existant accounts (EIP 1052)
|
||||
* Networking: support discovery-only peers (geth bootnodes)
|
||||
* Snapshotting: fix unclean shutdown while snappshotting is under way
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/paritytech/parity-ethereum/pull/10766))
|
||||
* fix docker tags for publishing ([#10741](https://github.com/paritytech/parity-ethereum/pull/10741))
|
||||
* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720))
|
||||
* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/paritytech/parity-ethereum/pull/10775))
|
||||
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/paritytech/parity-ethereum/pull/10705))
|
||||
* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/paritytech/parity-ethereum/pull/10744))
|
||||
|
||||
## Parity-Ethereum [v2.5.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.2)
|
||||
|
||||
Parity-Ethereum 2.5.2-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
Among others, it enables the _Atlantis_ hardfork on **Morden** and **Kotti** Classic networks.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [CI] allow cargo audit to fail ([#10676](https://github.com/paritytech/parity-ethereum/pull/10676))
|
||||
* Reset blockchain properly ([#10669](https://github.com/paritytech/parity-ethereum/pull/10669))
|
||||
* new image ([#10673](https://github.com/paritytech/parity-ethereum/pull/10673))
|
||||
* Update publishing ([#10644](https://github.com/paritytech/parity-ethereum/pull/10644))
|
||||
* enable lto for release builds ([#10717](https://github.com/paritytech/parity-ethereum/pull/10717))
|
||||
* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/paritytech/parity-ethereum/pull/10719))
|
||||
* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/paritytech/parity-ethereum/pull/10731))
|
||||
|
||||
## Parity-Ethereum [v2.5.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.1)
|
||||
|
||||
Parity-Ethereum 2.5.1-beta is a bugfix release that improves performance and stability.
|
||||
|
||||
Among others, it enables the Petersburg hardfork on **Rinkeby** and **POA-Core** Network, as well as the **Kovan** Network community hardfork.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638))
|
||||
|
||||
## Parity-Ethereum [v2.5.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.5.0)
|
||||
|
||||
Parity-Ethereum 2.5.0-beta is a minor release that improves performance and stabilizes the 2.5 branch by marking it as beta release.
|
||||
|
||||
- This release adds support for the Clique consensus engine ([#9981](https://github.com/paritytech/parity-ethereum/pull/9981))
|
||||
- This enables Parity-Ethereum users to use the Görli, the Kotti Classic, and the legacy Rinkeby testnet. To get started try `parity --chain goerli`; note that light client support is currently not yet fully functional.
|
||||
- This release removes the dead chain configs for Easthub and Ethereum Social ([#10531](https://github.com/paritytech/parity-ethereum/pull/10531))
|
||||
|
||||
As of today, Parity-Ethereum 2.3 reaches end of life and everyone is encouraged to upgrade.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* fix(light cull): poll light cull instead of timer ([#10559](https://github.com/paritytech/parity-ethereum/pull/10559))
|
||||
|
||||
307
docs/CHANGELOG-2.6.md
Normal file
307
docs/CHANGELOG-2.6.md
Normal file
@@ -0,0 +1,307 @@
|
||||
## Parity-Ethereum [v2.6.8](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.8)
|
||||
|
||||
Parity Ethereum v2.6.8-beta is a security release. Valid blocks with manipulated transactions (added/replaced) cause the client to stall.
|
||||
|
||||
The full list of included changes:
|
||||
* Make sure to not mark block header hash as invalid if only the body is wrong (#11356)
|
||||
|
||||
## Parity-Ethereum [v2.6.7](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.7)
|
||||
|
||||
Parity Ethereum v2.6.7-beta is a patch release that adds Istanbul hardfork
|
||||
block numbers for POA and xDai networks, implements ECIP-1056 and implements
|
||||
EIP-2384/2387 - Muir Glacier.
|
||||
|
||||
The full list of included changes:
|
||||
* Enable EIP-2384 for ice age hard fork (#11281)
|
||||
* ethcore/res: activate agharta on classic 9573000 (#11331)
|
||||
* Istanbul HF in xDai (2019-12-12) (#11299)
|
||||
* Istanbul HF in POA Core (2019-12-19) (#11298)
|
||||
* Istanbul HF in POA Sokol (2019-12-05) (#11282)
|
||||
* Activate ecip-1061 on kotti and mordor (#11338)
|
||||
* Enable basic verification of local transactions (#11332)
|
||||
* Disallow EIP-86 style null signatures for transactions outside tests (#11335)
|
||||
* SecretStore database migration to v4 (#11322)
|
||||
|
||||
## Parity-Ethereum [v2.6.6](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.6)
|
||||
|
||||
Parity Ethereum v2.6.6-beta is an emergency patch release that adds the missing
|
||||
eip1344_transition for mainnet - Users are advised to update as soon as possible
|
||||
to prevent any issues with the imminent Istanbul hardfork
|
||||
|
||||
The full list of included changes:
|
||||
* [chainspec]: add `eip1344_transition` for istanbul (#11301)
|
||||
|
||||
## Parity-Ethereum [v2.6.5](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.5)
|
||||
|
||||
Parity Ethereum v2.6.5-beta is a patch release that adds block numbers for activating the Istanbul hardfork on mainnet, as well as a large number of various bugfixes, QoL changes, some code cleanup/refactoring and other miscellaneous changes.
|
||||
|
||||
This release removes legacy aliases for the mainnet. If you specify `--chain homestead`, `--chain frontier` or `--chain byzantium`, this will need to be changed to one of: `--chain eth`, `--chain ethereum`, `--chain foundation` or `--chain mainnet`.
|
||||
|
||||
This release includes important changes to how snapshots are produced. The size of the Ethereum account state means that producing a snapshot takes a long while; most nodes today are not able to finish before the relevant state is pruned. Starting with v2.6.5, pruning is paused while a snapshot is underway, hopefully fixing the current dearth of recent snapshots. The downside to this is that memory usage goes up while a snapshot is produced.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* [CI] check evmbin build (#11096)
|
||||
* Correct EIP-712 encoding (#11092)
|
||||
* [client]: Fix for incorrectly dropped consensus messages (#11082) (#11086)
|
||||
* Update hardcoded headers (foundation, classic, kovan, xdai, ewc, ...) (#11053)
|
||||
* Add cargo-remote dir to .gitignore (?)
|
||||
* Update light client headers: ropsten 6631425 foundation 8798209 (#11201)
|
||||
* Update list of bootnodes for xDai chain (#11236)
|
||||
* ethcore/res: add mordor testnet configuration (#11200)
|
||||
* [chain specs]: activate Istanbul on mainnet (#11228)
|
||||
* [builtin]: support multiple prices and activations in chain spec (#11039)
|
||||
* [receipt]: add sender & receiver to RichReceipts (#11179)
|
||||
* [ethcore/builtin]: do not panic in blake2pricer on short input (#11180)
|
||||
* Made ecrecover implementation trait public (#11188)
|
||||
* Fix docker centos build (#11226)
|
||||
* Update MIX bootnodes. (#11203)
|
||||
* Insert explicit warning into the panic hook (#11225)
|
||||
* Use provided usd-per-eth value if an endpoint is specified (#11209)
|
||||
* Cleanup stratum a bit (#11161)
|
||||
* Add Constantinople EIPs to the dev (instant_seal) config (#10809) (already backported)
|
||||
* util Host: fix a double Read Lock bug in fn Host::session_readable() (#11175)
|
||||
* ethcore client: fix a double Read Lock bug in fn Client::logs() (#11172)
|
||||
* Type annotation for next_key() matching of json filter options (#11192)
|
||||
* Upgrade jsonrpc to latest (#11206)
|
||||
* [dependencies]: jsonrpc 14.0.1 (#11183)
|
||||
* Upgrade to jsonrpc v14 (#11151)
|
||||
* Switching sccache from local to Redis (#10971)
|
||||
* Snapshot restoration overhaul (#11219)
|
||||
* Add new line after writing block to hex file. (#10984)
|
||||
* Pause pruning while snapshotting (#11178)
|
||||
* Change how RPCs eth_call and eth_estimateGas handle "Pending" (#11127)
|
||||
* Fix block detail updating (#11015)
|
||||
* Make InstantSeal Instant again #11186
|
||||
* Filter out some bad ropsten warp snapshots (#11247)
|
||||
* Allow default block parameter to be blockHash (#10932)
|
||||
|
||||
## Parity-Ethereum [v2.6.4](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.4)
|
||||
|
||||
Parity Ethereum v2.6.4-stable is a patch release that adds the block numbers for activating the Istanbul hardfork on test networks: Ropsten, Görli, Rinkeby and Kovan.
|
||||
|
||||
A full list of included changes:
|
||||
|
||||
* ethcore/res: activate Istanbul on Ropsten, Görli, Rinkeby, Kovan (#11068)
|
||||
* cleanup json crate (#11027)
|
||||
* [json-spec] make blake2 pricing spec more readable (#11034)
|
||||
* Update JSON tests to d4f86ecf4aa7c (#11054)
|
||||
|
||||
## Parity-Ethereum [v2.6.3](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.3)
|
||||
|
||||
Parity Ethereum v2.6.3-stable is a patch release that improves security, stability and performance.
|
||||
|
||||
* The most noteworthy improvement in this release is incorporating all the EIPs required for the Istanbul hard fork.
|
||||
* This release also fixes certain security and performance issues, one of which was suspected to be consensus-threatening but turned out to be benign. Thanks to Martin Holst Swende and Felix Lange from the Ethereum Foundation for bringing the suspicious issue to our attention.
|
||||
|
||||
The full list of included changes:
|
||||
|
||||
* add more tx tests (#11038)
|
||||
* Fix parallel transactions race-condition (#10995)
|
||||
* Add blake2_f precompile (#11017)
|
||||
* [trace] introduce trace failed to Ext (#11019)
|
||||
* Edit publish-onchain.sh to use https (#11016)
|
||||
* Fix deadlock in network-devp2p (#11013)
|
||||
* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
|
||||
* xDai chain support and nodes list update (#10989)
|
||||
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
|
||||
* EIP-1344 Add CHAINID op-code (#10983)
|
||||
* manual publish jobs for releases, no changes for nightlies (#10977)
|
||||
* [blooms-db] Fix benchmarks (#10974)
|
||||
* Verify transaction against its block during import (#10954)
|
||||
* Better error message for rpc gas price errors (#10931)
|
||||
* Fix fork choice (#10837)
|
||||
* Fix compilation on recent nightlies (#10991)
|
||||
* Don't build rpc with ethcore test-helpers (#11048)
|
||||
* EIP 1884 Re-pricing of trie-size dependent operations (#10992)
|
||||
* Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191)
|
||||
|
||||
## Parity-Ethereum [v2.6.2](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.2)
|
||||
|
||||
Parity Ethereum v2.6.2-stable is a bugfix release that fixes a potential DoS attack in the trace_call RPC method. This is a critical upgrade for anyone running Parity nodes with RPC exposed to the public internet (and highly recommended for anyone else). For details see this blog post.
|
||||
|
||||
## Parity-Ethereum [v2.6.1](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.1)
|
||||
|
||||
Parity-Ethereum 2.6.1-beta is a patch release that improves stability.
|
||||
|
||||
This release includes:
|
||||
* Allow specifying hostnames for node URLs
|
||||
* Fix a bug where archive nodes were losing peers
|
||||
* Add support for Energy Web Foundations new chains 'Volta' and 'EWC', and remove their deprecated 'Tobalaba' chain.
|
||||
|
||||
The full list of included changes:
|
||||
* Add support for Energy Web Foundation's new chains (#10957)
|
||||
* Kaspersky AV whitelisting (#10919)
|
||||
* Avast whitelist script (#10900)
|
||||
* Docker images renaming (#10863)
|
||||
* Remove excessive warning (#10831)
|
||||
* Allow --nat extip:your.host.here.org (#10830)
|
||||
* When updating the client or when called from RPC, sleep should mean sleep (#10814)
|
||||
* added new ropsten-bootnode and removed old one (#10794)
|
||||
* ethkey no longer uses byteorder (#10786)
|
||||
* docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652)
|
||||
|
||||
## Parity-Ethereum [v2.6.0](https://github.com/paritytech/parity-ethereum/releases/tag/v2.6.0)
|
||||
|
||||
Parity-Ethereum 2.6.0-beta is a minor release that stabilizes the 2.6 branch by
|
||||
marking it as a beta release.
|
||||
|
||||
This release includes:
|
||||
* Major refactoring of the codebase
|
||||
* Many bugfixes
|
||||
* Significant improvements to logging, error and warning message clarity.
|
||||
* SecretStore: remove support of old database formats (#10757)
|
||||
* This is a potentially breaking change if you have not upgraded for
|
||||
quite some time.
|
||||
|
||||
As of today, Parity-Ethereum 2.4 reaches end of life, and everyone is
|
||||
encouraged to upgrade.
|
||||
|
||||
The full list of included changes:
|
||||
* update jsonrpc to 12.0 ([#10841](https://github.com/paritytech/parity-ethereum/pull/10841))
|
||||
* Move more code into state-account ([#10840](https://github.com/paritytech/parity-ethereum/pull/10840))
|
||||
* Extract AccountDB to account-db ([#10839](https://github.com/paritytech/parity-ethereum/pull/10839))
|
||||
* Extricate PodAccount and state Account to own crates ([#10838](https://github.com/paritytech/parity-ethereum/pull/10838))
|
||||
* Fix fork choice ([#10837](https://github.com/paritytech/parity-ethereum/pull/10837))
|
||||
* tests: Relates to #10655: Test instructions for Readme ([#10835](https://github.com/paritytech/parity-ethereum/pull/10835))
|
||||
* idiomatic changes to PodState ([#10834](https://github.com/paritytech/parity-ethereum/pull/10834))
|
||||
* Break circular dependency between Client and Engine (part 1) ([#10833](https://github.com/paritytech/parity-ethereum/pull/10833))
|
||||
* Remove excessive warning ([#10831](https://github.com/paritytech/parity-ethereum/pull/10831))
|
||||
* Allow --nat extip:your.host.here.org ([#10830](https://github.com/paritytech/parity-ethereum/pull/10830))
|
||||
* ethcore does not use byteorder ([#10829](https://github.com/paritytech/parity-ethereum/pull/10829))
|
||||
* Fix typo in README.md ([#10828](https://github.com/paritytech/parity-ethereum/pull/10828))
|
||||
* Update wordlist to v1.3 ([#10823](https://github.com/paritytech/parity-ethereum/pull/10823))
|
||||
* bump `smallvec 0.6.10` to fix vulnerability ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822))
|
||||
* removed additional_params method ([#10818](https://github.com/paritytech/parity-ethereum/pull/10818))
|
||||
* Improve logging when remote peer is unknown ([#10817](https://github.com/paritytech/parity-ethereum/pull/10817))
|
||||
* replace memzero with zeroize crate ([#10816](https://github.com/paritytech/parity-ethereum/pull/10816))
|
||||
* When updating the client or when called from RPC, sleep should mean sleep ([#10814](https://github.com/paritytech/parity-ethereum/pull/10814))
|
||||
* Don't reimplement the logic from the Default impl ([#10813](https://github.com/paritytech/parity-ethereum/pull/10813))
|
||||
* refactor: whisper: Add type aliases and update rustdocs in message.rs ([#10812](https://github.com/paritytech/parity-ethereum/pull/10812))
|
||||
* test: whisper/cli `add invalid pool size test depending on processor` ([#10811](https://github.com/paritytech/parity-ethereum/pull/10811))
|
||||
* Add Constantinople EIPs to the dev (instant_seal) config ([#10809](https://github.com/paritytech/parity-ethereum/pull/10809))
|
||||
* fix spurious test failure ([#10808](https://github.com/paritytech/parity-ethereum/pull/10808))
|
||||
* revert temp changes to .gitlab-ci.yml ([#10807](https://github.com/paritytech/parity-ethereum/pull/10807))
|
||||
* removed redundant fmt::Display implementations ([#10806](https://github.com/paritytech/parity-ethereum/pull/10806))
|
||||
* removed EthEngine alias ([#10805](https://github.com/paritytech/parity-ethereum/pull/10805))
|
||||
* ethcore-bloom-journal updated to 2018 ([#10804](https://github.com/paritytech/parity-ethereum/pull/10804))
|
||||
* Fix a few typos and unused warnings. ([#10803](https://github.com/paritytech/parity-ethereum/pull/10803))
|
||||
* updated price-info to edition 2018 ([#10801](https://github.com/paritytech/parity-ethereum/pull/10801))
|
||||
* updated parity-local-store to edition 2018 ([#10800](https://github.com/paritytech/parity-ethereum/pull/10800))
|
||||
* updated project to ansi_term 0.11 ([#10799](https://github.com/paritytech/parity-ethereum/pull/10799))
|
||||
* ethcore-light uses bincode 1.1 ([#10798](https://github.com/paritytech/parity-ethereum/pull/10798))
|
||||
* ethcore-network-devp2p uses igd 0.9 ([#10797](https://github.com/paritytech/parity-ethereum/pull/10797))
|
||||
* Better logging when backfilling ancient blocks fail ([#10796](https://github.com/paritytech/parity-ethereum/pull/10796))
|
||||
* added new ropsten-bootnode and removed old one ([#10794](https://github.com/paritytech/parity-ethereum/pull/10794))
|
||||
* Removed machine abstraction from ethcore ([#10791](https://github.com/paritytech/parity-ethereum/pull/10791))
|
||||
* Removed redundant ethcore-service error type ([#10788](https://github.com/paritytech/parity-ethereum/pull/10788))
|
||||
* Cleanup unused vm dependencies ([#10787](https://github.com/paritytech/parity-ethereum/pull/10787))
|
||||
* ethkey no longer uses byteorder ([#10786](https://github.com/paritytech/parity-ethereum/pull/10786))
|
||||
* Updated blooms-db to rust 2018 and removed redundant deps ([#10785](https://github.com/paritytech/parity-ethereum/pull/10785))
|
||||
* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/paritytech/parity-ethereum/pull/10775))
|
||||
* Do not drop the peer with None difficulty ([#10772](https://github.com/paritytech/parity-ethereum/pull/10772))
|
||||
* EIP-1702: Generalized Account Versioning Scheme ([#10771](https://github.com/paritytech/parity-ethereum/pull/10771))
|
||||
* Move Engine::register_client to be before other I/O handler registration ([#10767](https://github.com/paritytech/parity-ethereum/pull/10767))
|
||||
* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/paritytech/parity-ethereum/pull/10766))
|
||||
* Updated Bn128PairingImpl to use optimized batch pairing ([#10765](https://github.com/paritytech/parity-ethereum/pull/10765))
|
||||
* Remove unused code ([#10762](https://github.com/paritytech/parity-ethereum/pull/10762))
|
||||
* Initialize private tx logger only if private tx functionality is enabled ([#10758](https://github.com/paritytech/parity-ethereum/pull/10758))
|
||||
* SecretStore: remove support of old database formats ([#10757](https://github.com/paritytech/parity-ethereum/pull/10757))
|
||||
* Enable aesni ([#10756](https://github.com/paritytech/parity-ethereum/pull/10756))
|
||||
* updater: fix static id hashes initialization ([#10755](https://github.com/paritytech/parity-ethereum/pull/10755))
|
||||
* Use fewer threads for snapshotting ([#10752](https://github.com/paritytech/parity-ethereum/pull/10752))
|
||||
* Die error_chain, die ([#10747](https://github.com/paritytech/parity-ethereum/pull/10747))
|
||||
* Fix deprectation warnings on nightly ([#10746](https://github.com/paritytech/parity-ethereum/pull/10746))
|
||||
* Improve logging and cleanup in miner around block sealing ([#10745](https://github.com/paritytech/parity-ethereum/pull/10745))
|
||||
* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/paritytech/parity-ethereum/pull/10744))
|
||||
* fix docker tags for publishing ([#10741](https://github.com/paritytech/parity-ethereum/pull/10741))
|
||||
* refactor: Fix indentation in ethjson ([#10740](https://github.com/paritytech/parity-ethereum/pull/10740))
|
||||
* Log validator set changes in EpochManager ([#10734](https://github.com/paritytech/parity-ethereum/pull/10734))
|
||||
* Print warnings when using dangerous settings for ValidatorSet ([#10733](https://github.com/paritytech/parity-ethereum/pull/10733))
|
||||
* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/paritytech/parity-ethereum/pull/10731))
|
||||
* Stop breaking out of loop if a non-canonical hash is found ([#10729](https://github.com/paritytech/parity-ethereum/pull/10729))
|
||||
* Removed secret_store folder ([#10722](https://github.com/paritytech/parity-ethereum/pull/10722))
|
||||
* Revert "enable lto for release builds (#10717)" ([#10721](https://github.com/paritytech/parity-ethereum/pull/10721))
|
||||
* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/paritytech/parity-ethereum/pull/10720))
|
||||
* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/paritytech/parity-ethereum/pull/10719))
|
||||
* enable lto for release builds ([#10717](https://github.com/paritytech/parity-ethereum/pull/10717))
|
||||
* [devp2p] Update to 2018 edition ([#10716](https://github.com/paritytech/parity-ethereum/pull/10716))
|
||||
* [devp2p] Don't use `rust-crypto` ([#10714](https://github.com/paritytech/parity-ethereum/pull/10714))
|
||||
* [devp2p] Fix warnings and re-org imports ([#10710](https://github.com/paritytech/parity-ethereum/pull/10710))
|
||||
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/paritytech/parity-ethereum/pull/10705))
|
||||
* introduce MissingParent Error, fixes #10699 ([#10700](https://github.com/paritytech/parity-ethereum/pull/10700))
|
||||
* Refactor Clique stepping ([#10691](https://github.com/paritytech/parity-ethereum/pull/10691))
|
||||
* add_sync_notifier in EthPubSubClient holds on to a Client for too long ([#10689](https://github.com/paritytech/parity-ethereum/pull/10689))
|
||||
* Fix compiler warning (that will become an error) ([#10683](https://github.com/paritytech/parity-ethereum/pull/10683))
|
||||
* Don't panic if extra_data is longer than VANITY_LENGTH ([#10682](https://github.com/paritytech/parity-ethereum/pull/10682))
|
||||
* Remove annoying compiler warnings ([#10679](https://github.com/paritytech/parity-ethereum/pull/10679))
|
||||
* Remove support for hardware wallets ([#10678](https://github.com/paritytech/parity-ethereum/pull/10678))
|
||||
* [CI] allow cargo audit to fail ([#10676](https://github.com/paritytech/parity-ethereum/pull/10676))
|
||||
* new image ([#10673](https://github.com/paritytech/parity-ethereum/pull/10673))
|
||||
* Upgrade ethereum types ([#10670](https://github.com/paritytech/parity-ethereum/pull/10670))
|
||||
* Reset blockchain properly ([#10669](https://github.com/paritytech/parity-ethereum/pull/10669))
|
||||
* fix: Move PR template into .github/ folder ([#10663](https://github.com/paritytech/parity-ethereum/pull/10663))
|
||||
* docs: evmbin - Update Rust docs ([#10658](https://github.com/paritytech/parity-ethereum/pull/10658))
|
||||
* refactor: Related #9459 - evmbin: replace untyped json! macro with fully typed serde serialization using Rust structs ([#10657](https://github.com/paritytech/parity-ethereum/pull/10657))
|
||||
* docs: Add PR template ([#10654](https://github.com/paritytech/parity-ethereum/pull/10654))
|
||||
* docs: Add ProgPoW Rust docs to ethash module ([#10653](https://github.com/paritytech/parity-ethereum/pull/10653))
|
||||
* docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions ([#10652](https://github.com/paritytech/parity-ethereum/pull/10652))
|
||||
* Upgrade to parity-crypto 0.4 ([#10650](https://github.com/paritytech/parity-ethereum/pull/10650))
|
||||
* fix(compilation warnings) ([#10649](https://github.com/paritytech/parity-ethereum/pull/10649))
|
||||
* [whisper] Move needed aes_gcm crypto in-crate ([#10647](https://github.com/paritytech/parity-ethereum/pull/10647))
|
||||
* Update publishing ([#10644](https://github.com/paritytech/parity-ethereum/pull/10644))
|
||||
* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638))
|
||||
* Fix publish docs ([#10635](https://github.com/paritytech/parity-ethereum/pull/10635))
|
||||
* Fix rinkeby petersburg fork ([#10632](https://github.com/paritytech/parity-ethereum/pull/10632))
|
||||
* Update kovan.json to switch Kovan validator set to POA Consensus Contracts ([#10628](https://github.com/paritytech/parity-ethereum/pull/10628))
|
||||
* [ethcore] remove error_chain ([#10616](https://github.com/paritytech/parity-ethereum/pull/10616))
|
||||
* Remove unused import ([#10615](https://github.com/paritytech/parity-ethereum/pull/10615))
|
||||
* Adds parity_getRawBlockByNumber, parity_submitRawBlock ([#10609](https://github.com/paritytech/parity-ethereum/pull/10609))
|
||||
* adds rpc error message for --no-ancient-blocks ([#10608](https://github.com/paritytech/parity-ethereum/pull/10608))
|
||||
* Constantinople HF on POA Core ([#10606](https://github.com/paritytech/parity-ethereum/pull/10606))
|
||||
* Clique: zero-fill extradata when the supplied value is less than 32 bytes in length ([#10605](https://github.com/paritytech/parity-ethereum/pull/10605))
|
||||
* evm: add some mulmod benches ([#10600](https://github.com/paritytech/parity-ethereum/pull/10600))
|
||||
* sccache logs to stdout ([#10596](https://github.com/paritytech/parity-ethereum/pull/10596))
|
||||
* update bootnodes ([#10595](https://github.com/paritytech/parity-ethereum/pull/10595))
|
||||
* Merge `Notifier` and `TransactionsPoolNotifier` ([#10591](https://github.com/paritytech/parity-ethereum/pull/10591))
|
||||
* fix(whisper): change expiry `unix_time + ttl + work` ([#10587](https://github.com/paritytech/parity-ethereum/pull/10587))
|
||||
* fix(evmbin): make benches compile again ([#10586](https://github.com/paritytech/parity-ethereum/pull/10586))
|
||||
* fix issue with compilation when 'slow-blocks' feature enabled ([#10585](https://github.com/paritytech/parity-ethereum/pull/10585))
|
||||
* Allow CORS requests in Secret Store API ([#10584](https://github.com/paritytech/parity-ethereum/pull/10584))
|
||||
* CI improvements ([#10579](https://github.com/paritytech/parity-ethereum/pull/10579))
|
||||
* ethcore: improve timestamp handling ([#10574](https://github.com/paritytech/parity-ethereum/pull/10574))
|
||||
* Update Issue Template to direct security issue to email ([#10562](https://github.com/paritytech/parity-ethereum/pull/10562))
|
||||
* version: bump master to 2.6 ([#10560](https://github.com/paritytech/parity-ethereum/pull/10560))
|
||||
* fix(light cull): poll light cull instead of timer ([#10559](https://github.com/paritytech/parity-ethereum/pull/10559))
|
||||
* Watch transactions pool ([#10558](https://github.com/paritytech/parity-ethereum/pull/10558))
|
||||
* Add SealingState; don't prepare block when not ready. ([#10529](https://github.com/paritytech/parity-ethereum/pull/10529))
|
||||
* Explicitly enable or disable Stratum in config file (Issue 9785) ([#10521](https://github.com/paritytech/parity-ethereum/pull/10521))
|
||||
* Add filtering capability to `parity_pendingTransactions` (issue 8269) ([#10506](https://github.com/paritytech/parity-ethereum/pull/10506))
|
||||
* Remove calls to heapsize ([#10432](https://github.com/paritytech/parity-ethereum/pull/10432))
|
||||
* RPC: Implements eth_subscribe("syncing") ([#10311](https://github.com/paritytech/parity-ethereum/pull/10311))
|
||||
* SecretStore: non-blocking wait of session completion ([#10303](https://github.com/paritytech/parity-ethereum/pull/10303))
|
||||
* Node table limiting and cache for node filter ([#10288](https://github.com/paritytech/parity-ethereum/pull/10288))
|
||||
* SecretStore: expose restore_key_public in HTTP API ([#10241](https://github.com/paritytech/parity-ethereum/pull/10241))
|
||||
* Trivial journal for private transactions ([#10056](https://github.com/paritytech/parity-ethereum/pull/10056))
|
||||
|
||||
## Previous releases
|
||||
|
||||
- [CHANGELOG-2.5](docs/CHANGELOG-2.5.md) (_stable_)
|
||||
- [CHANGELOG-2.4](docs/CHANGELOG-2.4.md) (EOL: 2019-07-08)
|
||||
- [CHANGELOG-2.3](docs/CHANGELOG-2.3.md) (EOL: 2019-04-09)
|
||||
- [CHANGELOG-2.2](docs/CHANGELOG-2.2.md) (EOL: 2019-02-25)
|
||||
- [CHANGELOG-2.1](docs/CHANGELOG-2.1.md) (EOL: 2019-01-16)
|
||||
- [CHANGELOG-2.0](docs/CHANGELOG-2.0.md) (EOL: 2018-11-15)
|
||||
- [CHANGELOG-1.11](docs/CHANGELOG-1.11.md) (EOL: 2018-09-19)
|
||||
- [CHANGELOG-1.10](docs/CHANGELOG-1.10.md) (EOL: 2018-07-18)
|
||||
- [CHANGELOG-1.9](docs/CHANGELOG-1.9.md) (EOL: 2018-05-09)
|
||||
- [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)
|
||||
@@ -5,17 +5,18 @@ version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
crunchy = "0.1.0"
|
||||
common-types = { path = "../ethcore/types" }
|
||||
either = "1.0.0"
|
||||
ethereum-types = "0.4"
|
||||
keccak-hash = "0.1"
|
||||
ethereum-types = "0.8.0"
|
||||
keccak-hash = "0.4.0"
|
||||
log = "0.4"
|
||||
memmap = "0.6"
|
||||
parking_lot = "0.7"
|
||||
parking_lot = "0.9"
|
||||
primal = "0.2.3"
|
||||
static_assertions = "0.3.3"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.2"
|
||||
criterion = "0.3"
|
||||
rustc-hex = "1.0"
|
||||
serde_json = "1.0"
|
||||
tempdir = "0.3"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -17,26 +17,53 @@
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
extern crate ethash;
|
||||
extern crate common_types;
|
||||
|
||||
use criterion::Criterion;
|
||||
use ethash::{NodeCacheBuilder, OptimizeFor};
|
||||
use ethash::{NodeCacheBuilder, keccak};
|
||||
use common_types::engines::OptimizeFor;
|
||||
|
||||
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 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 MIX_HASH: [u8; 32] = [
|
||||
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,
|
||||
];
|
||||
const NONCE: u64 = 0xd7b3ac70a301a249;
|
||||
|
||||
criterion_group!(
|
||||
basic,
|
||||
bench_light_compute_memmap,
|
||||
bench_light_compute_memory,
|
||||
bench_light_new_round_trip_memmap,
|
||||
bench_light_new_round_trip_memory,
|
||||
bench_light_from_file_round_trip_memory,
|
||||
bench_light_from_file_round_trip_memmap
|
||||
);
|
||||
criterion_group! {
|
||||
name = basic;
|
||||
config = dont_take_an_eternity_to_run();
|
||||
targets = bench_keccak_512_inplace,
|
||||
bench_light_compute_memmap,
|
||||
bench_light_compute_memory,
|
||||
bench_light_new_round_trip_memmap,
|
||||
bench_light_new_round_trip_memory,
|
||||
bench_light_from_file_round_trip_memory,
|
||||
bench_light_from_file_round_trip_memmap,
|
||||
bench_quick_get_difficulty,
|
||||
}
|
||||
criterion_main!(basic);
|
||||
|
||||
fn dont_take_an_eternity_to_run() -> Criterion {
|
||||
Criterion::default().nresamples(1_000)
|
||||
.without_plots()
|
||||
.sample_size(10)
|
||||
}
|
||||
|
||||
fn bench_keccak_512_inplace(b: &mut Criterion) {
|
||||
b.bench_function("bench_keccak_512_inplace", move |b| b.iter(|| {
|
||||
let mut data = [4u8; 64];
|
||||
keccak::keccak_512::inplace(&mut data);
|
||||
}));
|
||||
}
|
||||
|
||||
fn bench_light_compute_memmap(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
@@ -52,13 +79,13 @@ fn bench_light_compute_memory(b: &mut Criterion) {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
|
||||
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value())));
|
||||
b.bench_function("bench_light_compute_memory", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value())));
|
||||
}
|
||||
|
||||
fn bench_light_new_round_trip_memmap(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
|
||||
b.bench_function("bench_light_new_round_trip_memmap", move |b| b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
@@ -68,7 +95,7 @@ fn bench_light_new_round_trip_memmap(b: &mut Criterion) {
|
||||
fn bench_light_new_round_trip_memory(b: &mut Criterion) {
|
||||
use std::env;
|
||||
|
||||
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
|
||||
b.bench_function("bench_light_new_round_trip_memory", move |b| b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
|
||||
let light = builder.light(&env::temp_dir(), 486382);
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
@@ -86,7 +113,7 @@ fn bench_light_from_file_round_trip_memory(b: &mut Criterion) {
|
||||
dummy.to_file().unwrap();
|
||||
}
|
||||
|
||||
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
|
||||
b.bench_function("bench_light_from_file_round_trip_memory", move |b| b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
|
||||
let light = builder.light_from_file(&dir, 486382).unwrap();
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
@@ -105,9 +132,21 @@ fn bench_light_from_file_round_trip_memmap(b: &mut Criterion) {
|
||||
dummy.to_file().unwrap();
|
||||
}
|
||||
|
||||
b.bench_function("bench_light_compute_memmap", move |b| b.iter(|| {
|
||||
b.bench_function("bench_light_from_file_round_trip_memmap", move |b| b.iter(|| {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
|
||||
let light = builder.light_from_file(&dir, 486382).unwrap();
|
||||
light.compute(&HASH, NONCE, u64::max_value());
|
||||
}));
|
||||
}
|
||||
|
||||
fn bench_quick_get_difficulty(b: &mut Criterion) {
|
||||
b.bench_function("bench_quick_get_difficulty", move |b| b.iter(|| {
|
||||
let d = ethash::quick_get_difficulty(&HASH, NONCE, &MIX_HASH, false);
|
||||
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!(d[..], boundary_good[..]);
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -3,14 +3,16 @@ extern crate criterion;
|
||||
extern crate ethash;
|
||||
extern crate rustc_hex;
|
||||
extern crate tempdir;
|
||||
extern crate common_types;
|
||||
|
||||
use criterion::Criterion;
|
||||
use ethash::progpow;
|
||||
|
||||
use tempdir::TempDir;
|
||||
use rustc_hex::FromHex;
|
||||
use ethash::{NodeCacheBuilder, OptimizeFor};
|
||||
use ethash::NodeCacheBuilder;
|
||||
use ethash::compute::light_compute;
|
||||
use common_types::engines::OptimizeFor;
|
||||
|
||||
fn bench_hashimoto_light(c: &mut Criterion) {
|
||||
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
|
||||
|
||||
@@ -3,84 +3,84 @@
|
||||
0,
|
||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"0000000000000000",
|
||||
"faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3",
|
||||
"63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b"
|
||||
"f4ac202715ded4136e72887c39e63a4738331c57fd9eb79f6ec421c281aa8743",
|
||||
"b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02"
|
||||
],
|
||||
[
|
||||
49,
|
||||
"63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b",
|
||||
"b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02",
|
||||
"0000000006ff2c47",
|
||||
"c789c1180f890ec555ff42042913465481e8e6bc512cb981e1c1108dc3f2227d",
|
||||
"9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922"
|
||||
"7730596f128f675ef9a6bb7281f268e4077d302f2b9078da1ece4349248561dd",
|
||||
"0b9ed0c11157f1365143e329a6e1cea4248d9d6cb44b9c6daf492c7a076654a4"
|
||||
],
|
||||
[
|
||||
50,
|
||||
"9e7248f20914913a73d80a70174c331b1d34f260535ac3631d770e656b5dd922",
|
||||
"0b9ed0c11157f1365143e329a6e1cea4248d9d6cb44b9c6daf492c7a076654a4",
|
||||
"00000000076e482e",
|
||||
"c7340542c2a06b3a7dc7222635f7cd402abf8b528ae971ddac6bbe2b0c7cb518",
|
||||
"de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d"
|
||||
"829136d4a704eb8d06da773f1a90466e7b5ed12119c44526f045bbff4475d891",
|
||||
"e2e881c5b893c2f1ef06b96a10cfcbcf7255b307f0818e7d30eb12b2edfc237b"
|
||||
],
|
||||
[
|
||||
99,
|
||||
"de37e1824c86d35d154cf65a88de6d9286aec4f7f10c3fc9f0fa1bcc2687188d",
|
||||
"e2e881c5b893c2f1ef06b96a10cfcbcf7255b307f0818e7d30eb12b2edfc237b",
|
||||
"000000003917afab",
|
||||
"f5e60b2c5bfddd136167a30cbc3c8dbdbd15a512257dee7964e0bc6daa9f8ba7",
|
||||
"ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce"
|
||||
"deb3d8b45bdc596c56aa37a5eba456f478c82e60e5c028ce95f2e654e4bb7b57",
|
||||
"9bdc2ad2286eaa051d6ca1f5196d2dd1c9a039f1d7ce3e1c856b793deed01778"
|
||||
],
|
||||
[
|
||||
29950,
|
||||
"ac7b55e801511b77e11d52e9599206101550144525b5679f2dab19386f23dcce",
|
||||
"9bdc2ad2286eaa051d6ca1f5196d2dd1c9a039f1d7ce3e1c856b793deed01778",
|
||||
"005d409dbc23a62a",
|
||||
"07393d15805eb08ee6fc6cb3ad4ad1010533bd0ff92d6006850246829f18fd6e",
|
||||
"e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5"
|
||||
"c01e6d339cc687c77f653b81c74cb9de8b595554f2c5db671a7dde3846d2fa01",
|
||||
"de0d693e597cf2fd70a4cfaa73f6baafc29e1eee695a81295b278c1116580b72"
|
||||
],
|
||||
[
|
||||
29999,
|
||||
"e43d7e0bdc8a4a3f6e291a5ed790b9fa1a0948a2b9e33c844888690847de19f5",
|
||||
"de0d693e597cf2fd70a4cfaa73f6baafc29e1eee695a81295b278c1116580b72",
|
||||
"005db5fa4c2a3d03",
|
||||
"7551bddf977491da2f6cfc1679299544b23483e8f8ee0931c4c16a796558a0b8",
|
||||
"d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454"
|
||||
"8b664cdbf396a7a185446c93dddd6611f5a736b11097381ae6bea45e802cec16",
|
||||
"21ec5d1984a4fd4394b042aa96365085225d964727a45def245ceab326e28128"
|
||||
],
|
||||
[
|
||||
30000,
|
||||
"d34519f72c97cae8892c277776259db3320820cb5279a299d0ef1e155e5c6454",
|
||||
"21ec5d1984a4fd4394b042aa96365085225d964727a45def245ceab326e28128",
|
||||
"005db8607994ff30",
|
||||
"f1c2c7c32266af9635462e6ce1c98ebe4e7e3ecab7a38aaabfbf2e731e0fbff4",
|
||||
"8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64"
|
||||
"276951d89c1ed262bcac00df4fb9bf7af36991532744a2e287b0b758a56e15aa",
|
||||
"dc070b76cc311cd82267f98936acbbbd3ec1c1ab25b55e2c885af6474e1e6841"
|
||||
],
|
||||
[
|
||||
30049,
|
||||
"8b6ce5da0b06d18db7bd8492d9e5717f8b53e7e098d9fef7886d58a6e913ef64",
|
||||
"dc070b76cc311cd82267f98936acbbbd3ec1c1ab25b55e2c885af6474e1e6841",
|
||||
"005e2e215a8ca2e7",
|
||||
"57fe6a9fbf920b4e91deeb66cb0efa971e08229d1a160330e08da54af0689add",
|
||||
"c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047"
|
||||
"6248ba0157d0f0592dacfe2963337948fffb37f67e7451a6862c1321d894cebe",
|
||||
"6fdecf719e2547f585a6ee807d8237db8e9489f63d3f259ab5236451eaded433"
|
||||
],
|
||||
[
|
||||
30050,
|
||||
"c2c46173481b9ced61123d2e293b42ede5a1b323210eb2a684df0874ffe09047",
|
||||
"6fdecf719e2547f585a6ee807d8237db8e9489f63d3f259ab5236451eaded433",
|
||||
"005e30899481055e",
|
||||
"ba30c61cc5a2c74a5ecaf505965140a08f24a296d687e78720f0b48baf712f2d",
|
||||
"ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71"
|
||||
"512d8f2bb0441fcfa1764c67e8dbed2afcbe9141de4bbebc5b51e0661dede550",
|
||||
"cb1587a1c372642cbd9ce4c1ba2f433985d44c571a676a032bc1e8c1ad066e24"
|
||||
],
|
||||
[
|
||||
30099,
|
||||
"ea42197eb2ba79c63cb5e655b8b1f612c5f08aae1a49ff236795a3516d87bc71",
|
||||
"cb1587a1c372642cbd9ce4c1ba2f433985d44c571a676a032bc1e8c1ad066e24",
|
||||
"005ea6aef136f88b",
|
||||
"cfd5e46048cd133d40f261fe8704e51d3f497fc14203ac6a9ef6a0841780b1cd",
|
||||
"49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6"
|
||||
"be0e7d6afa6edd483ccc304afa9bf0abaca5e0f037a4f05bf5550b9309d1d12c",
|
||||
"78be18f20569a834d839dad48e0e51d6df6b6537575f0ad29898c7cf357f12cb"
|
||||
],
|
||||
[
|
||||
59950,
|
||||
"49e15ba4bf501ce8fe8876101c808e24c69a859be15de554bf85dbc095491bd6",
|
||||
"78be18f20569a834d839dad48e0e51d6df6b6537575f0ad29898c7cf357f12cb",
|
||||
"02ebe0503bd7b1da",
|
||||
"21511fbaa31fb9f5fc4998a754e97b3083a866f4de86fa7500a633346f56d773",
|
||||
"f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf"
|
||||
"b85be51fce670aa437f28c02ea4fd7995fa8b6ac224e959b8dbfb5bdbc6f77ce",
|
||||
"a68a620ba17e0cf2817bc4397cf4b85f5770983aa7b7931319a7f61bd6f905b1"
|
||||
],
|
||||
[
|
||||
59999,
|
||||
"f5c50ba5c0d6210ddb16250ec3efda178de857b2b1703d8d5403bd0f848e19cf",
|
||||
"a68a620ba17e0cf2817bc4397cf4b85f5770983aa7b7931319a7f61bd6f905b1",
|
||||
"02edb6275bd221e3",
|
||||
"653eda37d337e39d311d22be9bbd3458d3abee4e643bee4a7280a6d08106ef98",
|
||||
"341562d10d4afb706ec2c8d5537cb0c810de02b4ebb0a0eea5ae335af6fb2e88"
|
||||
"ffe745a932c21c0704291bb416fe8bffec76621cd3434861885beab42cec1734",
|
||||
"9e6667a151ac6f5186a05cb20877a2b3df02317046256a762cb8ec2d96aa34f0"
|
||||
]
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -21,7 +21,7 @@ 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 shared::{ETHASH_CACHE_ROUNDS, NODE_BYTES, Node, epoch, get_cache_size, to_hex};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::fs;
|
||||
@@ -30,20 +30,10 @@ use std::path::{Path, PathBuf};
|
||||
use std::slice;
|
||||
use std::sync::Arc;
|
||||
|
||||
use common_types::engines::OptimizeFor;
|
||||
|
||||
type Cache = Either<Vec<Node>, 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};
|
||||
|
||||
@@ -327,11 +317,6 @@ unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
|
||||
// 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;
|
||||
@@ -341,11 +326,8 @@ unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
|
||||
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);
|
||||
}
|
||||
for (a, b) in data.as_dwords_mut().iter_mut().zip(rhs.as_dwords()) {
|
||||
*a ^= *b;
|
||||
}
|
||||
|
||||
data
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -26,7 +26,7 @@ use seed_compute::SeedHashCompute;
|
||||
use shared::*;
|
||||
use std::io;
|
||||
|
||||
use std::{mem, ptr};
|
||||
use std::mem;
|
||||
use std::path::Path;
|
||||
|
||||
const MIX_WORDS: usize = ETHASH_MIX_BYTES / 4;
|
||||
@@ -135,22 +135,16 @@ pub fn quick_get_difficulty(header_hash: &H256, nonce: u64, mix_hash: &H256, pro
|
||||
let seed = keccak_f800_short(*header_hash, nonce, [0u32; 8]);
|
||||
keccak_f800_long(*header_hash, seed, mem::transmute(*mix_hash))
|
||||
} else {
|
||||
// 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 `keccak_256`.
|
||||
//
|
||||
// This cannot be elided by the compiler as it doesn't know the implementation of
|
||||
// `keccak_512`.
|
||||
let mut buf: [u8; 64 + 32] = mem::uninitialized();
|
||||
let mut buf = [0u8; 64 + 32];
|
||||
|
||||
ptr::copy_nonoverlapping(header_hash.as_ptr(), buf.as_mut_ptr(), 32);
|
||||
ptr::copy_nonoverlapping(&nonce as *const u64 as *const u8, buf[32..].as_mut_ptr(), 8);
|
||||
let hash_len = header_hash.len();
|
||||
buf[..hash_len].copy_from_slice(header_hash);
|
||||
buf[hash_len..hash_len + mem::size_of::<u64>()].copy_from_slice(&nonce.to_ne_bytes());
|
||||
|
||||
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);
|
||||
buf[64..].copy_from_slice(mix_hash);
|
||||
|
||||
// This is initialized in `keccak_256`
|
||||
let mut hash: [u8; 32] = mem::uninitialized();
|
||||
let mut hash = [0u8; 32];
|
||||
keccak_256::unchecked(hash.as_mut_ptr(), hash.len(), buf.as_ptr(), buf.len());
|
||||
|
||||
hash
|
||||
@@ -205,17 +199,11 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
||||
let mut buf: MixBuf = MixBuf {
|
||||
half_mix: unsafe {
|
||||
// Pack `header_hash` and `nonce` together
|
||||
// We explicitly write the first 40 bytes, leaving the last 24 as uninitialized. Then
|
||||
// `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();
|
||||
let mut out = [0u8; NODE_BYTES];
|
||||
|
||||
ptr::copy_nonoverlapping(header_hash.as_ptr(), out.as_mut_ptr(), header_hash.len());
|
||||
ptr::copy_nonoverlapping(
|
||||
&nonce as *const u64 as *const u8,
|
||||
out[header_hash.len()..].as_mut_ptr(),
|
||||
mem::size_of::<u64>(),
|
||||
);
|
||||
let hash_len = header_hash.len();
|
||||
out[..hash_len].copy_from_slice(header_hash);
|
||||
out[hash_len..hash_len + mem::size_of::<u64>()].copy_from_slice(&nonce.to_ne_bytes());
|
||||
|
||||
// compute keccak-512 hash and replicate across mix
|
||||
keccak_512::unchecked(
|
||||
@@ -227,8 +215,7 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
||||
|
||||
Node { bytes: out }
|
||||
},
|
||||
// This is fully initialized before being read, see `let mut compress = ...` below
|
||||
compress_bytes: unsafe { mem::uninitialized() },
|
||||
compress_bytes: [0u8; MIX_WORDS],
|
||||
};
|
||||
|
||||
let mut mix: [_; MIX_NODES] = [buf.half_mix.clone(), buf.half_mix.clone()];
|
||||
@@ -252,24 +239,16 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
||||
fnv_hash(first_val ^ i, mix_words[i as usize % MIX_WORDS]) % num_full_pages
|
||||
};
|
||||
|
||||
unroll! {
|
||||
// MIX_NODES
|
||||
for n in 0..2 {
|
||||
let tmp_node = calculate_dag_item(
|
||||
index * MIX_NODES as u32 + n as u32,
|
||||
cache,
|
||||
);
|
||||
// MIX_NODES
|
||||
for n in 0..2 {
|
||||
let tmp_node = calculate_dag_item(
|
||||
index * MIX_NODES as u32 + n as u32,
|
||||
cache,
|
||||
);
|
||||
|
||||
unroll! {
|
||||
// NODE_WORDS
|
||||
for w in 0..16 {
|
||||
mix[n].as_words_mut()[w] =
|
||||
fnv_hash(
|
||||
mix[n].as_words()[w],
|
||||
tmp_node.as_words()[w],
|
||||
);
|
||||
}
|
||||
}
|
||||
// NODE_WORDS
|
||||
for (a, b) in mix[n].as_words_mut().iter_mut().zip(tmp_node.as_words()) {
|
||||
*a = fnv_hash(*a, *b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -277,25 +256,27 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
||||
let mix_words: [u32; MIX_WORDS] = unsafe { mem::transmute(mix) };
|
||||
|
||||
{
|
||||
// This is an uninitialized buffer to begin with, but we iterate precisely `compress.len()`
|
||||
// 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
|
||||
// We iterate precisely `compress.len()` 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 compress: &mut [u32; MIX_WORDS / 4] =
|
||||
unsafe { make_const_array!(MIX_WORDS / 4, &mut buf.compress_bytes) };
|
||||
#[cfg(target_endian = "big")]
|
||||
{
|
||||
compile_error!("parity-ethereum currently only supports little-endian targets");
|
||||
}
|
||||
|
||||
// Compress mix
|
||||
debug_assert_eq!(MIX_WORDS / 4, 8);
|
||||
unroll! {
|
||||
for i in 0..8 {
|
||||
let w = i * 4;
|
||||
for i in 0..8 {
|
||||
let w = i * 4;
|
||||
|
||||
let mut reduction = mix_words[w + 0];
|
||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
|
||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
|
||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
|
||||
compress[i] = reduction;
|
||||
}
|
||||
let mut reduction = mix_words[w + 0];
|
||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 1];
|
||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 2];
|
||||
reduction = reduction.wrapping_mul(FNV_PRIME) ^ mix_words[w + 3];
|
||||
compress[i] = reduction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,7 +302,6 @@ fn hash_compute(light: &Light, full_size: usize, header_hash: &H256, nonce: u64)
|
||||
ProofOfWork { mix_hash: mix_hash, value: value }
|
||||
}
|
||||
|
||||
// TODO: Use the `simd` crate
|
||||
pub 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();
|
||||
@@ -335,10 +315,8 @@ pub fn calculate_dag_item(node_index: u32, cache: &[Node]) -> Node {
|
||||
num_parent_nodes as u32;
|
||||
let parent = &cache[parent_index as usize];
|
||||
|
||||
unroll! {
|
||||
for w in 0..16 {
|
||||
ret.as_words_mut()[w] = fnv_hash(ret.as_words()[w], parent.as_words()[w]);
|
||||
}
|
||||
for (a, b) in ret.as_words_mut().iter_mut().zip(parent.as_words()) {
|
||||
*a = fnv_hash(*a, *b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -14,16 +14,17 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate common_types;
|
||||
extern crate either;
|
||||
extern crate ethereum_types;
|
||||
extern crate memmap;
|
||||
extern crate parking_lot;
|
||||
extern crate primal;
|
||||
|
||||
#[macro_use]
|
||||
extern crate crunchy;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate static_assertions;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate rustc_hex;
|
||||
@@ -41,6 +42,9 @@ mod compute;
|
||||
|
||||
mod seed_compute;
|
||||
mod cache;
|
||||
#[cfg(feature = "bench")]
|
||||
pub mod keccak;
|
||||
#[cfg(not(feature = "bench"))]
|
||||
mod keccak;
|
||||
mod shared;
|
||||
|
||||
@@ -49,17 +53,20 @@ pub mod progpow;
|
||||
#[cfg(not(feature = "bench"))]
|
||||
mod progpow;
|
||||
|
||||
pub use cache::{NodeCacheBuilder, OptimizeFor};
|
||||
pub use cache::NodeCacheBuilder;
|
||||
pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number};
|
||||
use compute::Light;
|
||||
use ethereum_types::{U256, U512};
|
||||
use keccak::H256;
|
||||
use parking_lot::Mutex;
|
||||
pub use seed_compute::SeedHashCompute;
|
||||
pub use shared::ETHASH_EPOCH_LENGTH;
|
||||
|
||||
use common_types::engines::OptimizeFor;
|
||||
use compute::Light;
|
||||
use ethereum_types::{BigEndianHash, U256, U512};
|
||||
use keccak::H256;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
use std::mem;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct LightCache {
|
||||
@@ -83,7 +90,7 @@ impl EthashManager {
|
||||
EthashManager {
|
||||
cache_dir: cache_dir.to_path_buf(),
|
||||
nodecache_builder: NodeCacheBuilder::new(optimize_for.into().unwrap_or_default(), progpow_transition),
|
||||
progpow_transition: progpow_transition,
|
||||
progpow_transition,
|
||||
cache: Mutex::new(LightCache {
|
||||
recent_epoch: None,
|
||||
recent: None,
|
||||
@@ -161,12 +168,12 @@ impl EthashManager {
|
||||
|
||||
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn boundary_to_difficulty(boundary: ðereum_types::H256) -> U256 {
|
||||
difficulty_to_boundary_aux(&**boundary)
|
||||
difficulty_to_boundary_aux(&boundary.into_uint())
|
||||
}
|
||||
|
||||
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 {
|
||||
difficulty_to_boundary_aux(difficulty).into()
|
||||
BigEndianHash::from_uint(&difficulty_to_boundary_aux(difficulty))
|
||||
}
|
||||
|
||||
fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U256 {
|
||||
@@ -177,8 +184,8 @@ fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U
|
||||
if difficulty == U512::one() {
|
||||
U256::max_value()
|
||||
} else {
|
||||
// difficulty > 1, so result should never overflow 256 bits
|
||||
U256::from((U512::one() << 256) / difficulty)
|
||||
const PROOF: &str = "difficulty > 1, so result never overflows 256 bits; qed";
|
||||
U256::try_from((U512::one() << 256) / difficulty).expect(PROOF)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,10 +210,10 @@ fn test_lru() {
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary() {
|
||||
use ethereum_types::H256;
|
||||
use ethereum_types::{H256, BigEndianHash};
|
||||
use std::str::FromStr;
|
||||
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(1)), BigEndianHash::from_uint(&U256::max_value()));
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
@@ -220,9 +227,18 @@ fn test_difficulty_to_boundary_regression() {
|
||||
// https://github.com/paritytech/parity-ethereum/issues/8397
|
||||
for difficulty in 1..9 {
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into())));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into())));
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into()));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into()));
|
||||
assert_eq!(
|
||||
H256::from_low_u64_be(difficulty),
|
||||
difficulty_to_boundary(&boundary_to_difficulty(&H256::from_low_u64_be(difficulty))),
|
||||
);
|
||||
assert_eq!(
|
||||
U256::from(difficulty),
|
||||
boundary_to_difficulty(&BigEndianHash::from_uint(&boundary_to_difficulty(&H256::from_low_u64_be(difficulty)))),
|
||||
);
|
||||
assert_eq!(
|
||||
H256::from_low_u64_be(difficulty),
|
||||
difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into_uint()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,5 +251,5 @@ fn test_difficulty_to_boundary_panics_on_zero() {
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_boundary_to_difficulty_panics_on_zero() {
|
||||
boundary_to_difficulty(ðereum_types::H256::from(0));
|
||||
boundary_to_difficulty(ðereum_types::H256::zero());
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
@@ -14,18 +14,37 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! ProgPoW (Programmatic Proof-of-Work) is the Ethereum network's proposed new Application-Specific Integrated
|
||||
//! Circuit (ASIC) resistant Proof-of-Work mining algorithm.
|
||||
//!
|
||||
//! ProgPoW's aim is to reduce the efficiencies of specialized mining devices known as ASIC chips
|
||||
//! (and accelerated GPU-based setups), and to maximize the performance of General Purpose Hardware (GPUs) to enable
|
||||
//! more users to compete for new cryptocurrency awarded by the protocol.
|
||||
//!
|
||||
//! ASIC chips are those that are tailored to efficiently mining cryptocurrency based on a specific hashing algorithm.
|
||||
//!
|
||||
//! GPU mining setups are less specialised are struggle to compete for mining rewards.
|
||||
//!
|
||||
//! It would be a change from Ethereum's current PoW mining algorithm known as Ethash.
|
||||
//!
|
||||
//! ProgPoW audits have been proposed to analyse the efficiency of a ProgPoW ASICs over
|
||||
//! GPUs and analysis of the economic impact on the Ethereum protocol.
|
||||
//!
|
||||
//! We use ProgPoW 0.9.3 version as suggested on Specification
|
||||
//! https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1057.md#specification
|
||||
|
||||
use compute::{FNV_PRIME, calculate_dag_item};
|
||||
use keccak::H256;
|
||||
use shared::{ETHASH_ACCESSES, ETHASH_MIX_BYTES, Node, get_data_size};
|
||||
|
||||
const PROGPOW_CACHE_BYTES: usize = 16 * 1024;
|
||||
const PROGPOW_CACHE_WORDS: usize = PROGPOW_CACHE_BYTES / 4;
|
||||
const PROGPOW_CNT_CACHE: usize = 12;
|
||||
const PROGPOW_CNT_MATH: usize = 20;
|
||||
const PROGPOW_CNT_CACHE: usize = 11;
|
||||
const PROGPOW_CNT_MATH: usize = 18;
|
||||
const PROGPOW_CNT_DAG: usize = ETHASH_ACCESSES;
|
||||
const PROGPOW_DAG_LOADS: usize = 4;
|
||||
const PROGPOW_MIX_BYTES: usize = 2 * ETHASH_MIX_BYTES;
|
||||
const PROGPOW_PERIOD_LENGTH: usize = 50; // blocks per progpow epoch (N)
|
||||
const PROGPOW_PERIOD_LENGTH: usize = 10; // blocks per progpow epoch (N)
|
||||
const PROGPOW_LANES: usize = 16;
|
||||
const PROGPOW_REGS: usize = 32;
|
||||
|
||||
@@ -403,7 +422,8 @@ pub fn generate_cdag(cache: &[Node]) -> CDag {
|
||||
mod test {
|
||||
use tempdir::TempDir;
|
||||
|
||||
use cache::{NodeCacheBuilder, OptimizeFor};
|
||||
use common_types::engines::OptimizeFor;
|
||||
use cache::NodeCacheBuilder;
|
||||
use keccak::H256;
|
||||
use rustc_hex::FromHex;
|
||||
use serde_json::{self, Value};
|
||||
@@ -529,8 +549,8 @@ mod test {
|
||||
&c_dag,
|
||||
);
|
||||
|
||||
let expected_digest = FromHex::from_hex("63155f732f2bf556967f906155b510c917e48e99685ead76ea83f4eca03ab12b").unwrap();
|
||||
let expected_result = FromHex::from_hex("faeb1be51075b03a4ff44b335067951ead07a3b078539ace76fd56fc410557a3").unwrap();
|
||||
let expected_digest = FromHex::from_hex("b3bad9ca6f7c566cf0377d1f8cce29d6516a96562c122d924626281ec948ef02").unwrap();
|
||||
let expected_result = FromHex::from_hex("f4ac202715ded4136e72887c39e63a4738331c57fd9eb79f6ec421c281aa8743").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
digest.to_vec(),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
|
||||
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity Ethereum.
|
||||
|
||||
// Parity Ethereum is free software: you can redistribute it and/or modify
|
||||
@@ -69,34 +69,7 @@ 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);
|
||||
assert_eq_size!(node; Node, NodeBytes, NodeWords, NodeDwords);
|
||||
|
||||
#[repr(C)]
|
||||
pub union Node {
|
||||
|
||||
@@ -7,89 +7,99 @@ version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
ansi_term = "0.10"
|
||||
account-state = { path = "account-state" }
|
||||
ansi_term = "0.11"
|
||||
basic-authority = { path = "./engines/basic-authority", optional = true} # used by test-helpers feature
|
||||
blooms-db = { path = "../util/blooms-db", optional = true }
|
||||
byteorder = "1.0"
|
||||
common-types = { path = "types" }
|
||||
crossbeam-utils = "0.6"
|
||||
eip-152 = { version = "0.1", path = "../util/EIP-152" }
|
||||
client-traits = { path = "./client-traits" }
|
||||
common-types = { path = "./types" }
|
||||
engine = { path = "./engine" }
|
||||
env_logger = { version = "0.5", optional = true }
|
||||
error-chain = { version = "0.12", default-features = false }
|
||||
ethabi = "6.0"
|
||||
ethabi-contract = "6.0"
|
||||
ethabi-derive = "6.0"
|
||||
ethash = { path = "../ethash" }
|
||||
ethash = { path = "../ethash", optional = true }
|
||||
ethjson = { path = "../json", optional = true }
|
||||
ethcore-blockchain = { path = "./blockchain" }
|
||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||
ethcore-builtin = { path = "./builtin" }
|
||||
ethcore-call-contract = { path = "./call-contract" }
|
||||
ethcore-db = { path = "./db" }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
ethcore-miner = { path = "../miner" }
|
||||
ethcore-stratum = { path = "../miner/stratum", optional = true }
|
||||
ethereum-types = "0.4"
|
||||
ethjson = { path = "../json" }
|
||||
ethkey = { path = "../accounts/ethkey" }
|
||||
ethereum-types = "0.8.0"
|
||||
evm = { path = "evm" }
|
||||
hash-db = "0.11.0"
|
||||
heapsize = "0.4"
|
||||
executive-state = { path = "executive-state" }
|
||||
futures = "0.1"
|
||||
hash-db = "0.15.0"
|
||||
itertools = "0.5"
|
||||
journaldb = { path = "../util/journaldb" }
|
||||
keccak-hash = "0.1"
|
||||
keccak-hasher = { path = "../util/keccak-hasher" }
|
||||
kvdb = "0.1"
|
||||
kvdb-memorydb = "0.1"
|
||||
kvdb-rocksdb = { version = "0.1.3", optional = true }
|
||||
lazy_static = "1.2.0"
|
||||
len-caching-lock = { path = "../util/len-caching-lock" }
|
||||
keccak-hash = "0.4.0"
|
||||
kvdb = "0.3.1"
|
||||
kvdb-memorydb = { version = "0.3.1", optional = true }
|
||||
kvdb-rocksdb = { version = "0.4.1", optional = true }
|
||||
lazy_static = { version = "1.3", optional = true }
|
||||
log = "0.4"
|
||||
lru-cache = "0.1"
|
||||
macros = { path = "../util/macros" }
|
||||
macros = { path = "../util/macros", optional = true }
|
||||
machine = { path = "./machine" }
|
||||
memory-cache = { path = "../util/memory-cache" }
|
||||
memory-db = "0.11"
|
||||
num_cpus = "1.2"
|
||||
parity-bytes = "0.1"
|
||||
parity-snappy = "0.1"
|
||||
parking_lot = "0.7"
|
||||
trie-db = "0.11.0"
|
||||
parking_lot = "0.9"
|
||||
pod = { path = "pod", optional = true }
|
||||
trie-db = "0.18.0"
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"], optional = true }
|
||||
patricia-trie-ethereum = { path = "../util/patricia-trie-ethereum" }
|
||||
rand = "0.4"
|
||||
rand = "0.7"
|
||||
rand_xorshift = "0.2"
|
||||
rayon = "1.1"
|
||||
rlp = { version = "0.3.0", features = ["ethereum"] }
|
||||
rlp_derive = { path = "../util/rlp-derive" }
|
||||
rustc-hex = "1.0"
|
||||
registrar = { path = "../util/registrar" }
|
||||
rlp = "0.4.0"
|
||||
rustc-hex = "2"
|
||||
scopeguard = "1.0.0"
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
stats = { path = "../util/stats" }
|
||||
tempdir = {version="0.3", optional = true}
|
||||
time-utils = { path = "../util/time-utils" }
|
||||
snapshot = { path = "snapshot" }
|
||||
spec = { path = "spec" }
|
||||
state-db = { path = "state-db" }
|
||||
tempdir = { version = "0.3", optional = true }
|
||||
trace = { path = "trace" }
|
||||
trace-time = "0.1"
|
||||
trie-vm-factories = { path = "trie-vm-factories" }
|
||||
triehash-ethereum = { version = "0.2", path = "../util/triehash-ethereum" }
|
||||
unexpected = { path = "../util/unexpected" }
|
||||
using_queue = { path = "../miner/using-queue" }
|
||||
verification = { path = "./verification" }
|
||||
vm = { path = "vm" }
|
||||
wasm = { path = "wasm" }
|
||||
|
||||
[dev-dependencies]
|
||||
account-db = { path = "account-db" }
|
||||
blooms-db = { path = "../util/blooms-db" }
|
||||
criterion = "0.2"
|
||||
criterion = "0.3"
|
||||
engine = { path = "./engine", features = ["test-helpers"] }
|
||||
env_logger = "0.5"
|
||||
ethcore-accounts = { path = "../accounts" }
|
||||
ethcore-builtin = { path = "./builtin" }
|
||||
ethjson = { path = "../json", features = ["test-helpers"] }
|
||||
parity-crypto = { version = "0.4.2", features = ["publickey"] }
|
||||
fetch = { path = "../util/fetch" }
|
||||
hex-literal = "0.2.1"
|
||||
kvdb-rocksdb = "0.1.3"
|
||||
kvdb-memorydb = "0.3.1"
|
||||
kvdb-rocksdb = "0.4.1"
|
||||
lazy_static = "1.3"
|
||||
machine = { path = "./machine", features = ["test-helpers"] }
|
||||
macros = { path = "../util/macros" }
|
||||
parity-runtime = { path = "../util/runtime" }
|
||||
rlp_compress = { path = "../util/rlp-compress" }
|
||||
serde_json = "1.0"
|
||||
stats = { path = "../util/stats" }
|
||||
pod = { path = "pod" }
|
||||
tempdir = "0.3"
|
||||
trie-standardmap = "0.1"
|
||||
trie-standardmap = "0.15.0"
|
||||
|
||||
[features]
|
||||
parity = ["work-notify", "price-info", "stratum"]
|
||||
parity = ["work-notify", "price-info", "stratum", "macros"]
|
||||
# Large optional features that are enabled by default for Parity,
|
||||
# but might be omitted for other dependent crates.
|
||||
work-notify = ["ethcore-miner/work-notify"]
|
||||
price-info = ["ethcore-miner/price-info"]
|
||||
stratum = [ "ethcore-stratum" ]
|
||||
stratum = [
|
||||
"ethash",
|
||||
"ethcore-stratum"
|
||||
]
|
||||
|
||||
|
||||
# Disables seal verification for mined blocks.
|
||||
@@ -106,15 +116,22 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"]
|
||||
# EVM debug traces are printed.
|
||||
slow-blocks = []
|
||||
# Run JSON consensus tests.
|
||||
json-tests = ["env_logger", "test-helpers", "to-pod-full"]
|
||||
# Skip JSON consensus tests with pending issues.
|
||||
ci-skip-tests = []
|
||||
json-tests = ["env_logger", "test-helpers", "lazy_static", "machine/test-helpers", "common-types/test-helpers"]
|
||||
# Run memory/cpu heavy tests.
|
||||
test-heavy = []
|
||||
# Compile test helpers
|
||||
test-helpers = ["tempdir", "kvdb-rocksdb", "blooms-db"]
|
||||
# Enables slow 'to-pod-full' method for use in tests and evmbin.
|
||||
to-pod-full = []
|
||||
# note[dvdplm]: "basic-authority/test-helpers" is needed so that `generate_dummy_client_with_spec` works
|
||||
test-helpers = [
|
||||
"blooms-db",
|
||||
"ethjson/test-helpers",
|
||||
"parity-crypto",
|
||||
"kvdb-memorydb",
|
||||
"kvdb-rocksdb",
|
||||
"macros",
|
||||
"pod",
|
||||
"tempdir",
|
||||
"basic-authority/test-helpers"
|
||||
]
|
||||
|
||||
[[bench]]
|
||||
name = "builtin"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user