Compare commits

..

362 Commits

Author SHA1 Message Date
Niklas Adolfsson
2662d1925e [eth classic chainspec]: remove balance = 1 (#11458) 2020-02-06 11:12:19 +01:00
s3krit
d961010f63 V2.7.2 stable (#11454)
* update classic testnet bootnodes (#11398)

* update classic testnet bootnodes

* Update kotti.json

* Update kotti.json

* Update kotti.json

* Update mordor.json

* verification: fix race same block + misc (#11400)

* ethcore: fix race in verification

* verification: fix some nits

* verification: refactor err type `Kind::create`

* fix: tests

* address grumbles

* address grumbles: don't panic

* fix: export hardcoded sync format (#11416)

* fix: export hardcoded sync format

* address grumbles

* make tests compile with rustc_hex 2.0

* fix grumbles: impl LowerHex for encoded Header

* goerli: replace foundation bootnode (#11433)

* Remove dead bootnodes, add new geth bootnodes (#11441)

* update kvdb-rocksdb to 0.4 (#11442)

* Avoid long state queries when serving GetNodeData requests (#11444)

* Remove dead bootnodes, add new geth bootnodes

* More granular locking when fetching state
Finish GetDataNode requests early if queries take too long

* typo

* Use latest kvdb-rocksdb

* Cleanup

* Update ethcore/sync/src/chain/supplier.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Address review grumbles

* Fix compilation

* Address review grumbles

Co-authored-by: Andronik Ordian <write@reusable.software>

* rlp_derive: cleanup (#11446)

* rlp_derive: update syn & co

* rlp_derive: remove dummy_const

* rlp_derive: remove unused attirubutes

* rlp-derive: change authors

* Cargo.lock: cargo update -p kvdb-rocksdb (#11447)

* Cargo.lock: new lockfile format

Manual backport of https://github.com/paritytech/parity-ethereum/pull/11448

* gcc to clang (#11453)

* gcc to clang

test
```
export CC="sccache "$CC
export CXX="sccache "$CXX
```
darwin build
```
CC=clang
CXX=clang
```

* darwin - > default clang

* Bump version and CHANGELOG.md

* chore: remove unused dependencies (#11432)

* fix: compiler warnings

* chore: remove unused dependencies

* Update CHANGELOG.md

* update Cargo.lock

* update CHANGELOG.md

* backwards compatible call_type creation_method (#11450)

* rlp_derive: update syn & co

* rlp_derive: remove dummy_const

* rlp_derive: remove unused attirubutes

* rlp-derive: change authors

* rlp_derive: add rlp(default) attribute

* Revert "Revert "[Trace] Distinguish between `create` and `create2` (#11311)" (#11427)"

This reverts commit 5d4993b0f8.

* trace: backwards compatible call_type and creation_method

* trace: add rlp backward compatibility tests

* cleanup

* i know, i hate backwards compatibility too

* address review grumbles

* update CHANGELOG.md

* just to make sure we don't screw up this again (#11455)

* Update CHANGELOG.md

Co-authored-by: Talha Cross <47772477+soc1c@users.noreply.github.com>
Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: David <dvdplm@gmail.com>
Co-authored-by: Andronik Ordian <write@reusable.software>
Co-authored-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>
2020-02-05 17:10:36 +01:00
David
6885be06a4 [release] v2.7.1 (#11430)
* Revert "[Trace] Distinguish between `create` and `create2` (#11311)" (#11427)

This reverts commit 87e1080581.

* Bump version

* Changelog

* Update publish-docker.sh (#11428)

Add :latest tag to building stable releases

Co-authored-by: s3krit <pugh@s3kr.it>
2020-01-30 17:13:40 +01:00
s3krit
aa0a703e7c update hardcoded headers: mainnet and ropsten (#11414) (#11418)
mainnet: #9361409
ropsten: #7202817

Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
2020-01-28 15:09:32 +01:00
Martin Pugh
748eda2aac update CHANGELOG.md 2020-01-27 13:12:53 +01:00
varasev
fabec3e3f1 Update POA bootnodes (#11411) 2020-01-27 12:55:31 +01:00
EtherCore Contributor
d688869035 Update ProgPoW to 0.9.3 (#11407)
0.9.2 version is deprecated due to efficiency
2020-01-27 12:55:25 +01:00
EtherCore Contributor
90fccf9651 Add EtherCore support (#11402)
* support ethercore mainnet with basic token metrics and ProgPoW support, ecip1017, bomb defuse & istanbul
2020-01-27 12:54:34 +01:00
Akihito Nakano
1b3787040b json-tests: Fix compile error (#11384) 2020-01-24 13:51:16 +01:00
/raw PONG _GHMoaCXLT
c253e1f33e ethcore/res: fix ethereum classic chainspec blake2_f activation block num (#11391) 2020-01-24 13:51:11 +01:00
Denis S. Soldatov aka General-Beck
5923146210 Switching to stable-track (#11377)
* sccache "stop server" - > "show stats"

* remove testing and beta from update, cli, etc.

* Beta->Nigthly updater

* Beta->Nightly

* ->Nightly and fix

* updater ->Stable

* Testing->Nightly

* Update scripts/gitlab/test-linux.sh

Co-Authored-By: Denis Pisarev <denis.pisarev@parity.io>

* sccache "stop server" - > "show stats"

* remove testing and beta from update, cli, etc.

* Beta->Nigthly updater

* Beta->Nightly

* ->Nightly and fix

* updater ->Stable

* Testing->Nightly

* Update scripts/gitlab/test-linux.sh

Co-Authored-By: Denis Pisarev <denis.pisarev@parity.io>

* Update CHANGELOGs and version

* temporarily allow darwin and windows to be built on any branch

* fix check-benches job

* Revert "temporarily allow darwin and windows to be built on any branch"

This reverts commit 45c72f69e99cbe891f694e528a53eb3c3bd8f331.

* fix check-benches job

* Revert changing track from `nightly` to `stable`

* fix test: rpc_parity_upgrade_ready

* fix tests: rpc_parity_version_info, rpc_parity_releases_info

Co-authored-by: Denis Pisarev <denis.pisarev@parity.io>
Co-authored-by: s3krit <pugh@s3kr.it>
2020-01-22 17:35:05 +01:00
Martin Pugh
9e28241b29 Revert "temporarily allow darwin and windows to be built on any branch"
This reverts commit 46f995ceb2.
2020-01-20 14:30:11 +01:00
s3krit
f22326ef81 Update copyright notice 2020 (#11386)
* Update copyright noticed 2020

* Update copyright in two overlooked files
2020-01-17 14:27:51 +01:00
Martin Pugh
46f995ceb2 temporarily allow darwin and windows to be built on any branch 2020-01-16 13:00:10 +01:00
Martin Pugh
713fc9ff94 Update CHANGELOGs and version 2020-01-15 17:33:19 +01:00
Niklas Adolfsson
a9214081c0 miner: fix deprecation warning Error::description (#11380) 2020-01-14 13:54:43 +01:00
Wei Tang
d8a0d38229 Fix Aztlan hard fork issues (#11347)
* Fix Aztlan hard fork issues

* Fix mordor block number

* Fix classic block number

* Add missing precompiles

* Make EIP-1283's comments reflact the current spec

Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
2020-01-13 22:54:00 +01:00
Andreas Fackler
ea8e7fcf73 authority_round: Fix next_step_time_duration. (#11379)
It's supposed to find the first step at or after `time`.
To compute that step's timestamp, it needs to add the total length
of all steps since the previous transitions to the timestamp of the
previous transition, not to `time`.
2020-01-13 22:42:14 +01:00
Vladimir Komendantskiy
73354d8d93 Set the block gas limit to the value returned by a contract call (#10928)
* Block gas limit contract

Lower gas limit if TxPermission.limitBlockGas.

Call blockGasLimit before every block.

Make the block gas limit contract a separate config option.

Add `info` level logging of block gas limit switching

block-gas-limit subcrate and responses to review comments

simplified call_contract_before

moved block_gas_limit_contract_transitions to AuRa params

removed call_contract_before

Update and fix test_verify_block.

Remove some unused imports and functions.

* Move gas limit override check to verify_block_basic.

Co-authored-by: Andreas Fackler <afck@users.noreply.github.com>
2020-01-13 11:27:03 +01:00
Felix Leupold
87e1080581 [Trace] Distinguish between create and create2 (#11311)
* adding a CreateType to ActionParams

* rename calltype to action type

* comments & line lengths

* rebame ActionParams.call_type

* Making call/create type optional

* Moving strict create/call type into trace package instead of storing loosely typed action type

* fix build

* Deriving ActionType from address_scheme in ext.create

* trigger build

* more detailed comments

* Change actions_type to call in vmtests

* skipping serialization for Option::None and using TryFrom instead of maybe_new

* retrigger build

* trigger build
2020-01-13 11:10:24 +01:00
Andronik Ordian
e95bbe36cb fix cargo audit (#11378)
* Cargo.lock: cargo update -p http

* fetch: cargo upgrade hyper-rustls@0.18 --all
2020-01-10 17:43:49 +01:00
meowsbits
b6afc81d69 Fix esoteric test config variable (#11292)
* Fix esoteric test config variable

EIP155 canonically (on Ethereum mainnet, for which these test were developed)
happens simultaneously with EIP158/161 and other "Spurious Dragon" upgrades.

This test is intended to test the transition from the EIP158/161 era (Spurious Dragon)
to the Byzantium era, with Byzantium changes happening at 5.

* Add missing 'modexp' precompiled contract

modexp was introduced via EIP198 as a part of the Byzantium fork,
which this test should be testing against.
2020-01-10 15:12:32 +01:00
Demi Obenour
b8d9b6f826 Rip out the C and Java bindings (#11346)
* Remove the C and Java bindings

* update Cargo.lock

* [ci]: don't build removed `parity-clib`

* [ci]: fix grumbles

Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
2020-01-07 15:53:02 +00:00
Anton Gavrilov
424b38a8d7 Encapsulate access to the client for secret store (#11232)
* Move all client usages into trusted_client

* Move confirmed hash method to trusted client

* Tree route and logs encapsuluted

* Remove not used method for keys sharing

* NodeKeyPair renamed and moved to trusted client

* Use public key error in trusted client

* Move contract address definition into trusted client

* Block id and number types from ethcore wrapped

* Trusted client renamed to more general Blockchain

* Trusted client implementation moved to parity code

* Move node key pair under secret store feature as well

* Registar crate removed from deps

* Accounts feature removed from secret store

* Fix after merge

* Blockchain renamed to SecretStoreChain

* Module documentations added
2020-01-07 14:37:02 +01:00
David
5bd6b208af Forward-port #11356 (#11359) 2020-01-06 10:46:05 +03:00
Max Johansen
23a23e7a18 Fix error message typo (#11363) 2020-01-02 19:54:29 +01:00
Niklas Adolfsson
9d8e6ee4c9 [util/migration]: remove needless static bounds (#11348) 2019-12-30 14:43:38 -08:00
RJ
280894691e Replace stale boot nodes with latest list (#11351) 2019-12-30 08:01:00 -08:00
David
b9f9d11929 Update to latest kvdb-*: no default column, DBValue is Vec (#11312)
* Only use kvdb "column families"

This PR contains the changes necessary to use the `kvdb-*` crates from https://github.com/paritytech/parity-common/pull/278 (so a synchronized merge is required) which drops support for the old-style rocksdb "default" column to get a smaller and less complex API.

As it stands this PR is working correctly except for secret-store; we need to migrate it to use a new column family.

* Fix secretstore build

* Fix secretstore build: include ethkey when building with the "accounts" feature

* typos

* Restore state test commit

* Override all of parity-common from git

* Be precise about version requirement to migrate secretstore code

* Update ethcore/db/src/db.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Address review grumbles

* Review grumbles

* Cleanup

Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
2019-12-20 12:27:38 +01:00
Denis Pisarev
860ef19e95 we do not profit from incremental now (#11302) 2019-12-19 16:57:00 +01:00
joshua-mir
f8f22245ec update autoupdate fork blocks for nightly (#11308) 2019-12-19 13:05:04 +01:00
Cho
e14d68e559 Add Nat PMP method to P2P module (#11210)
* Add Nat PMP method to P2P module

* Add test fn

* Use closure

* print richer error messages.

* reformat long code line

* remove closures
2019-12-19 09:01:39 +01:00
Andreas Fackler
2b1d148ceb Add randomness contract support to AuthorityRound. (#10946)
* Add randomness contract support to Authority Round.

Changes have been cherry-picked from poanetwork's aura-pos branch.
Most of the work has been done by @mbr.

* Address review comments for randomness contract.

Co-Authored-By: David <dvdplm@gmail.com>

* Rename revealSecret to revealNumber

* Update Randomness contract bytecode

* Use H256, rename secret to random number.

* Use get_commit_and_cipher

* Clean up Miner::prepare_block.

* Remove is_reveal_phase call.

* Add more comments, require randomness contract map.

* Simplify run_randomness_phase

* Address review comments.

* Remove Client::transact_contract.
2019-12-17 11:34:14 +01:00
Talha Cross
f6909d8243 ethcore/res: activate ecip-1061 on kotti and mordor (#11338)
* ethcore/res: activate ecip-1061 on kotti and mordor

* ethcore/res: update bootnodes for mordor
2019-12-16 07:32:12 +01:00
Andronik Ordian
fd29926a21 tx-q: enable basic verification of local transactions (#11332)
* tx-q: basic verification of local transactions

* miner: basic test for local import

* miner: info log when rejecting local txn

* Hernandofmt

Co-Authored-By: Hernando Castano <HCastano@users.noreply.github.com>

* miner: assert in a test with the concrete error type

* tx-q: info! -> warn! on local tx rejection
2019-12-13 20:25:51 +01:00
Andronik Ordian
63535860bc remove null signatures (#11335)
* tx: clean up legacy eip-86 based null signature

* tx: add a test for null signature rejection

* tx: revert json txn changes

* fix evmbin bench build

* tx: put UNSIGNED_SENDER behind 'test-helpers' feature

* Revert "tx: put UNSIGNED_SENDER behind 'test-helpers' feature"

This reverts commit 1dde47831e4dc5098d064e6022ead43512c31efb.

* tx: add comment for null_sign

* even more cleanup

* Revert "even more cleanup"

This reverts commit be29f032415c53d4d40842f93f1fd1fb6f9cc6bd.
2019-12-13 18:12:22 +01:00
Talha Cross
6e76be7fad ethcore/res: activate agharta on classic 9573000 (#11331) 2019-12-13 12:07:29 +01:00
Andronik Ordian
ae74e8df78 [secretstore] migrate to version 4 (#11322)
* secret-store: migrate the db to version 4

* Fix secretstore build

* Fix secretstore build: include ethkey when building with the "accounts" feature

* fix build

* secret-store: actually use new column

* a bunch of fixes

* last nits

* Apply suggestions from code review

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* secret-store: move db stuff to secret-store as per Anton's request
2019-12-12 13:21:51 +01:00
Wei Tang
4fa78e0537 Enable EIP-2384 for ice age hard fork (#11281)
* Enable EIP-2384 for Istanbul hard fork

* Update bomb delay block number

* Update ropsten.json
2019-12-11 22:32:20 +01:00
Boqin Qin
f1f64930cf Fix atomicity violation in network-devp2p (#11277) 2019-12-10 07:46:32 +01:00
varasev
4c6b282bee Istanbul activation on xDai (#11299) 2019-12-09 14:36:16 +01:00
varasev
07e3a7f3d4 Istanbul activation on POA Core (#11298) 2019-12-09 14:36:06 +01:00
Seun LanLege
64295fde62 Adds support for ipc socket permissions (#11273)
* adds support for ipc socket permissions

* bumped jsonrpc to 14.0.5

* change chmod default to 660, use casting

* set 660 default for --ipc-chmod

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Update parity/cli/mod.rs

Co-Authored-By: David <dvdplm@gmail.com>

* represent octal value as string

* return error for invalid octal values

* fix tests

* check if supplied octal range is within 0 to 7777

* Apply suggestions from code review

Co-Authored-By: Andronik Ordian <write@reusable.software>

* temporary fix

* bump jsonrpc-ipc-server

* fix: update `Cargo.lock`
2019-12-06 16:39:56 +01:00
Lewis Belcher
a6350c65aa Add check for deserialising hex values over U256 limit (#11309)
* Add check for hex values over U256 limit

* Update test in account.rs

Update spec.json field to match test name.

* Update json/src/uint.rs

Co-Authored-By: David <dvdplm@gmail.com>

* Add test for expected deserialisation error

* Update json/src/uint.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Update json/src/uint.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Remove superfluous serialisation test

The test `uint_deserialization_error_for_hex_too_large` sufficiently
covers the need for this test.
2019-12-06 14:07:44 +01:00
Andronik Ordian
36c917eb7a validate-chainspecs: check istanbul eips are in the foundation spec (#11305)
* validate-chainspecs: check istanbul eips are in foundation spec

* foundation: specify 1283 disable/reenable transitions
2019-12-06 13:12:08 +01:00
Niklas Adolfsson
cfe57633fa [chainspec]: add eip1344_transition for istanbul (#11301) 2019-12-05 12:58:01 +01:00
Seun LanLege
80a83c95d3 only add transactions to signing-queue if it is enabled (#11272)
* only add transactions to signing-queue if it is enabled

* Update rpc/src/v1/helpers/errors.rs

Co-Authored-By: David <dvdplm@gmail.com>

* use errors::codes::ACCOUNT_LOCKED

* bail early if account isn't unlocked

* use errors::signing

* Update rpc/src/v1/helpers/errors.rs

* Update rpc/src/v1/helpers/errors.rs

* test

* adds cli flag to enable signing queue.

* use helper method siginig_queue_disabled instead of accounts::SignError

* fix typo, use raw i64

* fixed tests
2019-12-05 09:38:14 +01:00
David
f6c3d4c695 Use upstream rocksdb (#11248)
* Use upstream rocksdb

…by way of https://github.com/paritytech/parity-common/pull/257 by @ordian.

* Hint at how `parity db reset` works in the error message

* migration-rocksdb: fix build

* Cargo.toml: use git dependency instead of path

* update to latest kvdb-rocksdb

* fix tests

* saner default for light client

* rename open_db to open_db_light

* update to latest kvdb-rocksdb

* moar update to latest kvdb-rocksdb

* even moar update to latest kvdb-rocksdb

* use kvdb-rocksdb from crates.io

* Update parity/db/rocksdb/helpers.rs

* add docs to memory_budget division
2019-12-03 16:59:11 +01:00
Anton Gavrilov
2895e3b2ab Treat only blocks in queue as synced (#11264) 2019-12-03 15:59:15 +01:00
Sebastian Dechant
f2f4217e3c add support for evan.network chains (#11289)
* add support for evan.network chains

* fix chainspec parsing errror

* add missing core param

* missing colon
2019-12-03 15:00:29 +01:00
David
4c3be46f93 Add benchmarks and tests for RlpNodeCodec decoding (#11287) 2019-12-03 12:30:07 +01:00
Andronik Ordian
71f4f61146 upgrade vergen to 3.0 (#11293)
* version: upgrade vergen to 3.0

* version: use vergen for target triple
2019-12-02 22:18:44 +01:00
Denis Pisarev
a016dc5c6c interruptible test and build jobs (#11294) 2019-12-02 18:16:14 +01:00
varasev
cf2cb58e1d Istanbul HF on POA Sokol (#11282) 2019-11-25 23:10:55 +01:00
Niklas Adolfsson
dcb69ba353 [ethcore]: apply filter when PendingSet::AlwaysQueue in ready_transactions_filtered (#11227)
* [ethcore]: apply filter when `from_queue`

In `ready_transactions_filtered` the filter were never applied when
the options PendingSet::AlwaysQueue` was configured which this fixes

It also adds a two tests for it

* [ethcore test-helpers]: stray printlns

* docs(ethcore filter options): more generic desc

* tests(ethcore miner): simply filter tests

* [ethcore filter_options]: fix nits

* doc: nit

Co-Authored-By: David <dvdplm@gmail.com>

* doc: nit

Co-Authored-By: David <dvdplm@gmail.com>

* doc: nit

Co-Authored-By: David <dvdplm@gmail.com>

* doc: nit

Co-Authored-By: David <dvdplm@gmail.com>

* doc: nit

Co-Authored-By: David <dvdplm@gmail.com>

* doc(miner filter): simplify documentation

* [rpc]: make tests compile
2019-11-25 12:03:50 +01:00
deke997
1b0948d9d1 Update lib.rs (#11286)
typo in stratum trace: pusing to pushing
2019-11-25 11:45:31 +01:00
David
6e34ee6837 Don't prune ancient state when instantiating a Client (#11270) 2019-11-22 12:18:24 +01:00
Marek Kotewicz
1986c4ee79 fixed verify_uncles error type (#11276)
* fixed verify_uncles error type

* cleanup and document fn verify_uncles bounds checking

* find_uncle_headers and find_uncle_hashes take u64 instead of u32 as an input param

* Update ethcore/verification/src/verification.rs

Co-Authored-By: David <dvdplm@gmail.com>
2019-11-22 10:26:50 +01:00
Andronik Ordian
df1c5ac616 ethcore: fix rlp deprecation warnings (#11280) 2019-11-21 17:23:49 +01:00
Jim Posen
c7219aae30 Upgrade trie-db to 0.16.0. (#11274)
* Upgrade trie-db to 0.16.0.

* Respond to review comments.
2019-11-21 11:08:49 +01:00
David
ee01612768 Clarify what first_block None means (#11269) 2019-11-20 11:26:47 +08:00
Marek Kotewicz
e0091c672a removed redundant VMType enum with one variant (#11266) 2019-11-20 11:11:36 +08:00
David
82c3265858 Ensure jsonrpc threading settings are sane (#11267)
* Ensure jsonrpc threading settings are sane

Starting with `jsonrpc` v14, the "server threads" setting is more important than before and the current default of 1 means the https server is effectively single-threaded. This PR proposes a new default of 4 (and ensures that crazy settings like e.g. `0` are bumped to at least `1`).

Also included: some docs, tests and cosmetics.

* Update parity/rpc.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update parity/rpc.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Remove (i.e. deprecate) `--jsonrpc-threads` command line option

* Call numbers NUM

* Don't show a default for --jsonrpc-threads (deprecated)

* Show deprecation warning when using `--jsonrpc-threads` or `processing_threads`

* Update parity/deprecated.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Fix test

* Fix tests for real
2019-11-18 19:40:48 +01:00
David
93f700d961 Return Ok(None) when the registrar contract returns empty slice (#11257) 2019-11-15 14:27:34 +01:00
David
eb565a7e2b Add a benchmark for snapshot::account::to_fat_rlps() (#11185)
* Add a benchmark for snapshot::account::to_fat_rlps()

`to_fat_rlps()` is a hot call during snapshots. I don't think it has a perf problem per se, but better to have benchmark for it.

The data used is a piece of Ropsten data sized to the ~95% percentile of account size on that network.

* Benchmark with more chunks, including mainnet data

* whitespace

* Move `used_code` inside the benchmark iteration

* Revert "Move `used_code` inside the benchmark iteration"

This reverts commit cff33ab30acbd1c009e745f646f1cc655ee01d8c.
2019-11-15 12:27:24 +01:00
David
e194a2c6e3 Fix misc compile warnings (#11258) 2019-11-14 00:01:21 +01:00
Marek Kotewicz
db1ea1dcd8 simplify verification (#11249)
* simplify verifier, remove NoopVerifier

* simplify verifier by removing Verifier trait and its only implementation

* remove unused imports

* fixed verification test failing to compile
2019-11-12 15:05:49 +01:00
joshua-mir
9d55f0b4ab update ropsten forkCanonHash, forkBlock (#11247)
value taken from https://ropsten.etherscan.io/block/6485847
2019-11-11 12:38:32 +01:00
Seun LanLege
887aa62fdb Make InstantSeal Instant again (#11186)
* Make InstantSeal Instant again

* update_sealing if there are transactions in pool after impoerting a block, some line formatting

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* InstantSeal specific behaviour

* introduce engine.should_reseal_on_update, remove InstantSealService

* remove unused code

* add force param to update_sealing

* better docc

* even better docs

* revert code changes, doc corrections, sort dep

* code optimization

* fix test

* fix bench
2019-11-10 11:41:31 +01:00
Thibaut Sardan
8adde605e9 ropsten #6631425 foundation #8798209 (#11201) 2019-11-05 12:15:24 +01:00
phahulin
5fdf6be798 Update list of bootnodes for xDai chain (#11236)
Reference PR in POA repository: https://github.com/poanetwork/poa-chain-spec/pull/127
2019-11-05 12:07:52 +01:00
Talha Cross
1b4d23fd20 ethcore/res: add mordor testnet configuration (#11200)
* ethcore/res: add mordor testnet configuration

* ethcore/spec: add mordor testnet configuration

* parity/cli: add mordor testnet configuration

* parity/config: fix tests

* ethcore/res: update mordor spec with agharta hardfork block 301243

*  ethcore/res: update kotti with agharta block 1705549

* ethcore/res: update morden with agharta block 5000381

* ethcore/res: multiple prices and activations for mordor testnet

* fix mordor spec json

* fix mordor spec json
2019-11-02 12:26:38 +01:00
Niklas Adolfsson
43dc9af03b [chain specs]: activate Istanbul on mainnet (#11228)
* [chains spec]: activate istanbul at mainnet

* Activate `Block >= 9,069,000` on the Ethereum mainnet
* Enable Blake2 compression function `F` precompile

* [chain specs]: add comments for EIP1108 activation

* [chainspec mainnet]: enable Istanbul transitions

* [chainspec mainnet]: simply configuration
2019-11-01 20:27:14 +01:00
Niklas Adolfsson
13729a0f7f [builtin]: support multiple prices and activations in chain spec (#11039)
* [builtin]: impl new builtin type

Have an enum to deserialize either a builtin of a single price or several prices

* [builtin]: style cleanup

* [builtin]: fix tests

* [builtin]: replace boxing with wrapper enum

* cleanup

* fix: make it backward compatible with old builtin

* fix: update chain specs

* fix: revert use of `type alias` on enum

The CI doesn't use the latest rust.

This commit reverts that change

* fix: builtin tests

* fix: revert use of `type alias` on enum

* [basic-authority]: update test-chainspec

* fix failing tests

* [builtin]: multi-prices add `info field`

It might be hard to read chain specs with several activations points.
This commit introduces a `info` field which may be used to write some
information about the current activation such as:

`Istanbul hardfork EIP-1108` or something similar.

* fix: bad rebase

Co-Authored-By: David <dvdplm@gmail.com>

* fix(grumbles): make it backward compatible

* grumbles: resolve `NOTE`

* revert chain specs changes

* rename test

Co-Authored-By: David <dvdplm@gmail.com>

* [builtin docs]: price -> Fixed price

Co-Authored-By: Andronik Ordian <write@reusable.software>

* [json]: address naming grumbles

InnerPricing -> PricingInner
PriceWithActivationAt -> PricingAt

* docs: revert changes for `AltBn128ConstOperations`

* [json]: usize -> u64

Use explicit types to cope with platform dependent issues for `usize`

* grumble: simplify `spec_backward_compability.json`

* docs: add issue link to `TODO`

* [builtin]: replace `match` with `map`

* [builtin]: add deprecation message `eip1108` params

* nits

* [json spec tests]: fix json indentation

* [json docs]: fix typos

* [json]: `compability layer` + deser to BTreeMap

Previously we had to match `Pricing::Single` and `PricingMulti` which this fixes.
It does by introducing a compability layer and into() implemenentation.

In addition, I switched the deserialization to `BTreeMap` instead of `Vec`.
That changes the format of the chain spec again

* [json]: rename `BuiltinCombat` -> `BuiltinCompat`

* Update ethcore/builtin/src/lib.rs

Co-Authored-By: David <dvdplm@gmail.com>

* [json builtin]: improve docs

Co-Authored-By: David <dvdplm@gmail.com>

* [json builtin]: improve docs

Co-Authored-By: David <dvdplm@gmail.com>

* chore(builtin): sort dependencies

* [json builtin]: deprecate `eip1108` params

* [machine]: add bench for calling builtin contract

* [machine]: reduce calls to `Builtin::is_active`

* [builtin]: fix nits

* [json]: revert breakage of chain specs

* [json builtin]: remove `eip1108` params

* [chain specs]: update to new format

* [machine]: revert changes

* [devp2p]: revert change

* [builtin]: doc nits
2019-10-31 17:09:08 +01:00
Anton Gavrilov
80754c3426 Insert explicit warning into the panic hook (#11225) 2019-10-31 16:17:12 +01:00
David
8c2199dd2a Snapshot restoration overhaul (#11219)
* Comments and todos
Use `snapshot_sync` as logging target

* fix compilation

* More todos, more logs

* Fix picking snapshot peer: prefer the one with the highest block number
More docs, comments, todos

* Adjust WAIT_PEERS_TIMEOUT to be a multiple of MAINTAIN_SYNC_TIMER to try to fix snapshot startup problems
Docs, todos, comments

* Tabs

* Formatting

* Don't build new rlp::EMPTY_LIST_RLP instances

* Dial down debug logging

* Don't warn about missing hashes in the manifest: it's normal
Log client version on peer connect

* Cleanup

* Do not skip snapshots further away than 30k block from the highest block seen

Currently we look for peers that seed snapshots that are close to the highest block seen on the network (where "close" means withing 30k blocks). When a node starts up we wait for some time (5sec, increased here to 10sec) to let peers connect and if we have found a suitable peer to sync a snapshot from at the end of that delay, we start the download; if none is found and --warp-barrier is used we stall, otherwise we start a slow-sync.
When looking for a suitable snapshot, we use the highest block seen on the network to check if a peer has a snapshot that is within 30k blocks of that highest block number. This means that in a situation where all available snapshots are older than that, we will often fail to start a snapshot at all. What's worse is that the longer we delay starting a snapshot sync (to let more peers connect, in the hope of finding a good snapshot), the more likely we are to have seen a high block and thus the more likely we become to accept a snapshot.
This commit removes this comparison with the highest blocknumber criteria entirely and picks the best snapshot we find in 10sec.

* lockfile

* Add a `ChunkType::Dupe` variant so that we do not disconnect a peer if they happen to send us a duplicate chunk (just ignore the chunk and keep going)
Resolve some documentation todos, add more

* tweak log message

* Don't warp sync twice
Check if our own block is beyond the given warp barrier (can happen after we've completed a warp sync but are not quite yet synced up to the tip) and if so, don't sync.
More docs, resolve todos.
Dial down some `sync` debug level logging to trace

* Avoid iterating over all snapshot block/state hashes to find the next work item

Use a HashSet instead of a Vec and remove items from the set as chunks are processed. Calculate and store the total number of chunks in the `Snapshot`  struct instead of counting pending chunks each time.

* Address review grumbles

* Log correct number of bytes written to disk

* Revert ChunkType::Dup change

* whitespace grumble

* Cleanup debugging code

* Fix docs

* Fix import and a typo

* Fix test impl

* Use `indexmap::IndexSet` to ensure chunk hashes are accessed in order

* Revert increased SNAPSHOT_MANIFEST_TIMEOUT: 5sec should be enough
2019-10-31 16:07:21 +01:00
Louis Pérez
6b17e321df Fix docker centos build (#11226)
- Update shell script to build docker centos
  image with the new path.
  - Update REAMDE.md with build instructions.

Closes [#11224](https://github.com/paritytech/parity-ethereum/issues/11224)
2019-10-31 14:59:51 +01:00
Denis Pisarev
f743829759 retry on gitlab system failures (#11222) 2019-10-30 19:16:18 +01:00
Jonathan Brown
29c364be43 Update bootnodes. (#11203) 2019-10-29 12:43:46 +01:00
Rakan Alhneiti
6993ec9531 Use provided usd-per-eth value if an endpoint is specified (#11209)
* Fix `invalid transaction price` error message

* Setup Calibrated GasPriceConfig when usd-per-eth is an endpoint

The change will try to check if the specified value is an endpoint.
If the value of `auto` is specified, the default endpoint URL will be used
otherwise, the user-provided value will be taken as-is for an endpoint.

* Use if-let and check for usd-per-eth arg:

1. auto = use etherscan
2. value = use fixed pricer
3. endpoint = use the provided endpoint as-is

* Fix typo in to_pricce error message

* Correct whitespace indentation

* Use arg_usd_per_eth directly
2019-10-29 12:18:30 +01:00
David
0d3423cbe0 Use a lock instead of atomics for snapshot Progress (#11197)
* WIP. Typos and logging.

* Format todos

* Pause pruning while a snapshot is under way
Logs, docs and todos

* Allocate memory for the full chunk

* Name snapshotting threads

* Ensure `taking_snapshot` is set to false whenever and however `take_snapshot`returns
Rename `take_at` to `request_snapshot_at`
Cleanup

* Let "in_progress" deletion fail
Fix tests

* Just use an atomic

* Review grumbles

* Finish the sentence

* Resolve a few todos and clarify comments.

* Calculate progress rate since last update

* Lockfile

* Fix tests

* typo

* Reinstate default snapshotting frequency
Cut down on the logging noise

* Use a lock instead of atomics for snapshot Progress

* Update ethcore/types/src/snapshot.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Avoid truncating cast
Cleanup
2019-10-28 18:24:45 +01:00
Niklas Adolfsson
293e06e0f4 [informant]: MillisecondDuration -> as_millis() (#11211)
* [informant]: `MillisecondDuration` -> `as_millis()`

This commit removes the trait `MillisecondDuration` and
replaces it with `Duration::as_millis` instead

* [grumble]: extract `elapsed()` to variable
2019-10-28 15:03:28 +01:00
Vladimir Komendantskiy
e0e79fdee0 Step duration map configuration parameter ported from the POA Network fork (#10902)
* step duration map configuration parameter ported from POA Network fork

* step duration map refactoring

* added a test of step duration change

* refactoring of vector search; return Err instead of panicking

* removed dead code and the Config engine error variant

* doc correction

* converted triples to struct StepDurationInfo
2019-10-28 14:39:18 +01:00
David
2c97bcc1a4 Upgrade jsonrpc to latest (#11206) 2019-10-26 11:26:04 +02:00
Niklas Adolfsson
c4ca84cdf3 [export hardcoded sync]: use debug for H256 (#11204)
Fixes #11202

The `Display` implementation for `SpecHardcodedSync` used the `Display` implementation of
`ethereum_types::H256` which doesn't show the full hash which this fixes.
2019-10-25 18:12:14 +02:00
David
ffeaee778c Pause pruning while snapshotting (#11178)
* WIP. Typos and logging.

* Format todos

* Pause pruning while a snapshot is under way
Logs, docs and todos

* Allocate memory for the full chunk

* Name snapshotting threads

* Ensure `taking_snapshot` is set to false whenever and however `take_snapshot`returns
Rename `take_at` to `request_snapshot_at`
Cleanup

* Let "in_progress" deletion fail
Fix tests

* Just use an atomic

* Review grumbles

* Finish the sentence

* Resolve a few todos and clarify comments.

* Calculate progress rate since last update

* Lockfile

* Fix tests

* typo

* Reinstate default snapshotting frequency
Cut down on the logging noise

* address grumble

* Log memory use with `journal_size()` and explain why.
2019-10-24 16:46:32 +02:00
Fabio Lama
acf7c48d7e Type annotation for next_key() matching of json filter options (#11192)
* type annotation for next_key matching of json filter options

* rpc tests for pending transactions

* mention git submodules in the readme
2019-10-23 14:20:47 +02:00
Anton Gavrilov
834585d61b Crypto primitives removed from ethkey (#11174)
* Crypto utils removed from ethkey

* Fix ethkey lib

* Switch ethsore to new crypto

* Accounts crate fixed

* Secret store crate switched to new crypto

* Ethcore builtin fixed

* Accounts crate fixed

* Ethcore crate fixed

* Util network fixed

* Util network-devp2p fixed

* Private tx fixed

* Ethcore sync fixed

* Secret store fixed

* Rpc fixed

* Parity fixed

* Ethkey cli fixed

* Local store fixed

* Ethcore blockchain fixed

* Cargo.lock pushed; doc comment added for reversed nonce

* Ethstore tests fixed

* Ethstore cli fixed

* Miner fixed

* Snapshot tests are fixed

* Single brackets removed

* Machine fixed

* Verification fixed

* Executive state fixed

* More single brackets removed

* Update version of parity-crypto

* Use published version 0.4.2 of parity-crypto

* New test in tx_filter fixed
2019-10-23 13:03:46 +02:00
Tino Breddin
81ca599f2a Made ecrecover implementation trait public (#11188)
* Made ecrecover Implementation trait public

* Make all builtin contract types public

This ensure the API is consistent in terms of visibility.
2019-10-22 22:03:52 +02:00
Andreas Fackler
20bd1fa789 Remove unused macro_use. (#11191) 2019-10-22 15:59:58 +02:00
Niklas Adolfsson
6960d35abb [dependencies]: jsonrpc 14.0.1 (#11183)
Closing #11169
2019-10-19 14:14:25 +02:00
Niklas Adolfsson
c8b4373e13 [receipt]: add sender & receiver to RichReceipts (#11179)
* [receipts]: add `to` & `from` to `RichReceipts`

* [rpc]: add test for `pending_receipt`

* docs(common_types/receipt): add note Option field
2019-10-18 18:12:02 +02:00
Niklas Adolfsson
2d2513b35a [dependencies] bump rand 0.7 (#11022)
* network-devp2p: bump rand `0.7`

* updater: bump rand `0.7`

* hash-fetch: bump rand `0.7`

* ethcore-sync: bump rand `0.7`

* rpc: dont work yet

* [private-tx] remove unused rand

* [ethcore-snapshot] bump rand 0.7

* [engine clique]: bump rand 0.7

* [engine authority-round]: remove rand

* [ethcore-blockchain]: bump rand 0.7

* [ethcore]: bump rand 0.7

* [ethcore-light]: bump rand 0.7

* [ethstore]: bump rand 0.7

* Fix for rand usage in rpc

* [rpc]: fix test build

* [ethcore-sync]: fix test build

* [snapshot tests]: rand 0.7

* [ethkey]: bump rand 0.7

* [rpc]: resolve TODO incompatible `rand versions`

* [ethkey] use `rust-secp256k1` master branch

* fix(bad merge): ethcoore-light remove itertools

* [rpc tests]: revert rpc test changes in #11139

`#11139` makes use a different `RNG/seed`, not `H64::random_using(&mut self.rand)`

This commit reverts the changed tests (the generated id by `Subscribers::next_id`)

* [ethkey/random]: resolve introduced `TODO`
2019-10-18 15:12:16 +02:00
Andronik Ordian
3696f68626 [ethcore/builtin]: do not panic in blake2pricer on short input (#11180)
* [ethcore/builtin]: do not panic in blake2pricer on short input

* [ethcore/builtin]: add a test for blake2pricer
2019-10-18 15:10:00 +02:00
Andreas Fackler
ff697b64b3 TxPermissions ver 3: gas price & data (#11170) 2019-10-18 12:12:06 +02:00
Niklas Adolfsson
9c8b7c23d1 [ethash] chainspec validate ecip1017EraRounds non-zero (#11123)
* [ethash]: validate `ecip1017EraRounds` non-zero

When `ecip1017EraRounds` ethash will divide by zero.

This commit ensures that the chainspec deserialization fails and
gives a better error message.

* [ecip1017_eras_block_reward]: document behaviour

* nit

* docs(ethash ecip1071): resolve `TODO`
2019-10-17 14:02:41 +02:00
Boqin Qin
f99819d326 util Host: fix a double Read Lock bug in fn Host::session_readable() (#11175) 2019-10-17 10:59:37 +02:00
Boqin Qin
6b57429d72 ethcore client: fix a double Read Lock bug in fn Client::logs() (#11172) 2019-10-16 12:03:48 +02:00
Andreas Fackler
f59ed47b1b Aura: Report malice on sibling blocks from the same validator (#11160)
* Aura: Report malice on sibling blocks from the same validator

This was originally written by @vkomenda, then squashed for
easier rebasing on master. Cleanup of `received_step_hashes`
was moved to `verify_block_family`, since `on_prepare_block`
does not exist on master, and a unit test was added.
Original commit messages:

added the map of received block header hashes

do not return an error and remove older received block records

optimised older record removal

block hash comparison optimisation and the weak client ref fix

SIBLING_MALICE_DETECTION_PERIOD constant

review comments

using step numbers instead of block numbers

* Add docs; use map_or.

* Update step hash record comment.

Co-Authored-By: David <dvdplm@gmail.com>

* Remove hash records after 2 rounds instead of 100 steps.
2019-10-14 12:56:38 +02:00
David
aefa8d5f59 Change how RPCs eth_call and eth_estimateGas handle "Pending" (#11127)
* Change how RPCs eth_call and eth_estimateGas handle "Pending"

Before this PR we would return a rather confusing error when calling `eth_call` and `eth_estimateGas` with `"Pending"`, e.g.:

```
{"jsonrpc":"2.0","error":{"code":-32000,"message":"This request is not supported because your node is running with state pruning. Run with --pruning=archive."},"id":"e237678f6648ed12ff05a74933d06d17"}
```

In reality what is going on is that users often use `"Pending"` when they really mean `"Latest"` (e.g. MyCrypto…) and when the block in question is not actually pending. This changes our behaviour for these two RPC calls to fall back to `"Latest"` when the query with `"Pending"` fails.
Note that we already behave this way for many other RPCs:

	- eth_call (after this PR)
	- eth_estimateGas (after this PR)
	- eth_getBalance
	- eth_getCode
	- eth_getStorageAt

Closes https://github.com/paritytech/parity-ethereum/issues/10096

* Fetch jsonrpc from git

* No real need to wait for new jsonrpc

* Add tests for calling eth_call/eth_estimateGas with "Pending"

* Fix a todo, add another

* Change client.latest_state to return the best header as well so we avoid potential data races and do less work

* Impl review suggestions

* Update rpc/src/v1/impls/eth.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Review grumbles

* update docs
2019-10-11 15:54:36 +02:00
David
f3015ce0c6 Cleanup stratum a bit (#11161)
* Cleanup stratum a bit

Salvage some code from https://github.com/paritytech/parity-ethereum/pull/10884 + some cleanup and typos.

* HashSet::new does not allocate before first insert

* Remove unused method push_work()
2019-10-11 11:52:09 +02:00
Niklas Adolfsson
4f25d43516 [keccak-hasher]: rust2018 (#11163) 2019-10-10 19:43:33 +02:00
David
9d313e31e6 Upgrade to jsonrpc v14 (#11151)
* Upgrade to jsonrpc v14

Contains https://github.com/paritytech/jsonrpc/pull/495 with good bugfixes to resource usage.

* Bump tokio & futures.

* Bump even further.

* Upgrade tokio to 0.1.22

* Partially revert "Bump tokio & futures."

This reverts commit 100907eb91907aa124d856d52374637256118e86.
2019-10-10 15:56:22 +01:00
Svyatoslav Nikolsky
330cdc1a4d Secret store: fix Instant::now() related race in net_keep_alive (#11155)
* try Instant fix in SS

* proper fix + add comment

* fix compilation
2019-10-10 11:19:23 +03:00
Vladimir Komendantskiy
93fbbb9aaf RPC method for clearing the engine signer (#10920)
* RPC method parity_clearEngineSigner

Add RPC method parity_clearEngineSigner
Fixes https://github.com/poanetwork/parity-ethereum/issues/113

* corrected the return type of clear_author

* review comment responses and a rebase fix

* removed a spurrious warning

* moved clear_signer functionality to set_signer

* Merge clear_author into MinerService::set_author.

* Add trace logs to Clique::set_signer.

* Clique: Don't lock signer multiple times.
2019-10-09 14:42:51 +02:00
Andy Weiss
a404dd5415 Use TryFrom instead of From+panic for Builtin (#11140)
* Use TryFrom instead of From+panic for Builtin

* fix tests

* change expect text to be more descriptive

* fix formatting
2019-10-09 14:42:03 +02:00
Denis S. Soldatov aka General-Beck
11c447dfbe Fix sccache statistics (#11145)
* Fix sccache statictics

* warning update for non x86_64 architectures

* sccache -s -> sccache --show-stats
2019-10-08 21:58:34 +03:00
Anton Gavrilov
f48780c29b Update ethereum types to 0.8.0 version (#11139)
* Ethereum types updated to 0.8 version

* Fix for rand usage in rpc

* Cargo lock fixed after rebase

* TODO added
2019-10-08 14:18:44 +02:00
Niklas Adolfsson
35513b14de [json]: add docs to hardfork specification (#11138)
* [json]: add docs to `hardfork specification`

* address grumbles
2019-10-07 15:25:03 +02:00
Toby Dimmick
63c7ae9a89 ServiceTransactionChecker::refresh_cache: allow registrar unavailable (#11126)
Return `Ok(false)` instead of `Err(...)`. Fixes regression from PR #11110.
2019-10-07 12:04:41 +02:00
David
b31bff5ce2 Fix some random typos, formatting/whitespace (#11128)
* Fix some random typos, formatting/whitespace

* Remove unecessary lifetime annotations

* Revert "Remove unecessary lifetime annotations"

This reverts commit 2357ccc3743a234e3181a79aff825370461543bf.
2019-10-04 19:54:28 +02:00
Juan Aguilar
4fd1ec643f Refactor parity_listStorageKeys with count parameter optional (#11124) 2019-10-04 14:38:57 +02:00
Patrick Tescher
79aeb95272 Make EIP712Domain Fields Optional (#11103)
According to
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-
of-domainseparator “Protocol designers only need to include the fields
that make sense for their signing domain.”
2019-10-03 22:20:20 +02:00
David
ca329078f5 EIP-712: bump version in prep for publishing (#11106)
* version 0.1.1

* lock file
2019-10-03 19:34:06 +02:00
Juan Aguilar
acc5bdfc35 move StateResult to common-types (#11121) 2019-10-03 16:52:29 +02:00
Toby Dimmick
79a17dedd0 Deduplicate registrar contract & calling logic (#11110)
* Rename RegistryInfo -> RegistryInfoDeprecated

* Add BlockId parameter to Registrar::get_address and RegistrarClient::call_contract

* Remove RegistrarClient::Call (use async for now); add RegistrarClient::get_address

* Remove Registrar type in favour of naked trait

* Use CallContract trait bound instead of separate call_contract method

* Make RegistrarClient::get_address and URLHint::resolve synchronous

* RegistrarClient::get_address: return check if address is zero

* Modify RegistryInfo::registry_address to take &str

* return Result from RegistryInfo::registry_address

* Replace RegistryInfo with RegistrarClient

- Modifed RegistrarClient::registrar_address to return Option
- Removed BlockChainClient::registrar_address

* Fix other build configs

* Fix unit test builds

* Remove local RegistrarClient type from run::execute_impl

* Remove registrar.json from ethcore

* Formatting/line breaks

* Update RegistrarClient docs, remove explicit lifetime

* Weak ref to ethcore client from hash fetch client

* Fix unit tests
2019-10-03 15:15:25 +02:00
Juan Aguilar
0c0f965354 Refactor return type of BlockChainClient::code #7098 (#11102)
* fix: refactor return type of `BlockChainClient::code`

* Add TODO move to `common-types`

Co-Authored-By: David <dvdplm@gmail.com>
2019-10-03 13:21:26 +02:00
Denis S. Soldatov aka General-Beck
0bd2979c04 Switching sccache from local to Redis (#10971)
* Switching cache from local to Radis

* sccache -s won't work. All the images are taken from own registry

* new images addresses

* statisticss after stop sccache server
sccache CC&CXX
2019-10-02 23:01:20 +03:00
Seun LanLege
f24bff5998 SIMD Implementation for EIP-152 (#11056)
* simd implementation

* adds benchmarks

* Update util/EIP-152/src/avx.rs

Co-Authored-By: David <dvdplm@gmail.com>

* enable avx 😅

* better benchmark, docs

* rename avx to avx2, compile on android

* fix android again

* remove ifunc, code formatting

* license

* nits

* docs, nits

* fix test
2019-10-02 14:32:21 +01:00
Juan Aguilar
ad633de6d9 Fix deprecated trait objects without an explicit dyn (#11112) 2019-10-02 10:55:31 +02:00
Andronik Ordian
d243b15ae0 [spec] fix rinkeby spec (#11108) 2019-10-02 10:52:25 +02:00
David
fcd042a487 Update to latest jsonrpc (#11111)
* Update to latest jsonrpc

* Fix percent_encoding not re-exported from url anymore
2019-10-02 10:25:51 +02:00
Denis Pisarev
1b1b44bb20 use images from our registry (#11105) 2019-10-01 13:58:12 +02:00
Seun LanLege
8471b91002 Correct EIP-712 encoding (#11092)
* support encoding custom array types as fields

* new line

* removed expect

* Update util/EIP-712/src/encode.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* bump lunarity

* update cargo lock

* nits

* nits
2019-09-30 22:16:30 +01:00
Andronik Ordian
4979c62bb5 [CI] check evmbin build (#11096) 2019-09-27 23:29:25 +02:00
David
2b8b8851ab Update kvdb, kvdb-rocksdb and h2 (#11091)
* Update a few dependencies

Updates two dependencies: `kvdb-rocksdb` and `h2`. Brings in `parking_lot 0.9` which is unintended but possibly fine.

* Bump parking_lot to 0.9
Bump kvdb-memorydb to 0.2 (from git atm)

* New kvdb-memorydb is not breaking

* Remove [patch]
2019-09-27 23:29:14 +02:00
David Forstenlechner
7c5fd042f3 [client]: Fix for incorrectly dropped consensus messages (#11082) (#11086)
Fixes a race condition causing the currently_queued counter to underflow and consensus messages getting dropped incorrectly as a consequence.
2019-09-25 19:45:49 +02:00
David
d9201aa6f2 Update JSON tests to d4f86ecf4aa7c (#11054)
* new ethereum consensus tests, #10908

* Update JSON tests to 725dbc73a

This PR reverts the controversial changes of the previous PR and skips the failing tests.

Maybe I misunderstand the suggested workaround of putting the fix under `#[cfg(test)]` but it seems odd to run different code in production than we run in tests. Instead here I suggest we skip the failing tests with the argument that we do not wish to fix this issue (at least not at this time) because it does not affect us. If I am wrong, and I likely am, I look forward to hearing why and what a better approach to updating the state tests is.

Branched off https://github.com/paritytech/parity-ethereum/pull/10923

ref #10908

* Update json test commit to 1dc9d20e97165708f7db0bbf2d1a87a6b4285827

* Fail with error message

* Handle missing r, s, v params in json tests
Light cleanup of json test runner

* Include the path to the test file

* Handle new `postState` format: string or map
Sort out tests
Missing docs

* WIP

* Include test-helpers from ethjson

* Sort out new paths

* Remove dead code

* Fix warnings stemming from code called only from macros
Skip failing tests in stRevert/ and stTransactionTest/ (too course a filter!)
Docs and light touch refactorings for readability

* Skip all failing tests

* Document the single-test-skipping madness

* Update tests to latest commit on the `develop` branch

* Rename test skipping types to reflect actual purpose

* Switch to skipping individual tests in currents.json
Add some logging to help debug skipping

* Fix rpc test by curve fitting to new json test source file

* Add refs to all issues for fixing failing&skipped json tests

* Sort out the need for Clone for tests

* [json-tests] populate state from genesis pod state (#11083)

* [json-tests] populate state from genesis pod state

* [json-tests] #11075 is resolved as well

* [json-tests] #11076 hopefully too

* [json-tests] #11077 🎉

* [json-tests] fix trailing comma

* Update ethcore/src/json_tests/chain.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Add issue numbers to TODOs

* Apply @ordians fix for wrong state_root

* Warn on invalid RLP

* Remove the `ci-skip-tests` feature
2019-09-25 10:02:04 +02:00
Cho
7f5ac8ba7a fix(network): typo (#11088) 2019-09-25 09:54:47 +02:00
Andronik Ordian
fc22c58408 [ethash] remove manual unrolling (#11069)
* [ethash] remove unroll in calculate_dag_item

* [ethash] add keccak bench

* [ethash] remove unroll! completely

* [ethash] specify required-features for benches

* [ethcore/verification] specify required-features for benches

* [CI] simplify cargo-check-benches step
2019-09-24 11:45:28 +02:00
Talha Cross
2627288311 ethcore/res: activate Istanbul on Ropsten, Görli, Rinkeby, Kovan (#11068)
* ethcore/res: activate Istanbul on Ropsten block 6485846

* ethcore/res: activate Istanbul on Goerli block 1561651

* ethcore/res: use hex values for Istanbul specs

* ethcore/res: fix trailing comma

* ethcore/res: be pedantic about EIP-1283 in Petersburg and Istanbul test specs

* ethcore/res: activate Istanbul on Rinkeby block 5435345

* ethcore/res: activate Istanbul on Kovan block 14111141

* ethcore/res: fix kovan istanbul number to 0xd751a5
2019-09-20 15:53:35 +08:00
Niklas Adolfsson
19184e8529 [sync]: rust 2018 (#11067)
* [sync]: rust 2018

* fix(grumble): explicit use for RlpResponseResult

* fix(grumble): types -> common_types

* fix: bad rebase

* fix: wildcard import

* fix(grumble): rename crate hash to `keccak_hash`
2019-09-19 13:12:07 +02:00
Niklas Adolfsson
b6415c6196 [ethcore]: move client test types to test-helpers (#11062) 2019-09-17 15:42:22 +01:00
Niklas Adolfsson
acad59b300 [sync]: remove unused dependencies or make dev (#11061) 2019-09-16 21:56:53 +02:00
Niklas Adolfsson
0051c26acf [ethcore]: reduce re-exports (#11059)
* [ethcore]: reduce re-exports

Last piece of refactoring to close #10130 after work done by @dvdplm et. al

After this PR, we have the following re-exports from other crates in `non-testbuilds`:
- evm::VMType (client)
- ethcore_miner::local_accounts::LocalAccounts (miner)
- ethcore_miner::pool::PendingOrdering (miner)

I think the miner re-exports make sense (closely tied to the module) and `VMType` (related to module but not closely)

* fix(grumbles): remove re-export `VerifierType`
2019-09-16 17:12:21 +02:00
Andronik Ordian
bceb1d5691 [evmbin] fix time formatting (#11060) 2019-09-16 15:14:34 +02:00
joshua-mir
61a7c30ed5 Update hardcoded headers (foundation, classic, kovan, xdai, ewc, ...) (#11053)
* update hardcoded headers for foundation

* update classic headers

* update kovan headers

* formatting and xdai hardcoded headers

* ewc headers and formatting

* volta formatting and headers

* headers for poacore and sokol

* indentation

* indentation volta

* remove unnecessary space

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* remove unnecessary space

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* remove random typo haha
2019-09-16 12:25:52 +02:00
Andronik Ordian
0659cb8592 cargo update -p eth-secp256k1 (#11052) 2019-09-13 19:48:51 +02:00
Niklas Adolfsson
a665116eb1 ethcore: remove test-helper feat from build (#11047) 2019-09-13 11:13:41 +02:00
David
0bd2348ca1 Include test-helpers from ethjson (#11045)
Closes https://github.com/paritytech/parity-ethereum/issues/11044
2019-09-13 09:38:24 +02:00
Niklas Adolfsson
eb81168674 [ethcore]: cleanup dependencies (#11043) 2019-09-12 22:56:59 +02:00
Andronik Ordian
ad9a53f486 add more tx tests (#11038) 2019-09-12 16:38:25 +02:00
Nicolas Gotchac
5e2def1b23 Fix parallel transactions race-condition (#10995)
* WiP : clear pending txs cache & tick in Miner

* Fixed pending transactions

* Revert debugging code

* Add ToDo comment

* Remove commented-out code

* Reverse LTO setting

* WiP

* Try to seal a new block if there are pending transactions

* Try resealing only for internal imports

* Remove logging

* Use AtomicU64 instead of Mutex<BlockNumber>

* Remove TxQueue cache clear // Update AtomicUint logic

* Update comments in Miner

* Revert import of `parking_lot`

* Update `transaction-pool` dependency

* Call directly `update_sealing`

* Call `update_sealing` directly
2019-09-11 18:44:31 +02:00
Niklas Adolfsson
240ef46c72 [ethcore]: make it compile without test-helpers feature (#11036)
* [ethcore]: rustc_hex not longer `optional`

Used by `ethcore/client/client` when importing blocks

* [ethcore-types]: `DataFormat` add docs + tabify

* fix(grumbles): bump `rustc-hex = 2`
2019-09-11 17:35:50 +02:00
David
f4d14e271f Benchmarks for block verification (#11035)
* WIP

* wip

* Benchmarks for block verification

Uses real blocks from mainnet to benchmark the `verify_*` family of methods in the `verification` module.

Also exposes the `TestBlockChain` in a test helper.

* Cleanup, fix CI

* Bash syntax error

* One more try

* Fix review grumbles
	Revert unwanted changes
	Tweak CI benchmark checks
2019-09-11 14:15:19 +02:00
David
48629c2bd4 Move snapshot related traits to their proper place (#11012)
* Move snapshot to own crate
Sort out imports

* WIP cargo toml

* Make snapshotting generic over the client
Sort out tests

* Sort out types from blockchain and client

* Sort out sync

* Sort out imports and generics

* Sort out main binary

* Fix sync test-helpers

* Sort out import for secret-store

* Sort out more imports

* Fix easy todos

* cleanup

* Move SnapshotClient and SnapshotWriter to their proper places
Sort out the circular dependency between snapshot and ethcore by moving all snapshot tests to own crate, snapshot-tests

* cleanup

* Cleanup

* fix merge issues

* Update ethcore/snapshot/snapshot-tests/Cargo.toml

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Sort out botched merge

* Ensure snapshot-tests run

* Docs

* Fix grumbles
2019-09-10 22:44:33 +02:00
Niklas Adolfsson
d311bebaee cleanup json crate (#11027)
* [json]: cleanup

write something here....

* nit: commit new/moved files

* nit: remove needless features

* nits

* fix(grumbles): use explicit import `DifficultyTest`

* fix(grumbles): remove needless type hints

* fix(grumble): docs `from -> used by`

Co-Authored-By: David <dvdplm@gmail.com>

* fix(grumbles): use explicit `imports`

* fix(grumble): merge `tx` and `tx_with_signing_info`

* fix(grumbles): resolve introduced `TODO's`
2019-09-10 20:46:50 +02:00
Andronik Ordian
fc9a2933af [spec] add istanbul test spec (#11033)
* [spec] add istanbul test spec (wip)

* [spec] fix trailing comma

* [spec] add blake2_f precompiled

* [spec] specify eip1283ReenableTransition

* [spec] update istanbul spec to new blake2 pricing spec
2019-09-10 18:28:21 +02:00
Andronik Ordian
feb87c901e [json-spec] make blake2 pricing spec more readable (#11034)
* [json-spec] make blake2 pricing spec more readable

* [ethcore] fix compilation
2019-09-10 17:52:04 +02:00
David
d8d7abc848 Add blake2_f precompile (#11017)
* feat: implement eip1108

* doc nit: price per point pair

Co-Authored-By: David <dvdplm@gmail.com>

* fix: test-build

* fix: update chain specs

* fix: basic_authority.json chain spec

* fix: change `eip_transition == 0x7fffffffffffff`

* Merge na-eip1108

* Pre-compile plumbing

* Use type alias instead of struct

* Extract the data from incoming EVM call and forward it to blake2_f

* Fetch parity-common from git for now

* Fix broken cost impl
Add remaining test vectors

* cleanup

* Trailing comma in json spec

* Update ethcore/builtin/src/lib.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Update ethcore/builtin/src/lib.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Rename pricer to be Blake2-specific
Return a cost of u32::MAX if conversion fails
Fix docs and todos

* Fix error handling in cost()

* fix chainspec

* EIP-152 crate

* Update ethcore/builtin/src/lib.rs

Co-Authored-By: Seun LanLege <seunlanlege@gmail.com>

* Address grumbles

* Update ethcore/builtin/src/lib.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Switch tests to use hex!

* remove parity-crypto from git

* Sort out the SIGMA

* Prefer arrays to vecs

* Update util/EIP-152/src/lib.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Update json/src/spec/builtin.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Update json/src/spec/builtin.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Review feedback

* Do not change chainspecs yet

* Do not assume endianess: precompile output is LE
2019-09-10 00:26:45 +02:00
Seun LanLege
80f0e4b58f Add new line after writing block to hex file. (#10984)
* add new line after writing block to hex file.

* refactor for testability

* correct import

* better error reporting, code formatting

* multiline imports

* docs

* better docs, move type to common types, merge ImportBlocks and ExportBlocks

* tabs over spaces

* correct test imports

* Apply suggestions from code review

Co-Authored-By: David <dvdplm@gmail.com>

* correct typo

* fixed test import
2019-09-09 13:46:05 +02:00
Niklas Adolfsson
53e590f54b fix: remove unused error-chain (#11028) 2019-09-09 09:55:06 +02:00
Niklas Adolfsson
a4969ca498 fix: remove needless use of itertools (#11029)
* Remove needless use of `itertools` in `ethcore-light`
* Replace `itertools::repeat::call` with `std::iter::repeat_with`
2019-09-08 14:30:54 +02:00
Toby Dimmick
680807e601 Convert std::test benchmarks to use Criterion (#10999)
* Convert std::test benches to Criterion

* Required feature for ethash benches

* gitlab-ci: Check all bench targets

* check ethash benches

* evmbin/benches/mod.rs: Update bench sample command

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Upgrade to criterion 0.3
2019-09-05 19:28:01 +02:00
Atkins
a89bbfe366 Fix block detail updating (#11015)
* Add finality parameter to `null engine`

* Add testcase for finalization marking in `ethcore` client

* Add double cache read for db

* Prevent lost update of block details

* Read with pending update for block details in batch
2019-09-05 19:27:05 +02:00
Andronik Ordian
44c00b1f74 [trace] introduce trace failed to Ext (#11019)
* [trace] add trace_failed to Ext, manage stack of trace data

* [evm] call trace_failed only if self.do_trace

* [evm] add a comment about do_trace set to true

* [vm] improve the doc in trace_prepare_execute

* [trace] add the bounds check back
2019-09-05 16:11:51 +02:00
Talha Cross
11d3cb3f08 cli: update usage and version headers (#10924) 2019-09-05 16:07:26 +02:00
Niklas Adolfsson
8c286125e6 [private-tx] remove unused rand (#11024) 2019-09-05 13:26:28 +02:00
David
d193ddde19 Extract snapshot to own crate (#11010)
* Move snapshot to own crate
Sort out imports

* WIP cargo toml

* Make snapshotting generic over the client
Sort out tests

* Sort out types from blockchain and client

* Sort out sync

* Sort out imports and generics

* Sort out main binary

* Fix sync test-helpers

* Sort out import for secret-store

* Sort out more imports

* Fix easy todos

* cleanup

* Cleanup

* remove unneded workspace member

* cleanup

* Sort out test-helpers dependency on account-db

* Update ethcore/client-traits/src/lib.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* Update ethcore/snapshot/Cargo.toml
2019-09-03 11:29:25 +02:00
s3krit
396ccdbcc1 Edit publish-onchain.sh to use https (#11016)
`update.parity.io` supports HTTPS, so it makes sense to use it.
2019-09-03 10:37:21 +02:00
Niklas Adolfsson
a9cb572238 EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
* feat: implement eip1108

* doc nit: price per point pair

Co-Authored-By: David <dvdplm@gmail.com>

* fix: test-build

* fix: update chain specs

* fix: basic_authority.json chain spec

* fix: change `eip_transition == 0x7fffffffffffff`

* add issue link to `TODO`
2019-09-02 11:38:27 +02:00
Atkins
05f9606bf2 Fix deadlock in network-devp2p (#11013)
* Fix deadlock in `network-devp2p`

* Add note for locking order in `network-devp2p`
2019-09-02 10:56:08 +02:00
Wei Tang
00124b5a4b Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200 (#10191)
* Add reentry protection for EIP-1283

* typo: should use <=

* Put things behind flag eip1706

* Fix compile

* Fix missing config in json and add eip1283_reenable_transition
2019-08-29 21:31:52 +02:00
David
dabfa2c663 EIP 1884 Re-pricing of trie-size dependent operations (#10992)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract

* Move many traits from ethcore/client/traits to client-traits crate
Initial version of extracted Engine trait

* Move snapshot related traits to the engine crate (eew)

* Move a few snapshot related types to common_types
Cleanup Executed as exported from machine crate

* fix warning

* Gradually introduce new engine crate: snapshot

* ethcore typechecks with new engine crate

* Sort out types outside ethcore

* Add an EpochVerifier to ethash and use that in Engine.epoch_verifier()
Cleanup

* Document pub members

* Sort out tests
Sort out default impls for EpochVerifier

* Add test-helpers feature and move EngineSigner impl to the right place

* Sort out tests

* Sort out tests and refactor verification types

* Fix missing traits

* More missing traits
Fix Histogram

* Fix tests and cleanup

* cleanup

* Put back needed logger import

* Don't rexport common_types from ethcore/src/client
Don't export ethcore::client::*

* Remove files no longer used
Use types from the engine crate
Explicit exports from engine::engine

* Get rid of itertools

* Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient

* Move ProvingBlockChainClient to client-traits

* Don't re-export ForkChoice and Transition from ethcore

* Address grumbles: sort imports, remove commented out code

* Fix merge resolution error

* Extract the Clique engine to own crate

* Extract NullEngine and the block_reward module from ethcore

* Extract InstantSeal engine to own crate

* Extract remaining engines

* Extract executive_state to own crate so it can be used by engine crates

* Remove snapshot stuff from the engine crate

* Put snapshot traits back in ethcore

* cleanup

* Remove stuff from ethcore

* Don't use itertools

* itertools in aura is legit-ish

* More post-merge fixes

* Re-export less types in client

* cleanup

* Extract spec to own crate

* Put back the test-helpers from basic-authority

* Fix ethcore benchmarks

* Reduce the public api of ethcore/verification

* WIP

* Add Cargo.toml

* Fix compilation outside ethcore

* Audit uses of import_verified_blocks() and remove unneeded calls
Cleanup

* cleanup

* Remove unused imports from ethcore

* Cleanup

* remove double semi-colons

* Add missing generic param

* More missing generics

* Update ethcore/block-reward/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/basic-authority/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/ethash/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/clique/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* signers is already a ref

* Add an EngineType enum to tighten up Engine.name()

* Add CHAINID opcode

* Introduce Snapshotting enum to distinguish the type of snapshots a chain uses

* Rename supports_warp to snapshot_mode

* Missing import

* Add chain_id wherever we instantiate EnvInfo

* more missing chain_id

* Tell serde to ignore the chain_id field on Env

* Update ethcore/src/snapshot/consensus/mod.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Use the chain_id from the machine by adding chain_id() to the Ext trait

* cleanup

* add missing impl
cleanup

* missing import

* Fix import

* Add transition marker for EIP 1344

* double semi

* Fix merge problem

* cleanup

* reprice SLOAD to 800 gas

* Reprice BALANCE and EXTCODEHASH

* Add SELFBALANCE opcode

* Add test for SELFBALANCE
Use InstructionParams.address as the self-address

* Use easier to read values in test

* merge conflict error

* Fix a few warnings

* Update ethcore/vm/src/schedule.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* more merge fallout
2019-08-29 13:19:55 +02:00
phahulin
3420c2bac0 xDai chain support and nodes list update (#10989)
* Update bootnodes list for known networks

* Add XDai chain

* Rename xdai chain in config

* Fix missing comma
2019-08-29 09:33:33 +02:00
Andronik Ordian
4f12d7ad12 [trace] check mem diff within range (#11002) 2019-08-28 18:24:06 +02:00
David
5ce249ac64 EIP-1344 Add CHAINID op-code (#10983)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract

* Move many traits from ethcore/client/traits to client-traits crate
Initial version of extracted Engine trait

* Move snapshot related traits to the engine crate (eew)

* Move a few snapshot related types to common_types
Cleanup Executed as exported from machine crate

* fix warning

* Gradually introduce new engine crate: snapshot

* ethcore typechecks with new engine crate

* Sort out types outside ethcore

* Add an EpochVerifier to ethash and use that in Engine.epoch_verifier()
Cleanup

* Document pub members

* Sort out tests
Sort out default impls for EpochVerifier

* Add test-helpers feature and move EngineSigner impl to the right place

* Sort out tests

* Sort out tests and refactor verification types

* Fix missing traits

* More missing traits
Fix Histogram

* Fix tests and cleanup

* cleanup

* Put back needed logger import

* Don't rexport common_types from ethcore/src/client
Don't export ethcore::client::*

* Remove files no longer used
Use types from the engine crate
Explicit exports from engine::engine

* Get rid of itertools

* Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient

* Move ProvingBlockChainClient to client-traits

* Don't re-export ForkChoice and Transition from ethcore

* Address grumbles: sort imports, remove commented out code

* Fix merge resolution error

* Extract the Clique engine to own crate

* Extract NullEngine and the block_reward module from ethcore

* Extract InstantSeal engine to own crate

* Extract remaining engines

* Extract executive_state to own crate so it can be used by engine crates

* Remove snapshot stuff from the engine crate

* Put snapshot traits back in ethcore

* cleanup

* Remove stuff from ethcore

* Don't use itertools

* itertools in aura is legit-ish

* More post-merge fixes

* Re-export less types in client

* cleanup

* Extract spec to own crate

* Put back the test-helpers from basic-authority

* Fix ethcore benchmarks

* Reduce the public api of ethcore/verification

* WIP

* Add Cargo.toml

* Fix compilation outside ethcore

* Audit uses of import_verified_blocks() and remove unneeded calls
Cleanup

* cleanup

* Remove unused imports from ethcore

* Cleanup

* remove double semi-colons

* Add missing generic param

* More missing generics

* Update ethcore/block-reward/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/basic-authority/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/ethash/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/clique/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* signers is already a ref

* Add an EngineType enum to tighten up Engine.name()

* Add CHAINID opcode

* Introduce Snapshotting enum to distinguish the type of snapshots a chain uses

* Rename supports_warp to snapshot_mode

* Missing import

* Add chain_id wherever we instantiate EnvInfo

* more missing chain_id

* Tell serde to ignore the chain_id field on Env

* Update ethcore/src/snapshot/consensus/mod.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Use the chain_id from the machine by adding chain_id() to the Ext trait

* cleanup

* add missing impl
cleanup

* missing import

* Fix import

* Add transition marker for EIP 1344

* double semi

* Fix merge problem

* cleanup

* merge conflict error

* Fix a few warnings

* Update ethcore/vm/src/schedule.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* more merge fallout
2019-08-28 16:15:50 +02:00
David
cd26526868 Make ClientIoMessage generic over the Client (#10981)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract

* Move many traits from ethcore/client/traits to client-traits crate
Initial version of extracted Engine trait

* Move snapshot related traits to the engine crate (eew)

* Move a few snapshot related types to common_types
Cleanup Executed as exported from machine crate

* fix warning

* Gradually introduce new engine crate: snapshot

* ethcore typechecks with new engine crate

* Sort out types outside ethcore

* Add an EpochVerifier to ethash and use that in Engine.epoch_verifier()
Cleanup

* Document pub members

* Sort out tests
Sort out default impls for EpochVerifier

* Add test-helpers feature and move EngineSigner impl to the right place

* Sort out tests

* Sort out tests and refactor verification types

* Fix missing traits

* More missing traits
Fix Histogram

* Fix tests and cleanup

* cleanup

* Put back needed logger import

* Don't rexport common_types from ethcore/src/client
Don't export ethcore::client::*

* Remove files no longer used
Use types from the engine crate
Explicit exports from engine::engine

* Get rid of itertools

* Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient

* Move ProvingBlockChainClient to client-traits

* Don't re-export ForkChoice and Transition from ethcore

* Address grumbles: sort imports, remove commented out code

* Fix merge resolution error

* Extract the Clique engine to own crate

* Extract NullEngine and the block_reward module from ethcore

* Extract InstantSeal engine to own crate

* Extract remaining engines

* Extract executive_state to own crate so it can be used by engine crates

* Remove snapshot stuff from the engine crate

* Put snapshot traits back in ethcore

* cleanup

* Remove stuff from ethcore

* Don't use itertools

* itertools in aura is legit-ish

* More post-merge fixes

* Re-export less types in client

* cleanup

* Extract spec to own crate

* Put back the test-helpers from basic-authority

* Fix ethcore benchmarks

* Reduce the public api of ethcore/verification

* WIP

* Add Cargo.toml

* Fix compilation outside ethcore

* Audit uses of import_verified_blocks() and remove unneeded calls
Cleanup

* cleanup

* Remove unused imports from ethcore

* Cleanup

* remove double semi-colons

* Add missing generic param

* More missing generics

* Update ethcore/block-reward/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/basic-authority/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/ethash/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/clique/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* signers is already a ref

* Add an EngineType enum to tighten up Engine.name()

* Introduce Snapshotting enum to distinguish the type of snapshots a chain uses

* Rename supports_warp to snapshot_mode

* Missing import

* Update ethcore/src/snapshot/consensus/mod.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* missing import

* Fix import

* double semi

* Fix merge problem

* cleanup

* Parametrise `ClientIoMessage` with `()` for the light client

* Add impl Tick for ()

* Address review feedback

* Move ClientIoMessage to common-types

* remove superseeded fixme

* fix merge conflict errors
2019-08-28 10:09:42 +02:00
Niklas Adolfsson
974b24549b bump spin to 0.5.2 (#10996)
patch vulnerability https://github.com/RustSec/advisory-db/pull/132
2019-08-27 23:59:39 +02:00
Niklas Adolfsson
dab2a6bd4b fix compile warnings (#10993)
* fix warnings

* fix: failing build, use `spec` as dev-dependency
2019-08-27 17:29:33 +02:00
David
505e284932 Fix compilation on recent nightlies (#10991)
For reasons unknown (to me) recent rustc nightlies can't find the `format!`-macro in `core` when there is an import named `core`. This PR removes the package rename and uses the full `jsonrpc_core` crate name instead.
2019-08-27 09:45:13 +02:00
David
b1e3acaf0c [ipfs] Convert to edition 2018 (#10979)
* [ipfs] Converto to edition 2018

Also: whitespace

* Review feedback
2019-08-26 12:09:44 +02:00
David
fbf425c4e2 Extract spec to own crate (#10978)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract

* Move many traits from ethcore/client/traits to client-traits crate
Initial version of extracted Engine trait

* Move snapshot related traits to the engine crate (eew)

* Move a few snapshot related types to common_types
Cleanup Executed as exported from machine crate

* fix warning

* Gradually introduce new engine crate: snapshot

* ethcore typechecks with new engine crate

* Sort out types outside ethcore

* Add an EpochVerifier to ethash and use that in Engine.epoch_verifier()
Cleanup

* Document pub members

* Sort out tests
Sort out default impls for EpochVerifier

* Add test-helpers feature and move EngineSigner impl to the right place

* Sort out tests

* Sort out tests and refactor verification types

* Fix missing traits

* More missing traits
Fix Histogram

* Fix tests and cleanup

* cleanup

* Put back needed logger import

* Don't rexport common_types from ethcore/src/client
Don't export ethcore::client::*

* Remove files no longer used
Use types from the engine crate
Explicit exports from engine::engine

* Get rid of itertools

* Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient

* Move ProvingBlockChainClient to client-traits

* Don't re-export ForkChoice and Transition from ethcore

* Address grumbles: sort imports, remove commented out code

* Fix merge resolution error

* Extract the Clique engine to own crate

* Extract NullEngine and the block_reward module from ethcore

* Extract InstantSeal engine to own crate

* Extract remaining engines

* Extract executive_state to own crate so it can be used by engine crates

* Remove snapshot stuff from the engine crate

* Put snapshot traits back in ethcore

* cleanup

* Remove stuff from ethcore

* Don't use itertools

* itertools in aura is legit-ish

* More post-merge fixes

* Re-export less types in client

* cleanup

* Extract spec to own crate

* Put back the test-helpers from basic-authority

* Fix ethcore benchmarks

* Reduce the public api of ethcore/verification

* Update ethcore/block-reward/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/basic-authority/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/ethash/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/clique/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* signers is already a ref

* Add an EngineType enum to tighten up Engine.name()

* Introduce Snapshotting enum to distinguish the type of snapshots a chain uses

* Rename supports_warp to snapshot_mode

* Missing import

* Update ethcore/src/snapshot/consensus/mod.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* missing import

* Fix import

* double semi
2019-08-23 15:32:58 +02:00
David
79b671f6c7 EIP 2028: transaction gas lowered from 68 to 16 (#10987) 2019-08-23 14:13:02 +02:00
David
2af3140a26 Extract engines to own crates (#10966)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract

* Move many traits from ethcore/client/traits to client-traits crate
Initial version of extracted Engine trait

* Move snapshot related traits to the engine crate (eew)

* Move a few snapshot related types to common_types
Cleanup Executed as exported from machine crate

* fix warning

* Gradually introduce new engine crate: snapshot

* ethcore typechecks with new engine crate

* Sort out types outside ethcore

* Add an EpochVerifier to ethash and use that in Engine.epoch_verifier()
Cleanup

* Document pub members

* Sort out tests
Sort out default impls for EpochVerifier

* Add test-helpers feature and move EngineSigner impl to the right place

* Sort out tests

* Sort out tests and refactor verification types

* Fix missing traits

* More missing traits
Fix Histogram

* Fix tests and cleanup

* cleanup

* Put back needed logger import

* Don't rexport common_types from ethcore/src/client
Don't export ethcore::client::*

* Remove files no longer used
Use types from the engine crate
Explicit exports from engine::engine

* Get rid of itertools

* Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient

* Move ProvingBlockChainClient to client-traits

* Don't re-export ForkChoice and Transition from ethcore

* Address grumbles: sort imports, remove commented out code

* Fix merge resolution error

* Extract the Clique engine to own crate

* Extract NullEngine and the block_reward module from ethcore

* Extract InstantSeal engine to own crate

* Extract remaining engines

* Extract executive_state to own crate so it can be used by engine crates

* Remove snapshot stuff from the engine crate

* Put snapshot traits back in ethcore

* cleanup

* Remove stuff from ethcore

* Don't use itertools

* itertools in aura is legit-ish

* More post-merge fixes

* Re-export less types in client

* cleanup

* Update ethcore/block-reward/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/basic-authority/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/ethash/Cargo.toml

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/engines/clique/src/lib.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* signers is already a ref

* Add an EngineType enum to tighten up Engine.name()

* Introduce Snapshotting enum to distinguish the type of snapshots a chain uses

* Rename supports_warp to snapshot_mode

* Missing import

* Update ethcore/src/snapshot/consensus/mod.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* remove double-semicolons
2019-08-22 18:25:49 +02:00
Vladimir Komendantskiy
efb390eb60 Configuration map of block reward contract addresses (#10875)
* configuration map of block reward contract addresses

* Revert test module updates.

* re-added block reward transition map tests and docs

* review comment
2019-08-22 10:45:24 +02:00
Andreas Fackler
175051bac7 Add a 2/3 quorum option to Authority Round. (#10909)
* Add a 2/3 quorum option to Authority Round.

This prevents the "Attack of the Clones":
https://arxiv.org/pdf/1902.10244.pdf

* Make RollingFinality::remove_signers more tolerant.

* Rename parameter to two_thirds_majority_transition.
2019-08-21 14:55:51 +02:00
cheme
0a654afecc Fix rlp decode for inline trie nodes. (#10980)
* Fix rlp decode test.

* Proper fix, with associated tests.

* Put tests in their own module.
2019-08-19 23:31:57 +02:00
Anton Gavrilov
66e4410be7 Private contract migration and offchain state sync (#10748)
* Temp storage for the private state added

* Temp storage for the private state added

* Request message added

* Store and retrieve offchain state logic

* State sync cache

* Private state column added to key value db

* Private state column added to key value db

* Indexing stored states via its hash

* Works with errors changed

* Private state stored into the local db

* Access to private state db added to sync io

* Private state db file added

* Rlp packets for retrieiving private state data added

* Handling of private sync completed message

* Test code fixed

* External flag for offchain storing added

* Test for private state sync added

* Saving private state logic corrected

* Migration code corrected

* Fixes after merge with master

* Merge with head

* Additional checks for slices

* Log for private state retrieval added

* Limit time of retrieving private states

* Store required hashes for every request, mark them stale if needed

* Store requested private state hashes and check received data

* Log stale requests

* State insertion fix

* Refactoring of how logging passed to state store

* Heapsize removed, syncing hashes structure reworked

* Check state length returned by contract

* Get rid of OverlayDB

* hash-db version updated

* Test fixed

* One more test fixed
2019-08-16 14:45:52 +02:00
TriplEight
bd1a578f93 manual publish jobs for releases, no changes for nightlies (#10977) 2019-08-16 12:59:36 +02:00
David
6a9de9b11e Extract the Engine trait (#10958)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract

* Move many traits from ethcore/client/traits to client-traits crate
Initial version of extracted Engine trait

* Move snapshot related traits to the engine crate (eew)

* Move a few snapshot related types to common_types
Cleanup Executed as exported from machine crate

* fix warning

* Gradually introduce new engine crate: snapshot

* ethcore typechecks with new engine crate

* Sort out types outside ethcore

* Add an EpochVerifier to ethash and use that in Engine.epoch_verifier()
Cleanup

* Document pub members

* Sort out tests
Sort out default impls for EpochVerifier

* Add test-helpers feature and move EngineSigner impl to the right place

* Sort out tests

* Sort out tests and refactor verification types

* Fix missing traits

* More missing traits
Fix Histogram

* Fix tests and cleanup

* cleanup

* Put back needed logger import

* Don't rexport common_types from ethcore/src/client
Don't export ethcore::client::*

* Remove files no longer used
Use types from the engine crate
Explicit exports from engine::engine

* Get rid of itertools

* Move a few more traits from ethcore to client-traits: BlockChainReset, ScheduleInfo, StateClient

* Move ProvingBlockChainClient to client-traits

* Don't re-export ForkChoice and Transition from ethcore

* Address grumbles: sort imports, remove commented out code

* Fix merge resolution error

* merge failure
2019-08-15 17:59:22 +02:00
Seun LanLege
1ba4df08f9 Better error message for rpc gas price errors (#10931)
* Better error message for rpc gas price errors

* correct tests

* dedupe error variants

* fixed tests, removed spacing
2019-08-15 16:48:41 +02:00
Andronik Ordian
abb2a8c5a2 [.gitlab.yml] cargo check ethcore benches (#10965) 2019-08-15 16:28:25 +02:00
Anton Gavrilov
fd75491103 Verify transaction against its block during import (#10954)
* Verify transaction against its block during import

* Client method for transaction verification added

* Verification methods united

* Verification sequence for transaction verifier returned
2019-08-15 16:10:39 +02:00
David
ef47426a93 [evmbin] fix compilation (#10976)
* Fix compilation error

Include the test-helpers from `machine` (used by json-tests, although I'm not sure why evmbin needs ethcore/json-tests)

* Update to edition
2019-08-15 16:06:43 +02:00
cheme
5807402a0b Update to latest trie version. (#10972)
* Switch to 'trie' crates, there is an unpublished deps to staging
parity-common triehash still.

* Use crates.io dependency.

* indentation

* Update util/journaldb/src/traits.rs

indentation

Co-Authored-By: cheme <emericchevalier.pro@gmail.com>

* Rem import braces

* switch deps to simple-codec branch (code broken)

* painfull update of trie and memdb, plus rework codec to be compatible
with simple_codec changes

* Removed useless implementation from trait.

* Remove some malloc size until update and patch triehash, seems ok
otherwhise.

* Update parity-util-mem.

* Switch to published triehash 0.8.

* Avoid redundancy in encode_partial functions.
Use better namings.

* Update util/patricia-trie-ethereum/src/rlp_node_codec.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Update util/patricia-trie-ethereum/src/rlp_node_codec.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Restore previous child rlp header length check.
Better comments and formatting.

* Update util/patricia-trie-ethereum/src/rlp_node_codec.rs

Co-Authored-By: David <dvdplm@gmail.com>

* Update util/patricia-trie-ethereum/src/rlp_node_codec.rs

Co-Authored-By: David <dvdplm@gmail.com>
2019-08-15 15:36:48 +02:00
David
e50eafe6e1 [blooms-db] Fix benchmarks (#10974)
* [blooms-db] Fix benchmarks

* Use Bloom::zero()
2019-08-15 15:36:07 +02:00
Andreas Fackler
a23f5b8fd9 Fix ethcore/benches build. (#10964) 2019-08-13 15:27:28 +02:00
Andrew Jones
bd2e4f9c13 tx-pool: accept local tx with higher gas price when pool full (#10901)
* tx-pool: accept local tx with higher gas price when pool full

* Revert "tx-pool: accept local tx with higher gas price when pool full"

This reverts commit 9d4adc5a

* tx-pool: new tx with same nonce as existing is ready

* tx-pool: explicit check for replacement tx (same sender & nonce)

* Update comment

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Replace `ReplaceOld` with `InsertNew` for replacement txs
2019-08-13 14:20:59 +01:00
joshua-mir
e551122ab9 Disable unsyncable expanse chain (#10926)
* Only remove expanse from cli

* remove whitespace

* remove whitespace (restart CI)

* (restart CI)
2019-08-13 13:37:43 +02:00
David
73f4564b66 Extract Machine from ethcore (#10949)
* Add client-traits crate
Move the BlockInfo trait to new crate

* New crate `machine`
Contains code extracted from ethcore that defines `Machine`, `Externalities` and other execution related code.

* Use new machine and client-traits crates in ethcore

* Use new crates machine and client-traits instead of ethcore where appropriate

* Fix tests

* Don't re-export so many types from ethcore::client

* Fixing more fallout from removing re-export

* fix test

* More fallout from not re-exporting types

* Add some docs

* cleanup

* import the macro edition style

* Tweak docs

* Add missing import

* remove unused ethabi_derive imports

* Use latest ethabi-contract
2019-08-13 12:33:34 +02:00
Marek Kotewicz
509fda727b removed redundant state_root function from spec, improve spec error types (#10955) 2019-08-12 16:10:46 +02:00
Adam Z. Nagy
ffc066e5a4 Add support for Energy Web Foundation's new chains (#10957)
* add(chain-support): new ewf chains support added

- volta test network
- ewc production chain

* remove(tobalaba): ewf chain tobalaba support removal

- tobalaba is deprecated so not officially supported by ewf any more
2019-08-12 13:20:12 +02:00
Andronik Ordian
cafdfa8107 [evmbin] add more tests to main.rs (#10956) 2019-08-09 13:14:41 +02:00
David
49f219451b Fix compiler warnings in util/io and upgrade to edition 2018 Upgrade mio to latest (#10953)
* Initial cleanup

* Fix compiler warnings in util/io and upgrade to edition 2018
Upgrade mio to latest version

* cleanup

* Update util/io/src/service_mio.rs

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>

* review suggestion
2019-08-08 09:41:22 +02:00
Marek Kotewicz
45978bc2bd unify loading spec && further spec cleanups (#10948)
* bundle_* macros for spec

* fixed failing tests

* renamed bundle.rs to chain.rs

* removed unused derives

* updated spec/chain.rs description
2019-08-07 16:52:48 +02:00
Luke Schoen
c689495826 refactor: Refactor evmbin CLI (#10742)
* docs: Add comments to run_transaction arguments

* docs: Add general state test example from github.com/ethereum/test

* docs: Add state test file used in ethjson

* refactor: Reorder CLI options. Modify CLI descriptions. See commit comments

* Reorder parity-evm CLI options
* Update descriptions for CLI options
* Change to `--chain PATH` (general) and `--chain CHAIN` (state test)
* Remove unncessary 'Display result state dump in standardized JSON format.

* refactor: Move  function to be ordered after

* refactor: Refactor run_state_test

* refactor: Modify run_stats_jsontests_vm comment to be more specific

* refactor: Refactor run_call

* refactor: Update Args struct including rustdocs

* refactor: Reorder functions in Args struct to match other orders

* tests: Update tests for evmbin

* revert unintentional changes

* comply with style guide

* docs: Info and Display Modules made public so appear in rustdocs

* docs: Rename VM to EVM

* docs: Update rustdocs

* docs: Update state-test cli command comments

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update chain path cli command description

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Prefix to specify only one chain type to be provided

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update to be lowercase fat

Co-Authored-By: David <dvdplm@gmail.com>

* rename err to stderr, out to stdout

* revert to wei for gas price

* review-fix: Do not expose private modules but still show docs

View docs with:
```
cargo doc -p evmbin --document-private-items --open
```

* test: Read from file. Add initial tests for state-test CLI command

* review-fix: Change to single TODO that links to new issue to create integration tests

* refactor: Move run_transaction params into fields of a TxInput struct and make doc comments of its fields (#10769)

* Question

* refactor: Further changes for doc comments to be part of public struct

* refactor: Rename InputData to TxInput for clarity in docs

* docs: Change String to fixed length str

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* refactor: Update evmbin/src/info.rs moving mut into fn declaration

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* refactor: Update evmbin/src/info.rs moving mut into fn declaration part 2

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* review-fix: Add missing docs to TxInput transaction and trie_spec

* docs: Improve grammar

* review-fix: Destructure tx_input

* WIP

* review-fix: Rename variables of InputTx

* rename `spec_from_json` to `fork_spec_from_json`
* rename `name` to `state_test_name`
* rename `spec` to `fork_spec_name`
* rename `spec_checked` to `fork_spec`

* review-fix: Rename idx to tx_index

* fix indentation

* review-fix: Add missing part of tests. Yet to fix tests and add assertions

* [evmbin] remove state-db dependency

* [evmbin] run_transaction returns bool

* [evmbin] more cleanup
2019-08-07 16:51:08 +02:00
Marek Kotewicz
46954527e7 journaldb changes (#10929)
* inject_batch && commit_batch are no longer a part of journaldb

* get rid of redundant KeyedHashDB trait

* journaldb edition 2018

* journaldb trait moved to the lib.rs file

* making journaldb more idiomatic

* fix parity_bytes reexport

* rename parity-util-mem package in Cargo.toml file
2019-08-07 01:45:10 +02:00
Seun LanLege
72279856cd Allow default block parameter to be blockHash (#10932)
* allow default block parameter to be blockHash

* requireCanonical

* block check takes precedence over canon check
2019-08-06 11:08:05 +02:00
Anton Gavrilov
13ccb9f827 Enable sealing when engine is ready (#10938) 2019-08-06 11:07:27 +02:00
Andreas Fackler
1503348782 Fix some warnings and typos. (#10941) 2019-08-06 11:07:07 +02:00
Kirill Pimenov
5de32a70da Updated security@parity.io key (#10939) 2019-08-05 14:09:32 +01:00
Ao Li
8e0c522931 Change the return type of step_inner function. (#10940)
* Change the return type of step_inner function.

* Fix indention.
2019-08-05 14:58:48 +02:00
Marek Kotewicz
6c7d0fef4e get rid of hidden mutability of Spec (#10904)
* get rid of hidden mutabilityof Spec

* small cleanups

* fixed SpecHardcodedSync printing
2019-07-30 12:48:54 +02:00
Marek Kotewicz
12256a1e97 simplify BlockReward::reward implementation (#10906)
* simplify BlockReward::reward implementation

* fixed failing tests
2019-07-30 12:05:06 +02:00
s3krit
ec90fc47bc Kaspersky AV whitelisting (#10919)
* Add Kaspersky's FTP to AV Whitelisting release script

* Uncommented lines commented for debugging
2019-07-29 16:44:19 +02:00
Vladimir Komendantskiy
ee9bfac625 additional arithmetic EVM opcode benchmarks (#10916) 2019-07-29 15:50:57 +02:00
Andronik Ordian
27786f014c [Cargo.lock] cargo update -p crossbeam-epoch (#10921) 2019-07-29 12:27:18 +02:00
Micah Zoltu
8099efe215 Fixes incorrect comment. (#10913)
I _believe_ (someone please double-check my work) that this comment is subtly incorrect and in fact the replacement will occur if the new gas price is exactly 12.5% (given current configuration) higher.

Relevant pieces of code:
```rust
fn bump_gas_price(old_gp: U256) -> U256 {
	old_gp.saturating_add(old_gp >> GAS_PRICE_BUMP_SHIFT)
}
```
```rust
let min_required_gp = bump_gas_price(*old_gp);
match min_required_gp.cmp(&new_gp) {
	cmp::Ordering::Greater => scoring::Choice::RejectNew,
	_ => scoring::Choice::ReplaceOld,
}
```
2019-07-24 12:28:48 +02:00
Vladyslav Lupashevskyi
cc796a232a Add file path to disk map write/read warnings (#10911) 2019-07-24 12:26:43 +02:00
Marek Kotewicz
d1b28bf57e remove verify_transaction_unordered from engine (#10891) 2019-07-21 21:15:08 +02:00
s3krit
acb1243214 Avast whitelist script (#10900)
* Add Avast AV whitelisting publish script

* Update gitlab-ci.yml, publish-av-whitelists.sh

* remove debug print
2019-07-21 15:03:31 +02:00
Marek Kotewicz
fa1f81b5a3 cleanup ethcore ethereum module (#10899) 2019-07-18 14:22:59 +02:00
David
1ef9d5b52f Move more types out of ethcore (#10880)
* WIP move errors, pod_account and state account to own crates

* Sort out dependencies, fix broken code and tests
Remove botched ethcore-error crate

* remove template line

* fix review feedback

* Remove test-only AccountDBMut::new

* Extract AccountDB to account-db

* Move Substate to state-account – wip

* Add lib.rs

* cleanup

* test failure

* test failure 2

* third time's the charm

* Add factories crate

* Use new factories crate

* Use factories crate

* Extract trace

* Fix tests

* Sort out parity-util-mem and parking_lot

* cleanup

* WIP port over the rest of state from ethcore

* Collect all impls for Machine

* some notes

* Rename pod-account to pod

* Move PodState to pod crate

* Use PodState from pod crate

* Fix use clause for json tests

* Sort out evmbin

* Add missing code and use PodState

* Move code that depends on Machine and Executive to own module

* Sort out cloning errors, fix ethcore to use new state crate

* Do without funky From impls

* Fix ethcore tests

* Fixes around the project to use new state crate

* Add back the more specific impls of StateOrBlock From conversions

* Move execute to freestanding function and remove it from trait
Sort out the error handling in executive_state by moving the result types from state to ethcore
Undo the verbose code added to work around the StateOrBlock From conversions

* cleanup

* Fix "error: enum variants on type aliases are experimental"

* Bring back the state tests
Fix whitespace

* remove ethcore/state/mod.rs

* cleanup

* cleanup

* Cleanup state-account errors

* Fix more todos
Add module docs

* Add error.rs

* Fixup Cargo.lock

* Smaller ethcore API is fine

* Add `to-pod-full` feature to state-account
Fix evmbin

* Fix a few more test failures

* Fix RPC test build

* Baptize the new trait

* Remove resolved TODOs

* Rename state-account to account-state

* Do not re-export the trace crate

* Don't export state_db from ethcore

* Let private-tx use StateDB. :(

* Remove ethcore/src/pod_state.rs

* Inner type does not need to be pub/pub(crate)

* optimise imports

* Revert "Inner type does not need to be pub/pub(crate)"

This reverts commit 2f839f8a0f72f71334da64620f57e6dd6039f06b.

* Move DatabaseExtras to ethcore-blockchain

* Add database_extra module to ethcore-blockchain

* Remove to-pod-full feature

* cosmetics

* New crate: state-db

* Add new crate

* Move PreverifiedBlock and BlockError to types

* Sort out the merge

* Add missing `license` meta data keys

* wip

* wip client-traits

* merge conflict

* verification crate type checks

* Move impls for CommonParams to common_types
Fix misc stuff in ethcore

* Fix tests

* Implement VerifyingEngine for all engines except Ethash
Temporarily sort out error handling
Move more types to common_types

* Split Engine in two and move code around

* cleanup

* verification: don't rexport common_types

* Use error from common_types

* Consolidate error types

* VerifyingEngine use Errors from common_types

* verification: Use error type from common_types

* SnapshotError moved to common_types

* Move more code from Engne to VerifyingEngine
Add a VerifyingClient trait: BlockInfo + CallContract
Whitespace

* Add MAX_UNCLE_AGE const

* Port over remaining code from ethcore/verification

* Use errors from common_types

* Fix the confusing "io" naming

* Move more types into common_types

* Add todos

* Experiment with Engine trait outside ethcore

* Hook up types from common_types in ethcore
Don't use verification crate
Don't use client-traits crate

* Revert to impl Engine for Arc<Ethash> and add note to explain why
Revert moving ClientIoMessage to common_types
Fix build

* Remove ClientIoMessage from common_types

* Cleanup

* More cleanup

* Sort error handling changes in the rest of parity

* Remove unused code

* Remove WIP types

* Cleanup todos not tackled here

* remove cruft

* Fix some whitespace and a merge error

* ethcore tests

* test failures

* Restore Engine impls to master to make review a bit easier

* cleanup

* whitespace

* applied review suggestions

* types does not depend on rustc-hex

* ethash engine moved to engine module

* applied review suggestion
2019-07-18 12:27:08 +02:00
Marek Kotewicz
7f707fa524 return block nonce when engine is clique (#10892)
* return block nonce when engine is clique, closes #10534

* Apply suggestions from code review

Co-Authored-By: Niklas Adolfsson <niklasadolfsson1@gmail.com>
2019-07-16 12:52:29 +02:00
Marek Kotewicz
c62e97d3c4 TransactionQueue::import accepts iterator (#10889) 2019-07-16 12:46:13 +02:00
Marek Kotewicz
27d1c2d7d1 rename is_pruned to is_prunable (#10888) 2019-07-16 12:45:24 +02:00
Marek Kotewicz
e3665ed9e3 simplify create_address_scheme (#10890)
* simplify create_address_scheme

* fix compilation errors
2019-07-16 12:43:46 +02:00
David
14e7641835 Move DatabaseExtras back to trace (#10868)
* Move DatabaseExtras back to trace
Add a new BlockChainWithExtras newtype to ethcore
Impl DatabaseExtras for BlockChainWithExtras

* Avoid double Arcs
Impl From for BlockChainWithExtras for convenient instantiation
Change TraceDB::new to take a T: DatabaseExtras (instead of an Arc)

* Use local type for BlockNumber and reduce dependencies

* Update ethcore/src/client/client.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update ethcore/src/client/client.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Revert "Update ethcore/src/client/client.rs"

This reverts commit cbf8a251d4acaff8b29e999aedcdaac473ddf300.

* Revert "Update ethcore/src/client/client.rs"

This reverts commit 2518873b3139e832fa57c11793624bf1bfe48d05.

* address grumbles

* Be explicit about using the BlockProvider provided block_hash()
2019-07-14 18:35:43 +02:00
s3krit
5baa7e8fb5 Update README.md and Changelogs (#10866)
* Update README.md and Changelogs
* Update changelogs
2019-07-12 15:50:58 +02:00
Marek Kotewicz
cfe826fae9 whisper is no longer a part of parity-ethereum repo (#10855)
* whisper is no longer a part of parity-ethereum repo

* fix failing tests

* update whisper help with the link to the new repo

* Removed AttachedProtocols

* updated whisper info in README.md files

* Update parity/deprecated.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>
2019-07-12 14:15:30 +02:00
Andronik Ordian
5a131175e8 [ethash] remove mem::uninitialized (#10861)
* [ethash] replace mem::uninitialized with MaybeUninit

* [ethash] replace another occurence of mem::uninitialized

* [ethash] remove last mem::uninitialized

* [ethash] clean up benches

* [ethash] update outdated comment

* [ethash] compile error on big endian targets

* [ethash] extract 32 into a constant

* [ethash] rename the constant to KECCAK_LEN

* [ethash] bench quick_get_difficulty

* [ethash] remove MaybeUninit completely

* [ethash] replace ptr::copy_nonoverlapping with copy_from_slice

* [ethash] s/header_len/hash_len

* [ethash] remove duplication in bench

* [ethash] add a config for basic benches

* [ethash] fix a typo in bench fn name

* [ethash] remove needless cast
2019-07-12 10:04:41 +02:00
TriplEight
d850eb0dd5 Docker images renaming (#10863)
* docker images renaming [skip ci]
2019-07-11 15:31:48 +02:00
Marek Kotewicz
34cdeac2a6 Move the substate module into ethcore/executive (#10867)
* substate is not a part of account-state

* fn cleanup_mode is a part of executive.rs

* test_cleanup_mode
2019-07-10 11:55:37 +03:00
David
f53c3e582c Run cargo fix on a few of the worst offenders (#10854)
* Run cargo fix on `vm`

* Run cargo fix on ethcore-db

* Run cargo fix on evm

* Run cargo fix on ethcore-light

* Run cargo fix on journaldb

* Run cargo fix on wasm

* Missing docs

* Run cargo fix on ethcore-sync
2019-07-09 09:04:20 +01:00
Marek Kotewicz
fdc7b0fdaa removed redundant fork choice abstraction (#10849) 2019-07-09 04:27:33 +02:00
David
0f337171bf Extract state-db from ethcore (#10858)
* WIP move errors, pod_account and state account to own crates

* Sort out dependencies, fix broken code and tests
Remove botched ethcore-error crate

* remove template line

* fix review feedback

* Remove test-only AccountDBMut::new

* Extract AccountDB to account-db

* Move Substate to state-account – wip

* Add lib.rs

* cleanup

* test failure

* test failure 2

* third time's the charm

* Add factories crate

* Use new factories crate

* Use factories crate

* Extract trace

* Fix tests

* Sort out parity-util-mem and parking_lot

* cleanup

* WIP port over the rest of state from ethcore

* Collect all impls for Machine

* some notes

* Rename pod-account to pod

* Move PodState to pod crate

* Use PodState from pod crate

* Fix use clause for json tests

* Sort out evmbin

* Add missing code and use PodState

* Move code that depends on Machine and Executive to own module

* Sort out cloning errors, fix ethcore to use new state crate

* Do without funky From impls

* Fix ethcore tests

* Fixes around the project to use new state crate

* Add back the more specific impls of StateOrBlock From conversions

* Move execute to freestanding function and remove it from trait
Sort out the error handling in executive_state by moving the result types from state to ethcore
Undo the verbose code added to work around the StateOrBlock From conversions

* cleanup

* Fix "error: enum variants on type aliases are experimental"

* Bring back the state tests
Fix whitespace

* remove ethcore/state/mod.rs

* cleanup

* cleanup

* Cleanup state-account errors

* Fix more todos
Add module docs

* Add error.rs

* Fixup Cargo.lock

* Smaller ethcore API is fine

* Add `to-pod-full` feature to state-account
Fix evmbin

* Fix a few more test failures

* Fix RPC test build

* Baptize the new trait

* Remove resolved TODOs

* Rename state-account to account-state

* Do not re-export the trace crate

* Don't export state_db from ethcore

* Let private-tx use StateDB. :(

* Remove ethcore/src/pod_state.rs

* Inner type does not need to be pub/pub(crate)

* optimise imports

* Revert "Inner type does not need to be pub/pub(crate)"

This reverts commit 2f839f8a0f72f71334da64620f57e6dd6039f06b.

* Move DatabaseExtras to ethcore-blockchain

* Add database_extra module to ethcore-blockchain

* Remove to-pod-full feature

* cosmetics

* New crate: state-db

* Add new crate

* Sort out the merge

* Fix unclean merge

* Add license
2019-07-08 22:01:47 +01:00
Nicolas Gotchac
073d242d1e Fix fork choice (#10837)
* Fix fork choice:
`is_from_route_finalized` check before switching to parent

* Add tests for `tree_route` with finalization

* Fix Cargo dependencies

* Add comment on `tree_route` for finalization.
Refactor a test.

* Fix compilation error

* Checkout Cargo.lock from master
2019-07-08 19:21:06 +02:00
David
44cc442d12 Move more code into state-account (#10840)
* WIP move errors, pod_account and state account to own crates

* Sort out dependencies, fix broken code and tests
Remove botched ethcore-error crate

* remove template line

* fix review feedback

* Remove test-only AccountDBMut::new

* Extract AccountDB to account-db

* Move Substate to state-account – wip

* Add lib.rs

* cleanup

* test failure

* test failure 2

* third time's the charm

* Add factories crate

* Use new factories crate

* Use factories crate

* Extract trace

* Fix tests

* Sort out parity-util-mem and parking_lot

* cleanup

* WIP port over the rest of state from ethcore

* Collect all impls for Machine

* some notes

* Rename pod-account to pod

* Move PodState to pod crate

* Use PodState from pod crate

* Fix use clause for json tests

* Sort out evmbin

* Add missing code and use PodState

* Move code that depends on Machine and Executive to own module

* Sort out cloning errors, fix ethcore to use new state crate

* Do without funky From impls

* Fix ethcore tests

* Fixes around the project to use new state crate

* Add back the more specific impls of StateOrBlock From conversions

* Move execute to freestanding function and remove it from trait
Sort out the error handling in executive_state by moving the result types from state to ethcore
Undo the verbose code added to work around the StateOrBlock From conversions

* cleanup

* Fix "error: enum variants on type aliases are experimental"

* Bring back the state tests
Fix whitespace

* remove ethcore/state/mod.rs

* cleanup

* cleanup

* Cleanup state-account errors

* Fix more todos
Add module docs

* Add error.rs

* Fixup Cargo.lock

* Smaller ethcore API is fine

* Add `to-pod-full` feature to state-account
Fix evmbin

* Fix a few more test failures

* Fix RPC test build

* Baptize the new trait

* Remove resolved TODOs

* Rename state-account to account-state

* Do not re-export the trace crate

* Don't export state_db from ethcore

* Let private-tx use StateDB. :(

* Remove ethcore/src/pod_state.rs

* Inner type does not need to be pub/pub(crate)

* optimise imports

* Revert "Inner type does not need to be pub/pub(crate)"

This reverts commit 2f839f8a0f72f71334da64620f57e6dd6039f06b.

* Move DatabaseExtras to ethcore-blockchain

* Add database_extra module to ethcore-blockchain

* Remove to-pod-full feature

* Sort out the merge

* sort imports

* address grumbles

* rename crate

* address more grumbles
2019-07-08 18:17:48 +02:00
Anton Gavrilov
d5c19bae1c Remove compiler warning (#10865) 2019-07-08 18:04:18 +02:00
Andronik Ordian
88e0cfe5ca [ethash] use static_assertions crate (#10860) 2019-07-08 17:25:49 +02:00
Wei Tang
141f6a047e EIP-1702: Generalized Account Versioning Scheme (#10771)
* EIP-1702: Generalized Account Versioning Scheme

* Fix pWASM's `create` and `create2` contract creation version

* Update ethcore/src/snapshot/account.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Update ethcore/src/factory.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* Add pWasm frontend config

* Add snapshot testing with version

* Fix merge conflict
2019-07-08 12:03:27 +02:00
Marek Kotewicz
fe7bc545bf ethcore-builtin (#10850)
* ethcore-builtin

* rename ethcore-builtin Impl to Implementation
2019-07-07 16:59:30 +02:00
Marek Kotewicz
c4c5d79a0f removed QueueError type (#10852) 2019-07-06 20:40:56 +02:00
Marek Kotewicz
0a9095626d removed unused macros (#10851) 2019-07-06 20:38:33 +02:00
Marek Kotewicz
a6e96b052e bump crossbeam (#10848) 2019-07-06 16:16:53 +02:00
Marek Kotewicz
86ef490a94 removed unused trait PrivateNotify and unused Error types (#10847) 2019-07-05 19:14:01 +02:00
Marek Kotewicz
b97bf81adf make fn submit_seal more idiomatic (#10843)
* make fn submit_seal more idiomatic

* applied review suggestions
2019-07-05 18:58:45 +02:00
Marek Kotewicz
d5584a01c7 update parking-lot to 0.8 (#10845) 2019-07-05 15:19:38 +02:00
s3krit
d83798db62 Update version to 2.7.0 (#10846) 2019-07-05 11:49:51 +02:00
Andronik Ordian
4bb517ec94 update jsonrpc to 12.0 (#10841)
* update jsonrpc to 12.0

* use reexported ws error
2019-07-05 16:24:23 +08:00
David
de906d4afd Improve logging and cleanup in miner around block sealing (#10745)
* Stop breaking out of loop if a non-canonical hash is found

* include expected hash in log msg

* More logging

* Scope

* Syntax

* Log in blank RollingFinality
Escalate bad proposer to warning

* Check validator set size: warn if 1 or even number

* More readable code

* Use SimpleList::new

* Extensive logging on unexpected non-canonical hash

* Wording

* wip

* Update ethcore/blockchain/src/blockchain.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Improved logging, address grumbles

* Update ethcore/src/engines/validator_set/simple_list.rs

Co-Authored-By: Luke Schoen <ltfschoen@users.noreply.github.com>

* Report benign misbehaviour iff currently a validator

* Report malicious behaviour iff we're a validator

* Escalate to warning and fix wording

* Test reporting behaviour
Don't require node to be part of the validator set to report malicious behaviour

* Include missing parent hash in MissingParent error

* Update ethcore/src/engines/validator_set/simple_list.rs

Co-Authored-By: Luke Schoen <ltfschoen@users.noreply.github.com>

* docs

* remove unneeded into()
Move check for parent_step == step for clarity&efficiency
Remove dead code for Seal::Proposal

* typo

* Wording

* naming

* WIP

* cleanup

* cosmetics

* cosmetics and one less lvar

* spelling

* Better loggin when a block is already in chain

* More logging

* On second thought non-validators are allowed to report

* cleanup

* remove dead code

* Keep track of the hash of the last imported block

* Let it lock

* Serialize access to block sealing

* Take a lock while sealing a block

* Cleanup

* whitespace
2019-07-04 18:03:22 +02:00
David
fafb534cd3 Extract AccountDB to account-db (#10839)
* WIP move errors, pod_account and state account to own crates

* Sort out dependencies, fix broken code and tests
Remove botched ethcore-error crate

* remove template line

* fix review feedback

* Remove test-only AccountDBMut::new

* Extract AccountDB to account-db

* test failure

* test failure 2

* third time's the charm
2019-07-04 17:50:31 +02:00
Luke Schoen
a5a06e49ba test: Update Whisper test for invalid pool size (#10811) 2019-07-04 16:56:16 +02:00
David
9f96fa0a73 Extricate PodAccount and state Account to own crates (#10838)
* WIP move errors, pod_account and state account to own crates

* Sort out dependencies, fix broken code and tests
Remove botched ethcore-error crate

* remove template line

* fix review feedback

* Remove test-only AccountDBMut::new
2019-07-04 15:20:44 +02:00
Seun LanLege
bbae075c60 logs (#10817) 2019-07-04 14:59:37 +02:00
Luke Schoen
bacc0f0b9a refactor: whisper: Add type aliases and update rustdocs in message.rs (#10812)
* refactor: Add type aliases to Whisper and update rustdocs

* remove my question that was answered
2019-07-04 13:45:56 +02:00
David
582a4ea339 Break circular dependency between Client and Engine (part 1) (#10833)
* First draft: pass the parent block header to on_close_block

* typos and cleanup

* whitespace

* Store parent in ClosedBlock as well so it can be reopen()'d

* Don't pass parent when reopening a block

* Remove the unused ancestry param
2019-07-04 13:43:20 +02:00
Luke Schoen
09edb94d53 tests: Relates to #10655: Test instructions for Readme (#10835)
* tests: Relates to #10655: Test instructions for Readme

* Add instructions to run tests
* Update instructions to view docs

* fix: Fix link to package list

* fix: Move link to line about title of package list

* Update README.md
2019-07-03 17:44:58 +02:00
Luke Schoen
02e33c4f91 refactor: Related #9459 - evmbin: replace untyped json! macro with fully typed serde serialization using Rust structs (#10657)
* fix: Replace multirust with rustup wince multirust is deprecated

* docs: Update evmbin Rust docs and code comments

* WIP: Add Response struct. Initial step using serde to serialize instead of hardcoding with JSON

* fix: Update Response struct types to be string after formatting

* fix: Fix move out of borrowed content error by cloning informant

* refactor: Change from camelcase to snake case to fix linting errors

* restore: Restore some code since now covered in separate PR #10658

* restore: Restore original Rustdocs of evmbin

* WIP

* add Clone type

* add newlines to end of json files

* remove uml file that was unintentionally commited

* rename chain spec to state test JSON fle

* remove log. fix indentation

* revert: Restore indentation now handled by separate PR #10740

* remove state test json files as moved to PR #10742

* revert changes in info.rs since covered in PR #10742

* revert changes to main.rs since covered in PR #10742

* revert newlines back to master

* revert newlines back to master2

* refactor: Rename Response to TraceData

* fix: Remove Clone and replace with lifetimes. Update tests since not ordered

* refactor: Change all json! to typed serde

* docs: Update rustdocs. Remove fixme

* fix: Add missing semicolons from printf

* fix: Change style from unwrap to expect in evmbin/src/display/json.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* fix: Change style from unwrap to expect in evmbin/src/display/std_json.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* revert updating module comments as will be done in separate PR #10742 instead

* review-fix: Remove useless reference

* Remove unncessary use of format macro

* Update evmbin/src/display/json.rs

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/json.rs with serialization in set_gas success

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/json.rs with serialization in set_gas failure

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization in finish for state root

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization in before_test

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization for state root

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization for finish success

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Update evmbin/src/display/std_json.rs with serialization for finish failure

Co-Authored-By: Andronik Ordian <write@reusable.software>

* refactor: Rename structs and variables. Remove space. Simplify MessageInitial struct

* refactor: Captialize expect message

* revert to previous struct name TraceDataStateRoot

* refactor: Simplify variable for consistency

* Update accounts/ethstore/src/json/crypto.rs

Co-Authored-By: David <dvdplm@gmail.com>
2019-07-03 16:02:41 +02:00
Marek Kotewicz
8d24b4e804 idiomatic changes to PodState (#10834) 2019-07-03 10:57:50 +02:00
David
895574b774 Allow --nat extip:your.host.here.org (#10830)
* Allow --nat extip:your.host.here.org

Closes #10604

* Use split instead of Regex
2019-07-03 15:44:32 +08:00
David
b4af8df535 When updating the client or when called from RPC, sleep should mean sleep (#10814)
Closes https://github.com/paritytech/parity-ethereum/issues/10687

`sleep()` is called from several places but when called from `disable()` or through the `setMode` RPC, we should ignore queue contents and go to sleep.
2019-07-02 21:26:26 +02:00
Anton Gavrilov
5f064a9076 Remove excessive warning (#10831) 2019-07-02 17:52:05 +02:00
Alexandre R. Baldé
5b30f22011 Fix typo in README.md (#10828)
Without this colon I first understood this line to refer to the `make` utility on Windows. Might be useful to fix this.
The additional whitespaces at the end are to trigger a line break.
2019-07-02 13:33:02 +02:00
Marek Kotewicz
9d9e2b43f2 ethcore does not use byteorder (#10829) 2019-07-02 09:06:27 +02:00
David
5dc5be1e58 Better logging when backfilling ancient blocks fail (#10796)
* Better logging when backfilling ancient blocks fail
Print total blocks imported, closes #10792

* `finalize()` doesn't need Engine
Pull out call to migrated_blocks() from replace_client_db()

* More logs

* Clarify that the percentage may be misleading

* Remove replace_client_db() and replace with a straight call to restore_db()

* Include the parent_hash in UnlinkedAncientBlockChain errors

* Add a new RestorationStatus varian: Finalizing (as it can take a loooong while)
Call abort_restore() when restoration fails

* Add missing cases for new variant

* typos

* Typo and derive Debug

* Do not attempt to salvage existing blocks unless they form a complete chain back to genesis

* Fix test

* Revert "Fix test"

This reverts commit f027d4b4cb7b6c23fceec528c1711886ba9cfe4e.

* Fix test again

* Update comment

* Be careful about locks

* fix test failure

* Do not defer returning an error when the chain is broken

* Review feedback

* no hex formatting for Option
2019-07-01 14:41:45 +02:00
Bryant Eisenbach
306c1764eb depends: Update wordlist to v1.3 (#10823) 2019-07-01 14:31:57 +02:00
Niklas Adolfsson
f6a390849b cargo update -p smallvec (#10822)
Fixes https://github.com/servo/rust-smallvec/issues/148
2019-06-30 23:20:46 +02:00
Andronik Ordian
cd088a4345 replace memzero with zeroize crate (#10816)
* [whisper] replace memzero with zeroize

* [ethkey] replace memzero with zeroize
2019-06-29 17:23:58 +08:00
David
bd9a8aa22b Don't repeat the logic from Default impl (#10813) 2019-06-29 16:43:57 +08:00
Marek Kotewicz
8fc504eb1a removed additional_params method (#10818) 2019-06-29 09:31:15 +02:00
Mohammad Rezaei
c1b3d5fe1a Add Constantinople eips to the dev (instant_seal) config (#10809)
Without EIP-1283
Fixes #10753
2019-06-28 16:17:33 +02:00
Marek Kotewicz
e53bf9a95e removed redundant fmt::Display implementations (#10806)
* removed redundant fmt::Display implementations for Account and State Diff

* bring back is_full() method

* fix failing test
2019-06-28 14:58:27 +02:00
Andronik Ordian
decc9eaa85 revert changes to .gitlab-ci.yml (#10807) 2019-06-28 11:23:58 +02:00
Fabio Lama
3f61f2d8d9 Add filtering capability to parity_pendingTransactions (issue 8269) (#10506)
* expand parameters for pending_transactions()

* move ready_transactions content into filtered method

* apply filter based on tx_hash, sender or receiver

* call filtered transactions from RPC interface

* attempt at testing...

* replace parameters with _ on light client

* addes some comments

* removed uncompleted tests in miner.rs

* attempt at testing, needs more work...

* Formatting for ready_transactions_filtered

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Use map_or instead of if-let

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* additional map_or replacement

* change receiver type to Option<Option<Address>>

* remove faulty MiningService tests, test RPC later

* remove tx hash from pending transaction filtering

* as_unsigned() method for SignedTransaction

* implement Deserialize for FilterOptions

* implement Validate for MapAccess type

* additional formatting

* directly name cover in pattern matching

* test valid vull deserialization

* test valid sender operators

* test valid receiver operators

* test valid gas operators

* test valid gas price operators

* test valid value operators

* test valid nonce operators

* additional tsets for defaults, unknown filter types, unknown operators and some renames

* move filter_options to ethcore to avoid package cycling

* adjusted function/method parameters for FilterOptions

* implement filter for sender and receiver

* implement filter for gas

* implement filter for gas price, tx value and nonce

* improve filtering implementation; use common function, use combinators

* improved documentation for FilterOptions

* small documentation adjustments

* remove warnings

* replace FilterOperator::ContractCreation with FilterOperator::Eq(None)

* implement validate_receiver

* make small changes like renames, preamble

* cleanup code according to suggestions, add docs

* small improvements like formatting and newline
2019-06-28 09:27:59 +01:00
Marek Kotewicz
7f02a08741 removed EthEngine alias (#10805) 2019-06-28 10:18:18 +02:00
Andronik Ordian
cff1bc88fa wait a bit longer in should_check_status_of_request_when_its_resolved (#10808) 2019-06-27 22:38:20 +02:00
Anton Gavrilov
59f0eb7e6b Do not drop the peer with None difficulty (#10772)
* Treat peer with None difficulty as legit

* Temporarily enable release binary build - REMOVE BEFORE MERGE
2019-06-27 17:45:21 +02:00
Marek Kotewicz
a729ca3223 ethcore-bloom-journal updated to 2018 (#10804) 2019-06-27 14:34:07 +02:00
Marek Kotewicz
afe14b42e2 ethcore-light uses bincode 1.1 (#10798) 2019-06-27 14:19:56 +02:00
Andreas Fackler
62832c93b0 Fix a few typos and unused warnings. (#10803) 2019-06-27 14:17:24 +02:00
Marek Kotewicz
1887080990 updated project to ansi_term 0.11 (#10799) 2019-06-27 13:34:40 +02:00
felix
edc38c2cee added new ropsten-bootnode and removed old one (#10794) 2019-06-27 18:10:00 +08:00
Marek Kotewicz
16e0ad1288 updated price-info to edition 2018 (#10801) 2019-06-27 17:29:24 +08:00
Marek Kotewicz
5a561997cf ethcore-network-devp2p uses igd 0.9 (#10797) 2019-06-27 09:54:54 +02:00
Marek Kotewicz
413442d7be updated parity-local-store to edition 2018 and removed redundant Error type (#10800) 2019-06-27 09:37:15 +02:00
Marek Kotewicz
4489ca0a38 Cleanup unused vm dependencies (#10787) 2019-06-26 14:17:17 +02:00
Marek Kotewicz
3a2c173fe1 Removed redundant ethcore-service error type (#10788) 2019-06-26 14:16:58 +02:00
Marek Kotewicz
9c051ab756 Removed machine abstraction from ethcore (#10791) 2019-06-26 14:16:05 +02:00
Marek Kotewicz
63221c5152 Updated blooms-db to rust 2018 and removed redundant deps (#10785) 2019-06-26 18:24:32 +08:00
Marek Kotewicz
8714a40d84 ethkey no longer uses byteorder (#10786) 2019-06-26 17:03:11 +08:00
David
825c7990f2 Log validator set changes in EpochManager (#10734)
* Stop breaking out of loop if a non-canonical hash is found

* include expected hash in log msg

* More logging

* Scope

* Syntax

* Log in blank RollingFinality
Escalate bad proposer to warning

* Check validator set size: warn if 1 or even number

* More readable code

* Use SimpleList::new

* Extensive logging on unexpected non-canonical hash

* Wording

* wip

* Update ethcore/blockchain/src/blockchain.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Improved logging, address grumbles

* Update ethcore/src/engines/validator_set/simple_list.rs

Co-Authored-By: Luke Schoen <ltfschoen@users.noreply.github.com>

* Report benign misbehaviour iff currently a validator

* Report malicious behaviour iff we're a validator

* Escalate to warning and fix wording

* Test reporting behaviour
Don't require node to be part of the validator set to report malicious behaviour

* Include missing parent hash in MissingParent error

* Update ethcore/src/engines/validator_set/simple_list.rs

Co-Authored-By: Luke Schoen <ltfschoen@users.noreply.github.com>

* cleanup

* On second thought non-validators are allowed to report

* cleanup

* remove dead code
2019-06-25 13:15:00 +02:00
Wei Tang
d743df549b Treat empty account the same as non-exist accounts in EIP-1052 (#10775) 2019-06-25 09:14:16 +02:00
Luke Schoen
6022c47b53 docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652)
* docs: Update Readme with TOC, Contributor Guide and License sections

* docs: Simplify package descriptions in Readme

* docs: Fix typos

* docs: Update Cargo package configs adding missing descriptions

* fix: Remove machine since was accidental from diff branch. Fix contribting indentation.

* fix: Fix formatting

* remove details snippet since not code and formats badly

* review-fix: Remove duplicate description

* fix dot point formatting

* fix: Add missing description to vm package

* fix: Remove duplicate Code of Conduct and Contributor guidelines

* docs: Update Contributing for consistency with other repos

* docs: Update Readme to link to existing Code of Conduct and Contributor guidelines in .github folder

* refactor: Add missing space

* fix: Fix links to be markdown format

* review-fix: Update CONTRIBUTING.md to link to Parity Ethereum Style Guide

* docs: Fix type in .github/CONTRIBUTING.md

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Fix typo in .github/CONTRIBUTING.md

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Rephrase parity-clib/Cargo.toml

Co-Authored-By: David <dvdplm@gmail.com>

* review-fix: Fix whole paragraph

* review-fix: Add comment to prevent direct pushes to master branch

* review-fix: Change some rules to recommendations

* Update .github/CONTRIBUTING.md

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* review-fix: Replace feature reduction with breaking changes dot point

* review-fix: Rephrase what to do when reviewing PR

* review-fix: Update parity-rpc package description and module rustdocs

* docs: Add missing fullstop

* review-fix: Update rustdoc section to show all packages first as default

* review-fix: Rename Parity Util to Parity Core Libraries

* review-fix: Rename readme too for the C bindings name change

* review-fix: Remove some docs since we do not teach the reader Rust

* review-fix: Wrap Parity Ethereum specific packages in a details section

* review-fix: Separate tools that are in this repo vs those that are not

* review-fix: Add link to ethabi on crates.io

* review-fix: Remove unnecessary extra line talking about pushing to master

* review-fix: Remove useless summary of parts of the rust book documentation section

* docs: Update .github/CONTRIBUTING.md to specify two reviewers required

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update README.md with simplification

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update README.md renaming to Test Runner instead of just Run

Co-Authored-By: David <dvdplm@gmail.com>

* review-fix: Remove hardware wallet from docs

* review-fix: Remove veto PR section of contributor doc

* review-fix: Change to test generator title
2019-06-25 08:15:13 +02:00
Wei Tang
02eb046774 Move Engine::register_client to be before other I/O handler registration (#10767) 2019-06-24 15:10:42 +02:00
David
f2dd032884 Print warnings when using dangerous settings for ValidatorSet (#10733)
* Stop breaking out of loop if a non-canonical hash is found

* include expected hash in log msg

* More logging

* Scope

* Syntax

* Log in blank RollingFinality
Escalate bad proposer to warning

* Check validator set size: warn if 1 or even number

* More readable code

* Use SimpleList::new

* Extensive logging on unexpected non-canonical hash

* Wording

* Update ethcore/blockchain/src/blockchain.rs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Improved logging, address grumbles

* Update ethcore/src/engines/validator_set/simple_list.rs

Co-Authored-By: Luke Schoen <ltfschoen@users.noreply.github.com>
2019-06-24 14:50:11 +02:00
Talha Cross
55c046cb88 ethcore/res: activate atlantis classic hf on block 8772000 (#10766) 2019-06-21 19:38:53 +02:00
Luke Schoen
7701f73cdf refactor: Fix indentation (#10740) 2019-06-21 10:03:38 +02:00
Seun LanLege
213e007a4b Updated Bn128PairingImpl to use optimized batch pairing (#10765)
* Bn128PairingImpl uses pairing_batch method in bn

* updated Cargo.lock
2019-06-20 23:16:11 +02:00
Niklas Adolfsson
78d0a8696f fix: aura don't add SystemTime::now() (#10720)
This commit does the following:
- Prevent overflow in `verify_timestamp()` by not adding `now` to found faulty timestamp
- Use explicit `CheckedSystemTime::checked_add` to prevent potential consensus issues because SystemTime is platform
depedent
- remove `#[cfg(not(time_checked_add))]` conditional compilation
2019-06-20 09:00:50 +02:00
Anton Gavrilov
e1333ea1e9 Initialize private tx logger only if private tx functionality is enabled (#10758)
* Initialize private tx logger only if private tx functionality is enabled

* Fix configuration test

* Use default contructor for config
2019-06-19 16:28:30 +02:00
David
4ee217ba7c Remove unused code (#10762) 2019-06-19 15:08:21 +01:00
cheme
6fc5014b4d Remove calls to heapsize (#10432)
* update memorydb trait
* use malloc_size_of instead of heapsize_of
* use jemalloc as default allocator for parity client.
2019-06-19 13:54:05 +02:00
David
859a41308c [devp2p] Update to 2018 edition (#10716)
* Run cargo fix

* Optimize imports

* compiles

* cleanup

* Use Secret to store mac-key
Truncate payload properly

* cleanup

* Reorg imports

* brwchk hand waving

* Fix a bunch of imports

* Fixup imports

* Sort

* indentation

* WIP

* Revert "WIP"

This reverts commit 85f7e74f4bd1990db865cf6acfa8d494798eeeaa.

* inclusive range pattern syntax is changing

* remove usless todo
2019-06-19 12:20:50 +02:00
David
d2120ded56 Add a way to signal shutdown to snapshotting threads (#10744)
* Add a way to signal shutdown to snapshotting threads

* Pass Progress to fat_rlps() so we can abort from there too.

* Checking for abort in a single spot

* Remove nightly-only weak/strong counts

* fix warning

* Fix tests

* Add dummy impl to abort snapshots

* Add another dummy impl for TestSnapshotService

* Remove debugging code

* Return error instead of the odd Ok(())
Switch to AtomicU64
2019-06-19 10:13:09 +02:00
David
be5db14160 Enable aesni (#10756)
* Run cargo fix

* Optimize imports

* compiles

* cleanup

* Use Secret to store mac-key
Truncate payload properly

* cleanup

* Reorg imports

* brwchk hand waving

* Review feedback

* whitespace

* error chain is dead

* Build parity-ethereum with SSE2, SSSE3 and AES enabled

This enables the `aesni` crate for 50x faster AES crypto.

* Correct rustflag setting

* List all target triples because [target.'cfg(…)'] is broken

* whitespace

* Enable hardware aes for CI builds

* Add note about synchronizing changes

* Remove "Linker" printout

* Build artefacts to check hardware aesni

* Skip signing windows binaries

* Build windows like before

* address grumble
2019-06-18 20:24:21 +02:00
Svyatoslav Nikolsky
1786b6eedd remove support of old SS db formats (#10757) 2019-06-18 13:49:59 +03:00
David
2d693be735 [devp2p] Don't use rust-crypto (#10714)
* Run cargo fix

* Optimize imports

* compiles

* cleanup

* Use Secret to store mac-key
Truncate payload properly

* cleanup

* Reorg imports

* brwchk hand waving

* Review feedback

* whitespace

* error chain is dead
2019-06-17 18:43:13 +02:00
Andronik Ordian
35c607f6be updater: fix static id hashes initialization (#10755)
* updater: fix static id hashes initialization

* Update updater/src/updater.rs
2019-06-17 13:22:53 +02:00
David
20248c443b Use fewer threads for snapshotting (#10752)
* Use fewer threads for snapshotting

When taking a snapshot the current default number of threads is equal to half the number of **logical** CPUs in the system. On HT enabled CPUs this value seems a bit high, e.g. 6 snapshotting threads on a 6/12 core/hyperthread CPU. Maybe a better default value is half the number of physical cores?

* fix test
2019-06-17 11:12:48 +02:00
Andrew Jones
bf55db4c7e Die error_chain, die (#10747)
* Replace error chain for network error

* Fix usages and add manual From impls

* OnDemand Error and remove remaining dependencies

* Die error_chain, die.

* DIE

* Hasta la vista, baby
2019-06-17 08:44:59 +02:00
David
dbdb57a8c0 Fix deprectation warnings on nightly (#10746)
* Run `cargo fix` on ethcore

* Add note about funky import needed-but-not-needed

* Fix benches

* cargo fix blockchain
2019-06-14 18:48:35 +02:00
TriplEight
78a1d8b7b4 fix docker tags for publishing (#10741) 2019-06-14 13:00:57 +02:00
Seun LanLege
1c076af5ee DevP2p: Get node IP address and udp port from Socket, if not included in PING packet (#10705)
* get node IP address and udp port from Socket, if not included in PING packet

* prevent bootnodes from being added to host nodes

* code corrections

* code corrections

* code corrections

* code corrections

* docs

* code corrections

* code corrections

* Apply suggestions from code review

Co-Authored-By: David <dvdplm@gmail.com>
2019-06-12 10:42:16 +02:00
Talha Cross
bf4fa658f3 ethcore: enable ECIP-1054 for classic (#10731)
* config: enable atlantis on ethereum classic

* config: enable atlantis on morden classic

* config: enable atlantis on morden classic

* config: enable atlantis on kotti classic

* ethcore: move kotti fork block to 0xAEF49

* ethcore: move morden fork block to 0x4829BA

* ethcore: move classic fork block to 0x81B320

* remove trailing comma

* remove trailing comma

* fix chainspec

* ethcore: move classic fork block to 0x7fffffffffffffff
2019-06-11 19:55:05 +02:00
David
5da8da68cc Stop breaking out of loop if a non-canonical hash is found (#10729)
* Stop breaking out of loop if a non-canonical hash is found

* include expected hash in log msg

* More logging

* Scope

* Syntax

* Log in blank RollingFinality
Escalate bad proposer to warning

* More readable code

* Extensive logging on unexpected non-canonical hash

* Wording
2019-06-10 18:58:14 +02:00
David
083dcc369b Refactor Clique stepping (#10691)
* Use Drop to shutdown stepper thread
Make period == 0 an error and remove the Option from step_service

* Remove StepService

Remove StepService and spawn the stepping thread in `Clique::new()`. Don't store the thread handle and instead trust the `AtomicBool` to signal shutdown time.
Don't check for `period > 0`: we assume a valid chainspec file.

* Don't shutdown the stepper thread at all, just let it run until exit
Also: fix a few warnings and tests

* Put kvdb_memorydb back

* Warn&exit when engine is dropped
Don't sleep too long!

* Don't delay stepping thread

* Better formatting
2019-06-10 12:10:26 +02:00
David
7827cc048e Use RUSTFLAGS to set the optimization level (#10719)
* Use RUSTFLAGS to set the optimization level

Cargo has a [quirk]() in how configuration settings are propagated when `cargo test` runs: local code respect the settings in `[profile.test]` but all dependencies use the `[profile.dev]` settings. Here we force `opt-level=3` for all dependencies.

* Remove unused profile settings

* Maybe like this?

* Turn off incremental compilation

* Remove colors; try again with overflow-checks on

* Use quiet CI machine

* Turn overflow checking back on

* Be explicit about what options we use

* Remove "quiet machine" override
2019-06-07 11:25:45 +02:00
Svyatoslav Nikolsky
9de1afeeb6 SecretStore: non-blocking wait of session completion (#10303)
* make SS sessions return future

* fix grumbles

* do not create unused Condvar in production mode
2019-06-06 13:35:06 +03:00
Svyatoslav Nikolsky
eed630a002 removed secret_store folder (#10722) 2019-06-05 15:58:11 +03:00
Svyatoslav Nikolsky
6be45367e9 SecretStore: expose restore_key_public in HTTP API (#10241) 2019-06-05 14:04:00 +02:00
David
f7dae48c17 Revert "enable lto for release builds (#10717)" (#10721)
This reverts commit 44161874ff.
2019-06-05 11:57:09 +02:00
Andronik Ordian
44161874ff enable lto for release builds (#10717) 2019-06-04 19:01:18 +02:00
Sfxdx
faf6f1f9ea Merge Notifier and TransactionsPoolNotifier (#10591)
* Merge `Notifier` and `TransactionsPoolNotifier`

* fix tests
2019-06-04 12:35:33 +01:00
David
425dcd45c2 [devp2p] Fix warnings and re-org imports (#10710)
* Run cargo fix

* Optimize imports

* Reorg imports

* Put TODO back in place
2019-06-03 19:21:29 +02:00
Andronik Ordian
dae5d75dd6 Upgrade ethereum types (#10670)
* cargo upgrade "ethereum-types" --all --allow-prerelease

* [ethash] fix compilation errors

* [ethkey] fix compilation errors

* [journaldb] fix compilation errors

* [dir] fix compilation errors

* [ethabi] update to 0.7

* wip

* [eip-712] fix compilation errors

* [ethjson] fix compilation errors

* [Cargo.toml] add TODO to remove patches

* [ethstore] fix compilation errors

* use patched keccak-hash with new primitive-types

* wip

* [ethcore-network-devp2p] fix compilation errors

* [vm] fix compilation errors

* [common-types, evm, wasm] fix compilation errors

* [ethcore-db] Require AsRef instead of Deref for keys

* [ethcore-blockchain] fix some compilation errors

* [blooms-db] fix compilation errors

Thanks a lot @dvdplm :)

* we don't need no rlp ethereum feature

* [ethcore] fix some compilation errors

* [parity-ipfs-api] fix compilation error

* [ethcore-light] fix compilation errors

* [Cargo.lock] update parity-common

* [ethcore-private-tx] fix some compilation errors

* wip

* [ethcore-private-tx] fix compilation errors

* [parity-updater] fix compilation errors

* [parity-rpc] fix compilation errors

* [parity-bin] fix other compilation errors

* update to new ethereum-types

* update keccak-hash

* [fastmap] fix compilation in tests

* [blooms-db] fix compilation in tests

* [common-types] fix compilation in tests

* [triehash-ethereum] fix compilation in tests

* [ethkey] fix compilation in tests

* [pwasm-run-test] fix compilation errors

* [wasm] fix compilation errors

* [ethjson] fix compilation in tests

* [eip-712] fix compilation in tests

* [ethcore-blockchain] fix compilation in tests

* [ethstore] fix compilation in tests

* [ethstore-accounts] fix compilation in tests

* [parity-hash-fetch] fix compilation in tests

* [parity-whisper] fix compilation in tests

* [ethcore-miner] fix compilation in tests

* [ethcore-network-devp2p] fix compilation in tests

* [*] upgrade rand to 0.6

* [evm] get rid of num-bigint conversions

* [ethcore] downgrade trie-standardmap and criterion

* [ethcore] fix some warnings

* [ethcore] fix compilation in tests

* [evmbin] fix compilation in tests

* [updater] fix compilation in tests

* [ethash] fix compilation in tests

* [ethcore-secretstore] fix compilation in tests

* [ethcore-sync] fix compilation in tests

* [parity-rpc] fix compilation in tests

* [ethcore] finally fix compilation in tests

FUCK YEAH!!!

* [ethstore] lazy_static is unused

* [ethcore] fix test

* fix up bad merge

* [Cargo.toml] remove unused patches

* [*] replace some git dependencies with crates.io

* [Cargo.toml] remove unused lazy_static

* [*] clean up

* [ethcore] fix transaction_filter_deprecated test

* [private-tx] fix serialization tests

* fix more serialization tests

* [ethkey] fix smoky test

* [rpc] fix tests, please?

* [ethcore] remove commented out code

* Apply suggestions from code review

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* [ethstore] remove unused dev-dependency

* [ethcore] remove resolved TODO

* [*] resolve keccak-hash TODO

* [*] s/Address::default()/Address::zero()

* [rpc] remove Subscribers::new_test

* [rpc] remove EthPubSubClient::new_test

* [ethcore] use trie-standardmap from crates.io

* [dir] fix db_root_path

* [ethcore] simplify snapshot::tests::helpers::fill_storage

* Apply suggestions from code review

Co-Authored-By: David <dvdplm@gmail.com>

* [ethcore-secretstore] resolve TODO in serialization

* [ethcore-network-devp2p] resolve TODO in save_key

* [Cargo.lock] update triehash

* [*] use ethabi from crates.io

* [ethkey] use secp256k1 from master branch

* [Cargo.lock] update eth-secp256k1
2019-06-03 15:36:21 +02:00
Lazaridis
33d3bfae8b introduce MissingParent Error, fixes #10699 (#10700) 2019-05-31 14:53:17 +02:00
TriplEight
7e89bab4aa Update publishing (#10644)
* docker images are now built on k8s: test run

* copy check_sync.sh in build-linux job

* copy scripts/docker/hub/* in build-linux job

* removed cache var

* cleanup, no more nightly dockers

* cleanup in dockerfile

* some new tags

* removed sccsche debug log, cleanup

* no_gits, new artifacts dir, changed scripts. Test run.

* define version once

* one source for TRACK

* stop kovan onchain updates

* moved changes for two images to a new branch

* rename Dockerfile

* no need in libudev-dev
2019-05-31 13:27:00 +02:00
David
9584faee55 Upgrade to parity-crypto 0.4 (#10650)
* [whisper] Move needed aes_gcm crypto in-crate

In the latest `parity-crypto` release (upcoming 0.4), the aes GCM features were removed (done to remove the dependency on `ring`).
This PR adds the bare minimum crypto needed for Whisper directly to the crate itself and as those were the only features needed from `parity-crypto`, removes the dependency on that crate altogether.

* Upgrade to parity-crypto 0.4

Reverts using NonZeroU32 (introduced [here](b347599cf7)).

* Check for 0 in `args.arg_keys_iteration`

* Use beta.4

* parity-crypto 0.4.0 is released
2019-05-28 07:50:10 +02:00
TriplEight
9bbf8b6c0f new image (#10673) 2019-05-24 11:15:41 +02:00
Andreas Fackler
bf242552f3 Add SealingState; don't prepare block when not ready. (#10529) 2019-05-24 10:30:31 +02:00
David
752031a657 Fix compiler warning (that will become an error) (#10683)
* Remove annoying compiler warnings

* Fix compiler warning (that will become an error)

Fixes https://github.com/paritytech/parity-ethereum/issues/10648

I'm not sure this fix is Good™ but rustc seems happy enough.

There's a deeper issue which may or may not be related to this: the Engine is not shutdown properly and the `StepService` thread keeps running indefinitely after Ctrl-C (so `update_sealing()` is called repeatedly for 300sec). I don't think this is related to Clique as I've seen this happen on mainnet as well, but I wonder if the effects of it are worse for a PoA network where the node can create new blocks all on its own?

* Use saturating_sub

* WIP

* Fix warning, second attempt

The idea here is to avoid using `Arc::get_mut()` (which does not work: fails every time here) and instead trust `drop()` to do the right thing.

This is a conservative change. I think this can be reformed further, e.g. by `impl Drop for StepService` and halt the thread there, or even skip `join()`ing the thread entirely and trust the `AtomicBool` to signal shutdown. I also have doubts abut the `Option<StepService>`: seems a bit much to have an `Option` there and it makes things cumbersome.
2019-05-23 17:37:12 +02:00
David
d250f348a3 add_sync_notifier in EthPubSubClient holds on to a Client for too long (#10689)
Need a weak ref so shutdown works
2019-05-23 07:50:45 +02:00
David
26d1303034 Don't panic if extra_data is longer than VANITY_LENGTH (#10682)
* Don't panic if extra_data is longer than VANITY_LENGTH

Seems like `extra_data().len()` can be longer than 32 (was 39 here) so this fixes that panic.

* Update ethcore/src/engines/clique/mod.rs
2019-05-22 12:35:17 +02:00
Luke Schoen
89987745f6 docs: evmbin - Update Rust docs (#10658)
* docs: Update evmbin to use rustup instead of multirust

* docs: Update evmbin with Rustdocs overview, usage, comments

* review-fix: Simplify evmbin usage commands

* docs: Update evmbin Overview typo

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update evmbin Overview grammer

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update evmbin Rust comments to be lowercase

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update evmbin Rust comments to be lowercase for gas price

Co-Authored-By: David <dvdplm@gmail.com>

* docs: Update evmbin build command Rust docs

Co-Authored-By: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* review-fix: Update evmbin Overview to create release per dvdplm comment

* review-fix: Fix explanation in usage section

* review-fix: Update evmbin usage suggesting user to copy the executable to PATH or create symlink

* review-fix: Update evmbin executable in path sentence

* review-fix: Remove explaining to users how to use binaries since out of scope of docs
2019-05-21 19:42:18 +02:00
David
c31ffab22e Remove annoying compiler warnings (#10679) 2019-05-21 16:12:49 +01:00
Seun LanLege
21a27fee9f Reset blockchain properly (#10669)
* delete BlockDetails from COL_EXTRA

* better proofs

* added tests

* PR suggestions
2019-05-21 13:52:48 +02:00
David
10c121a299 Remove support for hardware wallets (#10678)
* Remove support for hardware wallets

* Remove rpcs relative hardware support

* Remove libudev
2019-05-21 10:46:57 +02:00
Andronik Ordian
67e75e1da1 [CI] allow cargo audit to fail (#10676)
* [CI] allow cargo audit to fail

* [.gitlab-ci.yml] add a comment about cargo audit

* [Cargo.lock] cargo update -p protobuf
2019-05-20 11:59:35 +02:00
Luke Schoen
412e2ce3a0 docs: Add ProgPoW Rust docs to ethash module (#10653)
* docs: Add ProgPoW Rust docs to ethash module

* review-fix: Remove unnecessary lines

* fix: Fix incorrect naming of ProgPoW

Co-Authored-By: Talha Cross <47772477+soc1c@users.noreply.github.com>
2019-05-15 09:24:37 +02:00
Luke Schoen
73f2ff38ec fix: Move PR template into .github/ folder (#10663) 2019-05-14 15:54:29 +02:00
Luke Schoen
981ad0bc53 docs: Add PR template (#10654) 2019-05-14 10:47:13 +01:00
Anton Gavrilov
5a581c1c90 Trivial journal for private transactions (#10056)
* Journal for private txs added

* Tests after adding logging to private tx fixed

* Logs getter and tests added

* Time and amount limit for logs added

* RPC method for log retrieving added

* Correct path name and time validation implemented

* References for parameters added, redundant cloning reworked

* References for parameters added, redundant cloning reworked

* Work with json moved to the separate struct

* Serialization test added

* Fixed build after the merge with head

* Documentation for methods fixed, redundant field removed

* Fixed error usages

* Timestamp trait implemented for std struct

* Commented code removed

* Remove timestamp source, rework serialization test

* u64 replaced with SystemTime

* Path made mandatory for logging

* Source of monotonic time added

* into_system_time method renamed

* Initialize time source by max from current system time and max creation time from already saved logs

* Redundant conversions removed, code a little bit reworked according to review comments

* One more redundant conversion removed, rpc call simplified
2019-05-14 11:21:21 +02:00
Niklas Adolfsson
87699f8de0 fix(compilation warnings) (#10649) 2019-05-13 15:10:25 +02:00
David
42268fd1ef [whisper] Move needed aes_gcm crypto in-crate (#10647)
In the latest `parity-crypto` release (upcoming 0.4), the aes GCM features were removed (done to remove the dependency on `ring`).
This PR adds the bare minimum crypto needed for Whisper directly to the crate itself and as those were the only features needed from `parity-crypto`, removes the dependency on that crate altogether.
2019-05-13 11:25:56 +02:00
Seun LanLege
2cf0d7d775 Adds parity_getRawBlockByNumber, parity_submitRawBlock (#10609)
* adds parity_getRawBlockByNumber

(cherry picked from commit 1b418f592a03d45997f54304ca10889a96199509)

* added parity_submitRawBlock

* remove space

Co-Authored-By: Andronik Ordian <write@reusable.software>
2019-05-10 20:20:42 +01:00
Uxío
de91a5532d Fix rinkeby petersburg fork (#10632) 2019-05-09 15:28:30 +02:00
gabriel klawitter
e91eb337c9 ci: publish docs debug (#10638) 2019-05-08 17:58:51 +02:00
Denis S. Soldatov aka General-Beck
8dfa46f4f0 Fix publish docs (#10635)
* Fix publish docs

* this never should be forced, either way compiling previous versions will produce outdated docs

* fix array, var was moved to the group project global variables list
2019-05-08 14:29:29 +02:00
varasev
e04a2f926a Update kovan.json to switch validator set to POA Consensus Contracts (#10628) 2019-05-07 11:16:21 +02:00
Andrew Jones
98b89c8e4f [ethcore] remove error_chain (#10616)
* Derive Display for BlockError

* Convert error_chain errors

* Convert ethcore usages of errors

* Fix remaining compile errors in ethcore

* Fix other crates

* Fix tests compilation

* Implement error for Snapshot error

* Remove redundant into
2019-05-06 15:06:20 +02:00
Hernando Castano
b30b54e446 Remove unused import (#10615) 2019-04-29 16:08:58 +02:00
Andronik Ordian
4723ea69a1 evm: add some mulmod benches (#10600)
* evm: add blockhash_mulmod bench

* evm: use num-bigint for mod ops
2019-04-29 12:09:23 +02:00
jwasinger
64fd64fd6b Clique: zero-fill extradata when the supplied value is less than 32 bytes in length (#10605) 2019-04-29 10:12:22 +02:00
phahulin
28eb05f032 Constantinople HF on POA Core (#10606)
* Constantinople HF on POA Core

Plan Constantinople/St.Petersfork HF on POA Core network at block 8582254.
Original PR in POA repository: https://github.com/poanetwork/poa-chain-spec/pull/110

* Remove extra empty line
2019-04-26 12:05:04 +02:00
Seun LanLege
969a9815e4 adds rpc error message for --no-ancient-blocks (#10608)
* adds error message for --no-ancient-blocks, closes #10261

* Apply suggestions from code review

Co-Authored-By: seunlanlege <seunlanlege@gmail.com>
2019-04-23 13:54:45 +01:00
Antoine Detante
4cc274e75f Allow CORS requests in Secret Store API (#10584)
* allow CORS requests for Secret Store API (#10582)

* secretstore CORS: fix error with unit tests

* secretstore CORS: removed debug log

* secretstore CORS: add missing response's header

* secretstore CORS: switched to jsonrpc-server-utils for CORS validation
2019-04-20 07:31:37 +02:00
Talha Cross
c5fa7aab43 update bootnodes (#10595)
* config: update goerli bootnodes

* config: update kotti bootnodes
2019-04-17 11:56:24 +02:00
TriplEight
e7cdad6146 sccache logs to stdout (#10596)
* sccache logs to stdout

* trace level puts it to stdout

* superhardcore

* debug log listing

* debug log listing

* no more logs in artifacts, logs are in logs window
2019-04-16 19:46:46 +03:00
Niklas Adolfsson
92e770e916 fix(whisper expiry): current time + work + ttl (#10587) 2019-04-15 15:05:40 +02:00
TriplEight
6fcd775d48 CI improvements (#10579)
* check if it was the file

* collect tog files

* some debug

* some more debug

* some even more debug

* upload all the logs

* change cache max size

* test with max cache size overflow

* verbose for all cargo jobs

* lower max cache size

* Rust nightly and beta test runs reintroduced

* artifacts:when: always, coz on_success is default

* sccache full log

* normal artifacts name, big cache size

* add file to test the compilation again

* another way of getting artifacts

* per-job cache

* data race tests

* is it needed to clean the working folder?

* return to common cache dir

* do not pass logs between jobs

* typo

* avoid artifacts conflict

* colored logs

* always colored logs

* proper stages

* more proper stages skip-ci

* more proper stages [skip-ci]

* shouldn't skip ci
2019-04-12 18:51:01 +02:00
IntegralTeam
944bf6a59e Watch transactions pool (#10558)
adds `parity_watchTransactionsPool`
2019-04-12 12:36:49 +01:00
Niklas Adolfsson
90a7ca9d10 fix(evmbin): make benches compile again (#10586) 2019-04-12 08:49:39 +01:00
Andrew Plaza
9e2b2b361c fix issue with compilation when 'slow-blocks' feature enabled (#10585)
change call to a `header()` function to the field `header`
2019-04-11 11:02:39 +01:00
Talha Cross
08f0573fb5 Reject crazy timestamps instead of truncating. (#10574) 2019-04-08 11:32:51 +02:00
Vladyslav Lupashevskyi
8132d38b50 Node table limiting and cache for node filter (#10288)
* Fix nasty typo in NodeTable::update (add ;)

* Add limiting for NodeTable

* Add cache for NodeFilter

* Use expect instead of unwrap

* Move node in ordered_ids if it exists there in note_failure and note_success + fix expect msg

* Add comment

* Improve code style

* DRY in note_failure and note_success

* Fix nodes ordering

* Simplify match expression

* Add tests for get_index_to_insert

* Remove get_mut method from NodeTable, Add get method to NodeTable

* Fix table_last_contact_order for macos failing because of lost nanosecond precision
2019-04-05 13:30:31 +02:00
Niklas Adolfsson
10e1787ad1 fix(light cull): poll light cull instead of timer (#10559)
* fix(light cull): poll light cull instead of timer

* fix(grumbles): remove error + updated docs

* fix(on-demand request): `expect()` reason

* docs(remove misleading info)
2019-04-04 10:59:07 +02:00
Kirill Pimenov
69085aa282 Update Issue Template to direct security issue to email (#10562)
* Direct security issues to security@ email instead

* Explicitly mentioned out BugBounty and SECURITY.md docs

* Update .github/ISSUE_TEMPLATE.md
2019-04-02 17:35:07 +02:00
Seun LanLege
fba63de974 RPC: Implements eth_subscribe("syncing") (#10311)
* implement eth_subscibe syncing

* fix imports

* add is_major_syncing to SyncProvider

* add eth_subscribe(syncing) support for light clients

* tests

* fix TestSyncClient

* correct LightFetch impl

* added currentBlock, startingBlock, highestBlock to PubSubSyncStatus

* fixed tests

* fix PR grumbles

* improve code style

* is_syncing -> syncing

* code style

* use ethereum types
2019-04-02 17:13:55 +02:00
lamafab
288d73789a Explicitly enable or disable Stratum in config file (Issue 9785) (#10521)
* add disable field and check value while reading config

* test stratum configuration

* fix small typo
2019-04-02 11:19:20 +02:00
Talha Cross
002496603c version: bump master to 2.6 (#10560) 2019-04-02 10:41:47 +02:00
1096 changed files with 238950 additions and 173685 deletions

View File

@@ -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]
# Link the C runtime statically ; https://github.com/openethereum/openethereum/issues/6643
rustflags = ["-Ctarget-feature=+crt-static"]
# Enables the aes-ni instructions for RustCrypto dependency.
# Link the C runtime statically ; https://github.com/paritytech/parity-ethereum/issues/6643
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"]

View File

@@ -1,2 +0,0 @@
# Reformat the source code
610d9baba4af83b5767c659ca2ccfed337af1056

View File

@@ -2,11 +2,11 @@
## 1. Purpose
A primary goal of OpenEthereum is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
A primary goal of Parity is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
We invite all those who participate in OpenEthereum to help us create safe and positive experiences for everyone.
We invite all those who participate in Parity to help us create safe and positive experiences for everyone.
## 2. Open Source Citizenship
@@ -63,7 +63,7 @@ Additionally, community organizers are available to help community members engag
## 7. Addressing Grievances
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify OpenEthereum Technologies with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Parity Technologies with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
## 8. Scope
@@ -73,7 +73,7 @@ This code of conduct and its related procedures also applies to unacceptable beh
## 9. Contact info
You can contact OpenEthereum via Email: community@parity.io
You can contact Parity via Email: community@parity.io
## 10. License and attribution

View File

@@ -2,7 +2,7 @@
## Do you have a question?
Check out our [Basic Usage](https://openethereum.github.io/wiki/Basic-Usage), [Configuration](https://openethereum.github.io/wiki/Configuring-OpenEthereum), and [FAQ](https://openethereum.github.io/wiki/FAQ) articles on our [wiki](https://openethereum.github.io/wiki)!
Check out our [Basic Usage](https://wiki.parity.io/Basic-Usage), [Configuration](https://wiki.parity.io/Configuring-Parity-Ethereum), and [FAQ](https://wiki.parity.io/FAQ) articles on our [wiki](https://wiki.parity.io/)!
See also frequently asked questions [tagged with `parity`](https://ethereum.stackexchange.com/questions/tagged/parity?sort=votes&pageSize=50) on Stack Exchange.
@@ -10,11 +10,11 @@ See also frequently asked questions [tagged with `parity`](https://ethereum.stac
Do **not** open an issue on Github if you think your discovered bug could be a **security-relevant vulnerability**. Please, read our [security policy](../SECURITY.md) instead.
Otherwise, just create a [new issue](https://github.com/openethereum/openethereum/issues/new) in our repository and state:
Otherwise, just create a [new issue](https://github.com/paritytech/parity-ethereum/issues/new) in our repository and state:
- What's your OpenEthereum version?
- What's your Parity Ethereum version?
- What's your operating system and version?
- How did you install OpenEthereum?
- How did you install Parity Ethereum?
- Is your node fully synchronized?
- Did you try turning it off and on again?
@@ -22,11 +22,11 @@ Also, try to include **steps to reproduce** the issue and expand on the **actual
## Contribute!
If you would like to contribute to OpenEthereum, please **fork it**, fix bugs or implement features, and [propose a pull request](https://github.com/openethereum/openethereum/compare).
If you would like to contribute to Parity Ethereum, please **fork it**, fix bugs or implement features, and [propose a pull request](https://github.com/paritytech/parity-ethereum/compare).
### Labels & Milestones
We use [labels](https://github.com/openethereum/openethereum/labels) to manage PRs and issues and communicate the state of a PR. Please familiarize yourself with them. Furthermore we are organizing issues in [milestones](https://github.com/openethereum/openethereum/milestones). Best way to get started is to a pick a ticket from the current milestone tagged [`easy`](https://github.com/openethereum/openethereum/labels/Q2-easy%20%F0%9F%92%83) and get going, or [`mentor`](https://github.com/openethereum/openethereum/labels/Q1-mentor%20%F0%9F%95%BA) and get in contact with the mentor offering their support on that larger task.
We use [labels](https://github.com/paritytech/parity-ethereum/labels) to manage PRs and issues and communicate the state of a PR. Please familiarize yourself with them. Furthermore we are organizing issues in [milestones](https://github.com/paritytech/parity-ethereum/milestones). Best way to get started is to a pick a ticket from the current milestone tagged [`easy`](https://github.com/paritytech/parity-ethereum/labels/Q2-easy%20%F0%9F%92%83) and get going, or [`mentor`](https://github.com/paritytech/parity-ethereum/labels/Q1-mentor%20%F0%9F%95%BA) and get in contact with the mentor offering their support on that larger task.
### Rules
@@ -35,22 +35,22 @@ There are a few basic ground-rules for contributors (including the maintainer(s)
* **No pushing directly to the master branch**.
* **All modifications** must be made in a **pull-request** to solicit feedback from other contributors.
* Pull-requests cannot be merged before CI runs green and two reviewers have given their approval.
* Contributors should adhere to the [Parity Ethereum Style Guide](https://openethereum.github.io/wiki/Parity-Ethereum-Style-Guide).
* Contributors should adhere to the [Parity Ethereum Style Guide](https://wiki.parity.io/Parity-Ethereum-Style-Guide).
### Recommendations
* **Non-master branch names** *should* be prefixed with a short name moniker, followed by the associated Github Issue ID (if any), and a brief description of the task using the format `<GITHUB_USERNAME>-<ISSUE_ID>-<BRIEF_DESCRIPTION>` (e.g. `gavin-123-readme`). The name moniker helps people to inquiry about their unfinished work, and the GitHub Issue ID helps your future self and other developers (particularly those who are onboarding) find out about and understand the original scope of the task, and where it fits into Parity Ethereum [Projects](https://github.com/openethereum/openethereum/projects).
* **Non-master branch names** *should* be prefixed with a short name moniker, followed by the associated Github Issue ID (if any), and a brief description of the task using the format `<GITHUB_USERNAME>-<ISSUE_ID>-<BRIEF_DESCRIPTION>` (e.g. `gavin-123-readme`). The name moniker helps people to inquiry about their unfinished work, and the GitHub Issue ID helps your future self and other developers (particularly those who are onboarding) find out about and understand the original scope of the task, and where it fits into Parity Ethereum [Projects](https://github.com/paritytech/parity-ethereum/projects).
* **Remove stale branches periodically**
### Preparing Pull Requests
* If your PR does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged [`insubstantial`](https://github.com/openethereum/openethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22).
* If your PR does not alter any logic (e.g. comments, dependencies, docs), then it may be tagged [`insubstantial`](https://github.com/paritytech/parity-ethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22).
* Once a PR is ready for review please add the [`pleasereview`](https://github.com/openethereum/openethereum/pulls?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+label%3A%22A0-pleasereview+%F0%9F%A4%93%22+) label.
* Once a PR is ready for review please add the [`pleasereview`](https://github.com/paritytech/parity-ethereum/pulls?utf8=%E2%9C%93&q=is%3Aopen+is%3Apr+label%3A%22A0-pleasereview+%F0%9F%A4%93%22+) label.
### Reviewing Pull Requests*:
* At least two reviewers are required to review PRs (even for PRs tagged [`insubstantial`](https://github.com/openethereum/openethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22)).
* At least two reviewers are required to review PRs (even for PRs tagged [`insubstantial`](https://github.com/paritytech/parity-ethereum/pulls?q=is%3Aopen+is%3Apr+label%3A%22A2-insubstantial+%F0%9F%91%B6%22)).
When doing a review, make sure to look for any:

View File

@@ -1,10 +1,14 @@
_Before filing a new issue, please **provide the following information**._
- **OpenEthereum version**: 0.0.0
_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
View 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!
✄ -----------------------------------------------------------------------------

View File

@@ -1,99 +0,0 @@
name: Build and Test Suite
on:
pull_request:
push:
branches:
- main
- stable
jobs:
build-tests:
name: Test and Build
env:
SCCACHE_CACHE_SIZE: "1G"
SCCACHE_IDLE_TIMEOUT: 0
strategy:
matrix:
platform:
- ubuntu-16.04
- macos-latest
- windows-latest
toolchain:
- stable
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout sources
uses: actions/checkout@main
with:
submodules: true
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
profile: minimal
override: true
- name: Cache cargo registry
uses: actions/cache@v1.1.2
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-build-tests-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v1.1.2
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-git-build-tests-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v1.1.2
with:
path: target
key: ${{ runner.os }}-cargo-build-target-build-tests-${{ hashFiles('**/Cargo.lock') }}
- name: Cache sccache linux
if: matrix.platform == 'ubuntu-16.04'
uses: actions/cache@v1.1.2
with:
path: "/home/runner/.cache/sccache"
key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }}
- name: Cache sccache MacOS
if: matrix.platform == 'macos-latest'
uses: actions/cache@v1.1.2
with:
path: "/Users/runner/Library/Caches/Mozilla.sccache"
key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }}
- name: Cache sccache Windows
if: matrix.platform == 'windows-latest'
uses: actions/cache@v1.1.2
with:
path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache\\cache"
key: ${{ runner.os }}-sccache-build-tests-${{ hashFiles('**/Cargo.lock') }}
- name: Install sccache for ${{ matrix.platform }}
shell: pwsh
run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}}
- name: Install LLVM for Windows
if: matrix.platform == 'windows-latest'
run: choco install llvm
- name: Sccache statistics
run: sccache --show-stats
- name: Build tests
uses: actions-rs/cargo@v1
with:
command: test
args: --locked --all --release --features "json-tests" --verbose --no-run
- name: Run tests for ${{ matrix.platform }}
if: matrix.platform == 'windows-latest'
continue-on-error: true #Skip step if Windows tests failure
uses: actions-rs/cargo@v1
with:
command: test
args: --locked --all --release --features "json-tests" --verbose
- name: Run tests for ${{ matrix.platform }}
if: matrix.platform != 'windows-latest'
uses: actions-rs/cargo@v1
with:
command: test
args: --locked --all --release --features "json-tests" --verbose
- name: Stop sccache
if: always()
run: sccache --stop-server
- name: Prepare build directory for cache
shell: bash
run: bash scripts/actions/clean-target.sh

View File

@@ -1,341 +0,0 @@
name: Build Release Suite
on:
push:
branches:
- stable
tags:
- v*
# Global vars
env:
AWS_REGION: "us-east-1"
AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases"
jobs:
build:
name: Build Release
env:
SCCACHE_CACHE_SIZE: "1G"
SCCACHE_IDLE_TIMEOUT: 0
strategy:
matrix:
platform:
- ubuntu-16.04
- macos-latest
- windows-latest
toolchain:
- stable
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout sources
uses: actions/checkout@main
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.toolchain }}
profile: minimal
override: true
- name: Cache cargo registry
uses: actions/cache@v2
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-build-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v2
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-git-build-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v2
with:
path: target
key: ${{ runner.os }}-cargo-build-target-build-${{ hashFiles('**/Cargo.lock') }}
- name: Cache sccache linux
if: matrix.platform == 'ubuntu-16.04'
uses: actions/cache@v2
with:
path: "/home/runner/.cache/sccache"
key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }}
- name: Cache sccache MacOS
if: matrix.platform == 'macos-latest'
uses: actions/cache@v2
with:
path: "/Users/runner/Library/Caches/Mozilla.sccache"
key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }}
- name: Cache sccache Windows
if: matrix.platform == 'windows-latest'
uses: actions/cache@v2
with:
path: "C:\\Users\\runneradmin\\AppData\\Local\\Mozilla\\sccache\\cache"
key: ${{ runner.os }}-sccache-build-${{ hashFiles('**/Cargo.lock') }}
- name: Install sccache for ${{ matrix.platform }}
shell: pwsh
run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}}
# ==============================
# Windows Build
# ==============================
- name: Install LLVM for Windows
if: matrix.platform == 'windows-latest'
run: choco install llvm
- name: Sccache statistics
run: sccache --show-stats
- name: Build OpenEthereum for Windows
if: matrix.platform == 'windows-latest'
run: sh scripts/actions/build-windows.sh ${{matrix.platform}}
- name: Upload Windows build
uses: actions/upload-artifact@v2
if: matrix.platform == 'windows-latest'
with:
name: windows-artifacts
path: artifacts
# ==============================
# Linux/Macos Build
# ==============================
- name: Build OpenEthereum for ${{matrix.platform}}
if: matrix.platform != 'windows-latest'
run: sh scripts/actions/build-linux.sh ${{matrix.platform}}
- name: Upload Linux build
uses: actions/upload-artifact@v2
if: matrix.platform == 'ubuntu-16.04'
with:
name: linux-artifacts
path: artifacts
- name: Upload MacOS build
uses: actions/upload-artifact@v2
if: matrix.platform == 'macos-latest'
with:
name: macos-artifacts
path: artifacts
# ==============================
# End builds
# ==============================
- name: Stop sccache
if: always()
run: sccache --stop-server
- name: Prepare build directory for cache
shell: bash
run: bash scripts/actions/clean-target.sh
zip-artifacts-creator:
name: Create zip artifacts
needs: build
runs-on: ubuntu-16.04
steps:
- name: Set env
run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF#refs/*/}
# ==============================
# Create ZIP files
# ==============================
- name: Download Windows artifacts
uses: actions/download-artifact@v2
with:
name: windows-artifacts
path: windows-artifacts
- name: Download Linux artifacts
uses: actions/download-artifact@v2
with:
name: linux-artifacts
path: linux-artifacts
- name: Download MacOS artifacts
uses: actions/download-artifact@v2
with:
name: macos-artifacts
path: macos-artifacts
- name: Display structure of downloaded files
run: ls
- name: Create zip Linux
id: create_zip_linux
run: |
cd linux-artifacts/
zip -rT openethereum-linux-${{ env.RELEASE_VERSION }}.zip *
ls openethereum-linux-${{ env.RELEASE_VERSION }}.zip
cd ..
mv linux-artifacts/openethereum-linux-${{ env.RELEASE_VERSION }}.zip .
echo "Setting outputs..."
echo ::set-output name=LINUX_ARTIFACT::openethereum-linux-${{ env.RELEASE_VERSION }}.zip
echo ::set-output name=LINUX_SHASUM::$(shasum -a 256 openethereum-linux-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}')
- name: Create zip MacOS
id: create_zip_macos
run: |
cd macos-artifacts/
zip -rT openethereum-macos-${{ env.RELEASE_VERSION }}.zip *
ls openethereum-macos-${{ env.RELEASE_VERSION }}.zip
cd ..
mv macos-artifacts/openethereum-macos-${{ env.RELEASE_VERSION }}.zip .
echo "Setting outputs..."
echo ::set-output name=MACOS_ARTIFACT::openethereum-macos-${{ env.RELEASE_VERSION }}.zip
echo ::set-output name=MACOS_SHASUM::$(shasum -a 256 openethereum-macos-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}')
- name: Create zip Windows
id: create_zip_windows
run: |
cd windows-artifacts/
zip -rT openethereum-windows-${{ env.RELEASE_VERSION }}.zip *
ls openethereum-windows-${{ env.RELEASE_VERSION }}.zip
cd ..
mv windows-artifacts/openethereum-windows-${{ env.RELEASE_VERSION }}.zip .
echo "Setting outputs..."
echo ::set-output name=WINDOWS_ARTIFACT::openethereum-windows-${{ env.RELEASE_VERSION }}.zip
echo ::set-output name=WINDOWS_SHASUM::$(shasum -a 256 openethereum-windows-${{ env.RELEASE_VERSION }}.zip | awk '{print $1}')
# =======================================================================
# Upload artifacts
# This is required to share artifacts between different jobs
# =======================================================================
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip
path: openethereum-linux-${{ env.RELEASE_VERSION }}.zip
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip
path: openethereum-macos-${{ env.RELEASE_VERSION }}.zip
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip
path: openethereum-windows-${{ env.RELEASE_VERSION }}.zip
# =======================================================================
# Upload artifacts to S3
# This is required by some software distribution systems which require
# artifacts to be downloadable, like Brew on MacOS.
# =======================================================================
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Copy files to S3 with the AWS CLI
run: |
# Deploy zip artifacts to S3 bucket to a directory whose name is the tagged release version.
# Deploy macos binary artifact (if required, add more `aws s3 cp` commands to deploy specific OS versions)
aws s3 cp macos-artifacts/openethereum s3://${{ env.AWS_S3_ARTIFACTS_BUCKET }}/${{ env.RELEASE_VERSION }}/macos/ --region ${{ env.AWS_REGION }}
outputs:
linux-artifact: ${{ steps.create_zip_linux.outputs.LINUX_ARTIFACT }}
linux-shasum: ${{ steps.create_zip_linux.outputs.LINUX_SHASUM }}
macos-artifact: ${{ steps.create_zip_macos.outputs.MACOS_ARTIFACT }}
macos-shasum: ${{ steps.create_zip_macos.outputs.MACOS_SHASUM }}
windows-artifact: ${{ steps.create_zip_windows.outputs.WINDOWS_ARTIFACT }}
windows-shasum: ${{ steps.create_zip_windows.outputs.WINDOWS_SHASUM }}
draft-release:
name: Draft Release
needs: zip-artifacts-creator
runs-on: ubuntu-16.04
steps:
- name: Set env
run: echo ::set-env name=RELEASE_VERSION::${GITHUB_REF#refs/*/}
# ==============================
# Download artifacts
# ==============================
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip
- name: Display structure of downloaded files
run: ls
# ==============================
# Create release draft
# ==============================
- name: Create Release Draft
id: create_release_draft
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
with:
tag_name: ${{ github.ref }}
release_name: OpenEthereum ${{ github.ref }}
body: |
This release contains <ADD_TEXT>
| System | Architecture | Binary | Sha256 Checksum |
|:---:|:---:|:---:|:---|
| <img src="https://gist.github.com/5chdn/1fce888fde1d773761f809b607757f76/raw/44c4f0fc63f1ea8e61a9513af5131ef65eaa6c75/apple.png" alt="Apple Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect" style="width: 32px;"/> | x64 | [${{ needs.zip-artifacts-creator.outputs.macos-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.macos-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.macos-shasum }}` |
| <img src="https://gist.github.com/5chdn/1fce888fde1d773761f809b607757f76/raw/44c4f0fc63f1ea8e61a9513af5131ef65eaa6c75/linux.png" alt="Linux Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect" style="width: 32px;"/> | x64 | [${{ needs.zip-artifacts-creator.outputs.linux-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.linux-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.linux-shasum }}` |
| <img src="https://gist.github.com/5chdn/1fce888fde1d773761f809b607757f76/raw/44c4f0fc63f1ea8e61a9513af5131ef65eaa6c75/windows.png" alt="Windows Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect" style="width: 32px;"/> | x64 | [${{ needs.zip-artifacts-creator.outputs.windows-artifact }}](https://github.com/openethereum/openethereum/releases/download/${{ env.RELEASE_VERSION }}/${{ needs.zip-artifacts-creator.outputs.windows-artifact }}) | `${{ needs.zip-artifacts-creator.outputs.windows-shasum }}` |
| | | | |
| **System** | **Option** | - | **Resource** |
| <img src="https://gist.github.com/5chdn/1fce888fde1d773761f809b607757f76/raw/44c4f0fc63f1ea8e61a9513af5131ef65eaa6c75/settings.png" alt="Settings Icon by Pixel Perfect from https://www.flaticon.com/authors/pixel-perfect" style="width: 32px;"/> | Docker | - | [hub.docker.com/r/openethereum/openethereum](https://hub.docker.com/r/openethereum/openethereum) |
draft: true
prerelease: true
- name: Upload Release Asset - Linux
id: upload_release_asset_linux
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./openethereum-linux-${{ env.RELEASE_VERSION }}.zip
asset_name: openethereum-linux-${{ env.RELEASE_VERSION }}.zip
asset_content_type: application/zip
- name: Upload Release Asset - MacOS
id: upload_release_asset_macos
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./openethereum-macos-${{ env.RELEASE_VERSION }}.zip
asset_name: openethereum-macos-${{ env.RELEASE_VERSION }}.zip
asset_content_type: application/zip
- name: Upload Release Asset - Windows
id: upload_release_asset_windows
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release_draft.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./openethereum-windows-${{ env.RELEASE_VERSION }}.zip
asset_name: openethereum-windows-${{ env.RELEASE_VERSION }}.zip
asset_content_type: application/zip

View File

@@ -1,86 +0,0 @@
name: Check
on:
pull_request:
push:
branches:
- main
- stable
jobs:
check:
name: Check
runs-on: ubuntu-16.04
env:
SCCACHE_CACHE_SIZE: "1G"
SCCACHE_IDLE_TIMEOUT: 0
steps:
- name: Checkout sources
uses: actions/checkout@main
with:
submodules: true
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Cache cargo registry
uses: actions/cache@v2
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v2
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-git-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo build
uses: actions/cache@v2
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
# Install sccache based on https://github.com/denoland/rusty_v8/blob/master/.github/workflows/ci.yml#L69
- name: Cache sccache
uses: actions/cache@v2
with:
path: "/home/runner/.cache/sccache"
key: ${{ runner.os }}-sccache-check-${{ hashFiles('**/Cargo.lock') }}
- name: Install sccache for Linux
shell: pwsh
run: pwsh scripts/actions/install-sccache.ps1 ${{ runner.os}}
- name: Sccache statistics
run: sccache --show-stats
- name: Run cargo check 1/3
uses: actions-rs/cargo@v1
with:
command: check
args: --locked --no-default-features --verbose
- name: Run cargo check 2/3
uses: actions-rs/cargo@v1
with:
command: check
args: --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose
- name: Run cargo check 3/3
uses: actions-rs/cargo@v1
with:
command: check
args: --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose
- name: Run cargo check evmbin
uses: actions-rs/cargo@v1
with:
command: check
args: --locked -p evmbin --verbose
- name: Run cargo check benches
uses: actions-rs/cargo@v1
with:
command: check
args: --locked --all --benches --verbose
- name: Run validate chainspecs
run: ./scripts/actions/validate-chainspecs.sh
- name: Stop sccache
if: always()
run: sccache --stop-server
continue-on-error: true
- name: Prepare build directory for cache
shell: bash
run: bash scripts/actions/clean-target.sh

View File

@@ -1,30 +0,0 @@
name: Docker Image Release
on:
push:
branches:
- main
tags:
- v*
jobs:
deploy-docker:
name: Build Release
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@master
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
override: true
- name: Deploy to docker hub
uses: elgohr/Publish-Docker-Github-Action@master
with:
name: openethereum/openethereum
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
dockerfile: scripts/docker/alpine/Dockerfile
tag_names: true

View File

@@ -1,20 +0,0 @@
on: [push, pull_request]
name: rustfmt
jobs:
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- run: rustup component add rustfmt
- uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check --config merge_imports=true

4
.gitignore vendored
View File

@@ -38,10 +38,8 @@ node_modules
# Build artifacts
out/
parity-clib-examples/cpp/build/
.vscode
rls/
/parity.*
# cargo remote artifacts
remote-target

356
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,356 @@
stages:
- test
- build
- publish
- optional
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
- tags
- schedules
.collect_artifacts: &collect_artifacts
artifacts:
name: "${CI_JOB_NAME}_${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}"
when: on_success
expire_in: 1 mos
paths:
- artifacts/
- tools/
.docker-cache-status: &docker-cache-status
dependencies: []
interruptible: true
before_script:
- rustup show
- cargo --version
retry:
max: 2
when:
- runner_system_failure
- unknown_failure
- api_failure
tags:
- linux-docker
.build-on-linux: &build-on-linux
stage: build
<<: *docker-cache-status
<<: *collect_artifacts
script:
- scripts/gitlab/build-linux.sh
after_script:
- mkdir -p tools
- cp -r scripts/docker/hub/* ./tools
- cp scripts/gitlab/publish-snap.sh ./tools
- cp scripts/gitlab/publish-onchain.sh ./tools
- cp scripts/gitlab/safe-curl.sh ./tools
- echo v"$(sed -r -n '1,/^version/s/^version\s*=\s*"([^"]+)".*$/\1/p' Cargo.toml)" |
tee ./tools/VERSION
- echo "$(sed -r -n '1,/^track/s/^track\s*=\s*"([^"]+)".*$/\1/p' ./util/version/Cargo.toml)" |
tee ./tools/TRACK
cargo-check 0 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --no-default-features --verbose --color=always
- sccache --show-stats
cargo-check 1 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --no-default-features --verbose --color=always
- sccache --show-stats
cargo-check 2 3:
stage: test
<<: *docker-cache-status
script:
- time cargo check --target $CARGO_TARGET --locked --manifest-path util/io/Cargo.toml --features "mio" --verbose --color=always
- sccache --show-stats
cargo-check-evmbin:
stage: test
<<: *docker-cache-status
script:
- time cargo check -p evmbin --target $CARGO_TARGET --locked --verbose --color=always
- sccache --show-stats
cargo-check-benches:
stage: test
<<: *docker-cache-status
script:
- time cargo check --all --benches --target $CARGO_TARGET --locked --verbose --color=always
- sccache --show-stats
cargo-audit:
stage: test
<<: *docker-cache-status
script:
- cargo audit
allow_failure: true # failed cargo audit shouldn't prevent a PR from being merged
validate-chainspecs:
stage: test
<<: *docker-cache-status
script:
- ./scripts/gitlab/validate-chainspecs.sh
test-linux:
stage: build
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-linux.sh stable
test-linux-beta:
stage: build
only: *releaseable_branches
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-linux.sh beta
test-linux-nightly:
stage: build
only: *releaseable_branches
<<: *docker-cache-status
script:
- ./scripts/gitlab/test-linux.sh nightly
allow_failure: true
build-linux:
<<: *build-on-linux
only: *releaseable_branches
build-linux-i386:
<<: *build-on-linux
only: *releaseable_branches
image: ${REGISTRY}/parity-ci-i386:latest
variables:
CARGO_TARGET: i686-unknown-linux-gnu
build-linux-arm64:
<<: *build-on-linux
only: *releaseable_branches
image: ${REGISTRY}/parity-ci-arm64:latest
variables:
CARGO_TARGET: aarch64-unknown-linux-gnu
build-linux-armhf:
<<: *build-on-linux
only: *releaseable_branches
image: ${REGISTRY}/parity-ci-armhf:latest
variables:
CARGO_TARGET: armv7-unknown-linux-gnueabihf
build-darwin:
stage: build
<<: *collect_artifacts
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-apple-darwin
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
script:
- scripts/gitlab/build-linux.sh
tags:
- rust-osx
build-windows:
stage: build
<<: *collect_artifacts
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-pc-windows-msvc
CARGO_HOME: "C:/ci-cache/parity-ethereum/cargo/$CI_JOB_NAME"
GIT_SUBMODULE_STRATEGY: none
script:
- sh scripts/gitlab/build-windows.sh
tags:
- rust-windows
publish-docker:
stage: publish
only: *releaseable_branches
except:
- nightly
when: manual
dependencies:
- build-linux
environment:
name: parity-build
cache: {}
image: docker:stable
services:
- docker:dind
variables:
GIT_STRATEGY: none
DOCKER_HOST: tcp://localhost:2375
DOCKER_DRIVER: overlay2
GIT_STRATEGY: none
# DOCKERFILE: tools/Dockerfile
# CONTAINER_IMAGE: parity/parity
script:
- ./tools/publish-docker.sh
tags:
- kubernetes-parity-build
publish-snap-nightly: &publish-snap
stage: publish
only:
- nightly
image: snapcore/snapcraft
variables:
GIT_STRATEGY: none
BUILD_ARCH: amd64
cache: {}
dependencies:
- build-linux
tags:
- linux-docker
script:
- ./tools/publish-snap.sh
publish-snap-manually:
<<: *publish-snap
only: *releaseable_branches
when: manual
publish-snap-i386-nightly: &publish-snap-i386
<<: *publish-snap
variables:
BUILD_ARCH: i386
CARGO_TARGET: i686-unknown-linux-gnu
dependencies:
- build-linux-i386
publish-snap-i386-manually:
<<: *publish-snap-i386
only: *releaseable_branches
when: manual
publish-snap-arm64-nightly: &publish-snap-arm64
<<: *publish-snap
variables:
BUILD_ARCH: arm64
CARGO_TARGET: aarch64-unknown-linux-gnu
dependencies:
- build-linux-arm64
publish-snap-arm64-manually:
<<: *publish-snap-arm64
only: *releaseable_branches
when: manual
publish-snap-armhf-nightly: &publish-snap-armhf
<<: *publish-snap
variables:
BUILD_ARCH: armhf
CARGO_TARGET: armv7-unknown-linux-gnueabihf
dependencies:
- build-linux-armhf
publish-snap-armhf-manually:
<<: *publish-snap-armhf
only: *releaseable_branches
when: manual
publish-onchain-nightly: &publish-onchain
stage: publish
only:
- nightly
cache: {}
variables:
GIT_STRATEGY: none
dependencies:
- build-linux
- build-darwin
- build-windows
script:
- ./tools/publish-onchain.sh
tags:
- linux-docker
publish-onchain-manually:
<<: *publish-onchain
only: *releaseable_branches
when: manual
publish-release-awss3-nightly: &publish-release-awss3
image: ${REGISTRY}/awscli:latest
stage: publish
only:
- nightly
variables:
GIT_STRATEGY: none
cache: {}
dependencies:
- build-linux
- build-darwin
- build-windows
script:
- echo "__________Push binaries to AWS S3____________"
- case "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" in
(stable|nightly)
export BUCKET=releases.parity.io/ethereum;
;;
(*)
export BUCKET=builds-parity;
;;
esac
- aws s3 sync ./artifacts s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}/
- echo "__________Read from S3____________"
- aws s3 ls s3://${BUCKET}/${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}} --recursive --human-readable --summarize
tags:
- linux-docker
publish-release-awss3-manually:
<<: *publish-release-awss3
only: *releaseable_branches
when: manual
publish-docs:
stage: publish
image: ${REGISTRY}/parity-ci-docs:latest
only:
- tags
except:
- nightly
when: manual
cache: {}
dependencies: []
script:
- scripts/gitlab/publish-docs.sh
tags:
- linux-docker
allow_failure: true
publish-av-whitelist:
stage: publish
variables:
GIT_STRATEGY: none
only: *releaseable_branches
except:
- nightly
when: manual
cache: {}
dependencies:
- build-windows
script:
- scripts/gitlab/publish-av-whitelists.sh
tags:
- linux-docker

View File

@@ -1,34 +1,397 @@
## OpenEthereum v3.1RC1
## 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.
OpenEthereum 3.1rc1 is a candidate release based on v2.5.13 which is the last stable version known of the client that does not include any of the issues introduced in v2.7.
It removes non core features like Ethereum Classic, Private Transactions, Light Client, Updater, IPFS and Swarm support, currently deprecated flags such as expanse, kotti, mordor testnets.
The full list of included changes:
Database migration utility currently in beta: https://github.com/openethereum/3.1-db-upgrade-tool
* 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)
The full list of included changes from v2.5.13 to v3.1:
## 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.
- Remove classic, kotti, mordor, expanse (#52)
- Added bad block header hash for ropsten (#49)
- Remove accounts bloom (#33)
- Bump jsonrpc-- to v15
- Implement eth/64, remove eth/62 (#46)
- No snapshotting by default (#11814)
- Update Ellaism chainspec
- Prometheus, heavy memory calls removed (#27)
- Update ethereum/tests
- Implement JSON test suite (#11801)
- Fix issues during block sync (#11265)
- Fix race same block (#11400)
- EIP-2537: Precompile for BLS12-381 curve operations (#11707)
- Remove private transactions
- Remove GetNodeData
- Remove IPFS integration (#11532)
- Remove updater
- Remove light client
- Remove C and Java bindings (#11346)
- Remove whisper (#10855)
- EIP-2315: Simple Subroutines for the EVM (#11629)
- Remove deprecated flags (removal of --geth flag)
- Remove support for hardware wallets (#10678)
- Update bootnodes
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)
* [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)
* 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)
* Insert explicit warning into the panic hook (#11225)
* Snapshot restoration overhaul (#11219)
* Fix docker centos build (#11226)
* retry on gitlab system failures (#11222)
* Update bootnodes. (#11203)
* Use provided usd-per-eth value if an endpoint is specified (#11209)
* 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)
* [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)
* 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)
* [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)
* 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)
* [trace] check mem diff within range (#11002)
* EIP-1344 Add CHAINID op-code (#10983)
* Make ClientIoMessage generic over the Client (#10981)
* bump spin to 0.5.2 (#10996)
* fix compile warnings (#10993)
* Fix compilation on recent nightlies (#10991)
* [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)
* 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)
* 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)
* 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)

3796
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,78 +1,82 @@
[package]
description = "OpenEthereum"
name = "openethereum"
description = "Parity Ethereum client"
name = "parity-ethereum"
# NOTE Make sure to update util/version/Cargo.toml as well
version = "3.1.0"
version = "2.7.2"
license = "GPL-3.0"
authors = [
"OpenEthereum developers",
"Parity Technologies <admin@parity.io>"
]
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"
hyper = { version = "0.12" }
fdlimit = "0.1"
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
jsonrpc-core = "15.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" }
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" }
fetch = { path = "util/fetch" }
node-filter = { path = "ethcore/node-filter" }
rlp = { version = "0.3.0", features = ["ethereum"] }
cli-signer= { path = "cli-signer" }
parity-daemonize = "0.3"
parity-local-store = { path = "miner/local-store" }
parity-runtime = { path = "util/runtime" }
parity-rpc = { path = "rpc" }
parity-version = { path = "util/version" }
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"
fdlimit = "0.1"
futures = "0.1"
journaldb = { path = "util/journaldb" }
stats = { path = "util/stats" }
prometheus = "0.9.0"
ethcore-secretstore = { path = "secret-store", optional = true }
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" }
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-path = "0.1"
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"
@@ -82,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"] }
@@ -92,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.
@@ -107,17 +109,17 @@ deadlock_detection = ["parking_lot/deadlock_detection"]
# `valgrind --tool=massif /path/to/parity <parity params>`
# and `massif-visualizer` for visualization
memory_profiling = []
# hardcode version number 1.3.7 of parity to force an update
# in order to manually test that parity fall-over to the local version
# in case of invalid or deprecated command line arguments are entered
test-updater = ["parity-updater/test-updater"]
[lib]
path = "parity/lib.rs"
[[bin]]
path = "parity/main.rs"
name = "openethereum"
[profile.test]
lto = false
opt-level = 3 # makes tests slower to compile, but faster to run
name = "parity"
[profile.release]
debug = false
@@ -133,12 +135,4 @@ members = [
"chainspec",
"ethcore/wasm/run",
"evmbin",
"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" }

227
README.md
View File

@@ -1,19 +1,11 @@
# OpenEthereum
![Parity Ethereum](docs/logo-parity-ethereum.svg)
Fast and feature-rich multi-network Ethereum client.
<h2 align="center">The Fastest and most Advanced Ethereum Client.</h2>
[» Download the latest release «](https://github.com/openethereum/openethereum/releases/latest)
<p align="center"><strong><a href="https://github.com/paritytech/parity-ethereum/releases/latest">» Download the latest release «</a></strong></p>
[![GPL licensed][license-badge]][license-url]
[![Build Status][ci-badge]][ci-url]
[![Discord chat][chat-badge]][chat-url]
[license-badge]: https://img.shields.io/badge/license-GPL_v3-green.svg
[license-url]: LICENSE
[ci-badge]: https://github.com/openethereum/openethereum/workflows/Build%20and%20Test%20Suite/badge.svg
[ci-url]: https://github.com/openethereum/openethereum/actions
[chat-badge]: https://img.shields.io/discord/669192218728202270.svg?logo=discord
[chat-url]: https://discord.io/openethereum
<p align="center"><a href="https://gitlab.parity.io/parity/parity-ethereum/commits/master" target="_blank"><img src="https://gitlab.parity.io/parity/parity-ethereum/badges/master/build.svg" /></a>
<a href="https://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank"><img src="https://img.shields.io/badge/license-GPL%20v3-green.svg" /></a></p>
## Table of Contents
@@ -22,17 +14,19 @@ Fast and feature-rich multi-network Ethereum client.
3. [Building](#chapter-003)<br>
3.1 [Building Dependencies](#chapter-0031)<br>
3.2 [Building from Source Code](#chapter-0032)<br>
3.3 [Starting OpenEthereum](#chapter-0034)
3.3 [Simple One-Line Installer for Mac and Linux](#chapter-0033)<br>
3.4 [Starting Parity Ethereum](#chapter-0034)
4. [Testing](#chapter-004)
5. [Documentation](#chapter-005)
6. [Toolchain](#chapter-006)
7. [Contributing](#chapter-008)
8. [License](#chapter-009)
7. [Community](#chapter-007)
8. [Contributing](#chapter-008)
9. [License](#chapter-009)
## 1. Description <a id="chapter-001"></a>
**Built for mission-critical use**: Miners, service providers, and exchanges need fast synchronisation and maximum uptime. OpenEthereum provides the core infrastructure essential for speedy and reliable services.
**Built for mission-critical use**: Miners, service providers, and exchanges need fast synchronisation and maximum uptime. Parity Ethereum provides the core infrastructure essential for speedy and reliable services.
- Clean, modular codebase for easy customisation
- Advanced CLI-based client
@@ -42,19 +36,19 @@ Fast and feature-rich multi-network Ethereum client.
## 2. Technical Overview <a id="chapter-002"></a>
OpenEthereum's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing OpenEthereum using the **Rust programming language**. OpenEthereum is licensed under the GPLv3 and can be used for all your Ethereum needs.
Parity Ethereum's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity Ethereum using the sophisticated and cutting-edge **Rust programming language**. Parity Ethereum is licensed under the GPLv3 and can be used for all your Ethereum needs.
By default, OpenEthereum runs a JSON-RPC HTTP server on port `:8545` and a Web-Sockets server on port `:8546`. This is fully configurable and supports a number of APIs.
By default, Parity Ethereum runs a JSON-RPC HTTP server on port `:8545` and a Web-Sockets server on port `:8546`. This is fully configurable and supports a number of APIs.
If you run into problems while using OpenEthereum, check out the [old wiki for documentation](https://openethereum.github.io/wiki/), feel free to [file an issue in this repository](https://github.com/openethereum/openethereum/issues/new), or hop on our [Discord](https://discord.io/openethereum) chat room to ask a question. We are glad to help!
If you run into problems while using Parity Ethereum, check out the [wiki for documentation](https://wiki.parity.io/), feel free to [file an issue in this repository](https://github.com/paritytech/parity-ethereum/issues/new), or hop on our [Gitter](https://gitter.im/paritytech/parity) or [Riot](https://riot.im/app/#/group/+parity:matrix.parity.io) chat room to ask a question. We are glad to help! **For security-critical issues**, please refer to the security policy outlined in [SECURITY.md](SECURITY.md).
You can download OpenEthereum's latest release at [the releases page](https://github.com/openethereum/openethereum/releases) or follow the instructions below to build from source. Read the [CHANGELOG.md](CHANGELOG.md) for a list of all changes between different versions.
Parity Ethereum's current beta-release is 2.6. You can download it at [the releases page](https://github.com/paritytech/parity-ethereum/releases) or follow the instructions below to build from source. Please, mind the [CHANGELOG.md](CHANGELOG.md) for a list of all changes between different versions.
## 3. Building <a id="chapter-003"></a>
### 3.1 Build Dependencies <a id="chapter-0031"></a>
OpenEthereum requires **latest stable Rust version** to build.
Parity Ethereum requires **latest stable Rust version** to build.
We recommend installing Rust through [rustup](https://www.rustup.rs/). If you don't already have `rustup`, you can install it like this:
@@ -63,7 +57,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
$ curl https://sh.rustup.rs -sSf | sh
```
OpenEthereum also requires `clang` (>= 9.0), `clang++`, `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
@@ -83,14 +77,14 @@ Once you have `rustup` installed, then you need to install:
* [Perl](https://www.perl.org)
* [Yasm](https://yasm.tortall.net)
Make sure that these binaries are in your `PATH`. After that, you should be able to build OpenEthereum from source.
Make sure that these binaries are in your `PATH`. After that, you should be able to build Parity Ethereum from source.
### 3.2 Build from Source Code <a id="chapter-0032"></a>
```bash
# download OpenEthereum code
$ git clone https://github.com/openethereum/openethereum
$ cd openethereum
# download Parity Ethereum code
$ git clone https://github.com/paritytech/parity-ethereum
$ cd parity-ethereum
# build in release mode
$ cargo build --release --features final
@@ -110,32 +104,50 @@ Note, when compiling a crate and you receive errors, it's in most cases your out
$ cargo clean
```
This always compiles the latest nightly builds. If you want to build stable, do a
This always compiles the latest nightly builds. If you want to build stable or beta, do a
```bash
$ git checkout stable
```
### 3.3 Starting OpenEthereum <a id="chapter-0034"></a>
or
```bash
$ git checkout beta
```
### 3.3 Simple One-Line Installer for Mac and Linux <a id="chapter-0033"></a>
```bash
bash <(curl https://get.parity.io -L)
```
The one-line installer always defaults to the latest beta release. To install a stable release, run:
```bash
bash <(curl https://get.parity.io -L) -r stable
```
### 3.4 Starting Parity Ethereum <a id="chapter-0034"></a>
#### Manually
To start OpenEthereum manually, just run
To start Parity Ethereum manually, just run
```bash
$ ./target/release/openethereum
$ ./target/release/parity
```
so OpenEthereum begins syncing the Ethereum blockchain.
so Parity Ethereum begins syncing the Ethereum blockchain.
#### Using `systemd` service file
To start OpenEthereum as a regular user using `systemd` init:
To start Parity Ethereum as a regular user using `systemd` init:
1. Copy `./scripts/openethereum.service` to your
1. Copy `./scripts/parity.service` to your
`systemd` user directory (usually `~/.config/systemd/user`).
2. Copy release to bin folder, write `sudo install ./target/release/openethereum /usr/bin/openethereum`
3. To configure OpenEthereum, see [our old wiki](https://openethereum.github.io/wiki/Configuring-OpenEthereum) for details.
2. Copy release to bin folder, write `sudo install ./target/release/parity /usr/bin/parity`
3. To configure Parity Ethereum, write a `/etc/parity/config.toml` config file, see [Configuring Parity Ethereum](https://paritytech.github.io/wiki/Configuring-Parity) for details.
## 4. Testing <a id="chapter-004"></a>
@@ -157,11 +169,13 @@ You can show your logs in the test output by passing `--nocapture` (i.e. `cargo
## 5. Documentation <a id="chapter-005"></a>
Be sure to [check out our old wiki](https://openethereum.github.io/wiki/) for more information.
Official website: https://parity.io
### Viewing documentation for OpenEthereum packages
Be sure to [check out our wiki](https://wiki.parity.io) for more information.
You can generate documentation for OpenEthereum Rust packages that automatically opens in your web browser using [rustdoc with Cargo](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo) (of the The Rustdoc Book), by running the the following commands:
### Viewing documentation for Parity Ethereum packages
You can generate documentation for Parity Ethereum Rust packages that automatically opens in your web browser using [rustdoc with Cargo](https://doc.rust-lang.org/rustdoc/what-is-rustdoc.html#using-rustdoc-with-cargo) (of the The Rustdoc Book), by running the the following commands:
* **All** packages
```
@@ -175,137 +189,192 @@ You can generate documentation for OpenEthereum Rust packages that automatically
Use`--document-private-items` to also view private documentation and `--no-deps` to exclude building documentation for dependencies.
Replacing `<spec>` with one of the following from the details section below (i.e. `cargo doc --package openethereum --open`):
Replacing `<spec>` with one of the following from the details section below (i.e. `cargo doc --package parity-ethereum --open`):
<a id="package-list"></a>
**Package List**
<details><p>
* OpenEthereum Client Application
* Parity Ethereum (EthCore) Client Application
```bash
openethereum
parity-ethereum
```
* OpenEthereum Account Management, Key Management Tool, and Keys Generator
* Parity Ethereum Account Management, Key Management Tool, and Keys Generator
```bash
ethcore-accounts, ethkey-cli, ethstore, ethstore-cli
```
* OpenEthereum Chain Specification
* Parity Chain Specification
```bash
chainspec
```
* OpenEthereum CLI Signer Tool & RPC Client
* Parity CLI Signer Tool & RPC Client
```bash
cli-signer parity-rpc-client
```
* OpenEthereum Ethash & ProgPoW Implementations
* Parity Ethereum Ethash & ProgPoW Implementations
```bash
ethash
```
* EthCore Library
* Parity (EthCore) Library
```bash
ethcore
```
* OpenEthereum Blockchain Database, Test Generator, Configuration,
* Parity Ethereum Blockchain Database, Test Generator, Configuration,
Caching, Importing Blocks, and Block Information
```bash
ethcore-blockchain
```
* OpenEthereum Contract Calls and Blockchain Service & Registry Information
* Parity Ethereum (EthCore) Contract Calls and Blockchain Service & Registry Information
```bash
ethcore-call-contract
```
* OpenEthereum Database Access & Utilities, Database Cache Manager
* Parity Ethereum (EthCore) Database Access & Utilities, Database Cache Manager
```bash
ethcore-db
```
* OpenEthereum Virtual Machine (EVM) Rust Implementation
* Parity Ethereum Virtual Machine (EVM) Rust Implementation
```bash
evm
```
* OpenEthereum Light Client Implementation
* Parity Ethereum (EthCore) Light Client Implementation
```bash
ethcore-light
```
* Smart Contract based Node Filter, Manage Permissions of Network Connections
* Parity Smart Contract based Node Filter, Manage Permissions of Network Connections
```bash
node-filter
```
* OpenEthereum Client & Network Service Creation & Registration with the I/O Subsystem
* Parity Private Transactions
```bash
ethcore-private-tx
```
* Parity Ethereum (EthCore) Client & Network Service Creation & Registration with the I/O Subsystem
```bash
ethcore-service
```
* OpenEthereum Blockchain Synchronization
* Parity Ethereum (EthCore) Blockchain Synchronization
```bash
ethcore-sync
```
* OpenEthereum Common Types
* Parity Ethereum Common Types
```bash
common-types
```
* OpenEthereum Virtual Machines (VM) Support Library
* Parity Ethereum Virtual Machines (VM) Support Library
```bash
vm
```
* OpenEthereum WASM Interpreter
* Parity Ethereum WASM Interpreter
```bash
wasm
```
* OpenEthereum WASM Test Runner
* Parity Ethereum WASM Test Runner
```bash
pwasm-run-test
```
* OpenEthereum EVM Implementation
* Parity EVM Implementation
```bash
evmbin
```
* OpenEthereum JSON Deserialization
* Parity Ethereum IPFS-compatible API
```bash
parity-ipfs-api
```
* Parity Ethereum JSON Deserialization
```bash
ethjson
```
* OpenEthereum State Machine Generalization for Consensus Engines
* Parity Ethereum State Machine Generalization for Consensus Engines
```bash
parity-machine
```
* OpenEthereum Miner Interface
* Parity Ethereum (EthCore) Miner Interface
```bash
ethcore-miner parity-local-store price-info ethcore-stratum using_queue
```
* OpenEthereum Logger Implementation
* Parity Ethereum (EthCore) Logger Implementation
```bash
ethcore-logger
```
* OpenEthereum JSON-RPC Servers
* C bindings library for the Parity Ethereum client
```bash
parity-clib
```
* Parity Ethereum JSON-RPC Servers
```bash
parity-rpc
```
* OpenEthereum Updater Service
* Parity Ethereum (EthCore) Secret Store
```bash
ethcore-secretstore
```
* Parity Updater Service
```bash
parity-updater parity-hash-fetch
```
* OpenEthereum Core Libraries (`util`)
* Parity Core Libraries (Parity Util)
```bash
accounts-bloom blooms-db dir eip-712 fake-fetch fastmap fetch ethcore-io
journaldb keccak-hasher len-caching-lock memory-cache memzero
ethcore-bloom-journal blooms-db dir eip-712 fake-fetch fastmap fetch ethcore-io
journaldb keccak-hasher len-caching-lock macros memory-cache memzero
migration-rocksdb ethcore-network ethcore-network-devp2p panic_hook
patricia-trie-ethereum registrar rlp_compress stats
patricia-trie-ethereum registrar rlp_compress rlp_derive parity-runtime stats
time-utils triehash-ethereum unexpected parity-version
```
</p></details>
### Contributing to documentation for Parity Ethereum packages
[Document source code](https://doc.rust-lang.org/1.9.0/book/documentation.html) for Parity Ethereum packages by annotating the source code with documentation comments.
Example (generic documentation comment):
```markdown
/// Summary
///
/// Description
///
/// # Panics
///
/// # Errors
///
/// # Safety
///
/// # Examples
///
/// Summary of Example 1
///
/// ```rust
/// // insert example 1 code here for use with documentation as tests
/// ```
///
```
## 6. Toolchain <a id="chapter-006"></a>
In addition to the OpenEthereum client, there are additional tools in this repository available:
In addition to the Parity Ethereum client, there are additional tools in this repository available:
- [evmbin](./evmbin) - OpenEthereum EVM Implementation.
- [ethstore](./accounts/ethstore) - OpenEthereum Key Management.
- [ethkey](./accounts/ethkey) - OpenEthereum Keys Generator.
- [evmbin](./evmbin) - Parity Ethereum EVM Implementation.
- [ethstore](./accounts/ethstore) - Parity Ethereum Key Management.
- [ethkey](./accounts/ethkey) - Parity Ethereum Keys Generator.
The following tools are available in a separate repository:
- [ethabi](https://github.com/openethereum/ethabi) - OpenEthereum Encoding of Function Calls. [Docs here](https://crates.io/crates/ethabi)
- [whisper](https://github.com/openethereum/whisper) - OpenEthereum 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. Contributing <a id="chapter-007"></a>
## 7. Community <a id="chapter-007"></a>
### Join the chat!
Questions? Get in touch with us on Gitter:
[![Gitter: Parity](https://img.shields.io/badge/gitter-parity-4AB495.svg)](https://gitter.im/paritytech/parity)
[![Gitter: Parity.js](https://img.shields.io/badge/gitter-parity.js-4AB495.svg)](https://gitter.im/paritytech/parity.js)
[![Gitter: Parity/Miners](https://img.shields.io/badge/gitter-parity/miners-4AB495.svg)](https://gitter.im/paritytech/parity/miners)
[![Gitter: Parity-PoA](https://img.shields.io/badge/gitter-parity--poa-4AB495.svg)](https://gitter.im/paritytech/parity-poa)
Alternatively, join our community on Matrix:
[![Riot: +Parity](https://img.shields.io/badge/riot-%2Bparity%3Amatrix.parity.io-orange.svg)](https://riot.im/app/#/group/+parity:matrix.parity.io)
## 8. Contributing <a id="chapter-008"></a>
An introduction has been provided in the ["So You Want to be a Core Developer" presentation slides by Hernando Castano](http://tiny.cc/contrib-to-parity-eth). Additional guidelines are provided in [CONTRIBUTING](./.github/CONTRIBUTING.md).
@@ -313,6 +382,6 @@ An introduction has been provided in the ["So You Want to be a Core Developer" p
[CODE_OF_CONDUCT](./.github/CODE_OF_CONDUCT.md)
## 8. License <a id="chapter-008"></a>
## 9. License <a id="chapter-009"></a>
[LICENSE](./LICENSE)

101
SECURITY.md Normal file
View File

@@ -0,0 +1,101 @@
# Security Policy
Parity Technologies is committed to resolving security vulnerabilities in our software quickly and carefully. We take the necessary steps to minimize risk, provide timely information, and deliver vulnerability fixes and mitigations required to address security issues.
## Reporting a Vulnerability
Security vulnerabilities in Parity software should be reported by email to security@parity.io. If you think your report might be eligible for the Parity Bug Bounty Program, your email should be send to bugbounty@parity.io.
Your report should include the following:
- your name
- description of the vulnerability
- attack scenario (if any)
- components
- reproduction
- other details
Try to include as much information in your report as you can, including a description of the vulnerability, its potential impact, and steps for reproducing it. Be sure to use a descriptive subject line.
You'll receive a response to your email within two business days indicating the next steps in handling your report. We encourage finders to use encrypted communication channels to protect the confidentiality of vulnerability reports. You can encrypt your report using our public key. This key is [on MIT's key server](https://pgp.mit.edu/pks/lookup?op=get&search=0x5D0F03018D07DE73) server and reproduced below.
After the initial reply to your report, our team will endeavor to keep you informed of the progress being made towards a fix. These updates will be sent at least every five business days.
Thank you for taking the time to responsibly disclose any vulnerabilities you find.
## Responsible Investigation and Reporting
Responsible investigation and reporting includes, but isn't limited to, the following:
- Don't violate the privacy of other users, destroy data, etc.
- Dont defraud or harm Parity Technologies Ltd or its users during your research; you should make a good faith effort to not interrupt or degrade our services.
- Don't target our physical security measures, or attempt to use social engineering, spam, distributed denial of service (DDOS) attacks, etc.
- Initially report the bug only to us and not to anyone else.
- Give us a reasonable amount of time to fix the bug before disclosing it to anyone else, and give us adequate written warning before disclosing it to anyone else.
- In general, please investigate and report bugs in a way that makes a reasonable, good faith effort not to be disruptive or harmful to us or our users. Otherwise your actions might be interpreted as an attack rather than an effort to be helpful.
## Bug Bounty Program
Our Bug Bounty Program allows us to recognise and reward members of the Parity community for helping us find and address significant bugs, in accordance with the terms of the Parity Bug Bounty Program. A detailed description on eligibility, rewards, legal information and terms & conditions for contributors can be found on [our website](https://paritytech.io/bug-bounty.html).
## Plaintext PGP Key
```
-----BEGIN PGP PUBLIC KEY BLOCK-----
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-----
```

View File

@@ -1,6 +1,6 @@
[package]
description = "OpenEthereum Account Management"
homepage = "https://github.com/openethereum/openethereum"
description = "Parity Ethereum Account Management"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore-accounts"
version = "0.1.0"
@@ -8,15 +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"
[dev-dependencies]
ethereum-types = "0.4"
ethereum-types = "0.8.0"
tempdir = "0.3"

View File

@@ -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"

View File

@@ -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,3 +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/whisper) - Implementation of Whisper-v2 PoC.

View File

@@ -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"

View File

@@ -1,24 +1,25 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate docopt;
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;
@@ -26,18 +27,17 @@ extern crate threadpool;
#[macro_use]
extern crate serde_derive;
use std::{env, fmt, io, num::ParseIntError, process, sync};
use std::num::ParseIntError;
use std::{env, fmt, process, io, sync};
use docopt::Docopt;
use ethkey::{
brain_recover, sign, verify_address, verify_public, Brain, BrainPrefix, Error as EthkeyError,
Generator, KeyPair, Prefix, Random,
};
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]
@@ -67,428 +67,387 @@ Commands:
#[derive(Debug, Deserialize)]
struct Args {
cmd_info: bool,
cmd_generate: bool,
cmd_random: bool,
cmd_prefix: bool,
cmd_sign: bool,
cmd_verify: bool,
cmd_public: bool,
cmd_address: bool,
cmd_recover: bool,
arg_prefix: String,
arg_secret: String,
arg_secret_or_phrase: String,
arg_known_phrase: String,
arg_message: String,
arg_public: String,
arg_address: String,
arg_signature: String,
flag_secret: bool,
flag_public: bool,
flag_address: bool,
flag_brain: bool,
cmd_info: bool,
cmd_generate: bool,
cmd_random: bool,
cmd_prefix: bool,
cmd_sign: bool,
cmd_verify: bool,
cmd_public: bool,
cmd_address: bool,
cmd_recover: bool,
arg_prefix: String,
arg_secret: String,
arg_secret_or_phrase: String,
arg_known_phrase: String,
arg_message: String,
arg_public: String,
arg_address: String,
arg_signature: String,
flag_secret: bool,
flag_public: bool,
flag_address: bool,
flag_brain: bool,
}
#[derive(Debug)]
enum Error {
Ethkey(EthkeyError),
FromHex(FromHexError),
ParseInt(ParseIntError),
Docopt(docopt::Error),
Io(io::Error),
Ethkey(EthkeyError),
FromHex(FromHexError),
ParseInt(ParseIntError),
Docopt(docopt::Error),
Io(io::Error),
}
impl From<EthkeyError> for Error {
fn from(err: EthkeyError) -> Self {
Error::Ethkey(err)
}
fn from(err: EthkeyError) -> Self {
Error::Ethkey(err)
}
}
impl From<FromHexError> for Error {
fn from(err: FromHexError) -> Self {
Error::FromHex(err)
}
fn from(err: FromHexError) -> Self {
Error::FromHex(err)
}
}
impl From<ParseIntError> for Error {
fn from(err: ParseIntError) -> Self {
Error::ParseInt(err)
}
fn from(err: ParseIntError) -> Self {
Error::ParseInt(err)
}
}
impl From<docopt::Error> for Error {
fn from(err: docopt::Error) -> Self {
Error::Docopt(err)
}
fn from(err: docopt::Error) -> Self {
Error::Docopt(err)
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Self {
Error::Io(err)
}
fn from(err: io::Error) -> Self {
Error::Io(err)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Error::Ethkey(ref e) => write!(f, "{}", e),
Error::FromHex(ref e) => write!(f, "{}", e),
Error::ParseInt(ref e) => write!(f, "{}", e),
Error::Docopt(ref e) => write!(f, "{}", e),
Error::Io(ref e) => write!(f, "{}", e),
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Error::Ethkey(ref e) => write!(f, "{}", e),
Error::FromHex(ref e) => write!(f, "{}", e),
Error::ParseInt(ref e) => write!(f, "{}", e),
Error::Docopt(ref e) => write!(f, "{}", e),
Error::Io(ref e) => write!(f, "{}", e),
}
}
}
enum DisplayMode {
KeyPair,
Secret,
Public,
Address,
KeyPair,
Secret,
Public,
Address,
}
impl DisplayMode {
fn new(args: &Args) -> Self {
if args.flag_secret {
DisplayMode::Secret
} else if args.flag_public {
DisplayMode::Public
} else if args.flag_address {
DisplayMode::Address
} else {
DisplayMode::KeyPair
}
}
fn new(args: &Args) -> Self {
if args.flag_secret {
DisplayMode::Secret
} else if args.flag_public {
DisplayMode::Public
} else if args.flag_address {
DisplayMode::Address
} else {
DisplayMode::KeyPair
}
}
}
fn main() {
panic_hook::set_abort();
env_logger::try_init().expect("Logger initialized only once.");
panic_hook::set_abort();
env_logger::try_init().expect("Logger initialized only once.");
match execute(env::args()) {
Ok(ok) => println!("{}", ok),
Err(Error::Docopt(ref e)) => e.exit(),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
}
}
match execute(env::args()) {
Ok(ok) => println!("{}", ok),
Err(Error::Docopt(ref e)) => e.exit(),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
}
}
}
fn display(result: (KeyPair, Option<String>), mode: DisplayMode) -> String {
let keypair = result.0;
match mode {
DisplayMode::KeyPair => match result.1 {
Some(extra_data) => format!("{}\n{}", extra_data, keypair),
None => format!("{}", keypair),
},
DisplayMode::Secret => format!("{:x}", keypair.secret()),
DisplayMode::Public => format!("{:x}", keypair.public()),
DisplayMode::Address => format!("{:x}", keypair.address()),
}
let keypair = result.0;
match mode {
DisplayMode::KeyPair => match result.1 {
Some(extra_data) => format!("{}\n{}", extra_data, keypair),
None => format!("{}", keypair)
},
DisplayMode::Secret => format!("{:x}", keypair.secret()),
DisplayMode::Public => format!("{:x}", keypair.public()),
DisplayMode::Address => format!("{:x}", keypair.address()),
}
}
fn execute<S, I>(command: I) -> Result<String, Error>
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let args: Args = Docopt::new(USAGE).and_then(|d| d.argv(command).deserialize())?;
fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item=S>, S: AsRef<str> {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.argv(command).deserialize())?;
return if args.cmd_info {
let display_mode = DisplayMode::new(&args);
return if args.cmd_info {
let display_mode = DisplayMode::new(&args);
let result = if args.flag_brain {
let phrase = args.arg_secret_or_phrase;
let phrase_info = validate_phrase(&phrase);
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)?;
(KeyPair::from_secret(secret)?, None)
};
Ok(display(result, display_mode))
} else if args.cmd_generate {
let display_mode = DisplayMode::new(&args);
let result = if args.cmd_random {
if args.flag_brain {
let mut brain = BrainPrefix::new(vec![0], usize::max_value(), BRAIN_WORDS);
let keypair = brain.generate()?;
let phrase = format!("recovery phrase: {}", brain.phrase());
(keypair, Some(phrase))
} else {
(Random.generate()?, None)
}
} else if args.cmd_prefix {
let prefix = args.arg_prefix.from_hex()?;
let brain = args.flag_brain;
in_threads(move || {
let iterations = 1024;
let prefix = prefix.clone();
move || {
let prefix = prefix.clone();
let res = if brain {
let mut brain = BrainPrefix::new(prefix, iterations, BRAIN_WORDS);
let result = brain.generate();
let phrase = format!("recovery phrase: {}", brain.phrase());
result.map(|keypair| (keypair, Some(phrase)))
} else {
let result = Prefix::new(prefix, iterations).generate();
result.map(|res| (res, None))
};
let result = if args.flag_brain {
let phrase = args.arg_secret_or_phrase;
let phrase_info = validate_phrase(&phrase);
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::InvalidSecretKey)?;
(KeyPair::from_secret(secret)?, None)
};
Ok(display(result, display_mode))
} else if args.cmd_generate {
let display_mode = DisplayMode::new(&args);
let result = if args.cmd_random {
if args.flag_brain {
let mut brain = BrainPrefix::new(vec![0], usize::max_value(), BRAIN_WORDS);
let keypair = brain.generate()?;
let phrase = format!("recovery phrase: {}", brain.phrase());
(keypair, Some(phrase))
} else {
(Random.generate()?, None)
}
} else if args.cmd_prefix {
let prefix = args.arg_prefix.from_hex()?;
let brain = args.flag_brain;
in_threads(move || {
let iterations = 1024;
let prefix = prefix.clone();
move || {
let prefix = prefix.clone();
let res = if brain {
let mut brain = BrainPrefix::new(prefix, iterations, BRAIN_WORDS);
let result = brain.generate();
let phrase = format!("recovery phrase: {}", brain.phrase());
result.map(|keypair| (keypair, Some(phrase)))
} else {
let result = Prefix::new(prefix, iterations).generate();
result.map(|res| (res, None))
};
Ok(res.map(Some).unwrap_or(None))
}
})?
} else {
return Ok(format!("{}", USAGE));
};
Ok(display(result, display_mode))
} else if args.cmd_sign {
let secret = args
.arg_secret
.parse()
.map_err(|_| EthkeyError::InvalidSecret)?;
let message = args
.arg_message
.parse()
.map_err(|_| EthkeyError::InvalidMessage)?;
let signature = sign(&secret, &message)?;
Ok(format!("{}", signature))
} else if args.cmd_verify {
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)?;
verify_public(&public, &signature, &message)?
} else if args.cmd_address {
let address = args
.arg_address
.parse()
.map_err(|_| EthkeyError::InvalidAddress)?;
verify_address(&address, &signature, &message)?
} else {
return Ok(format!("{}", USAGE));
};
Ok(format!("{}", ok))
} else if args.cmd_recover {
let display_mode = DisplayMode::new(&args);
let known_phrase = args.arg_known_phrase;
let address = args
.arg_address
.parse()
.map_err(|_| EthkeyError::InvalidAddress)?;
let (phrase, keypair) = in_threads(move || {
let mut it =
brain_recover::PhrasesIterator::from_known_phrase(&known_phrase, BRAIN_WORDS);
move || {
let mut i = 0;
while let Some(phrase) = it.next() {
i += 1;
Ok(res.map(Some).unwrap_or(None))
}
})?
} else {
return Ok(format!("{}", USAGE))
};
Ok(display(result, display_mode))
} else if args.cmd_sign {
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))
} else if args.cmd_verify {
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::InvalidPublicKey)?;
verify_public(&public, &signature, &message)?
} else if args.cmd_address {
let address = args.arg_address.parse().map_err(|_| EthkeyError::InvalidAddress)?;
verify_address(&address, &signature, &message)?
} else {
return Ok(format!("{}", USAGE))
};
Ok(format!("{}", ok))
} else if args.cmd_recover {
let display_mode = DisplayMode::new(&args);
let known_phrase = args.arg_known_phrase;
let address = args.arg_address.parse().map_err(|_| EthkeyError::InvalidAddress)?;
let (phrase, keypair) = in_threads(move || {
let mut it = brain_recover::PhrasesIterator::from_known_phrase(&known_phrase, BRAIN_WORDS);
move || {
let mut i = 0;
while let Some(phrase) = it.next() {
i += 1;
let keypair = Brain::new(phrase.clone()).generate().unwrap();
if keypair.address() == address {
return Ok(Some((phrase, keypair)));
}
let keypair = Brain::new(phrase.clone()).generate().unwrap();
if keypair.address() == address {
return Ok(Some((phrase, keypair)))
}
if i >= 1024 {
return Ok(None);
}
}
if i >= 1024 {
return Ok(None)
}
}
Err(EthkeyError::Custom("Couldn't find any results.".into()))
}
})?;
Ok(display((keypair, Some(phrase)), display_mode))
} else {
Ok(format!("{}", USAGE))
};
Err(EthkeyError::Custom("Couldn't find any results.".into()))
}
})?;
Ok(display((keypair, Some(phrase)), display_mode))
} else {
Ok(format!("{}", USAGE))
}
}
const BRAIN_WORDS: usize = 12;
fn validate_phrase(phrase: &str) -> String {
match Brain::validate_phrase(phrase, BRAIN_WORDS) {
Ok(()) => format!("The recovery phrase looks correct.\n"),
Err(err) => format!("The recover phrase was not generated by Parity: {}", err),
}
match Brain::validate_phrase(phrase, BRAIN_WORDS) {
Ok(()) => format!("The recovery phrase looks correct.\n"),
Err(err) => format!("The recover phrase was not generated by Parity: {}", err)
}
}
fn in_threads<F, X, O>(prepare: F) -> Result<O, EthkeyError>
where
O: Send + 'static,
X: Send + 'static,
F: Fn() -> X,
X: FnMut() -> Result<Option<O>, EthkeyError>,
fn in_threads<F, X, O>(prepare: F) -> Result<O, EthkeyError> where
O: Send + 'static,
X: Send + 'static,
F: Fn() -> X,
X: FnMut() -> Result<Option<O>, EthkeyError>,
{
let pool = threadpool::Builder::new().build();
let pool = threadpool::Builder::new().build();
let (tx, rx) = sync::mpsc::sync_channel(1);
let is_done = sync::Arc::new(sync::atomic::AtomicBool::default());
let (tx, rx) = sync::mpsc::sync_channel(1);
let is_done = sync::Arc::new(sync::atomic::AtomicBool::default());
for _ in 0..pool.max_count() {
let is_done = is_done.clone();
let tx = tx.clone();
let mut task = prepare();
pool.execute(move || {
loop {
if is_done.load(sync::atomic::Ordering::SeqCst) {
return;
}
for _ in 0..pool.max_count() {
let is_done = is_done.clone();
let tx = tx.clone();
let mut task = prepare();
pool.execute(move || {
loop {
if is_done.load(sync::atomic::Ordering::SeqCst) {
return;
}
let res = match task() {
Ok(None) => continue,
Ok(Some(v)) => Ok(v),
Err(err) => Err(err),
};
let res = match task() {
Ok(None) => continue,
Ok(Some(v)) => Ok(v),
Err(err) => Err(err),
};
// We are interested only in the first response.
let _ = tx.send(res);
}
});
}
// We are interested only in the first response.
let _ = tx.send(res);
}
});
}
if let Ok(solution) = rx.recv() {
is_done.store(true, sync::atomic::Ordering::SeqCst);
return solution;
}
if let Ok(solution) = rx.recv() {
is_done.store(true, sync::atomic::Ordering::SeqCst);
return solution;
}
Err(EthkeyError::Custom("No results found.".into()))
Err(EthkeyError::Custom("No results found.".into()))
}
#[cfg(test)]
mod tests {
use super::execute;
use super::execute;
#[test]
fn info() {
let command = vec![
"ethkey",
"info",
"17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55",
]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
#[test]
fn info() {
let command = vec!["ethkey", "info", "17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected =
let expected =
"secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55
public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124
address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn brain() {
let command = vec!["ethkey", "info", "--brain", "this is sparta"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
#[test]
fn brain() {
let command = vec!["ethkey", "info", "--brain", "this is sparta"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected =
let expected =
"The recover phrase was not generated by Parity: The word 'this' does not come from the dictionary.
secret: aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2
public: c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4
address: 006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn secret() {
let command = vec!["ethkey", "info", "--brain", "this is sparta", "--secret"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected =
"aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn public() {
let command = vec!["ethkey", "info", "--brain", "this is sparta", "--public"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn address() {
let command = vec!["ethkey", "info", "-b", "this is sparta", "--address"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn sign() {
let command = vec![
"ethkey",
"sign",
"17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55",
"bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987",
]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn verify_valid_public() {
let command = vec!["ethkey", "verify", "public", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"]
#[test]
fn secret() {
let command = vec!["ethkey", "info", "--brain", "this is sparta", "--secret"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "true".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
let expected = "aa22b54c0cb43ee30a014afe5ef3664b1cde299feabca46cd3167a85a57c39f2".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn verify_valid_address() {
let command = vec!["ethkey", "verify", "address", "26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"]
#[test]
fn public() {
let command = vec!["ethkey", "info", "--brain", "this is sparta", "--public"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "true".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
let expected = "c4c5398da6843632c123f543d714d2d2277716c11ff612b2a2f23c6bda4d6f0327c31cd58c55a9572c3cc141dade0c32747a13b7ef34c241b26c84adbb28fcf4".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn verify_invalid() {
let command = vec!["ethkey", "verify", "public", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec986"]
#[test]
fn address() {
let command = vec!["ethkey", "info", "-b", "this is sparta", "--address"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "false".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
let expected = "006e27b6a72e1f34c626762f3c4761547aff1421".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn sign() {
let command = vec!["ethkey", "sign", "17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn verify_valid_public() {
let command = vec!["ethkey", "verify", "public", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "true".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn verify_valid_address() {
let command = vec!["ethkey", "verify", "address", "26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec987"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "true".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
#[test]
fn verify_invalid() {
let command = vec!["ethkey", "verify", "public", "689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124", "c1878cf60417151c766a712653d26ef350c8c75393458b7a9be715f053215af63dfd3b02c2ae65a8677917a8efa3172acb71cb90196e42106953ea0363c5aaf200", "bd50b7370c3f96733b31744c6c45079e7ae6c8d299613246d28ebcef507ec986"]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected = "false".to_owned();
assert_eq!(execute(command).unwrap(), expected);
}
}

View File

@@ -1,74 +1,75 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Generator, KeyPair, Secret};
use keccak::Keccak256;
use std::convert::Infallible;
use parity_crypto::publickey::{KeyPair, Generator, Secret};
use parity_crypto::Keccak256;
use parity_wordlist;
/// Simple brainwallet.
pub struct Brain(String);
impl Brain {
pub fn new(s: String) -> Self {
Brain(s)
}
pub fn new(s: String) -> Self {
Brain(s)
}
pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> {
parity_wordlist::validate_phrase(phrase, expected_words)
}
pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> {
parity_wordlist::validate_phrase(phrase, expected_words)
}
}
impl Generator for Brain {
type Error = ::Void;
type Error = Infallible;
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let seed = self.0.clone();
let mut secret = seed.into_bytes().keccak256();
fn generate(&mut self) -> Result<KeyPair, Self::Error> {
let seed = self.0.clone();
let mut secret = seed.into_bytes().keccak256();
let mut i = 0;
loop {
secret = secret.keccak256();
let mut i = 0;
loop {
secret = secret.keccak256();
match i > 16384 {
false => i += 1,
true => {
if let Ok(pair) =
Secret::from_unsafe_slice(&secret).and_then(KeyPair::from_secret)
{
if pair.address()[0] == 0 {
trace!("Testing: {}, got: {:?}", self.0, pair.address());
return Ok(pair);
}
}
}
}
}
}
match i > 16384 {
false => i += 1,
true => {
if let Ok(pair) = Secret::import_key(&secret)
.and_then(KeyPair::from_secret)
{
if pair.address()[0] == 0 {
trace!("Testing: {}, got: {:?}", self.0, pair.address());
return Ok(pair)
}
}
},
}
}
}
}
#[cfg(test)]
mod tests {
use Brain;
use Generator;
use Brain;
use parity_crypto::publickey::Generator;
#[test]
fn test_brain() {
let words = "this is sparta!".to_owned();
let first_keypair = Brain::new(words.clone()).generate().unwrap();
let second_keypair = Brain::new(words.clone()).generate().unwrap();
assert_eq!(first_keypair.secret(), second_keypair.secret());
}
#[test]
fn test_brain() {
let words = "this is sparta!".to_owned();
let first_keypair = Brain::new(words.clone()).generate().unwrap();
let second_keypair = Brain::new(words.clone()).generate().unwrap();
assert_eq!(first_keypair.secret(), second_keypair.secret());
}
}

View File

@@ -1,73 +1,72 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Brain, Error, Generator, KeyPair};
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.
pub struct BrainPrefix {
prefix: Vec<u8>,
iterations: usize,
no_of_words: usize,
last_phrase: String,
prefix: Vec<u8>,
iterations: usize,
no_of_words: usize,
last_phrase: String,
}
impl BrainPrefix {
pub fn new(prefix: Vec<u8>, iterations: usize, no_of_words: usize) -> Self {
BrainPrefix {
prefix,
iterations,
no_of_words,
last_phrase: String::new(),
}
}
pub fn new(prefix: Vec<u8>, iterations: usize, no_of_words: usize) -> Self {
BrainPrefix {
prefix,
iterations,
no_of_words,
last_phrase: String::new(),
}
}
pub fn phrase(&self) -> &str {
&self.last_phrase
}
pub fn phrase(&self) -> &str {
&self.last_phrase
}
}
impl Generator for BrainPrefix {
type Error = Error;
type Error = Error;
fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let phrase = wordlist::random_phrase(self.no_of_words);
let keypair = Brain::new(phrase.clone()).generate().unwrap();
if keypair.address().starts_with(&self.prefix) {
self.last_phrase = phrase;
return Ok(keypair);
}
}
fn generate(&mut self) -> Result<KeyPair, Error> {
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().as_ref().starts_with(&self.prefix) {
self.last_phrase = phrase;
return Ok(keypair)
}
}
Err(Error::Custom("Could not find keypair".into()))
}
Err(Error::Custom("Could not find keypair".into()))
}
}
#[cfg(test)]
mod tests {
use BrainPrefix;
use Generator;
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));
}
#[test]
fn prefix_generator() {
let prefix = vec![0x00u8];
let keypair = BrainPrefix::new(prefix.clone(), usize::max_value(), 12).generate().unwrap();
assert!(keypair.address().as_bytes().starts_with(&prefix));
}
}

View File

@@ -1,178 +1,174 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
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.
///
/// Returns `None` if phrase couldn't be found.
pub fn brain_recover(
address: &Address,
known_phrase: &str,
expected_words: usize,
address: &Address,
known_phrase: &str,
expected_words: usize,
) -> Option<String> {
let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words);
for phrase in it {
let keypair = Brain::new(phrase.clone())
.generate()
.expect("Brain wallets are infallible; qed");
trace!("Testing: {}, got: {:?}", phrase, keypair.address());
if &keypair.address() == address {
return Some(phrase);
}
}
let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words);
for phrase in it {
let keypair = Brain::new(phrase.clone()).generate().expect("Brain wallets are infallible; qed");
trace!("Testing: {}, got: {:?}", phrase, keypair.address());
if &keypair.address() == address {
return Some(phrase);
}
}
None
None
}
fn generate_substitutions(word: &str) -> Vec<&'static str> {
let mut words = parity_wordlist::WORDS
.iter()
.cloned()
.map(|w| (edit_distance(w, word), w))
.collect::<Vec<_>>();
words.sort_by(|a, b| a.0.cmp(&b.0));
let mut words = parity_wordlist::WORDS.iter().cloned()
.map(|w| (edit_distance(w, word), w))
.collect::<Vec<_>>();
words.sort_by(|a, b| a.0.cmp(&b.0));
words.into_iter().map(|pair| pair.1).collect()
words.into_iter()
.map(|pair| pair.1)
.collect()
}
/// Iterator over possible
pub struct PhrasesIterator {
words: Vec<Vec<&'static str>>,
combinations: u64,
indexes: Vec<usize>,
has_next: bool,
words: Vec<Vec<&'static str>>,
combinations: u64,
indexes: Vec<usize>,
has_next: bool,
}
impl PhrasesIterator {
pub fn from_known_phrase(known_phrase: &str, expected_words: usize) -> Self {
let known_words = parity_wordlist::WORDS
.iter()
.cloned()
.collect::<HashSet<_>>();
let mut words = known_phrase
.split(' ')
.map(|word| match known_words.get(word) {
None => {
info!(
"Invalid word '{}', looking for potential substitutions.",
word
);
let substitutions = generate_substitutions(word);
info!("Closest words: {:?}", &substitutions[..10]);
substitutions
}
Some(word) => vec![*word],
})
.collect::<Vec<_>>();
pub fn from_known_phrase(known_phrase: &str, expected_words: usize) -> Self {
let known_words = parity_wordlist::WORDS.iter().cloned().collect::<HashSet<_>>();
let mut words = known_phrase.split(' ')
.map(|word| match known_words.get(word) {
None => {
info!("Invalid word '{}', looking for potential substitutions.", word);
let substitutions = generate_substitutions(word);
info!("Closest words: {:?}", &substitutions[..10]);
substitutions
},
Some(word) => vec![*word],
})
.collect::<Vec<_>>();
// add missing words
if words.len() < expected_words {
let to_add = expected_words - words.len();
info!("Number of words is insuficcient adding {} more.", to_add);
for _ in 0..to_add {
words.push(parity_wordlist::WORDS.iter().cloned().collect());
}
}
// add missing words
if words.len() < expected_words {
let to_add = expected_words - words.len();
info!("Number of words is insuficcient adding {} more.", to_add);
for _ in 0..to_add {
words.push(parity_wordlist::WORDS.iter().cloned().collect());
}
}
// start searching
PhrasesIterator::new(words)
}
// start searching
PhrasesIterator::new(words)
}
pub fn new(words: Vec<Vec<&'static str>>) -> Self {
let combinations = words.iter().fold(1u64, |acc, x| acc * x.len() as u64);
let indexes = words.iter().map(|_| 0).collect();
info!("Starting to test {} possible combinations.", combinations);
pub fn new(words: Vec<Vec<&'static str>>) -> Self {
let combinations = words.iter().fold(1u64, |acc, x| acc * x.len() as u64);
let indexes = words.iter().map(|_| 0).collect();
info!("Starting to test {} possible combinations.", combinations);
PhrasesIterator {
words,
combinations,
indexes,
has_next: combinations > 0,
}
}
PhrasesIterator {
words,
combinations,
indexes,
has_next: combinations > 0,
}
}
pub fn combinations(&self) -> u64 {
self.combinations
}
pub fn combinations(&self) -> u64 {
self.combinations
}
fn current(&self) -> String {
let mut s = self.words[0][self.indexes[0]].to_owned();
for i in 1..self.indexes.len() {
s.push(' ');
s.push_str(self.words[i][self.indexes[i]]);
}
s
}
fn current(&self) -> String {
let mut s = self.words[0][self.indexes[0]].to_owned();
for i in 1..self.indexes.len() {
s.push(' ');
s.push_str(self.words[i][self.indexes[i]]);
}
s
}
fn next_index(&mut self) -> bool {
let mut pos = self.indexes.len();
while pos > 0 {
pos -= 1;
self.indexes[pos] += 1;
if self.indexes[pos] >= self.words[pos].len() {
self.indexes[pos] = 0;
} else {
return true;
}
}
fn next_index(&mut self) -> bool {
let mut pos = self.indexes.len();
while pos > 0 {
pos -= 1;
self.indexes[pos] += 1;
if self.indexes[pos] >= self.words[pos].len() {
self.indexes[pos] = 0;
} else {
return true;
}
}
false
}
false
}
}
impl Iterator for PhrasesIterator {
type Item = String;
type Item = String;
fn next(&mut self) -> Option<String> {
if !self.has_next {
return None;
}
fn next(&mut self) -> Option<String> {
if !self.has_next {
return None;
}
let phrase = self.current();
self.has_next = self.next_index();
Some(phrase)
}
let phrase = self.current();
self.has_next = self.next_index();
Some(phrase)
}
}
#[cfg(test)]
mod tests {
use super::PhrasesIterator;
use super::PhrasesIterator;
#[test]
fn should_generate_possible_combinations() {
let mut it =
PhrasesIterator::new(vec![vec!["1", "2", "3"], vec!["test"], vec!["a", "b", "c"]]);
#[test]
fn should_generate_possible_combinations() {
let mut it = PhrasesIterator::new(vec![
vec!["1", "2", "3"],
vec!["test"],
vec!["a", "b", "c"],
]);
assert_eq!(it.combinations(), 9);
assert_eq!(it.next(), Some("1 test a".to_owned()));
assert_eq!(it.next(), Some("1 test b".to_owned()));
assert_eq!(it.next(), Some("1 test c".to_owned()));
assert_eq!(it.next(), Some("2 test a".to_owned()));
assert_eq!(it.next(), Some("2 test b".to_owned()));
assert_eq!(it.next(), Some("2 test c".to_owned()));
assert_eq!(it.next(), Some("3 test a".to_owned()));
assert_eq!(it.next(), Some("3 test b".to_owned()));
assert_eq!(it.next(), Some("3 test c".to_owned()));
assert_eq!(it.next(), None);
}
assert_eq!(it.combinations(), 9);
assert_eq!(it.next(), Some("1 test a".to_owned()));
assert_eq!(it.next(), Some("1 test b".to_owned()));
assert_eq!(it.next(), Some("1 test c".to_owned()));
assert_eq!(it.next(), Some("2 test a".to_owned()));
assert_eq!(it.next(), Some("2 test b".to_owned()));
assert_eq!(it.next(), Some("2 test c".to_owned()));
assert_eq!(it.next(), Some("3 test a".to_owned()));
assert_eq!(it.next(), Some("3 test b".to_owned()));
assert_eq!(it.next(), Some("3 test c".to_owned()));
assert_eq!(it.next(), None);
}
}

View File

@@ -1,202 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
#![allow(deprecated)]
use parity_crypto::error::SymmError;
use secp256k1;
use std::io;
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 super::Error;
use secp256k1::{self, ecdh, key};
use Public;
use Secret;
use 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 super::{ecdh, Error};
use ethereum_types::H128;
use parity_crypto::{aes, digest, hmac, is_equal};
use Generator;
use Public;
use Random;
use 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 Generator;
use Random;
#[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[..]);
}
}

View File

@@ -1,81 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use std::{error, fmt};
#[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)
}
}

View File

@@ -1,589 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Extended keys
pub use self::derivation::Error as DerivationError;
use ethereum_types::H256;
use secret::Secret;
use Public;
/// 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 super::{Derivation, Label};
use ethereum_types::{H256, H512, U256, U512};
use keccak;
use math::curve_order;
use parity_crypto::hmac;
use secp256k1::key::{PublicKey, SecretKey};
use SECP256K1;
#[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::{derivation, Derivation, ExtendedKeyPair, ExtendedPublic, ExtendedSecret};
use ethereum_types::{H128, H256};
use secret::Secret;
use std::str::FromStr;
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"),
);
}
}

View File

@@ -1,33 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use tiny_keccak::Keccak;
pub trait Keccak256<T> {
fn keccak256(&self) -> T
where
T: Sized;
}
impl Keccak256<[u8; 32]> for [u8] {
fn keccak256(&self) -> [u8; 32] {
let mut keccak = Keccak::new_keccak256();
let mut result = [0u8; 32];
keccak.update(self);
keccak.finalize(&mut result);
result
}
}

View File

@@ -1,120 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Address, Error, Public, Secret, SECP256K1};
use keccak::Keccak256;
use rustc_hex::ToHex;
use secp256k1::key;
use std::fmt;
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;
use 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);
}
}

View File

@@ -1,36 +1,26 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
// #![warn(missing_docs)]
extern crate edit_distance;
extern crate ethereum_types;
extern crate memzero;
extern crate parity_crypto;
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,52 +28,13 @@ extern crate serde_derive;
mod brain;
mod brain_prefix;
mod error;
mod extended;
mod keccak;
mod keypair;
mod password;
mod prefix;
mod random;
mod secret;
mod signature;
pub mod brain_recover;
pub mod crypto;
pub mod math;
pub use self::{
brain::Brain,
brain_prefix::BrainPrefix,
error::Error,
extended::{Derivation, DerivationError, ExtendedKeyPair, ExtendedPublic, ExtendedSecret},
keypair::{public_to_address, KeyPair},
math::public_is_valid,
parity_wordlist::Error as WordlistError,
password::Password,
prefix::Prefix,
random::Random,
secret::Secret,
signature::{recover, sign, verify_address, verify_public, Signature},
};
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::parity_wordlist::Error as WordlistError;
pub use self::brain::Brain;
pub use self::brain_prefix::BrainPrefix;
pub use self::password::Password;
pub use self::prefix::Prefix;

View File

@@ -1,134 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Error, Public, Secret, SECP256K1};
use ethereum_types::{H256, U256};
use secp256k1::{
constants::{CURVE_ORDER, GENERATOR_X, GENERATOR_Y},
key,
};
/// 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::{Generator, Random},
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);
}
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::{fmt, ptr};
@@ -20,40 +20,40 @@ use std::{fmt, ptr};
pub struct Password(String);
impl fmt::Debug for Password {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Password(******)")
}
}
impl Password {
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
}
// Custom drop impl to zero out memory.
impl Drop for Password {
fn drop(&mut self) {
unsafe {
for byte_ref in self.0.as_mut_vec() {
ptr::write_volatile(byte_ref, 0)
}
}
}
fn drop(&mut self) {
unsafe {
for byte_ref in self.0.as_mut_vec() {
ptr::write_volatile(byte_ref, 0)
}
}
}
}
impl From<String> for Password {
fn from(s: String) -> Password {
Password(s)
}
fn from(s: String) -> Password {
Password(s)
}
}
impl<'a> From<&'a str> for Password {
fn from(s: &'a str) -> Password {
Password::from(String::from(s))
}
fn from(s: &'a str) -> Password {
Password::from(String::from(s))
}
}

View File

@@ -1,62 +1,60 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Error, Generator, KeyPair, Random};
use parity_crypto::publickey::{Random, Generator, KeyPair, Error};
/// Tries to find keypair with address starting with given prefix.
pub struct Prefix {
prefix: Vec<u8>,
iterations: usize,
prefix: Vec<u8>,
iterations: usize,
}
impl Prefix {
pub fn new(prefix: Vec<u8>, iterations: usize) -> Self {
Prefix {
prefix: prefix,
iterations: iterations,
}
}
pub fn new(prefix: Vec<u8>, iterations: usize) -> Self {
Prefix {
prefix: prefix,
iterations: iterations,
}
}
}
impl Generator for Prefix {
type Error = Error;
type Error = Error;
fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let keypair = Random.generate()?;
if keypair.address().starts_with(&self.prefix) {
return Ok(keypair);
}
}
fn generate(&mut self) -> Result<KeyPair, Error> {
for _ in 0..self.iterations {
let keypair = Random.generate()?;
if keypair.address().as_ref().starts_with(&self.prefix) {
return Ok(keypair)
}
}
Err(Error::Custom("Could not find keypair".into()))
}
Err(Error::Custom("Could not find keypair".into()))
}
}
#[cfg(test)]
mod tests {
use Generator;
use 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));
}
#[test]
fn prefix_generator() {
let prefix = vec![0xffu8];
let keypair = Prefix::new(prefix.clone(), usize::max_value()).generate().unwrap();
assert!(keypair.address().as_bytes().starts_with(&prefix));
}
}

View File

@@ -1,45 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Generator, KeyPair, SECP256K1};
use rand::os::OsRng;
/// 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))
}
}

View File

@@ -1,322 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::H256;
use memzero::Memzero;
use rustc_hex::ToHex;
use secp256k1::{constants::SECRET_KEY_SIZE as SECP256K1_SECRET_KEY_SIZE, key};
use std::{fmt, ops::Deref, str::FromStr};
use Error;
use 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 super::{
super::{Generator, Random},
Secret,
};
use std::str::FromStr;
#[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);
}
}

View File

@@ -1,325 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::{H256, H520};
use public_to_address;
use rustc_hex::{FromHex, ToHex};
use secp256k1::{
key::{PublicKey, SecretKey},
Error as SecpError, Message as SecpMessage, RecoverableSignature, RecoveryId,
};
use std::{
cmp::PartialEq,
fmt,
hash::{Hash, Hasher},
ops::{Deref, DerefMut},
str::FromStr,
};
use Address;
use Error;
use Message;
use Public;
use Secret;
use SECP256K1;
/// 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 super::{recover, sign, verify_address, verify_public, Signature};
use std::str::FromStr;
use Generator;
use Message;
use Random;
#[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());
}
}

View File

@@ -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"

View File

@@ -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,3 +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/whisper) - Implementation of Whisper-v2 PoC.

View File

@@ -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"

View File

@@ -1,66 +1,67 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::{cmp, thread};
use std::sync::Arc;
use std::collections::VecDeque;
use parking_lot::Mutex;
use std::{cmp, collections::VecDeque, sync::Arc, thread};
use ethstore::{ethkey::Password, Error, PresaleWallet};
use ethstore::{PresaleWallet, Error};
use ethkey::Password;
use num_cpus;
pub fn run(passwords: VecDeque<Password>, wallet_path: &str) -> Result<(), Error> {
let passwords = Arc::new(Mutex::new(passwords));
let passwords = Arc::new(Mutex::new(passwords));
let mut handles = Vec::new();
let mut handles = Vec::new();
for _ in 0..num_cpus::get() {
let passwords = passwords.clone();
let wallet = PresaleWallet::open(&wallet_path)?;
handles.push(thread::spawn(move || {
look_for_password(passwords, wallet);
}));
}
for _ in 0..num_cpus::get() {
let passwords = passwords.clone();
let wallet = PresaleWallet::open(&wallet_path)?;
handles.push(thread::spawn(move || {
look_for_password(passwords, wallet);
}));
}
for handle in handles {
handle
.join()
.map_err(|err| Error::Custom(format!("Error finishing thread: {:?}", err)))?;
}
for handle in handles {
handle.join().map_err(|err| Error::Custom(format!("Error finishing thread: {:?}", err)))?;
}
Ok(())
Ok(())
}
fn look_for_password(passwords: Arc<Mutex<VecDeque<Password>>>, wallet: PresaleWallet) {
let mut counter = 0;
while !passwords.lock().is_empty() {
let package = {
let mut passwords = passwords.lock();
let len = passwords.len();
passwords.split_off(cmp::min(len, 32))
};
for pass in package {
counter += 1;
match wallet.decrypt(&pass) {
Ok(_) => {
println!("Found password: {}", pass.as_str());
passwords.lock().clear();
return;
}
_ if counter % 100 == 0 => print!("."),
_ => {}
}
}
}
let mut counter = 0;
while !passwords.lock().is_empty() {
let package = {
let mut passwords = passwords.lock();
let len = passwords.len();
passwords.split_off(cmp::min(len, 32))
};
for pass in package {
counter += 1;
match wallet.decrypt(&pass) {
Ok(_) => {
println!("Found password: {}", pass.as_str());
passwords.lock().clear();
return;
},
_ if counter % 100 == 0 => print!("."),
_ => {},
}
}
}
}

View File

@@ -1,25 +1,27 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
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;
@@ -28,21 +30,21 @@ extern crate env_logger;
#[macro_use]
extern crate serde_derive;
use std::{collections::VecDeque, env, fmt, fs, io::Read, process};
use std::collections::VecDeque;
use std::io::Read;
use std::{env, process, fs, fmt};
use docopt::Docopt;
use ethstore::{
accounts_dir::{KeyDirectory, RootDiskDirectory},
ethkey::{Address, Password},
import_accounts, EthStore, PresaleWallet, SecretStore, SecretVaultRef, SimpleSecretStore,
StoreAccountRef,
};
use ethstore::accounts_dir::{KeyDirectory, RootDiskDirectory};
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]
@@ -93,271 +95,226 @@ Commands:
#[derive(Debug, Deserialize)]
struct Args {
cmd_insert: bool,
cmd_change_pwd: bool,
cmd_list: bool,
cmd_import: bool,
cmd_import_wallet: bool,
cmd_find_wallet_pass: bool,
cmd_remove: bool,
cmd_sign: bool,
cmd_public: bool,
cmd_list_vaults: bool,
cmd_create_vault: bool,
cmd_change_vault_pwd: bool,
cmd_move_to_vault: bool,
cmd_move_from_vault: bool,
arg_secret: String,
arg_password: String,
arg_old_pwd: String,
arg_new_pwd: String,
arg_address: String,
arg_message: String,
arg_path: String,
arg_vault: String,
flag_src: String,
flag_dir: String,
flag_vault: String,
flag_vault_pwd: String,
cmd_insert: bool,
cmd_change_pwd: bool,
cmd_list: bool,
cmd_import: bool,
cmd_import_wallet: bool,
cmd_find_wallet_pass: bool,
cmd_remove: bool,
cmd_sign: bool,
cmd_public: bool,
cmd_list_vaults: bool,
cmd_create_vault: bool,
cmd_change_vault_pwd: bool,
cmd_move_to_vault: bool,
cmd_move_from_vault: bool,
arg_secret: String,
arg_password: String,
arg_old_pwd: String,
arg_new_pwd: String,
arg_address: String,
arg_message: String,
arg_path: String,
arg_vault: String,
flag_src: String,
flag_dir: String,
flag_vault: String,
flag_vault_pwd: String,
}
enum Error {
Ethstore(ethstore::Error),
Docopt(docopt::Error),
Ethstore(ethstore::Error),
Docopt(docopt::Error),
}
impl From<ethstore::Error> for Error {
fn from(err: ethstore::Error) -> Self {
Error::Ethstore(err)
}
fn from(err: ethstore::Error) -> Self {
Error::Ethstore(err)
}
}
impl From<docopt::Error> for Error {
fn from(err: docopt::Error) -> Self {
Error::Docopt(err)
}
fn from(err: docopt::Error) -> Self {
Error::Docopt(err)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Ethstore(ref err) => fmt::Display::fmt(err, f),
Error::Docopt(ref err) => fmt::Display::fmt(err, f),
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Ethstore(ref err) => fmt::Display::fmt(err, f),
Error::Docopt(ref err) => fmt::Display::fmt(err, f),
}
}
}
fn main() {
panic_hook::set_abort();
if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "warn")
}
env_logger::try_init().expect("Logger initialized only once.");
panic_hook::set_abort();
if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "warn")
}
env_logger::try_init().expect("Logger initialized only once.");
match execute(env::args()) {
Ok(result) => println!("{}", result),
Err(Error::Docopt(ref e)) => e.exit(),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
}
}
match execute(env::args()) {
Ok(result) => println!("{}", result),
Err(Error::Docopt(ref e)) => e.exit(),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
}
}
}
fn key_dir(location: &str, password: Option<Password>) -> Result<Box<dyn KeyDirectory>, Error> {
let dir: RootDiskDirectory = match location {
path if path.starts_with("parity") => {
let chain = path.split('-').nth(1).unwrap_or("ethereum");
let mut path = dir::default_data_pathbuf();
path.push("keys");
path.push(chain);
RootDiskDirectory::create(path)?
}
path => RootDiskDirectory::create(path)?,
};
let dir: RootDiskDirectory = match location {
"geth" => RootDiskDirectory::create(dir::geth(false))?,
"geth-test" => RootDiskDirectory::create(dir::geth(true))?,
path if path.starts_with("parity") => {
let chain = path.split('-').nth(1).unwrap_or("ethereum");
let path = dir::parity(chain);
RootDiskDirectory::create(path)?
},
path => RootDiskDirectory::create(path)?,
};
Ok(Box::new(dir.with_password(password)))
Ok(Box::new(dir.with_password(password)))
}
fn open_args_vault(store: &EthStore, args: &Args) -> Result<SecretVaultRef, Error> {
if args.flag_vault.is_empty() {
return Ok(SecretVaultRef::Root);
}
if args.flag_vault.is_empty() {
return Ok(SecretVaultRef::Root);
}
let vault_pwd = load_password(&args.flag_vault_pwd)?;
store.open_vault(&args.flag_vault, &vault_pwd)?;
Ok(SecretVaultRef::Vault(args.flag_vault.clone()))
let vault_pwd = load_password(&args.flag_vault_pwd)?;
store.open_vault(&args.flag_vault, &vault_pwd)?;
Ok(SecretVaultRef::Vault(args.flag_vault.clone()))
}
fn open_args_vault_account(
store: &EthStore,
address: Address,
args: &Args,
) -> Result<StoreAccountRef, Error> {
match open_args_vault(store, args)? {
SecretVaultRef::Root => Ok(StoreAccountRef::root(address)),
SecretVaultRef::Vault(name) => Ok(StoreAccountRef::vault(&name, address)),
}
fn open_args_vault_account(store: &EthStore, address: Address, args: &Args) -> Result<StoreAccountRef, Error> {
match open_args_vault(store, args)? {
SecretVaultRef::Root => Ok(StoreAccountRef::root(address)),
SecretVaultRef::Vault(name) => Ok(StoreAccountRef::vault(&name, address)),
}
}
fn format_accounts(accounts: &[Address]) -> String {
accounts
.iter()
.enumerate()
.map(|(i, a)| format!("{:2}: 0x{:x}", i, a))
.collect::<Vec<String>>()
.join("\n")
accounts.iter()
.enumerate()
.map(|(i, a)| format!("{:2}: 0x{:x}", i, a))
.collect::<Vec<String>>()
.join("\n")
}
fn format_vaults(vaults: &[String]) -> String {
vaults.join("\n")
vaults.join("\n")
}
fn load_password(path: &str) -> Result<Password, Error> {
let mut file = fs::File::open(path).map_err(|e| {
ethstore::Error::Custom(format!("Error opening password file '{}': {}", path, e))
})?;
let mut password = String::new();
file.read_to_string(&mut password).map_err(|e| {
ethstore::Error::Custom(format!("Error reading password file '{}': {}", path, e))
})?;
// drop EOF
let _ = password.pop();
Ok(password.into())
let mut file = fs::File::open(path).map_err(|e| ethstore::Error::Custom(format!("Error opening password file '{}': {}", path, e)))?;
let mut password = String::new();
file.read_to_string(&mut password).map_err(|e| ethstore::Error::Custom(format!("Error reading password file '{}': {}", path, e)))?;
// drop EOF
let _ = password.pop();
Ok(password.into())
}
fn execute<S, I>(command: I) -> Result<String, Error>
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let args: Args = Docopt::new(USAGE).and_then(|d| d.argv(command).deserialize())?;
fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item=S>, S: AsRef<str> {
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.argv(command).deserialize())?;
let store = EthStore::open(key_dir(&args.flag_dir, None)?)?;
let store = EthStore::open(key_dir(&args.flag_dir, None)?)?;
return if args.cmd_insert {
let secret = args
.arg_secret
.parse()
.map_err(|_| ethstore::Error::InvalidSecret)?;
let password = load_password(&args.arg_password)?;
let vault_ref = open_args_vault(&store, &args)?;
let account_ref = store.insert_account(vault_ref, secret, &password)?;
Ok(format!("0x{:x}", account_ref.address))
} else if args.cmd_change_pwd {
let address = args
.arg_address
.parse()
.map_err(|_| ethstore::Error::InvalidAccount)?;
let old_pwd = load_password(&args.arg_old_pwd)?;
let new_pwd = load_password(&args.arg_new_pwd)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let ok = store
.change_password(&account_ref, &old_pwd, &new_pwd)
.is_ok();
Ok(format!("{}", ok))
} else if args.cmd_list {
let vault_ref = open_args_vault(&store, &args)?;
let accounts = store.accounts()?;
let accounts: Vec<_> = accounts
.into_iter()
.filter(|a| &a.vault == &vault_ref)
.map(|a| a.address)
.collect();
Ok(format_accounts(&accounts))
} else if args.cmd_import {
let password = match args.arg_password.as_ref() {
"" => None,
_ => Some(load_password(&args.arg_password)?),
};
let src = key_dir(&args.flag_src, password)?;
let dst = key_dir(&args.flag_dir, None)?;
return if args.cmd_insert {
let secret = args.arg_secret.parse().map_err(|_| ethstore::Error::InvalidSecret)?;
let password = load_password(&args.arg_password)?;
let vault_ref = open_args_vault(&store, &args)?;
let account_ref = store.insert_account(vault_ref, secret, &password)?;
Ok(format!("0x{:x}", account_ref.address))
} else if args.cmd_change_pwd {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let old_pwd = load_password(&args.arg_old_pwd)?;
let new_pwd = load_password(&args.arg_new_pwd)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let ok = store.change_password(&account_ref, &old_pwd, &new_pwd).is_ok();
Ok(format!("{}", ok))
} else if args.cmd_list {
let vault_ref = open_args_vault(&store, &args)?;
let accounts = store.accounts()?;
let accounts: Vec<_> = accounts
.into_iter()
.filter(|a| &a.vault == &vault_ref)
.map(|a| a.address)
.collect();
Ok(format_accounts(&accounts))
} else if args.cmd_import {
let password = match args.arg_password.as_ref() {
"" => None,
_ => Some(load_password(&args.arg_password)?)
};
let src = key_dir(&args.flag_src, password)?;
let dst = key_dir(&args.flag_dir, None)?;
let accounts = import_accounts(&*src, &*dst)?;
Ok(format_accounts(&accounts))
} else if args.cmd_import_wallet {
let wallet = PresaleWallet::open(&args.arg_path)?;
let password = load_password(&args.arg_password)?;
let kp = wallet.decrypt(&password)?;
let vault_ref = open_args_vault(&store, &args)?;
let account_ref = store.insert_account(vault_ref, kp.secret().clone(), &password)?;
Ok(format!("0x{:x}", account_ref.address))
} else if args.cmd_find_wallet_pass {
let passwords = load_password(&args.arg_password)?;
let passwords = passwords
.as_str()
.lines()
.map(|line| str::to_owned(line).into())
.collect::<VecDeque<_>>();
crack::run(passwords, &args.arg_path)?;
Ok(format!("Password not found."))
} else if args.cmd_remove {
let address = args
.arg_address
.parse()
.map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let ok = store.remove_account(&account_ref, &password).is_ok();
Ok(format!("{}", ok))
} else if args.cmd_sign {
let address = args
.arg_address
.parse()
.map_err(|_| ethstore::Error::InvalidAccount)?;
let message = args
.arg_message
.parse()
.map_err(|_| ethstore::Error::InvalidMessage)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let signature = store.sign(&account_ref, &password, &message)?;
Ok(format!("0x{}", signature))
} else if args.cmd_public {
let address = args
.arg_address
.parse()
.map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let public = store.public(&account_ref, &password)?;
Ok(format!("0x{:x}", public))
} else if args.cmd_list_vaults {
let vaults = store.list_vaults()?;
Ok(format_vaults(&vaults))
} else if args.cmd_create_vault {
let password = load_password(&args.arg_password)?;
store.create_vault(&args.arg_vault, &password)?;
Ok("OK".to_owned())
} else if args.cmd_change_vault_pwd {
let old_pwd = load_password(&args.arg_old_pwd)?;
let new_pwd = load_password(&args.arg_new_pwd)?;
store.open_vault(&args.arg_vault, &old_pwd)?;
store.change_vault_password(&args.arg_vault, &new_pwd)?;
Ok("OK".to_owned())
} else if args.cmd_move_to_vault {
let address = args
.arg_address
.parse()
.map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
store.open_vault(&args.arg_vault, &password)?;
store.change_account_vault(SecretVaultRef::Vault(args.arg_vault), account_ref)?;
Ok("OK".to_owned())
} else if args.cmd_move_from_vault {
let address = args
.arg_address
.parse()
.map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
store.open_vault(&args.arg_vault, &password)?;
store.change_account_vault(
SecretVaultRef::Root,
StoreAccountRef::vault(&args.arg_vault, address),
)?;
Ok("OK".to_owned())
} else {
Ok(format!("{}", USAGE))
};
let accounts = import_accounts(&*src, &*dst)?;
Ok(format_accounts(&accounts))
} else if args.cmd_import_wallet {
let wallet = PresaleWallet::open(&args.arg_path)?;
let password = load_password(&args.arg_password)?;
let kp = wallet.decrypt(&password)?;
let vault_ref = open_args_vault(&store, &args)?;
let account_ref = store.insert_account(vault_ref, kp.secret().clone(), &password)?;
Ok(format!("0x{:x}", account_ref.address))
} else if args.cmd_find_wallet_pass {
let passwords = load_password(&args.arg_password)?;
let passwords = passwords.as_str().lines().map(|line| str::to_owned(line).into()).collect::<VecDeque<_>>();
crack::run(passwords, &args.arg_path)?;
Ok(format!("Password not found."))
} else if args.cmd_remove {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let ok = store.remove_account(&account_ref, &password).is_ok();
Ok(format!("{}", ok))
} else if args.cmd_sign {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let message = args.arg_message.parse().map_err(|_| ethstore::Error::InvalidMessage)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let signature = store.sign(&account_ref, &password, &message)?;
Ok(format!("0x{}", signature))
} else if args.cmd_public {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
let public = store.public(&account_ref, &password)?;
Ok(format!("0x{:x}", public))
} else if args.cmd_list_vaults {
let vaults = store.list_vaults()?;
Ok(format_vaults(&vaults))
} else if args.cmd_create_vault {
let password = load_password(&args.arg_password)?;
store.create_vault(&args.arg_vault, &password)?;
Ok("OK".to_owned())
} else if args.cmd_change_vault_pwd {
let old_pwd = load_password(&args.arg_old_pwd)?;
let new_pwd = load_password(&args.arg_new_pwd)?;
store.open_vault(&args.arg_vault, &old_pwd)?;
store.change_vault_password(&args.arg_vault, &new_pwd)?;
Ok("OK".to_owned())
} else if args.cmd_move_to_vault {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
let account_ref = open_args_vault_account(&store, address, &args)?;
store.open_vault(&args.arg_vault, &password)?;
store.change_account_vault(SecretVaultRef::Vault(args.arg_vault), account_ref)?;
Ok("OK".to_owned())
} else if args.cmd_move_from_vault {
let address = args.arg_address.parse().map_err(|_| ethstore::Error::InvalidAccount)?;
let password = load_password(&args.arg_password)?;
store.open_vault(&args.arg_vault, &password)?;
store.change_account_vault(SecretVaultRef::Root, StoreAccountRef::vault(&args.arg_vault, address))?;
Ok("OK".to_owned())
} else {
Ok(format!("{}", USAGE))
}
}

View File

@@ -0,0 +1,82 @@
// 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
// it under the terms of the GNU 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/>.
extern crate tempdir;
use std::process::Command;
use tempdir::TempDir;
use std::fs::File;
use std::io::Write;
fn run(args: &[&str]) -> String {
let output = Command::new("cargo")
.args(&["run", "--"])
.args(args)
.output()
.unwrap();
assert!(output.status.success());
String::from_utf8(output.stdout).unwrap()
}
#[test]
fn cli_cmd() {
Command::new("cargo")
.arg("build")
.output()
.unwrap();
let dir = TempDir::new("test-vault").unwrap();
let mut passwd = File::create(dir.path().join("test-password")).unwrap();
writeln!(passwd, "password").unwrap();
let mut passwd2 = File::create(dir.path().join("test-vault-addr")).unwrap();
writeln!(passwd2, "password2").unwrap();
let test_password_buf = dir.path().join("test-password");
let test_password: &str = test_password_buf.to_str().unwrap();
let dir_str: &str = dir.path().to_str().unwrap();
let test_vault_addr_buf = dir.path().join("test-vault-addr");
let test_vault_addr = test_vault_addr_buf.to_str().unwrap();
run(&["create-vault", "test-vault", test_password, "--dir", dir_str]);
let output = run(&["insert", "7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5",
test_vault_addr,
"--dir", dir_str,
"--vault", "test-vault",
"--vault-pwd", test_password]);
let address = output.trim();
let output = run(&["list",
"--dir", dir_str,
"--vault", "test-vault",
"--vault-pwd", test_password]);
assert_eq!(output, " 0: 0xa8fa5dd30a87bb9e3288d604eb74949c515ab66e\n");
let output = run(&["sign", &address[2..],
test_vault_addr,
"7d29fab185a33e2cd955812397354c472d2b84615b645aa135ff539f6b0d70d5",
"--dir", dir_str,
"--vault", "test-vault",
"--vault-pwd", test_password]);
assert_eq!(output, "0x54ab6e5cf0c5cb40043fdca5d15d611a3a94285414a076dafecc8dc9c04183f413296a3defff61092c0bb478dc9887ec01070e1275234211208fb8f4be4a9b0101\n");
let output = run(&["public", &address[2..], test_vault_addr,
"--dir", dir_str,
"--vault", "test-vault",
"--vault-pwd", test_password]);
assert_eq!(output, "0x35f222d88b80151857a2877826d940104887376a94c1cbd2c8c7c192eb701df88a18a4ecb8b05b1466c5b3706042027b5e079fe3a3683e66d822b0e047aa3418\n");
}

View File

@@ -1,57 +1,59 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use json;
#[derive(Debug, PartialEq, Clone)]
pub struct Aes128Ctr {
pub iv: [u8; 16],
pub iv: [u8; 16],
}
#[derive(Debug, PartialEq, Clone)]
pub enum Cipher {
Aes128Ctr(Aes128Ctr),
Aes128Ctr(Aes128Ctr),
}
impl From<json::Aes128Ctr> for Aes128Ctr {
fn from(json: json::Aes128Ctr) -> Self {
Aes128Ctr { iv: json.iv.into() }
}
fn from(json: json::Aes128Ctr) -> Self {
Aes128Ctr {
iv: json.iv.into()
}
}
}
impl Into<json::Aes128Ctr> for Aes128Ctr {
fn into(self) -> json::Aes128Ctr {
json::Aes128Ctr {
iv: From::from(self.iv),
}
}
fn into(self) -> json::Aes128Ctr {
json::Aes128Ctr {
iv: From::from(self.iv)
}
}
}
impl From<json::Cipher> for Cipher {
fn from(json: json::Cipher) -> Self {
match json {
json::Cipher::Aes128Ctr(params) => Cipher::Aes128Ctr(From::from(params)),
}
}
fn from(json: json::Cipher) -> Self {
match json {
json::Cipher::Aes128Ctr(params) => Cipher::Aes128Ctr(From::from(params)),
}
}
}
impl Into<json::Cipher> for Cipher {
fn into(self) -> json::Cipher {
match self {
Cipher::Aes128Ctr(params) => json::Cipher::Aes128Ctr(params.into()),
}
}
fn into(self) -> json::Cipher {
match self {
Cipher::Aes128Ctr(params) => json::Cipher::Aes128Ctr(params.into()),
}
}
}

View File

@@ -1,234 +1,207 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use account::{Aes128Ctr, Cipher, Kdf, Pbkdf2, Prf};
use crypto::{self, Keccak256};
use ethkey::{Password, Secret};
use json;
use std::str;
use crypto::publickey::Secret;
use ethkey::Password;
use {json, Error, crypto};
use crypto::Keccak256;
use random::Random;
use smallvec::SmallVec;
use std::{num::NonZeroU32, str};
use Error;
use account::{Cipher, Kdf, Aes128Ctr, Pbkdf2, Prf};
/// Encrypted data
#[derive(Debug, PartialEq, Clone)]
pub struct Crypto {
/// Encryption parameters
pub cipher: Cipher,
/// Encrypted data buffer
pub ciphertext: Vec<u8>,
/// Key derivation function parameters
pub kdf: Kdf,
/// Message authentication code
pub mac: [u8; 32],
/// Encryption parameters
pub cipher: Cipher,
/// Encrypted data buffer
pub ciphertext: Vec<u8>,
/// Key derivation function parameters
pub kdf: Kdf,
/// Message authentication code
pub mac: [u8; 32],
}
impl From<json::Crypto> for Crypto {
fn from(json: json::Crypto) -> Self {
Crypto {
cipher: json.cipher.into(),
ciphertext: json.ciphertext.into(),
kdf: json.kdf.into(),
mac: json.mac.into(),
}
}
fn from(json: json::Crypto) -> Self {
Crypto {
cipher: json.cipher.into(),
ciphertext: json.ciphertext.into(),
kdf: json.kdf.into(),
mac: json.mac.into(),
}
}
}
impl From<Crypto> for json::Crypto {
fn from(c: Crypto) -> Self {
json::Crypto {
cipher: c.cipher.into(),
ciphertext: c.ciphertext.into(),
kdf: c.kdf.into(),
mac: c.mac.into(),
}
}
fn from(c: Crypto) -> Self {
json::Crypto {
cipher: c.cipher.into(),
ciphertext: c.ciphertext.into(),
kdf: c.kdf.into(),
mac: c.mac.into(),
}
}
}
impl str::FromStr for Crypto {
type Err = <json::Crypto as str::FromStr>::Err;
type Err = <json::Crypto as str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<json::Crypto>().map(Into::into)
}
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<json::Crypto>().map(Into::into)
}
}
impl From<Crypto> for String {
fn from(c: Crypto) -> Self {
json::Crypto::from(c).into()
}
fn from(c: Crypto) -> Self {
json::Crypto::from(c).into()
}
}
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)
}
/// Encrypt account secret
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> {
let salt: [u8; 32] = Random::random();
let iv: [u8; 16] = Random::random();
/// Encrypt custom plain data
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();
// two parts of derived key
// DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits]
let (derived_left_bits, derived_right_bits) =
crypto::derive_key_iterations(password.as_bytes(), &salt, iterations);
// two parts of derived key
// DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits]
let (derived_left_bits, derived_right_bits) =
crypto::derive_key_iterations(password.as_bytes(), &salt, iterations);
// preallocated (on-stack in case of `Secret`) buffer to hold cipher
// length = length(plain) as we are using CTR-approach
let plain_len = plain.len();
let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; plain_len]);
// preallocated (on-stack in case of `Secret`) buffer to hold cipher
// length = length(plain) as we are using CTR-approach
let plain_len = plain.len();
let mut ciphertext: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; plain_len]);
// aes-128-ctr with initial vector of iv
crypto::aes::encrypt_128_ctr(&derived_left_bits, &iv, plain, &mut *ciphertext)?;
// aes-128-ctr with initial vector of iv
crypto::aes::encrypt_128_ctr(&derived_left_bits, &iv, plain, &mut *ciphertext)?;
// KECCAK(DK[16..31] ++ <ciphertext>), where DK[16..31] - derived_right_bits
let mac = crypto::derive_mac(&derived_right_bits, &*ciphertext).keccak256();
// KECCAK(DK[16..31] ++ <ciphertext>), where DK[16..31] - derived_right_bits
let mac = crypto::derive_mac(&derived_right_bits, &*ciphertext).keccak256();
Ok(Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr { iv: iv }),
ciphertext: ciphertext.into_vec(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
dklen: crypto::KEY_LENGTH as u32,
salt: salt.to_vec(),
c: iterations,
prf: Prf::HmacSha256,
}),
mac: mac,
})
}
Ok(Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: iv,
}),
ciphertext: ciphertext.into_vec(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
dklen: crypto::KEY_LENGTH as u32,
salt: salt.to_vec(),
c: iterations,
prf: Prf::HmacSha256,
}),
mac: mac,
})
}
/// Try to decrypt and convert result to account secret
pub fn secret(&self, password: &Password) -> Result<Secret, Error> {
if self.ciphertext.len() > 32 {
return Err(Error::InvalidSecret);
}
/// Try to decrypt and convert result to account secret
pub fn secret(&self, password: &Password) -> Result<Secret, Error> {
if self.ciphertext.len() > 32 {
return Err(Error::InvalidSecret);
}
let secret = self.do_decrypt(password, 32)?;
Ok(Secret::from_unsafe_slice(&secret)?)
}
let secret = self.do_decrypt(password, 32)?;
Ok(Secret::import_key(&secret)?)
}
/// Try to decrypt and return result as is
pub fn decrypt(&self, password: &Password) -> Result<Vec<u8>, Error> {
let expected_len = self.ciphertext.len();
self.do_decrypt(password, expected_len)
}
/// Try to decrypt and return result as is
pub fn decrypt(&self, password: &Password) -> Result<Vec<u8>, Error> {
let expected_len = self.ciphertext.len();
self.do_decrypt(password, expected_len)
}
fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result<Vec<u8>, Error> {
let (derived_left_bits, derived_right_bits) = match self.kdf {
Kdf::Pbkdf2(ref params) => {
crypto::derive_key_iterations(password.as_bytes(), &params.salt, params.c)
}
Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(
password.as_bytes(),
&params.salt,
params.n,
params.p,
params.r,
)?,
};
fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result<Vec<u8>, Error> {
let (derived_left_bits, derived_right_bits) = match self.kdf {
Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password.as_bytes(), &params.salt, params.c),
Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password.as_bytes(), &params.salt, params.n, params.p, params.r)?,
};
let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256();
let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256();
if !crypto::is_equal(&mac, &self.mac) {
return Err(Error::InvalidPassword);
}
if !crypto::is_equal(&mac, &self.mac) {
return Err(Error::InvalidPassword)
}
let mut plain: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; expected_len]);
let mut plain: SmallVec<[u8; 32]> = SmallVec::from_vec(vec![0; expected_len]);
match self.cipher {
Cipher::Aes128Ctr(ref params) => {
// checker by callers
debug_assert!(expected_len >= self.ciphertext.len());
match self.cipher {
Cipher::Aes128Ctr(ref params) => {
// checker by callers
debug_assert!(expected_len >= self.ciphertext.len());
let from = expected_len - self.ciphertext.len();
crypto::aes::decrypt_128_ctr(
&derived_left_bits,
&params.iv,
&self.ciphertext,
&mut plain[from..],
)?;
Ok(plain.into_iter().collect())
}
}
}
let from = expected_len - self.ciphertext.len();
crypto::aes::decrypt_128_ctr(&derived_left_bits, &params.iv, &self.ciphertext, &mut plain[from..])?;
Ok(plain.into_iter().collect())
},
}
}
}
#[cfg(test)]
mod tests {
use super::{Crypto, Error, NonZeroU32};
use ethkey::{Generator, Random};
use crypto::publickey::{Generator, Random};
use super::{Crypto, Error};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
}
#[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, 10240).unwrap();
let secret = crypto.secret(&passwd).unwrap();
assert_eq!(keypair.secret(), &secret);
}
#[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 secret = crypto.secret(&passwd).unwrap();
assert_eq!(keypair.secret(), &secret);
}
#[test]
fn crypto_with_secret_invalid_password() {
let keypair = Random.generate().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))
}
#[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();
assert_matches!(
crypto.secret(&"this is sparta!".into()),
Err(Error::InvalidPassword)
)
}
#[test]
fn crypto_with_null_plain_data() {
let original_data = b"";
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
#[test]
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 decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
#[test]
fn crypto_with_tiny_plain_data() {
let original_data = b"{}";
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
#[test]
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 decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
#[test]
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 decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(&original_data, &decrypted_data);
}
#[test]
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, 10240).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(&original_data, &decrypted_data);
}
}

View File

@@ -1,126 +1,125 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// 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 {
HmacSha256,
HmacSha256,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Pbkdf2 {
pub c: NonZeroU32,
pub dklen: u32,
pub prf: Prf,
pub salt: Vec<u8>,
pub c: u32,
pub dklen: u32,
pub prf: Prf,
pub salt: Vec<u8>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Scrypt {
pub dklen: u32,
pub p: u32,
pub n: u32,
pub r: u32,
pub salt: Vec<u8>,
pub dklen: u32,
pub p: u32,
pub n: u32,
pub r: u32,
pub salt: Vec<u8>,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Kdf {
Pbkdf2(Pbkdf2),
Scrypt(Scrypt),
Pbkdf2(Pbkdf2),
Scrypt(Scrypt),
}
impl From<json::Prf> for Prf {
fn from(json: json::Prf) -> Self {
match json {
json::Prf::HmacSha256 => Prf::HmacSha256,
}
}
fn from(json: json::Prf) -> Self {
match json {
json::Prf::HmacSha256 => Prf::HmacSha256,
}
}
}
impl Into<json::Prf> for Prf {
fn into(self) -> json::Prf {
match self {
Prf::HmacSha256 => json::Prf::HmacSha256,
}
}
fn into(self) -> json::Prf {
match self {
Prf::HmacSha256 => json::Prf::HmacSha256,
}
}
}
impl From<json::Pbkdf2> for Pbkdf2 {
fn from(json: json::Pbkdf2) -> Self {
Pbkdf2 {
c: json.c,
dklen: json.dklen,
prf: From::from(json.prf),
salt: json.salt.into(),
}
}
fn from(json: json::Pbkdf2) -> Self {
Pbkdf2 {
c: json.c,
dklen: json.dklen,
prf: From::from(json.prf),
salt: json.salt.into(),
}
}
}
impl Into<json::Pbkdf2> for Pbkdf2 {
fn into(self) -> json::Pbkdf2 {
json::Pbkdf2 {
c: self.c,
dklen: self.dklen,
prf: self.prf.into(),
salt: From::from(self.salt),
}
}
fn into(self) -> json::Pbkdf2 {
json::Pbkdf2 {
c: self.c,
dklen: self.dklen,
prf: self.prf.into(),
salt: From::from(self.salt),
}
}
}
impl From<json::Scrypt> for Scrypt {
fn from(json: json::Scrypt) -> Self {
Scrypt {
dklen: json.dklen,
p: json.p,
n: json.n,
r: json.r,
salt: json.salt.into(),
}
}
fn from(json: json::Scrypt) -> Self {
Scrypt {
dklen: json.dklen,
p: json.p,
n: json.n,
r: json.r,
salt: json.salt.into(),
}
}
}
impl Into<json::Scrypt> for Scrypt {
fn into(self) -> json::Scrypt {
json::Scrypt {
dklen: self.dklen,
p: self.p,
n: self.n,
r: self.r,
salt: From::from(self.salt),
}
}
fn into(self) -> json::Scrypt {
json::Scrypt {
dklen: self.dklen,
p: self.p,
n: self.n,
r: self.r,
salt: From::from(self.salt),
}
}
}
impl From<json::Kdf> for Kdf {
fn from(json: json::Kdf) -> Self {
match json {
json::Kdf::Pbkdf2(params) => Kdf::Pbkdf2(From::from(params)),
json::Kdf::Scrypt(params) => Kdf::Scrypt(From::from(params)),
}
}
fn from(json: json::Kdf) -> Self {
match json {
json::Kdf::Pbkdf2(params) => Kdf::Pbkdf2(From::from(params)),
json::Kdf::Scrypt(params) => Kdf::Scrypt(From::from(params)),
}
}
}
impl Into<json::Kdf> for Kdf {
fn into(self) -> json::Kdf {
match self {
Kdf::Pbkdf2(params) => json::Kdf::Pbkdf2(params.into()),
Kdf::Scrypt(params) => json::Kdf::Scrypt(params.into()),
}
}
fn into(self) -> json::Kdf {
match self {
Kdf::Pbkdf2(params) => json::Kdf::Pbkdf2(params.into()),
Kdf::Scrypt(params) => json::Kdf::Scrypt(params.into()),
}
}
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
mod cipher;
mod crypto;
@@ -20,10 +20,8 @@ mod kdf;
mod safe_account;
mod version;
pub use self::{
cipher::{Aes128Ctr, Cipher},
crypto::Crypto,
kdf::{Kdf, Pbkdf2, Prf, Scrypt},
safe_account::SafeAccount,
version::Version,
};
pub use self::cipher::{Cipher, Aes128Ctr};
pub use self::crypto::Crypto;
pub use self::kdf::{Kdf, Pbkdf2, Scrypt, Prf};
pub use self::safe_account::SafeAccount;
pub use self::version::Version;

View File

@@ -1,286 +1,230 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::crypto::Crypto;
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 ethkey::{
self, crypto::ecdh::agree, sign, Address, KeyPair, Message, Password, Public, Secret, Signature,
};
use json;
use std::num::NonZeroU32;
use Error;
use super::crypto::Crypto;
/// Account representation.
#[derive(Debug, PartialEq, Clone)]
pub struct SafeAccount {
/// Account ID
pub id: [u8; 16],
/// Account version
pub version: Version,
/// Account address
pub address: Address,
/// Account private key derivation definition.
pub crypto: Crypto,
/// Account filename
pub filename: Option<String>,
/// Account name
pub name: String,
/// Account metadata
pub meta: String,
/// Account ID
pub id: [u8; 16],
/// Account version
pub version: Version,
/// Account address
pub address: Address,
/// Account private key derivation definition.
pub crypto: Crypto,
/// Account filename
pub filename: Option<String>,
/// Account name
pub name: String,
/// Account metadata
pub meta: String,
}
impl Into<json::KeyFile> for SafeAccount {
fn into(self) -> json::KeyFile {
json::KeyFile {
id: From::from(self.id),
version: self.version.into(),
address: Some(self.address.into()),
crypto: self.crypto.into(),
name: Some(self.name.into()),
meta: Some(self.meta.into()),
}
}
fn into(self) -> json::KeyFile {
json::KeyFile {
id: From::from(self.id),
version: self.version.into(),
address: Some(self.address.into()),
crypto: self.crypto.into(),
name: Some(self.name.into()),
meta: Some(self.meta.into()),
}
}
}
impl SafeAccount {
/// Create a new account
pub fn create(
keypair: &KeyPair,
id: [u8; 16],
password: &Password,
iterations: NonZeroU32,
name: String,
meta: String,
) -> Result<Self, crypto::Error> {
Ok(SafeAccount {
id: id,
version: Version::V3,
crypto: Crypto::with_secret(keypair.secret(), password, iterations)?,
address: keypair.address(),
filename: None,
name: name,
meta: meta,
})
}
/// Create a new account
pub fn create(
keypair: &KeyPair,
id: [u8; 16],
password: &Password,
iterations: u32,
name: String,
meta: String
) -> Result<Self, crypto::Error> {
Ok(SafeAccount {
id: id,
version: Version::V3,
crypto: Crypto::with_secret(keypair.secret(), password, iterations)?,
address: keypair.address(),
filename: None,
name: name,
meta: meta,
})
}
/// Create a new `SafeAccount` from the given `json`; if it was read from a
/// file, the `filename` should be `Some` name. If it is as yet anonymous, then it
/// can be left `None`.
/// In case `password` is provided, we will attempt to read the secret from the keyfile
/// and derive the address from it instead of reading it directly.
/// Providing password is required for `json::KeyFile`s with no address.
pub fn from_file(
json: json::KeyFile,
filename: Option<String>,
password: &Option<Password>,
) -> Result<Self, Error> {
let crypto = Crypto::from(json.crypto);
let address = match (password, &json.address) {
(None, Some(json_address)) => json_address.into(),
(None, None) => Err(Error::Custom(
"This keystore does not contain address. You need to provide password to import it"
.into(),
))?,
(Some(password), json_address) => {
let derived_address = KeyPair::from_secret(
crypto
.secret(&password)
.map_err(|_| Error::InvalidPassword)?,
)?
.address();
/// Create a new `SafeAccount` from the given `json`; if it was read from a
/// file, the `filename` should be `Some` name. If it is as yet anonymous, then it
/// can be left `None`.
/// In case `password` is provided, we will attempt to read the secret from the keyfile
/// and derive the address from it instead of reading it directly.
/// Providing password is required for `json::KeyFile`s with no address.
pub fn from_file(json: json::KeyFile, filename: Option<String>, password: &Option<Password>) -> Result<Self, Error> {
let crypto = Crypto::from(json.crypto);
let address = match (password, &json.address) {
(None, Some(json_address)) => json_address.into(),
(None, None) => Err(Error::Custom(
"This keystore does not contain address. You need to provide password to import it".into()))?,
(Some(password), json_address) => {
let derived_address = KeyPair::from_secret(
crypto.secret(&password).map_err(|_| Error::InvalidPassword)?
)?.address();
match json_address {
Some(json_address) => {
let json_address = json_address.into();
if derived_address != json_address {
warn!("Detected address mismatch when opening an account. Derived: {:?}, in json got: {:?}",
match json_address {
Some(json_address) => {
let json_address = json_address.into();
if derived_address != json_address {
warn!("Detected address mismatch when opening an account. Derived: {:?}, in json got: {:?}",
derived_address, json_address);
}
}
_ => {}
}
derived_address
}
};
}
},
_ => {},
}
derived_address
}
};
Ok(SafeAccount {
id: json.id.into(),
version: json.version.into(),
address,
crypto,
filename,
name: json.name.unwrap_or(String::new()),
meta: json.meta.unwrap_or("{}".to_owned()),
})
}
Ok(SafeAccount {
id: json.id.into(),
version: json.version.into(),
address,
crypto,
filename,
name: json.name.unwrap_or(String::new()),
meta: json.meta.unwrap_or("{}".to_owned()),
})
}
/// Create a new `SafeAccount` from the given vault `json`; if it was read from a
/// file, the `filename` should be `Some` name. If it is as yet anonymous, then it
/// can be left `None`.
pub fn from_vault_file(
password: &Password,
json: json::VaultKeyFile,
filename: Option<String>,
) -> Result<Self, Error> {
let meta_crypto: Crypto = json.metacrypto.into();
let meta_plain = meta_crypto.decrypt(password)?;
let meta_plain =
json::VaultKeyMeta::load(&meta_plain).map_err(|e| Error::Custom(format!("{:?}", e)))?;
/// Create a new `SafeAccount` from the given vault `json`; if it was read from a
/// file, the `filename` should be `Some` name. If it is as yet anonymous, then it
/// can be left `None`.
pub fn from_vault_file(password: &Password, json: json::VaultKeyFile, filename: Option<String>) -> Result<Self, Error> {
let meta_crypto: Crypto = json.metacrypto.into();
let meta_plain = meta_crypto.decrypt(password)?;
let meta_plain = json::VaultKeyMeta::load(&meta_plain).map_err(|e| Error::Custom(format!("{:?}", e)))?;
SafeAccount::from_file(
json::KeyFile {
id: json.id,
version: json.version,
crypto: json.crypto,
address: Some(meta_plain.address),
name: meta_plain.name,
meta: meta_plain.meta,
},
filename,
&None,
)
}
SafeAccount::from_file(json::KeyFile {
id: json.id,
version: json.version,
crypto: json.crypto,
address: Some(meta_plain.address),
name: meta_plain.name,
meta: meta_plain.meta,
}, filename, &None)
}
/// Create a new `VaultKeyFile` from the given `self`
pub fn into_vault_file(
self,
iterations: NonZeroU32,
password: &Password,
) -> Result<json::VaultKeyFile, Error> {
let meta_plain = json::VaultKeyMeta {
address: self.address.into(),
name: Some(self.name),
meta: Some(self.meta),
};
let meta_plain = meta_plain
.write()
.map_err(|e| Error::Custom(format!("{:?}", e)))?;
let meta_crypto = Crypto::with_plain(&meta_plain, password, iterations)?;
/// Create a new `VaultKeyFile` from the given `self`
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),
meta: Some(self.meta),
};
let meta_plain = meta_plain.write().map_err(|e| Error::Custom(format!("{:?}", e)))?;
let meta_crypto = Crypto::with_plain(&meta_plain, password, iterations)?;
Ok(json::VaultKeyFile {
id: self.id.into(),
version: self.version.into(),
crypto: self.crypto.into(),
metacrypto: meta_crypto.into(),
})
}
Ok(json::VaultKeyFile {
id: self.id.into(),
version: self.version.into(),
crypto: self.crypto.into(),
metacrypto: meta_crypto.into(),
})
}
/// Sign a message.
pub fn sign(&self, password: &Password, message: &Message) -> Result<Signature, Error> {
let secret = self.crypto.secret(password)?;
sign(&secret, message).map_err(From::from)
}
/// Sign a message.
pub fn sign(&self, password: &Password, message: &Message) -> Result<Signature, Error> {
let secret = self.crypto.secret(password)?;
sign(&secret, message).map_err(From::from)
}
/// 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)
}
/// Decrypt a message.
pub fn decrypt(&self, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
let secret = self.crypto.secret(password)?;
crypto::publickey::ecies::decrypt(&secret, shared_mac, message).map_err(From::from)
}
/// Agree on shared key.
pub fn agree(&self, password: &Password, other: &Public) -> Result<Secret, Error> {
let secret = self.crypto.secret(password)?;
agree(&secret, other).map_err(From::from)
}
/// Agree on shared key.
pub fn agree(&self, password: &Password, other: &Public) -> Result<Secret, Error> {
let secret = self.crypto.secret(password)?;
agree(&secret, other).map_err(From::from)
}
/// Derive public key.
pub fn public(&self, password: &Password) -> Result<Public, Error> {
let secret = self.crypto.secret(password)?;
Ok(KeyPair::from_secret(secret)?.public().clone())
}
/// Derive public key.
pub fn public(&self, password: &Password) -> Result<Public, Error> {
let secret = self.crypto.secret(password)?;
Ok(KeyPair::from_secret(secret)?.public().clone())
}
/// Change account's password.
pub fn change_password(
&self,
old_password: &Password,
new_password: &Password,
iterations: NonZeroU32,
) -> Result<Self, Error> {
let secret = self.crypto.secret(old_password)?;
let result = SafeAccount {
id: self.id.clone(),
version: self.version.clone(),
crypto: Crypto::with_secret(&secret, new_password, iterations)?,
address: self.address.clone(),
filename: self.filename.clone(),
name: self.name.clone(),
meta: self.meta.clone(),
};
Ok(result)
}
/// Change account's password.
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(),
version: self.version.clone(),
crypto: Crypto::with_secret(&secret, new_password, iterations)?,
address: self.address.clone(),
filename: self.filename.clone(),
name: self.name.clone(),
meta: self.meta.clone(),
};
Ok(result)
}
/// Check if password matches the account.
pub fn check_password(&self, password: &Password) -> bool {
self.crypto.secret(password).is_ok()
}
/// Check if password matches the account.
pub fn check_password(&self, password: &Password) -> bool {
self.crypto.secret(password).is_ok()
}
}
#[cfg(test)]
mod tests {
use super::{NonZeroU32, SafeAccount};
use ethkey::{verify_public, Generator, Message, Random};
use crypto::publickey::{Generator, Random, verify_public, Message};
use super::SafeAccount;
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
}
#[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, 10240, "Test".to_owned(), "{}".to_owned());
let signature = account.unwrap().sign(&password, &message).unwrap();
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
}
#[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 signature = account.unwrap().sign(&password, &message).unwrap();
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
}
#[test]
fn change_password() {
let keypair = Random.generate().unwrap();
let first_password = "hello world".into();
let sec_password = "this is sparta".into();
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();
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());
assert!(new_account.sign(&sec_password, &message).is_ok());
}
#[test]
fn change_password() {
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, 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());
assert!(new_account.sign(&sec_password, &message).is_ok());
}
}

View File

@@ -1,38 +1,38 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use json;
#[derive(Debug, PartialEq, Clone)]
pub enum Version {
V3,
V3,
}
impl From<json::Version> for Version {
fn from(json: json::Version) -> Self {
match json {
json::Version::V3 => Version::V3,
}
}
fn from(json: json::Version) -> Self {
match json {
json::Version::V3 => Version::V3,
}
}
}
impl Into<json::Version> for Version {
fn into(self) -> json::Version {
match self {
Version::V3 => json::Version::V3,
}
}
fn into(self) -> json::Version {
match self {
Version::V3 => json::Version::V3,
}
}
}

View File

@@ -1,112 +1,101 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{
vault::{VaultDiskDirectory, VAULT_FILE_NAME},
KeyDirectory, VaultKey, VaultKeyDirectory, VaultKeyDirectoryProvider,
};
use ethkey::Password;
use json::{self, Uuid};
use std::{
collections::HashMap,
fs, io,
io::Write,
path::{Path, PathBuf},
};
use std::{fs, io};
use std::io::Write;
use std::path::{PathBuf, Path};
use std::collections::HashMap;
use time;
use Error;
use SafeAccount;
use {json, SafeAccount, Error};
use json::Uuid;
use super::{KeyDirectory, VaultKeyDirectory, VaultKeyDirectoryProvider, VaultKey};
use super::vault::{VAULT_FILE_NAME, VaultDiskDirectory};
use ethkey::Password;
const IGNORED_FILES: &'static [&'static str] = &[
"thumbs.db",
"address_book.json",
"dapps_policy.json",
"dapps_accounts.json",
"dapps_history.json",
"vault.json",
"thumbs.db",
"address_book.json",
"dapps_policy.json",
"dapps_accounts.json",
"dapps_history.json",
"vault.json",
];
/// Find a unique filename that does not exist using four-letter random suffix.
pub fn find_unique_filename_using_random_suffix(
parent_path: &Path,
original_filename: &str,
) -> io::Result<String> {
let mut path = parent_path.join(original_filename);
let mut deduped_filename = original_filename.to_string();
pub fn find_unique_filename_using_random_suffix(parent_path: &Path, original_filename: &str) -> io::Result<String> {
let mut path = parent_path.join(original_filename);
let mut deduped_filename = original_filename.to_string();
if path.exists() {
const MAX_RETRIES: usize = 500;
let mut retries = 0;
if path.exists() {
const MAX_RETRIES: usize = 500;
let mut retries = 0;
while path.exists() {
if retries >= MAX_RETRIES {
return Err(io::Error::new(
io::ErrorKind::Other,
"Exceeded maximum retries when deduplicating filename.",
));
}
while path.exists() {
if retries >= MAX_RETRIES {
return Err(io::Error::new(io::ErrorKind::Other, "Exceeded maximum retries when deduplicating filename."));
}
let suffix = ::random::random_string(4);
deduped_filename = format!("{}-{}", original_filename, suffix);
path.set_file_name(&deduped_filename);
retries += 1;
}
}
let suffix = ::random::random_string(4);
deduped_filename = format!("{}-{}", original_filename, suffix);
path.set_file_name(&deduped_filename);
retries += 1;
}
}
Ok(deduped_filename)
Ok(deduped_filename)
}
/// 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 std::os::unix::fs::OpenOptionsExt;
use std::os::unix::fs::OpenOptionsExt;
fs::OpenOptions::new()
.write(true)
.create_new(true)
.mode((libc::S_IWUSR | libc::S_IRUSR) as u32)
.open(file_path)
fs::OpenOptions::new()
.write(true)
.create_new(true)
.mode((libc::S_IWUSR | libc::S_IRUSR) as u32)
.open(file_path)
}
/// Create a new file and restrict permissions to owner only. It errors if the file already exists.
#[cfg(not(unix))]
pub fn create_new_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(file_path)
fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(file_path)
}
/// 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 std::os::unix::fs::PermissionsExt;
use std::os::unix::fs::PermissionsExt;
let file = fs::File::create(file_path)?;
let mut permissions = file.metadata()?.permissions();
permissions.set_mode((libc::S_IWUSR | libc::S_IRUSR) as u32);
file.set_permissions(permissions)?;
let file = fs::File::create(file_path)?;
let mut permissions = file.metadata()?.permissions();
permissions.set_mode((libc::S_IWUSR | libc::S_IRUSR) as u32);
file.set_permissions(permissions)?;
Ok(file)
Ok(file)
}
/// Create a new file and restrict permissions to owner only. It replaces the existing file if it already exists.
#[cfg(not(unix))]
pub fn replace_file_with_permissions_to_owner(file_path: &Path) -> io::Result<fs::File> {
fs::File::create(file_path)
fs::File::create(file_path)
}
/// Root keys directory implementation
@@ -114,495 +103,382 @@ pub type RootDiskDirectory = DiskDirectory<DiskKeyFileManager>;
/// Disk directory key file manager
pub trait KeyFileManager: Send + Sync {
/// Read `SafeAccount` from given key file stream
fn read<T>(&self, filename: Option<String>, reader: T) -> Result<SafeAccount, Error>
where
T: io::Read;
/// Read `SafeAccount` from given key file stream
fn read<T>(&self, filename: Option<String>, reader: T) -> Result<SafeAccount, Error> where T: io::Read;
/// Write `SafeAccount` to given key file stream
fn write<T>(&self, account: SafeAccount, writer: &mut T) -> Result<(), Error>
where
T: io::Write;
/// Write `SafeAccount` to given key file stream
fn write<T>(&self, account: SafeAccount, writer: &mut T) -> Result<(), Error> where T: io::Write;
}
/// Disk-based keys directory implementation
pub struct DiskDirectory<T>
where
T: KeyFileManager,
{
path: PathBuf,
key_manager: T,
pub struct DiskDirectory<T> where T: KeyFileManager {
path: PathBuf,
key_manager: T,
}
/// Keys file manager for root keys directory
#[derive(Default)]
pub struct DiskKeyFileManager {
password: Option<Password>,
password: Option<Password>,
}
impl RootDiskDirectory {
pub fn create<P>(path: P) -> Result<Self, Error>
where
P: AsRef<Path>,
{
fs::create_dir_all(&path)?;
Ok(Self::at(path))
}
pub fn create<P>(path: P) -> Result<Self, Error> where P: AsRef<Path> {
fs::create_dir_all(&path)?;
Ok(Self::at(path))
}
/// allows to read keyfiles with given password (needed for keyfiles w/o address)
pub fn with_password(&self, password: Option<Password>) -> Self {
DiskDirectory::new(&self.path, DiskKeyFileManager { password })
}
/// allows to read keyfiles with given password (needed for keyfiles w/o address)
pub fn with_password(&self, password: Option<Password>) -> Self {
DiskDirectory::new(&self.path, DiskKeyFileManager { password })
}
pub fn at<P>(path: P) -> Self
where
P: AsRef<Path>,
{
DiskDirectory::new(path, DiskKeyFileManager::default())
}
pub fn at<P>(path: P) -> Self where P: AsRef<Path> {
DiskDirectory::new(path, DiskKeyFileManager::default())
}
}
impl<T> DiskDirectory<T>
where
T: KeyFileManager,
{
/// Create new disk directory instance
pub fn new<P>(path: P, key_manager: T) -> Self
where
P: AsRef<Path>,
{
DiskDirectory {
path: path.as_ref().to_path_buf(),
key_manager: key_manager,
}
}
impl<T> DiskDirectory<T> where T: KeyFileManager {
/// Create new disk directory instance
pub fn new<P>(path: P, key_manager: T) -> Self where P: AsRef<Path> {
DiskDirectory {
path: path.as_ref().to_path_buf(),
key_manager: key_manager,
}
}
fn files(&self) -> Result<Vec<PathBuf>, Error> {
Ok(fs::read_dir(&self.path)?
.flat_map(Result::ok)
.filter(|entry| {
let metadata = entry.metadata().ok();
let file_name = entry.file_name();
let name = file_name.to_string_lossy();
// filter directories
metadata.map_or(false, |m| !m.is_dir()) &&
fn files(&self) -> Result<Vec<PathBuf>, Error> {
Ok(fs::read_dir(&self.path)?
.flat_map(Result::ok)
.filter(|entry| {
let metadata = entry.metadata().ok();
let file_name = entry.file_name();
let name = file_name.to_string_lossy();
// filter directories
metadata.map_or(false, |m| !m.is_dir()) &&
// hidden files
!name.starts_with(".") &&
// other ignored files
!IGNORED_FILES.contains(&&*name)
})
.map(|entry| entry.path())
.collect::<Vec<PathBuf>>())
}
})
.map(|entry| entry.path())
.collect::<Vec<PathBuf>>()
)
}
pub fn files_hash(&self) -> Result<u64, Error> {
use std::{collections::hash_map::DefaultHasher, hash::Hasher};
pub fn files_hash(&self) -> Result<u64, Error> {
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
let mut hasher = DefaultHasher::new();
let files = self.files()?;
for file in files {
hasher.write(file.to_str().unwrap_or("").as_bytes())
}
let mut hasher = DefaultHasher::new();
let files = self.files()?;
for file in files {
hasher.write(file.to_str().unwrap_or("").as_bytes())
}
Ok(hasher.finish())
}
Ok(hasher.finish())
}
fn last_modification_date(&self) -> Result<u64, Error> {
use std::time::{Duration, UNIX_EPOCH};
let duration = fs::metadata(&self.path)?
.modified()?
.duration_since(UNIX_EPOCH)
.unwrap_or(Duration::default());
let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64);
Ok(timestamp)
}
fn last_modification_date(&self) -> Result<u64, Error> {
use std::time::{Duration, UNIX_EPOCH};
let duration = fs::metadata(&self.path)?.modified()?.duration_since(UNIX_EPOCH).unwrap_or(Duration::default());
let timestamp = duration.as_secs() ^ (duration.subsec_nanos() as u64);
Ok(timestamp)
}
/// all accounts found in keys directory
fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
// it's not done using one iterator cause
// there is an issue with rustc and it takes tooo much time to compile
let paths = self.files()?;
Ok(paths
.into_iter()
.filter_map(|path| {
let filename = Some(
path.file_name()
.and_then(|n| n.to_str())
.expect("Keys have valid UTF8 names only.")
.to_owned(),
);
fs::File::open(path.clone())
.map_err(Into::into)
.and_then(|file| self.key_manager.read(filename, file))
.map_err(|err| {
warn!("Invalid key file: {:?} ({})", path, err);
err
})
.map(|account| (path, account))
.ok()
})
.collect())
}
/// all accounts found in keys directory
fn files_content(&self) -> Result<HashMap<PathBuf, SafeAccount>, Error> {
// it's not done using one iterator cause
// there is an issue with rustc and it takes tooo much time to compile
let paths = self.files()?;
Ok(paths
.into_iter()
.filter_map(|path| {
let filename = Some(path.file_name().and_then(|n| n.to_str()).expect("Keys have valid UTF8 names only.").to_owned());
fs::File::open(path.clone())
.map_err(Into::into)
.and_then(|file| self.key_manager.read(filename, file))
.map_err(|err| {
warn!("Invalid key file: {:?} ({})", path, err);
err
})
.map(|account| (path, account))
.ok()
})
.collect()
)
}
/// insert account with given filename. if the filename is a duplicate of any stored account and dedup is set to
/// true, a random suffix is appended to the filename.
pub fn insert_with_filename(
&self,
account: SafeAccount,
mut filename: String,
dedup: bool,
) -> Result<SafeAccount, Error> {
if dedup {
filename = find_unique_filename_using_random_suffix(&self.path, &filename)?;
}
/// insert account with given filename. if the filename is a duplicate of any stored account and dedup is set to
/// true, a random suffix is appended to the filename.
pub fn insert_with_filename(&self, account: SafeAccount, mut filename: String, dedup: bool) -> Result<SafeAccount, Error> {
if dedup {
filename = find_unique_filename_using_random_suffix(&self.path, &filename)?;
}
// path to keyfile
let keyfile_path = self.path.join(filename.as_str());
// path to keyfile
let keyfile_path = self.path.join(filename.as_str());
// update account filename
let original_account = account.clone();
let mut account = account;
account.filename = Some(filename);
// update account filename
let original_account = account.clone();
let mut account = account;
account.filename = Some(filename);
{
// save the file
let mut file = if dedup {
create_new_file_with_permissions_to_owner(&keyfile_path)?
} else {
replace_file_with_permissions_to_owner(&keyfile_path)?
};
{
// save the file
let mut file = if dedup {
create_new_file_with_permissions_to_owner(&keyfile_path)?
} else {
replace_file_with_permissions_to_owner(&keyfile_path)?
};
// write key content
self.key_manager
.write(original_account, &mut file)
.map_err(|e| Error::Custom(format!("{:?}", e)))?;
// write key content
self.key_manager.write(original_account, &mut file).map_err(|e| Error::Custom(format!("{:?}", e)))?;
file.flush()?;
file.sync_all()?;
}
file.flush()?;
file.sync_all()?;
}
Ok(account)
}
Ok(account)
}
/// Get key file manager referece
pub fn key_manager(&self) -> &T {
&self.key_manager
}
/// Get key file manager referece
pub fn key_manager(&self) -> &T {
&self.key_manager
}
}
impl<T> KeyDirectory for DiskDirectory<T>
where
T: KeyFileManager,
{
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
let accounts = self
.files_content()?
.into_iter()
.map(|(_, account)| account)
.collect();
Ok(accounts)
}
impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
let accounts = self.files_content()?
.into_iter()
.map(|(_, account)| account)
.collect();
Ok(accounts)
}
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
// Disk store handles updates correctly iff filename is the same
let filename = account_filename(&account);
self.insert_with_filename(account, filename, false)
}
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
// Disk store handles updates correctly iff filename is the same
let filename = account_filename(&account);
self.insert_with_filename(account, filename, false)
}
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
let filename = account_filename(&account);
self.insert_with_filename(account, filename, true)
}
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
let filename = account_filename(&account);
self.insert_with_filename(account, filename, true)
}
fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
// enumerate all entries in keystore
// and find entry with given address
let to_remove = self
.files_content()?
.into_iter()
.find(|&(_, ref acc)| acc.id == account.id && acc.address == account.address);
fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
// enumerate all entries in keystore
// and find entry with given address
let to_remove = self.files_content()?
.into_iter()
.find(|&(_, ref acc)| acc.id == account.id && acc.address == account.address);
// remove it
match to_remove {
None => Err(Error::InvalidAccount),
Some((path, _)) => fs::remove_file(path).map_err(From::from),
}
}
// remove it
match to_remove {
None => Err(Error::InvalidAccount),
Some((path, _)) => fs::remove_file(path).map_err(From::from)
}
}
fn path(&self) -> Option<&PathBuf> {
Some(&self.path)
}
fn path(&self) -> Option<&PathBuf> { Some(&self.path) }
fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> {
Some(self)
}
fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> {
Some(self)
}
fn unique_repr(&self) -> Result<u64, Error> {
self.last_modification_date()
}
fn unique_repr(&self) -> Result<u64, Error> {
self.last_modification_date()
}
}
impl<T> VaultKeyDirectoryProvider for DiskDirectory<T>
where
T: KeyFileManager,
{
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))
}
impl<T> VaultKeyDirectoryProvider for DiskDirectory<T> where T: KeyFileManager {
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<dyn VaultKeyDirectory>, Error> {
let vault_dir = VaultDiskDirectory::at(&self.path, name, key)?;
Ok(Box::new(vault_dir))
}
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))
}
fn list_vaults(&self) -> Result<Vec<String>, Error> {
Ok(fs::read_dir(&self.path)?
.filter_map(|e| e.ok().map(|e| e.path()))
.filter_map(|path| {
let mut vault_file_path = path.clone();
vault_file_path.push(VAULT_FILE_NAME);
if vault_file_path.is_file() {
path.file_name()
.and_then(|f| f.to_str())
.map(|f| f.to_owned())
} else {
None
}
})
.collect())
}
fn list_vaults(&self) -> Result<Vec<String>, Error> {
Ok(fs::read_dir(&self.path)?
.filter_map(|e| e.ok().map(|e| e.path()))
.filter_map(|path| {
let mut vault_file_path = path.clone();
vault_file_path.push(VAULT_FILE_NAME);
if vault_file_path.is_file() {
path.file_name().and_then(|f| f.to_str()).map(|f| f.to_owned())
} else {
None
}
})
.collect())
}
fn vault_meta(&self, name: &str) -> Result<String, Error> {
VaultDiskDirectory::meta_at(&self.path, name)
}
fn vault_meta(&self, name: &str) -> Result<String, Error> {
VaultDiskDirectory::meta_at(&self.path, name)
}
}
impl KeyFileManager for DiskKeyFileManager {
fn read<T>(&self, filename: Option<String>, reader: T) -> Result<SafeAccount, Error>
where
T: io::Read,
{
let key_file =
json::KeyFile::load(reader).map_err(|e| Error::Custom(format!("{:?}", e)))?;
SafeAccount::from_file(key_file, filename, &self.password)
}
fn read<T>(&self, filename: Option<String>, reader: T) -> Result<SafeAccount, Error> where T: io::Read {
let key_file = json::KeyFile::load(reader).map_err(|e| Error::Custom(format!("{:?}", e)))?;
SafeAccount::from_file(key_file, filename, &self.password)
}
fn write<T>(&self, mut account: SafeAccount, writer: &mut T) -> Result<(), Error>
where
T: io::Write,
{
// when account is moved back to root directory from vault
// => remove vault field from meta
account.meta = json::remove_vault_name_from_json_meta(&account.meta)
.map_err(|err| Error::Custom(format!("{:?}", err)))?;
fn write<T>(&self, mut account: SafeAccount, writer: &mut T) -> Result<(), Error> where T: io::Write {
// when account is moved back to root directory from vault
// => remove vault field from meta
account.meta = json::remove_vault_name_from_json_meta(&account.meta)
.map_err(|err| Error::Custom(format!("{:?}", err)))?;
let key_file: json::KeyFile = account.into();
key_file
.write(writer)
.map_err(|e| Error::Custom(format!("{:?}", e)))
}
let key_file: json::KeyFile = account.into();
key_file.write(writer).map_err(|e| Error::Custom(format!("{:?}", e)))
}
}
fn account_filename(account: &SafeAccount) -> String {
// build file path
account.filename.clone().unwrap_or_else(|| {
let timestamp = time::strftime("%Y-%m-%dT%H-%M-%S", &time::now_utc())
.expect("Time-format string is valid.");
format!("UTC--{}Z--{}", timestamp, Uuid::from(account.id))
})
// build file path
account.filename.clone().unwrap_or_else(|| {
let timestamp = time::strftime("%Y-%m-%dT%H-%M-%S", &time::now_utc()).expect("Time-format string is valid.");
format!("UTC--{}Z--{}", timestamp, Uuid::from(account.id))
})
}
#[cfg(test)]
mod test {
extern crate tempdir;
extern crate tempdir;
use self::tempdir::TempDir;
use super::{KeyDirectory, RootDiskDirectory, VaultKey};
use account::SafeAccount;
use ethkey::{Generator, Random};
use std::{env, fs, num::NonZeroU32};
use std::{env, fs};
use super::{KeyDirectory, RootDiskDirectory, VaultKey};
use account::SafeAccount;
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
let mut dir = env::temp_dir();
dir.push("ethstore_should_create_new_account");
let keypair = Random.generate().unwrap();
let password = "hello world".into();
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
#[test]
fn should_create_new_account() {
// given
let mut dir = env::temp_dir();
dir.push("ethstore_should_create_new_account");
let keypair = Random.generate().unwrap();
let password = "hello world".into();
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
// when
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned());
let res = directory.insert(account.unwrap());
// when
let account = SafeAccount::create(
&keypair,
[0u8; 16],
&password,
*ITERATIONS,
"Test".to_owned(),
"{}".to_owned(),
);
let res = directory.insert(account.unwrap());
// then
assert!(res.is_ok(), "Should save account succesfuly.");
assert!(res.unwrap().filename.is_some(), "Filename has been assigned.");
// then
assert!(res.is_ok(), "Should save account succesfuly.");
assert!(
res.unwrap().filename.is_some(),
"Filename has been assigned."
);
// cleanup
let _ = fs::remove_dir_all(dir);
}
// cleanup
let _ = fs::remove_dir_all(dir);
}
#[test]
fn should_handle_duplicate_filenames() {
// given
let mut dir = env::temp_dir();
dir.push("ethstore_should_handle_duplicate_filenames");
let keypair = Random.generate().unwrap();
let password = "hello world".into();
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
#[test]
fn should_handle_duplicate_filenames() {
// given
let mut dir = env::temp_dir();
dir.push("ethstore_should_handle_duplicate_filenames");
let keypair = Random.generate().unwrap();
let password = "hello world".into();
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
// when
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap();
let filename = "test".to_string();
let dedup = true;
// when
let account = SafeAccount::create(
&keypair,
[0u8; 16],
&password,
*ITERATIONS,
"Test".to_owned(),
"{}".to_owned(),
)
.unwrap();
let filename = "test".to_string();
let dedup = true;
directory.insert_with_filename(account.clone(), "foo".to_string(), dedup).unwrap();
let file1 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap();
let file2 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap();
let file3 = directory.insert_with_filename(account.clone(), filename.clone(), dedup).unwrap().filename.unwrap();
directory
.insert_with_filename(account.clone(), "foo".to_string(), dedup)
.unwrap();
let file1 = directory
.insert_with_filename(account.clone(), filename.clone(), dedup)
.unwrap()
.filename
.unwrap();
let file2 = directory
.insert_with_filename(account.clone(), filename.clone(), dedup)
.unwrap()
.filename
.unwrap();
let file3 = directory
.insert_with_filename(account.clone(), filename.clone(), dedup)
.unwrap()
.filename
.unwrap();
// then
// the first file should have the original names
assert_eq!(file1, filename);
// then
// the first file should have the original names
assert_eq!(file1, filename);
// the following duplicate files should have a suffix appended
assert!(file2 != file3);
assert_eq!(file2.len(), filename.len() + 5);
assert_eq!(file3.len(), filename.len() + 5);
// the following duplicate files should have a suffix appended
assert!(file2 != file3);
assert_eq!(file2.len(), filename.len() + 5);
assert_eq!(file3.len(), filename.len() + 5);
// cleanup
let _ = fs::remove_dir_all(dir);
}
// cleanup
let _ = fs::remove_dir_all(dir);
}
#[test]
fn should_manage_vaults() {
// given
let mut dir = env::temp_dir();
dir.push("should_create_new_vault");
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
let vault_name = "vault";
let password = "password".into();
#[test]
fn should_manage_vaults() {
// given
let mut dir = env::temp_dir();
dir.push("should_create_new_vault");
let directory = RootDiskDirectory::create(dir.clone()).unwrap();
let vault_name = "vault";
let password = "password".into();
// then
assert!(directory.as_vault_provider().is_some());
// then
assert!(directory.as_vault_provider().is_some());
// 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, 1024));
// 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));
// then
assert!(vault.is_ok());
let after_root_items_count = fs::read_dir(&dir).unwrap().count();
assert!(after_root_items_count > before_root_items_count);
// then
assert!(vault.is_ok());
let after_root_items_count = fs::read_dir(&dir).unwrap().count();
assert!(after_root_items_count > before_root_items_count);
// and when
let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, 1024));
// and when
let vault = directory
.as_vault_provider()
.unwrap()
.open(vault_name, VaultKey::new(&password, *ITERATIONS));
// then
assert!(vault.is_ok());
let after_root_items_count2 = fs::read_dir(&dir).unwrap().count();
assert!(after_root_items_count == after_root_items_count2);
// then
assert!(vault.is_ok());
let after_root_items_count2 = fs::read_dir(&dir).unwrap().count();
assert!(after_root_items_count == after_root_items_count2);
// cleanup
let _ = fs::remove_dir_all(dir);
}
// cleanup
let _ = fs::remove_dir_all(dir);
}
#[test]
fn should_list_vaults() {
// given
let temp_path = TempDir::new("").unwrap();
let directory = RootDiskDirectory::create(&temp_path).unwrap();
let vault_provider = directory.as_vault_provider().unwrap();
vault_provider.create("vault1", VaultKey::new(&"password1".into(), 1)).unwrap();
vault_provider.create("vault2", VaultKey::new(&"password2".into(), 1)).unwrap();
#[test]
fn should_list_vaults() {
// given
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();
// then
let vaults = vault_provider.list_vaults().unwrap();
assert_eq!(vaults.len(), 2);
assert!(vaults.iter().any(|v| &*v == "vault1"));
assert!(vaults.iter().any(|v| &*v == "vault2"));
}
// then
let vaults = vault_provider.list_vaults().unwrap();
assert_eq!(vaults.len(), 2);
assert!(vaults.iter().any(|v| &*v == "vault1"));
assert!(vaults.iter().any(|v| &*v == "vault2"));
}
#[test]
fn hash_of_files() {
let temp_path = TempDir::new("").unwrap();
let directory = RootDiskDirectory::create(&temp_path).unwrap();
#[test]
fn hash_of_files() {
let temp_path = TempDir::new("").unwrap();
let directory = RootDiskDirectory::create(&temp_path).unwrap();
let hash = directory.files_hash().expect("Files hash should be calculated ok");
assert_eq!(
hash,
15130871412783076140
);
let hash = directory
.files_hash()
.expect("Files hash should be calculated ok");
assert_eq!(hash, 15130871412783076140);
let keypair = Random.generate().unwrap();
let password = "test pass".into();
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 keypair = Random.generate().unwrap();
let password = "test pass".into();
let account = SafeAccount::create(
&keypair,
[0u8; 16],
&password,
*ITERATIONS,
"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");
let new_hash = directory
.files_hash()
.expect("New files hash should be calculated ok");
assert!(
new_hash != hash,
"hash of the file list should change once directory content changed"
);
}
assert!(new_hash != hash, "hash of the file list should change once directory content changed");
}
}

View File

@@ -1,77 +1,74 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use ethkey::Address;
use itertools;
use parking_lot::RwLock;
use std::collections::HashMap;
use parking_lot::RwLock;
use itertools;
use crypto::publickey::Address;
use {SafeAccount, Error};
use super::KeyDirectory;
use Error;
use SafeAccount;
/// Accounts in-memory storage.
#[derive(Default)]
pub struct MemoryDirectory {
accounts: RwLock<HashMap<Address, Vec<SafeAccount>>>,
accounts: RwLock<HashMap<Address, Vec<SafeAccount>>>,
}
impl KeyDirectory for MemoryDirectory {
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
Ok(itertools::Itertools::flatten(self.accounts.read().values().cloned()).collect())
}
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
Ok(itertools::Itertools::flatten(self.accounts.read().values().cloned()).collect())
}
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
let mut lock = self.accounts.write();
let accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new);
// If the filename is the same we just need to replace the entry
accounts.retain(|acc| acc.filename != account.filename);
accounts.push(account.clone());
Ok(account)
}
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
let mut lock = self.accounts.write();
let accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new);
// If the filename is the same we just need to replace the entry
accounts.retain(|acc| acc.filename != account.filename);
accounts.push(account.clone());
Ok(account)
}
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
let mut lock = self.accounts.write();
let accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new);
accounts.push(account.clone());
Ok(account)
}
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
let mut lock = self.accounts.write();
let accounts = lock.entry(account.address.clone()).or_insert_with(Vec::new);
accounts.push(account.clone());
Ok(account)
}
fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
let mut accounts = self.accounts.write();
let is_empty = if let Some(accounts) = accounts.get_mut(&account.address) {
if let Some(position) = accounts.iter().position(|acc| acc == account) {
accounts.remove(position);
}
accounts.is_empty()
} else {
false
};
if is_empty {
accounts.remove(&account.address);
}
Ok(())
}
fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
let mut accounts = self.accounts.write();
let is_empty = if let Some(accounts) = accounts.get_mut(&account.address) {
if let Some(position) = accounts.iter().position(|acc| acc == account) {
accounts.remove(position);
}
accounts.is_empty()
} else {
false
};
if is_empty {
accounts.remove(&account.address);
}
Ok(())
}
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()
}
Ok(val)
}
fn unique_repr(&self) -> Result<u64, Error> {
let mut val = 0u64;
let accounts = self.accounts.read();
for acc in accounts.keys() { val = val ^ acc.to_low_u64_be() }
Ok(val)
}
}

View File

@@ -1,25 +1,24 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Accounts Directory
use ethkey::Password;
use std::{num::NonZeroU32, path::PathBuf};
use Error;
use SafeAccount;
use std::path::{PathBuf};
use {SafeAccount, Error};
mod disk;
mod memory;
@@ -28,85 +27,79 @@ mod vault;
/// `VaultKeyDirectory::set_key` error
#[derive(Debug)]
pub enum SetKeyError {
/// Error is fatal and directory is probably in inconsistent state
Fatal(Error),
/// Error is non fatal, directory is reverted to pre-operation state
NonFatalOld(Error),
/// Error is non fatal, directory is consistent with new key
NonFatalNew(Error),
/// Error is fatal and directory is probably in inconsistent state
Fatal(Error),
/// Error is non fatal, directory is reverted to pre-operation state
NonFatalOld(Error),
/// Error is non fatal, directory is consistent with new key
NonFatalNew(Error),
}
/// Vault key
#[derive(Clone, PartialEq, Eq)]
pub struct VaultKey {
/// Vault password
pub password: Password,
/// Number of iterations to produce a derived key from password
pub iterations: NonZeroU32,
/// Vault password
pub password: Password,
/// Number of iterations to produce a derived key from password
pub iterations: u32,
}
/// Keys directory
pub trait KeyDirectory: Send + Sync {
/// Read keys from directory
fn load(&self) -> Result<Vec<SafeAccount>, Error>;
/// Insert new key to directory
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error>;
/// Update key in the directory
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error>;
/// Remove key from directory
fn remove(&self, account: &SafeAccount) -> Result<(), Error>;
/// Get directory filesystem path, if available
fn path(&self) -> Option<&PathBuf> {
None
}
/// Return vault provider, if available
fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> {
None
}
/// Unique representation of directory account collection
fn unique_repr(&self) -> Result<u64, Error>;
/// Read keys from directory
fn load(&self) -> Result<Vec<SafeAccount>, Error>;
/// Insert new key to directory
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error>;
/// Update key in the directory
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error>;
/// Remove key from directory
fn remove(&self, account: &SafeAccount) -> Result<(), Error>;
/// Get directory filesystem path, if available
fn path(&self) -> Option<&PathBuf> { None }
/// Return vault provider, if available
fn as_vault_provider(&self) -> Option<&dyn VaultKeyDirectoryProvider> { None }
/// Unique representation of directory account collection
fn unique_repr(&self) -> Result<u64, Error>;
}
/// Vaults provider
pub trait VaultKeyDirectoryProvider {
/// Create new vault with given key
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<dyn VaultKeyDirectory>, Error>;
/// List all vaults
fn list_vaults(&self) -> Result<Vec<String>, Error>;
/// Get vault meta
fn vault_meta(&self, name: &str) -> Result<String, Error>;
/// Create new vault with given key
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<dyn VaultKeyDirectory>, Error>;
/// List all vaults
fn list_vaults(&self) -> Result<Vec<String>, Error>;
/// Get vault meta
fn vault_meta(&self, name: &str) -> Result<String, Error>;
}
/// Vault directory
pub trait VaultKeyDirectory: KeyDirectory {
/// Cast to `KeyDirectory`
fn as_key_directory(&self) -> &dyn KeyDirectory;
/// Vault name
fn name(&self) -> &str;
/// Get vault key
fn key(&self) -> VaultKey;
/// Set new key for vault
fn set_key(&self, key: VaultKey) -> Result<(), SetKeyError>;
/// Get vault meta
fn meta(&self) -> String;
/// Set vault meta
fn set_meta(&self, meta: &str) -> Result<(), Error>;
/// Cast to `KeyDirectory`
fn as_key_directory(&self) -> &dyn KeyDirectory;
/// Vault name
fn name(&self) -> &str;
/// Get vault key
fn key(&self) -> VaultKey;
/// Set new key for vault
fn set_key(&self, key: VaultKey) -> Result<(), SetKeyError>;
/// Get vault meta
fn meta(&self) -> String;
/// Set vault meta
fn set_meta(&self, meta: &str) -> Result<(), Error>;
}
pub use self::{
disk::{DiskKeyFileManager, KeyFileManager, RootDiskDirectory},
memory::MemoryDirectory,
vault::VaultDiskDirectory,
};
pub use self::disk::{RootDiskDirectory, DiskKeyFileManager, KeyFileManager};
pub use self::memory::MemoryDirectory;
pub use self::vault::VaultDiskDirectory;
impl VaultKey {
/// Create new vault key
pub fn new(password: &Password, iterations: NonZeroU32) -> Self {
VaultKey {
password: password.clone(),
iterations: iterations,
}
}
/// Create new vault key
pub fn new(password: &Password, iterations: u32) -> Self {
VaultKey {
password: password.clone(),
iterations: iterations,
}
}
}

View File

@@ -1,33 +1,27 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{
super::account::Crypto,
disk::{self, DiskDirectory, KeyFileManager},
KeyDirectory, SetKeyError, VaultKey, VaultKeyDirectory,
};
use crypto::Keccak256;
use json;
use std::{fs, io};
use std::path::{PathBuf, Path};
use parking_lot::Mutex;
use std::{
fs, io,
path::{Path, PathBuf},
};
use Error;
use SafeAccount;
use {json, SafeAccount, Error};
use crypto::Keccak256;
use super::super::account::Crypto;
use super::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError};
use super::disk::{self, DiskDirectory, KeyFileManager};
/// Name of vault metadata file
pub const VAULT_FILE_NAME: &'static str = "vault.json";
@@ -39,489 +33,411 @@ pub type VaultDiskDirectory = DiskDirectory<VaultKeyFileManager>;
/// Vault key file manager
pub struct VaultKeyFileManager {
name: String,
key: VaultKey,
meta: Mutex<String>,
name: String,
key: VaultKey,
meta: Mutex<String>,
}
impl VaultDiskDirectory {
/// Create new vault directory with given key
pub fn create<P>(root: P, name: &str, key: VaultKey) -> Result<Self, Error>
where
P: AsRef<Path>,
{
// check that vault directory does not exists
let vault_dir_path = make_vault_dir_path(root, name, true)?;
if vault_dir_path.exists() {
return Err(Error::CreationFailed);
}
/// Create new vault directory with given key
pub fn create<P>(root: P, name: &str, key: VaultKey) -> Result<Self, Error> where P: AsRef<Path> {
// check that vault directory does not exists
let vault_dir_path = make_vault_dir_path(root, name, true)?;
if vault_dir_path.exists() {
return Err(Error::CreationFailed);
}
// create vault && vault file
let vault_meta = "{}";
fs::create_dir_all(&vault_dir_path)?;
if let Err(err) = create_vault_file(&vault_dir_path, &key, vault_meta) {
let _ = fs::remove_dir_all(&vault_dir_path); // can't do anything with this
return Err(err);
}
// create vault && vault file
let vault_meta = "{}";
fs::create_dir_all(&vault_dir_path)?;
if let Err(err) = create_vault_file(&vault_dir_path, &key, vault_meta) {
let _ = fs::remove_dir_all(&vault_dir_path); // can't do anything with this
return Err(err);
}
Ok(DiskDirectory::new(
vault_dir_path,
VaultKeyFileManager::new(name, key, vault_meta),
))
}
Ok(DiskDirectory::new(vault_dir_path, VaultKeyFileManager::new(name, key, vault_meta)))
}
/// Open existing vault directory with given key
pub fn at<P>(root: P, name: &str, key: VaultKey) -> Result<Self, Error>
where
P: AsRef<Path>,
{
// check that vault directory exists
let vault_dir_path = make_vault_dir_path(root, name, true)?;
if !vault_dir_path.is_dir() {
return Err(Error::CreationFailed);
}
/// Open existing vault directory with given key
pub fn at<P>(root: P, name: &str, key: VaultKey) -> Result<Self, Error> where P: AsRef<Path> {
// check that vault directory exists
let vault_dir_path = make_vault_dir_path(root, name, true)?;
if !vault_dir_path.is_dir() {
return Err(Error::CreationFailed);
}
// check that passed key matches vault file
let meta = read_vault_file(&vault_dir_path, Some(&key))?;
// check that passed key matches vault file
let meta = read_vault_file(&vault_dir_path, Some(&key))?;
Ok(DiskDirectory::new(
vault_dir_path,
VaultKeyFileManager::new(name, key, &meta),
))
}
Ok(DiskDirectory::new(vault_dir_path, VaultKeyFileManager::new(name, key, &meta)))
}
/// Read vault meta without actually opening the vault
pub fn meta_at<P>(root: P, name: &str) -> Result<String, Error>
where
P: AsRef<Path>,
{
// check that vault directory exists
let vault_dir_path = make_vault_dir_path(root, name, true)?;
if !vault_dir_path.is_dir() {
return Err(Error::VaultNotFound);
}
/// Read vault meta without actually opening the vault
pub fn meta_at<P>(root: P, name: &str) -> Result<String, Error> where P: AsRef<Path> {
// check that vault directory exists
let vault_dir_path = make_vault_dir_path(root, name, true)?;
if !vault_dir_path.is_dir() {
return Err(Error::VaultNotFound);
}
// check that passed key matches vault file
read_vault_file(&vault_dir_path, None)
}
// check that passed key matches vault file
read_vault_file(&vault_dir_path, None)
}
fn create_temp_vault(&self, key: VaultKey) -> Result<VaultDiskDirectory, Error> {
let original_path = self
.path()
.expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed");
let mut path: PathBuf = original_path.clone();
let name = self.name();
fn create_temp_vault(&self, key: VaultKey) -> Result<VaultDiskDirectory, Error> {
let original_path = self.path().expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed");
let mut path: PathBuf = original_path.clone();
let name = self.name();
path.push(name); // to jump to the next level
path.push(name); // to jump to the next level
let mut index = 0;
loop {
let name = format!("{}_temp_{}", name, index);
path.set_file_name(&name);
if !path.exists() {
return VaultDiskDirectory::create(original_path, &name, key);
}
let mut index = 0;
loop {
let name = format!("{}_temp_{}", name, index);
path.set_file_name(&name);
if !path.exists() {
return VaultDiskDirectory::create(original_path, &name, key);
}
index += 1;
}
}
index += 1;
}
}
fn copy_to_vault(&self, vault: &VaultDiskDirectory) -> Result<(), Error> {
for account in self.load()? {
let filename = account.filename.clone().expect(
"self is instance of DiskDirectory; DiskDirectory fills filename in load; qed",
);
vault.insert_with_filename(account, filename, true)?;
}
fn copy_to_vault(&self, vault: &VaultDiskDirectory) -> Result<(), Error> {
for account in self.load()? {
let filename = account.filename.clone().expect("self is instance of DiskDirectory; DiskDirectory fills filename in load; qed");
vault.insert_with_filename(account, filename, true)?;
}
Ok(())
}
Ok(())
}
fn delete(&self) -> Result<(), Error> {
let path = self
.path()
.expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed");
fs::remove_dir_all(path).map_err(Into::into)
}
fn delete(&self) -> Result<(), Error> {
let path = self.path().expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed");
fs::remove_dir_all(path).map_err(Into::into)
}
}
impl VaultKeyDirectory for VaultDiskDirectory {
fn as_key_directory(&self) -> &dyn KeyDirectory {
self
}
fn as_key_directory(&self) -> &dyn KeyDirectory {
self
}
fn name(&self) -> &str {
&self.key_manager().name
}
fn name(&self) -> &str {
&self.key_manager().name
}
fn key(&self) -> VaultKey {
self.key_manager().key.clone()
}
fn key(&self) -> VaultKey {
self.key_manager().key.clone()
}
fn set_key(&self, new_key: VaultKey) -> Result<(), SetKeyError> {
let temp_vault = VaultDiskDirectory::create_temp_vault(self, new_key.clone())
.map_err(|err| SetKeyError::NonFatalOld(err))?;
let mut source_path = temp_vault
.path()
.expect(
"temp_vault is instance of DiskDirectory; DiskDirectory always returns path; qed",
)
.clone();
let mut target_path = self
.path()
.expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed")
.clone();
fn set_key(&self, new_key: VaultKey) -> Result<(), SetKeyError> {
let temp_vault = VaultDiskDirectory::create_temp_vault(self, new_key.clone()).map_err(|err| SetKeyError::NonFatalOld(err))?;
let mut source_path = temp_vault.path().expect("temp_vault is instance of DiskDirectory; DiskDirectory always returns path; qed").clone();
let mut target_path = self.path().expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed").clone();
// preserve meta
temp_vault
.set_meta(&self.meta())
.map_err(SetKeyError::NonFatalOld)?;
// preserve meta
temp_vault.set_meta(&self.meta()).map_err(SetKeyError::NonFatalOld)?;
// jump to next fs level
source_path.push("next");
target_path.push("next");
// jump to next fs level
source_path.push("next");
target_path.push("next");
let temp_accounts = self
.copy_to_vault(&temp_vault)
.and_then(|_| temp_vault.load())
.map_err(|err| {
// ignore error, as we already processing error
let _ = temp_vault.delete();
SetKeyError::NonFatalOld(err)
})?;
let temp_accounts = self.copy_to_vault(&temp_vault)
.and_then(|_| temp_vault.load())
.map_err(|err| {
// ignore error, as we already processing error
let _ = temp_vault.delete();
SetKeyError::NonFatalOld(err)
})?;
// we can't just delete temp vault until all files moved, because
// original vault content has already been partially replaced
// => when error or crash happens here, we can't do anything
for temp_account in temp_accounts {
let filename = temp_account.filename.expect(
"self is instance of DiskDirectory; DiskDirectory fills filename in load; qed",
);
source_path.set_file_name(&filename);
target_path.set_file_name(&filename);
fs::rename(&source_path, &target_path).map_err(|err| SetKeyError::Fatal(err.into()))?;
}
source_path.set_file_name(VAULT_FILE_NAME);
target_path.set_file_name(VAULT_FILE_NAME);
fs::rename(source_path, target_path).map_err(|err| SetKeyError::Fatal(err.into()))?;
// we can't just delete temp vault until all files moved, because
// original vault content has already been partially replaced
// => when error or crash happens here, we can't do anything
for temp_account in temp_accounts {
let filename = temp_account.filename.expect("self is instance of DiskDirectory; DiskDirectory fills filename in load; qed");
source_path.set_file_name(&filename);
target_path.set_file_name(&filename);
fs::rename(&source_path, &target_path).map_err(|err| SetKeyError::Fatal(err.into()))?;
}
source_path.set_file_name(VAULT_FILE_NAME);
target_path.set_file_name(VAULT_FILE_NAME);
fs::rename(source_path, target_path).map_err(|err| SetKeyError::Fatal(err.into()))?;
temp_vault
.delete()
.map_err(|err| SetKeyError::NonFatalNew(err))
}
temp_vault.delete().map_err(|err| SetKeyError::NonFatalNew(err))
}
fn meta(&self) -> String {
self.key_manager().meta.lock().clone()
}
fn meta(&self) -> String {
self.key_manager().meta.lock().clone()
}
fn set_meta(&self, meta: &str) -> Result<(), Error> {
let key_manager = self.key_manager();
let vault_path = self
.path()
.expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed");
create_vault_file(vault_path, &key_manager.key, meta)?;
*key_manager.meta.lock() = meta.to_owned();
Ok(())
}
fn set_meta(&self, meta: &str) -> Result<(), Error> {
let key_manager = self.key_manager();
let vault_path = self.path().expect("self is instance of DiskDirectory; DiskDirectory always returns path; qed");
create_vault_file(vault_path, &key_manager.key, meta)?;
*key_manager.meta.lock() = meta.to_owned();
Ok(())
}
}
impl VaultKeyFileManager {
pub fn new(name: &str, key: VaultKey, meta: &str) -> Self {
VaultKeyFileManager {
name: name.into(),
key: key,
meta: Mutex::new(meta.to_owned()),
}
}
pub fn new(name: &str, key: VaultKey, meta: &str) -> Self {
VaultKeyFileManager {
name: name.into(),
key: key,
meta: Mutex::new(meta.to_owned()),
}
}
}
impl KeyFileManager for VaultKeyFileManager {
fn read<T>(&self, filename: Option<String>, reader: T) -> Result<SafeAccount, Error>
where
T: io::Read,
{
let vault_file =
json::VaultKeyFile::load(reader).map_err(|e| Error::Custom(format!("{:?}", e)))?;
let mut safe_account =
SafeAccount::from_vault_file(&self.key.password, vault_file, filename.clone())?;
fn read<T>(&self, filename: Option<String>, reader: T) -> Result<SafeAccount, Error> where T: io::Read {
let vault_file = json::VaultKeyFile::load(reader).map_err(|e| Error::Custom(format!("{:?}", e)))?;
let mut safe_account = SafeAccount::from_vault_file(&self.key.password, vault_file, filename.clone())?;
safe_account.meta = json::insert_vault_name_to_json_meta(&safe_account.meta, &self.name)
.map_err(|err| Error::Custom(format!("{:?}", err)))?;
Ok(safe_account)
}
safe_account.meta = json::insert_vault_name_to_json_meta(&safe_account.meta, &self.name)
.map_err(|err| Error::Custom(format!("{:?}", err)))?;
Ok(safe_account)
}
fn write<T>(&self, mut account: SafeAccount, writer: &mut T) -> Result<(), Error>
where
T: io::Write,
{
account.meta = json::remove_vault_name_from_json_meta(&account.meta)
.map_err(|err| Error::Custom(format!("{:?}", err)))?;
fn write<T>(&self, mut account: SafeAccount, writer: &mut T) -> Result<(), Error> where T: io::Write {
account.meta = json::remove_vault_name_from_json_meta(&account.meta)
.map_err(|err| Error::Custom(format!("{:?}", err)))?;
let vault_file: json::VaultKeyFile =
account.into_vault_file(self.key.iterations, &self.key.password)?;
vault_file
.write(writer)
.map_err(|e| Error::Custom(format!("{:?}", e)))
}
let vault_file: json::VaultKeyFile = account.into_vault_file(self.key.iterations, &self.key.password)?;
vault_file.write(writer).map_err(|e| Error::Custom(format!("{:?}", e)))
}
}
/// Makes path to vault directory, checking that vault name is appropriate
fn make_vault_dir_path<P>(root: P, name: &str, check_name: bool) -> Result<PathBuf, Error>
where
P: AsRef<Path>,
{
// check vault name
if check_name && !check_vault_name(name) {
return Err(Error::InvalidVaultName);
}
fn make_vault_dir_path<P>(root: P, name: &str, check_name: bool) -> Result<PathBuf, Error> where P: AsRef<Path> {
// check vault name
if check_name && !check_vault_name(name) {
return Err(Error::InvalidVaultName);
}
let mut vault_dir_path: PathBuf = root.as_ref().into();
vault_dir_path.push(name);
Ok(vault_dir_path)
let mut vault_dir_path: PathBuf = root.as_ref().into();
vault_dir_path.push(name);
Ok(vault_dir_path)
}
/// Every vault must have unique name => we rely on filesystem to check this
/// => vault name must not contain any fs-special characters to avoid directory traversal
/// => we only allow alphanumeric + separator characters in vault name.
fn check_vault_name(name: &str) -> bool {
!name.is_empty()
&& name
.chars()
.all(|c| c.is_alphanumeric() || c.is_whitespace() || c == '-' || c == '_')
!name.is_empty()
&& name.chars()
.all(|c| c.is_alphanumeric()
|| c.is_whitespace()
|| c == '-' || c == '_')
}
/// Vault can be empty, but still must be pluggable => we store vault password in separate file
fn create_vault_file<P>(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error>
where
P: AsRef<Path>,
{
let password_hash = key.password.as_bytes().keccak256();
let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations)?;
fn create_vault_file<P>(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error> where P: AsRef<Path> {
let password_hash = key.password.as_bytes().keccak256();
let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations)?;
let vault_file_path = vault_dir_path.as_ref().join(VAULT_FILE_NAME);
let temp_vault_file_name = disk::find_unique_filename_using_random_suffix(
vault_dir_path.as_ref(),
&VAULT_TEMP_FILE_NAME,
)?;
let temp_vault_file_path = vault_dir_path.as_ref().join(&temp_vault_file_name);
let vault_file_path = vault_dir_path.as_ref().join(VAULT_FILE_NAME);
let temp_vault_file_name = disk::find_unique_filename_using_random_suffix(vault_dir_path.as_ref(), &VAULT_TEMP_FILE_NAME)?;
let temp_vault_file_path = vault_dir_path.as_ref().join(&temp_vault_file_name);
// this method is used to rewrite existing vault file
// => write to temporary file first, then rename temporary file to vault file
let mut vault_file = disk::create_new_file_with_permissions_to_owner(&temp_vault_file_path)?;
let vault_file_contents = json::VaultFile {
crypto: crypto.into(),
meta: Some(meta.to_owned()),
};
vault_file_contents
.write(&mut vault_file)
.map_err(|e| Error::Custom(format!("{:?}", e)))?;
drop(vault_file);
fs::rename(&temp_vault_file_path, &vault_file_path)?;
// this method is used to rewrite existing vault file
// => write to temporary file first, then rename temporary file to vault file
let mut vault_file = disk::create_new_file_with_permissions_to_owner(&temp_vault_file_path)?;
let vault_file_contents = json::VaultFile {
crypto: crypto.into(),
meta: Some(meta.to_owned()),
};
vault_file_contents.write(&mut vault_file).map_err(|e| Error::Custom(format!("{:?}", e)))?;
drop(vault_file);
fs::rename(&temp_vault_file_path, &vault_file_path)?;
Ok(())
Ok(())
}
/// When vault is opened => we must check that password matches && read metadata
fn read_vault_file<P>(vault_dir_path: P, key: Option<&VaultKey>) -> Result<String, Error>
where
P: AsRef<Path>,
{
let mut vault_file_path: PathBuf = vault_dir_path.as_ref().into();
vault_file_path.push(VAULT_FILE_NAME);
fn read_vault_file<P>(vault_dir_path: P, key: Option<&VaultKey>) -> Result<String, Error> where P: AsRef<Path> {
let mut vault_file_path: PathBuf = vault_dir_path.as_ref().into();
vault_file_path.push(VAULT_FILE_NAME);
let vault_file = fs::File::open(vault_file_path)?;
let vault_file_contents =
json::VaultFile::load(vault_file).map_err(|e| Error::Custom(format!("{:?}", e)))?;
let vault_file_meta = vault_file_contents.meta.unwrap_or("{}".to_owned());
let vault_file_crypto: Crypto = vault_file_contents.crypto.into();
let vault_file = fs::File::open(vault_file_path)?;
let vault_file_contents = json::VaultFile::load(vault_file).map_err(|e| Error::Custom(format!("{:?}", e)))?;
let vault_file_meta = vault_file_contents.meta.unwrap_or("{}".to_owned());
let vault_file_crypto: Crypto = vault_file_contents.crypto.into();
if let Some(key) = key {
let password_bytes = vault_file_crypto.decrypt(&key.password)?;
let password_hash = key.password.as_bytes().keccak256();
if password_hash != password_bytes.as_slice() {
return Err(Error::InvalidPassword);
}
}
if let Some(key) = key {
let password_bytes = vault_file_crypto.decrypt(&key.password)?;
let password_hash = key.password.as_bytes().keccak256();
if password_hash != password_bytes.as_slice() {
return Err(Error::InvalidPassword);
}
}
Ok(vault_file_meta)
Ok(vault_file_meta)
}
#[cfg(test)]
mod test {
extern crate tempdir;
extern crate tempdir;
use self::tempdir::TempDir;
use super::{
check_vault_name, create_vault_file, make_vault_dir_path, read_vault_file,
VaultDiskDirectory, VaultKey, VAULT_FILE_NAME,
};
use std::{fs, io::Write, num::NonZeroU32, path::PathBuf};
use std::fs;
use std::io::Write;
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"));
assert!(check_vault_name("vault with spaces"));
assert!(check_vault_name("vault with tabs"));
assert!(check_vault_name("vault_with_underscores"));
assert!(check_vault_name("vault-with-dashes"));
assert!(check_vault_name("vault-with-digits-123"));
assert!(check_vault_name("vault中文名字"));
}
#[test]
fn check_vault_name_succeeds() {
assert!(check_vault_name("vault"));
assert!(check_vault_name("vault with spaces"));
assert!(check_vault_name("vault with tabs"));
assert!(check_vault_name("vault_with_underscores"));
assert!(check_vault_name("vault-with-dashes"));
assert!(check_vault_name("vault-with-digits-123"));
assert!(check_vault_name("vault中文名字"));
}
#[test]
fn check_vault_name_fails() {
assert!(!check_vault_name(""));
assert!(!check_vault_name("."));
assert!(!check_vault_name("*"));
assert!(!check_vault_name("../.bash_history"));
assert!(!check_vault_name("/etc/passwd"));
assert!(!check_vault_name("c:\\windows"));
}
#[test]
fn check_vault_name_fails() {
assert!(!check_vault_name(""));
assert!(!check_vault_name("."));
assert!(!check_vault_name("*"));
assert!(!check_vault_name("../.bash_history"));
assert!(!check_vault_name("/etc/passwd"));
assert!(!check_vault_name("c:\\windows"));
}
#[test]
fn make_vault_dir_path_succeeds() {
use std::path::Path;
#[test]
fn make_vault_dir_path_succeeds() {
use std::path::Path;
assert_eq!(&make_vault_dir_path("/home/user/parity", "vault", true).unwrap(), &Path::new("/home/user/parity/vault"));
assert_eq!(&make_vault_dir_path("/home/user/parity", "*bad-name*", false).unwrap(), &Path::new("/home/user/parity/*bad-name*"));
}
assert_eq!(
&make_vault_dir_path("/home/user/parity", "vault", true).unwrap(),
&Path::new("/home/user/parity/vault")
);
assert_eq!(
&make_vault_dir_path("/home/user/parity", "*bad-name*", false).unwrap(),
&Path::new("/home/user/parity/*bad-name*")
);
}
#[test]
fn make_vault_dir_path_fails() {
assert!(make_vault_dir_path("/home/user/parity", "*bad-name*", true).is_err());
}
#[test]
fn make_vault_dir_path_fails() {
assert!(make_vault_dir_path("/home/user/parity", "*bad-name*", true).is_err());
}
#[test]
fn create_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
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();
#[test]
fn create_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let mut vault_dir: PathBuf = temp_path.path().into();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
// when
let result = create_vault_file(&vault_dir, &key, "{}");
// when
let result = create_vault_file(&vault_dir, &key, "{}");
// then
assert!(result.is_ok());
let mut vault_file_path = vault_dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
assert!(vault_file_path.exists() && vault_file_path.is_file());
}
// then
assert!(result.is_ok());
let mut vault_file_path = vault_dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
assert!(vault_file_path.exists() && vault_file_path.is_file());
}
#[test]
fn read_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
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();
vault_file_path.push(VAULT_FILE_NAME);
{
let mut vault_file = fs::File::create(vault_file_path).unwrap();
vault_file.write_all(vault_file_contents.as_bytes()).unwrap();
}
#[test]
fn read_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
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();
vault_file_path.push(VAULT_FILE_NAME);
{
let mut vault_file = fs::File::create(vault_file_path).unwrap();
vault_file
.write_all(vault_file_contents.as_bytes())
.unwrap();
}
// when
let result = read_vault_file(&dir, Some(&key));
// when
let result = read_vault_file(&dir, Some(&key));
// then
assert!(result.is_ok());
}
// then
assert!(result.is_ok());
}
#[test]
fn read_vault_file_fails() {
// given
let temp_path = TempDir::new("").unwrap();
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);
#[test]
fn read_vault_file_fails() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password1".into(), *ITERATIONS);
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
// when
let result = read_vault_file(&dir, Some(&key));
// when
let result = read_vault_file(&dir, Some(&key));
// then
assert!(result.is_err());
// then
assert!(result.is_err());
// and when given
let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"0155e3690be19fbfbecabcd440aa284b"},"ciphertext":"4d6938a1f49b7782","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5"},"mac":"16381463ea11c6eb2239a9f339c2e780516d29d234ce30ac5f166f9080b5a262"}}"#;
{
let mut vault_file = fs::File::create(vault_file_path).unwrap();
vault_file.write_all(vault_file_contents.as_bytes()).unwrap();
}
// and when given
let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"0155e3690be19fbfbecabcd440aa284b"},"ciphertext":"4d6938a1f49b7782","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5"},"mac":"16381463ea11c6eb2239a9f339c2e780516d29d234ce30ac5f166f9080b5a262"}}"#;
{
let mut vault_file = fs::File::create(vault_file_path).unwrap();
vault_file
.write_all(vault_file_contents.as_bytes())
.unwrap();
}
// when
let result = read_vault_file(&dir, Some(&key));
// when
let result = read_vault_file(&dir, Some(&key));
// then
assert!(result.is_err());
}
// then
assert!(result.is_err());
}
#[test]
fn vault_directory_can_be_created() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
#[test]
fn vault_directory_can_be_created() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), *ITERATIONS);
let dir: PathBuf = temp_path.path().into();
// when
let vault = VaultDiskDirectory::create(&dir, "vault", key.clone());
// when
let vault = VaultDiskDirectory::create(&dir, "vault", key.clone());
// then
assert!(vault.is_ok());
// then
assert!(vault.is_ok());
// and when
let vault = VaultDiskDirectory::at(&dir, "vault", key);
// and when
let vault = VaultDiskDirectory::at(&dir, "vault", key);
// then
assert!(vault.is_ok());
}
// then
assert!(vault.is_ok());
}
#[test]
fn vault_directory_cannot_be_created_if_already_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
let mut vault_dir = dir.clone();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
#[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 dir: PathBuf = temp_path.path().into();
let mut vault_dir = dir.clone();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
// when
let vault = VaultDiskDirectory::create(&dir, "vault", key);
// when
let vault = VaultDiskDirectory::create(&dir, "vault", key);
// then
assert!(vault.is_err());
}
// then
assert!(vault.is_err());
}
#[test]
fn vault_directory_cannot_be_opened_if_not_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
#[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 dir: PathBuf = temp_path.path().into();
// when
let vault = VaultDiskDirectory::at(&dir, "vault", key);
// when
let vault = VaultDiskDirectory::at(&dir, "vault", key);
// then
assert!(vault.is_err());
}
// then
assert!(vault.is_err());
}
}

View File

@@ -1,126 +1,118 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
use std::io::Error as IoError;
use crypto::{self, Error as EthCryptoError};
use ethkey::{self, DerivationError, Error as EthKeyError};
use std::{fmt, io::Error as IoError};
use crypto::publickey::{Error as EthPublicKeyCryptoError, DerivationError};
/// Account-related errors.
#[derive(Debug)]
pub enum Error {
/// IO error
Io(IoError),
/// Invalid Password
InvalidPassword,
/// Account's secret is invalid.
InvalidSecret,
/// Invalid Vault Crypto meta.
InvalidCryptoMeta,
/// Invalid Account.
InvalidAccount,
/// Invalid Message.
InvalidMessage,
/// Invalid Key File
InvalidKeyFile(String),
/// Vaults are not supported.
VaultsAreNotSupported,
/// Unsupported vault
UnsupportedVault,
/// Invalid vault name
InvalidVaultName,
/// Vault not found
VaultNotFound,
/// Account creation failed.
CreationFailed,
/// `EthKey` error
EthKey(EthKeyError),
/// `ethkey::crypto::Error`
EthKeyCrypto(ethkey::crypto::Error),
/// `EthCrypto` error
EthCrypto(EthCryptoError),
/// Derivation error
Derivation(DerivationError),
/// Custom error
Custom(String),
/// IO error
Io(IoError),
/// Invalid Password
InvalidPassword,
/// Account's secret is invalid.
InvalidSecret,
/// Invalid Vault Crypto meta.
InvalidCryptoMeta,
/// Invalid Account.
InvalidAccount,
/// Invalid Message.
InvalidMessage,
/// Invalid Key File
InvalidKeyFile(String),
/// Vaults are not supported.
VaultsAreNotSupported,
/// Unsupported vault
UnsupportedVault,
/// Invalid vault name
InvalidVaultName,
/// Vault not found
VaultNotFound,
/// Account creation failed.
CreationFailed,
/// `EthCrypto` error
EthCrypto(EthCryptoError),
/// `EthPublicKeyCryptoError` error
EthPublicKeyCrypto(EthPublicKeyCryptoError),
/// Derivation error
Derivation(DerivationError),
/// Custom error
Custom(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let s = match *self {
Error::Io(ref err) => err.to_string(),
Error::InvalidPassword => "Invalid password".into(),
Error::InvalidSecret => "Invalid secret".into(),
Error::InvalidCryptoMeta => "Invalid crypted metadata".into(),
Error::InvalidAccount => "Invalid account".into(),
Error::InvalidMessage => "Invalid message".into(),
Error::InvalidKeyFile(ref reason) => format!("Invalid key file: {}", reason),
Error::VaultsAreNotSupported => "Vaults are not supported".into(),
Error::UnsupportedVault => "Vault is not supported for this operation".into(),
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::Derivation(ref err) => format!("Derivation error: {:?}", err),
Error::Custom(ref s) => s.clone(),
};
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let s = match *self {
Error::Io(ref err) => err.to_string(),
Error::InvalidPassword => "Invalid password".into(),
Error::InvalidSecret => "Invalid secret".into(),
Error::InvalidCryptoMeta => "Invalid crypted metadata".into(),
Error::InvalidAccount => "Invalid account".into(),
Error::InvalidMessage => "Invalid message".into(),
Error::InvalidKeyFile(ref reason) => format!("Invalid key file: {}", reason),
Error::VaultsAreNotSupported => "Vaults are not supported".into(),
Error::UnsupportedVault => "Vault is not supported for this operation".into(),
Error::InvalidVaultName => "Invalid vault name".into(),
Error::VaultNotFound => "Vault not found".into(),
Error::CreationFailed => "Account creation failed".into(),
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(),
};
write!(f, "{}", s)
}
write!(f, "{}", s)
}
}
impl From<IoError> for Error {
fn from(err: IoError) -> Self {
Error::Io(err)
}
fn from(err: IoError) -> Self {
Error::Io(err)
}
}
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)
}
}
impl From<EthCryptoError> for Error {
fn from(err: EthCryptoError) -> Self {
Error::EthCrypto(err)
}
fn from(err: EthCryptoError) -> Self {
Error::EthCrypto(err)
}
}
impl From<crypto::error::ScryptError> for Error {
fn from(err: crypto::error::ScryptError) -> Self {
Error::EthCrypto(err.into())
}
fn from(err: crypto::error::ScryptError) -> Self {
Error::EthCrypto(err.into())
}
}
impl From<crypto::error::SymmError> for Error {
fn from(err: crypto::error::SymmError) -> Self {
Error::EthCrypto(err.into())
}
fn from(err: crypto::error::SymmError) -> Self {
Error::EthCrypto(err.into())
}
}
impl From<DerivationError> for Error {
fn from(err: DerivationError) -> Self {
Error::Derivation(err)
}
fn from(err: DerivationError) -> Self {
Error::Derivation(err)
}
}

View File

@@ -1,41 +0,0 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. 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)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,67 +1,80 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::{collections::HashSet, fs, path::Path};
use std::collections::HashSet;
use std::path::Path;
use std::fs;
use accounts_dir::{DiskKeyFileManager, KeyDirectory, KeyFileManager};
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: &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());
let account = fs::File::open(&path)
.map_err(Into::into)
.and_then(|file| key_manager.read(filename, file))?;
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());
let account = fs::File::open(&path)
.map_err(Into::into)
.and_then(|file| key_manager.read(filename, file))?;
let address = account.address.clone();
if !existing_accounts.contains(&address) {
dst.insert(account)?;
}
Ok(address)
let address = account.address.clone();
if !existing_accounts.contains(&address) {
dst.insert(account)?;
}
Ok(address)
}
/// Import all accounts from one directory to the other.
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)
.collect::<HashSet<_>>();
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)
.collect::<HashSet<_>>();
accounts
.into_iter()
.filter(|a| !existing_accounts.contains(&a.address))
.map(|a| {
let address = a.address.clone();
dst.insert(a)?;
Ok(address)
})
.collect()
accounts.into_iter()
.filter(|a| !existing_accounts.contains(&a.address))
.map(|a| {
let address = a.address.clone();
dst.insert(a)?;
Ok(address)
}).collect()
}
/// Provide a `HashSet` of all accounts available for import from the Geth keystore.
pub fn read_geth_accounts(testnet: bool) -> Vec<Address> {
RootDiskDirectory::at(dir::geth(testnet))
.load()
.map(|d| d.into_iter().map(|a| a.address).collect())
.unwrap_or_else(|_| Vec::new())
}
/// Import specific `desired` accounts from the Geth keystore into `dst`.
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<_>>();
accounts.into_iter()
.filter(|a| !existing_accounts.contains(&a.address))
.filter(|a| desired.contains(&a.address))
.map(|a| {
let address = a.address.clone();
dst.insert(a)?;
Ok(address)
}).collect()
}

View File

@@ -1,82 +1,74 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use rustc_hex::{FromHex, FromHexError, ToHex};
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
use std::{ops, str};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error;
use rustc_hex::{ToHex, FromHex, FromHexError};
#[derive(Debug, PartialEq)]
pub struct Bytes(Vec<u8>);
impl ops::Deref for Bytes {
type Target = [u8];
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<'a> Deserialize<'a> for Bytes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
let s = String::deserialize(deserializer)?;
let data = s
.from_hex()
.map_err(|e| Error::custom(format!("Invalid hex value {}", e)))?;
Ok(Bytes(data))
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a>
{
let s = String::deserialize(deserializer)?;
let data = s.from_hex().map_err(|e| Error::custom(format!("Invalid hex value {}", e)))?;
Ok(Bytes(data))
}
}
impl Serialize for Bytes {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.0.to_hex())
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
serializer.serialize_str(&self.0.to_hex())
}
}
impl str::FromStr for Bytes {
type Err = FromHexError;
type Err = FromHexError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.from_hex().map(Bytes)
}
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.from_hex().map(Bytes)
}
}
impl From<&'static str> for Bytes {
fn from(s: &'static str) -> Self {
s.parse().expect(&format!(
"invalid string literal for {}: '{}'",
stringify!(Self),
s
))
}
fn from(s: &'static str) -> Self {
s.parse().expect(&format!("invalid string literal for {}: '{}'", stringify!(Self), s))
}
}
impl From<Vec<u8>> for Bytes {
fn from(v: Vec<u8>) -> Self {
Bytes(v)
}
fn from(v: Vec<u8>) -> Self {
Bytes(v)
}
}
impl From<Bytes> for Vec<u8> {
fn from(b: Bytes) -> Self {
b.0
}
fn from(b: Bytes) -> Self {
b.0
}
}

View File

@@ -1,112 +1,96 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Error, H128};
use serde::{
de::{Error as SerdeError, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Visitor, Error as SerdeError};
use super::{Error, H128};
#[derive(Debug, PartialEq)]
pub enum CipherSer {
Aes128Ctr,
Aes128Ctr,
}
impl Serialize for CipherSer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
CipherSer::Aes128Ctr => serializer.serialize_str("aes-128-ctr"),
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
match *self {
CipherSer::Aes128Ctr => serializer.serialize_str("aes-128-ctr"),
}
}
}
impl<'a> Deserialize<'a> for CipherSer {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(CipherSerVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(CipherSerVisitor)
}
}
struct CipherSerVisitor;
impl<'a> Visitor<'a> for CipherSerVisitor {
type Value = CipherSer;
type Value = CipherSer;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid cipher identifier")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid cipher identifier")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: SerdeError,
{
match value {
"aes-128-ctr" => Ok(CipherSer::Aes128Ctr),
_ => Err(SerdeError::custom(Error::UnsupportedCipher)),
}
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: SerdeError {
match value {
"aes-128-ctr" => Ok(CipherSer::Aes128Ctr),
_ => Err(SerdeError::custom(Error::UnsupportedCipher))
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: SerdeError,
{
self.visit_str(value.as_ref())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: SerdeError {
self.visit_str(value.as_ref())
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Aes128Ctr {
pub iv: H128,
pub iv: H128,
}
#[derive(Debug, PartialEq)]
pub enum CipherSerParams {
Aes128Ctr(Aes128Ctr),
Aes128Ctr(Aes128Ctr),
}
impl Serialize for CipherSerParams {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
CipherSerParams::Aes128Ctr(ref params) => params.serialize(serializer),
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
match *self {
CipherSerParams::Aes128Ctr(ref params) => params.serialize(serializer),
}
}
}
impl<'a> Deserialize<'a> for CipherSerParams {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
Aes128Ctr::deserialize(deserializer)
.map(CipherSerParams::Aes128Ctr)
.map_err(|_| Error::InvalidCipherParams)
.map_err(SerdeError::custom)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
Aes128Ctr::deserialize(deserializer)
.map(CipherSerParams::Aes128Ctr)
.map_err(|_| Error::InvalidCipherParams)
.map_err(SerdeError::custom)
}
}
#[derive(Debug, PartialEq)]
pub enum Cipher {
Aes128Ctr(Aes128Ctr),
Aes128Ctr(Aes128Ctr),
}

View File

@@ -1,218 +1,194 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Bytes, Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256};
use serde::{
de::{Error, MapAccess, Visitor},
ser::SerializeStruct,
Deserialize, Deserializer, Serialize, Serializer,
};
use serde_json;
use std::{fmt, str};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde::de::{Visitor, MapAccess, Error};
use serde_json;
use super::{Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256, Bytes};
pub type CipherText = Bytes;
#[derive(Debug, PartialEq)]
pub struct Crypto {
pub cipher: Cipher,
pub ciphertext: CipherText,
pub kdf: Kdf,
pub mac: H256,
pub cipher: Cipher,
pub ciphertext: CipherText,
pub kdf: Kdf,
pub mac: H256,
}
impl str::FromStr for Crypto {
type Err = serde_json::error::Error;
type Err = serde_json::error::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
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")
}
fn from(c: Crypto) -> Self {
serde_json::to_string(&c).expect("Serialization cannot fail, because all crypto keys are strings")
}
}
enum CryptoField {
Cipher,
CipherParams,
CipherText,
Kdf,
KdfParams,
Mac,
Version,
Cipher,
CipherParams,
CipherText,
Kdf,
KdfParams,
Mac,
Version,
}
impl<'a> Deserialize<'a> for CryptoField {
fn deserialize<D>(deserializer: D) -> Result<CryptoField, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(CryptoFieldVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<CryptoField, D::Error>
where D: Deserializer<'a>
{
deserializer.deserialize_any(CryptoFieldVisitor)
}
}
struct CryptoFieldVisitor;
impl<'a> Visitor<'a> for CryptoFieldVisitor {
type Value = CryptoField;
type Value = CryptoField;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid crypto struct description")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid crypto struct description")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"cipher" => Ok(CryptoField::Cipher),
"cipherparams" => Ok(CryptoField::CipherParams),
"ciphertext" => Ok(CryptoField::CipherText),
"kdf" => Ok(CryptoField::Kdf),
"kdfparams" => Ok(CryptoField::KdfParams),
"mac" => Ok(CryptoField::Mac),
"version" => Ok(CryptoField::Version),
_ => Err(Error::custom(format!("Unknown field: '{}'", value))),
}
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where E: Error
{
match value {
"cipher" => Ok(CryptoField::Cipher),
"cipherparams" => Ok(CryptoField::CipherParams),
"ciphertext" => Ok(CryptoField::CipherText),
"kdf" => Ok(CryptoField::Kdf),
"kdfparams" => Ok(CryptoField::KdfParams),
"mac" => Ok(CryptoField::Mac),
"version" => Ok(CryptoField::Version),
_ => Err(Error::custom(format!("Unknown field: '{}'", value))),
}
}
}
impl<'a> Deserialize<'a> for Crypto {
fn deserialize<D>(deserializer: D) -> Result<Crypto, D::Error>
where
D: Deserializer<'a>,
{
static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"];
deserializer.deserialize_struct("Crypto", FIELDS, CryptoVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Crypto, D::Error>
where D: Deserializer<'a>
{
static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"];
deserializer.deserialize_struct("Crypto", FIELDS, CryptoVisitor)
}
}
struct CryptoVisitor;
impl<'a> Visitor<'a> for CryptoVisitor {
type Value = Crypto;
type Value = Crypto;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid vault crypto object")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid vault crypto object")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'a>,
{
let mut cipher = None;
let mut cipherparams = None;
let mut ciphertext = None;
let mut kdf = None;
let mut kdfparams = None;
let mut mac = None;
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: MapAccess<'a>
{
let mut cipher = None;
let mut cipherparams = None;
let mut ciphertext = None;
let mut kdf = None;
let mut kdfparams = None;
let mut mac = None;
loop {
match visitor.next_key()? {
Some(CryptoField::Cipher) => {
cipher = Some(visitor.next_value()?);
}
Some(CryptoField::CipherParams) => {
cipherparams = Some(visitor.next_value()?);
}
Some(CryptoField::CipherText) => {
ciphertext = Some(visitor.next_value()?);
}
Some(CryptoField::Kdf) => {
kdf = Some(visitor.next_value()?);
}
Some(CryptoField::KdfParams) => {
kdfparams = Some(visitor.next_value()?);
}
Some(CryptoField::Mac) => {
mac = Some(visitor.next_value()?);
}
// skip not required version field (it appears in pyethereum generated keystores)
Some(CryptoField::Version) => visitor.next_value().unwrap_or(()),
None => {
break;
}
}
}
loop {
match visitor.next_key()? {
Some(CryptoField::Cipher) => { cipher = Some(visitor.next_value()?); }
Some(CryptoField::CipherParams) => { cipherparams = Some(visitor.next_value()?); }
Some(CryptoField::CipherText) => { ciphertext = Some(visitor.next_value()?); }
Some(CryptoField::Kdf) => { kdf = Some(visitor.next_value()?); }
Some(CryptoField::KdfParams) => { kdfparams = Some(visitor.next_value()?); }
Some(CryptoField::Mac) => { mac = Some(visitor.next_value()?); }
// skip not required version field (it appears in pyethereum generated keystores)
Some(CryptoField::Version) => { visitor.next_value().unwrap_or(()) }
None => { break; }
}
}
let cipher = match (cipher, cipherparams) {
(Some(CipherSer::Aes128Ctr), Some(CipherSerParams::Aes128Ctr(params))) => {
Cipher::Aes128Ctr(params)
}
(None, _) => return Err(V::Error::missing_field("cipher")),
(Some(_), None) => return Err(V::Error::missing_field("cipherparams")),
};
let cipher = match (cipher, cipherparams) {
(Some(CipherSer::Aes128Ctr), Some(CipherSerParams::Aes128Ctr(params))) => Cipher::Aes128Ctr(params),
(None, _) => return Err(V::Error::missing_field("cipher")),
(Some(_), None) => return Err(V::Error::missing_field("cipherparams")),
};
let ciphertext = match ciphertext {
Some(ciphertext) => ciphertext,
None => return Err(V::Error::missing_field("ciphertext")),
};
let ciphertext = match ciphertext {
Some(ciphertext) => ciphertext,
None => return Err(V::Error::missing_field("ciphertext")),
};
let kdf = match (kdf, kdfparams) {
(Some(KdfSer::Pbkdf2), Some(KdfSerParams::Pbkdf2(params))) => Kdf::Pbkdf2(params),
(Some(KdfSer::Scrypt), Some(KdfSerParams::Scrypt(params))) => Kdf::Scrypt(params),
(Some(_), Some(_)) => return Err(V::Error::custom("Invalid cipherparams")),
(None, _) => return Err(V::Error::missing_field("kdf")),
(Some(_), None) => return Err(V::Error::missing_field("kdfparams")),
};
let kdf = match (kdf, kdfparams) {
(Some(KdfSer::Pbkdf2), Some(KdfSerParams::Pbkdf2(params))) => Kdf::Pbkdf2(params),
(Some(KdfSer::Scrypt), Some(KdfSerParams::Scrypt(params))) => Kdf::Scrypt(params),
(Some(_), Some(_)) => return Err(V::Error::custom("Invalid cipherparams")),
(None, _) => return Err(V::Error::missing_field("kdf")),
(Some(_), None) => return Err(V::Error::missing_field("kdfparams")),
};
let mac = match mac {
Some(mac) => mac,
None => return Err(V::Error::missing_field("mac")),
};
let mac = match mac {
Some(mac) => mac,
None => return Err(V::Error::missing_field("mac")),
};
let result = Crypto {
cipher: cipher,
ciphertext: ciphertext,
kdf: kdf,
mac: mac,
};
let result = Crypto {
cipher: cipher,
ciphertext: ciphertext,
kdf: kdf,
mac: mac,
};
Ok(result)
}
Ok(result)
}
}
impl Serialize for Crypto {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut crypto = serializer.serialize_struct("Crypto", 6)?;
match self.cipher {
Cipher::Aes128Ctr(ref params) => {
crypto.serialize_field("cipher", &CipherSer::Aes128Ctr)?;
crypto.serialize_field("cipherparams", params)?;
}
}
crypto.serialize_field("ciphertext", &self.ciphertext)?;
match self.kdf {
Kdf::Pbkdf2(ref params) => {
crypto.serialize_field("kdf", &KdfSer::Pbkdf2)?;
crypto.serialize_field("kdfparams", params)?;
}
Kdf::Scrypt(ref params) => {
crypto.serialize_field("kdf", &KdfSer::Scrypt)?;
crypto.serialize_field("kdfparams", params)?;
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer
{
let mut crypto = serializer.serialize_struct("Crypto", 6)?;
match self.cipher {
Cipher::Aes128Ctr(ref params) => {
crypto.serialize_field("cipher", &CipherSer::Aes128Ctr)?;
crypto.serialize_field("cipherparams", params)?;
},
}
crypto.serialize_field("ciphertext", &self.ciphertext)?;
match self.kdf {
Kdf::Pbkdf2(ref params) => {
crypto.serialize_field("kdf", &KdfSer::Pbkdf2)?;
crypto.serialize_field("kdfparams", params)?;
},
Kdf::Scrypt(ref params) => {
crypto.serialize_field("kdf", &KdfSer::Scrypt)?;
crypto.serialize_field("kdfparams", params)?;
},
}
crypto.serialize_field("mac", &self.mac)?;
crypto.end()
}
crypto.serialize_field("mac", &self.mac)?;
crypto.end()
}
}

View File

@@ -1,50 +1,50 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
#[derive(Debug, PartialEq)]
pub enum Error {
UnsupportedCipher,
InvalidCipherParams,
UnsupportedKdf,
InvalidUuid,
UnsupportedVersion,
InvalidCiphertext,
InvalidH256,
InvalidPrf,
UnsupportedCipher,
InvalidCipherParams,
UnsupportedKdf,
InvalidUuid,
UnsupportedVersion,
InvalidCiphertext,
InvalidH256,
InvalidPrf,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Error::InvalidUuid => write!(f, "Invalid Uuid"),
Error::UnsupportedVersion => write!(f, "Unsupported version"),
Error::UnsupportedKdf => write!(f, "Unsupported kdf"),
Error::InvalidCiphertext => write!(f, "Invalid ciphertext"),
Error::UnsupportedCipher => write!(f, "Unsupported cipher"),
Error::InvalidCipherParams => write!(f, "Invalid cipher params"),
Error::InvalidH256 => write!(f, "Invalid hash"),
Error::InvalidPrf => write!(f, "Invalid prf"),
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Error::InvalidUuid => write!(f, "Invalid Uuid"),
Error::UnsupportedVersion => write!(f, "Unsupported version"),
Error::UnsupportedKdf => write!(f, "Unsupported kdf"),
Error::InvalidCiphertext => write!(f, "Invalid ciphertext"),
Error::UnsupportedCipher => write!(f, "Unsupported cipher"),
Error::InvalidCipherParams => write!(f, "Invalid cipher params"),
Error::InvalidH256 => write!(f, "Invalid hash"),
Error::InvalidPrf => write!(f, "Invalid prf"),
}
}
}
impl Into<String> for Error {
fn into(self) -> String {
format!("{}", self)
}
fn into(self) -> String {
format!("{}", self)
}
}

View File

@@ -1,133 +1,117 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::Error;
use std::{ops, fmt, str};
use rustc_hex::{FromHex, ToHex};
use serde::{
de::{Error as SerdeError, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, ops, str};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Visitor, Error as SerdeError};
use super::Error;
macro_rules! impl_hash {
($name: ident, $size: expr) => {
pub struct $name([u8; $size]);
($name: ident, $size: expr) => {
pub struct $name([u8; $size]);
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let self_ref: &[u8] = &self.0;
write!(f, "{:?}", self_ref)
}
}
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let self_ref: &[u8] = &self.0;
write!(f, "{:?}", self_ref)
}
}
impl PartialEq for $name {
fn eq(&self, other: &Self) -> bool {
let self_ref: &[u8] = &self.0;
let other_ref: &[u8] = &other.0;
self_ref == other_ref
}
}
impl PartialEq for $name {
fn eq(&self, other: &Self) -> bool {
let self_ref: &[u8] = &self.0;
let other_ref: &[u8] = &other.0;
self_ref == other_ref
}
}
impl ops::Deref for $name {
type Target = [u8];
impl ops::Deref for $name {
type Target = [u8];
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.0.to_hex())
}
}
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
serializer.serialize_str(&self.0.to_hex())
}
}
impl<'a> Deserialize<'a> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
struct HashVisitor;
impl<'a> Deserialize<'a> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
struct HashVisitor;
impl<'b> Visitor<'b> for HashVisitor {
type Value = $name;
impl<'b> Visitor<'b> for HashVisitor {
type Value = $name;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex-encoded {}", stringify!($name))
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex-encoded {}", stringify!($name))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: SerdeError,
{
value.parse().map_err(SerdeError::custom)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: SerdeError {
value.parse().map_err(SerdeError::custom)
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: SerdeError,
{
self.visit_str(value.as_ref())
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: SerdeError {
self.visit_str(value.as_ref())
}
}
deserializer.deserialize_any(HashVisitor)
}
}
deserializer.deserialize_any(HashVisitor)
}
}
impl str::FromStr for $name {
type Err = Error;
impl str::FromStr for $name {
type Err = Error;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value.from_hex() {
Ok(ref hex) if hex.len() == $size => {
let mut hash = [0u8; $size];
hash.clone_from_slice(hex);
Ok($name(hash))
}
_ => Err(Error::InvalidH256),
}
}
}
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value.from_hex() {
Ok(ref hex) if hex.len() == $size => {
let mut hash = [0u8; $size];
hash.clone_from_slice(hex);
Ok($name(hash))
}
_ => Err(Error::InvalidH256),
}
}
}
impl From<&'static str> for $name {
fn from(s: &'static str) -> Self {
s.parse().expect(&format!(
"invalid string literal for {}: '{}'",
stringify!($name),
s
))
}
}
impl From<&'static str> for $name {
fn from(s: &'static str) -> Self {
s.parse().expect(&format!("invalid string literal for {}: '{}'", stringify!($name), s))
}
}
impl From<[u8; $size]> for $name {
fn from(bytes: [u8; $size]) -> Self {
$name(bytes)
}
}
impl From<[u8; $size]> for $name {
fn from(bytes: [u8; $size]) -> Self {
$name(bytes)
}
}
impl Into<[u8; $size]> for $name {
fn into(self) -> [u8; $size] {
self.0
}
}
};
impl Into<[u8; $size]> for $name {
fn into(self) -> [u8; $size] {
self.0
}
}
}
}
impl_hash!(H128, 16);

View File

@@ -1,179 +1,153 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Universaly unique identifier.
use super::Error;
use rustc_hex::{FromHex, ToHex};
use serde::{
de::{Error as SerdeError, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, str};
use rustc_hex::{ToHex, FromHex};
use serde::{Deserialize, Serialize, Deserializer, Serializer};
use serde::de::{Visitor, Error as SerdeError};
use super::Error;
/// Universaly unique identifier.
#[derive(Debug, PartialEq)]
pub struct Uuid([u8; 16]);
impl From<[u8; 16]> for Uuid {
fn from(uuid: [u8; 16]) -> Self {
Uuid(uuid)
}
fn from(uuid: [u8; 16]) -> Self {
Uuid(uuid)
}
}
impl<'a> Into<String> for &'a Uuid {
fn into(self) -> String {
let d1 = &self.0[0..4];
let d2 = &self.0[4..6];
let d3 = &self.0[6..8];
let d4 = &self.0[8..10];
let d5 = &self.0[10..16];
[d1, d2, d3, d4, d5]
.iter()
.map(|d| d.to_hex())
.collect::<Vec<String>>()
.join("-")
}
fn into(self) -> String {
let d1 = &self.0[0..4];
let d2 = &self.0[4..6];
let d3 = &self.0[6..8];
let d4 = &self.0[8..10];
let d5 = &self.0[10..16];
[d1, d2, d3, d4, d5].iter().map(|d| d.to_hex()).collect::<Vec<String>>().join("-")
}
}
impl Into<String> for Uuid {
fn into(self) -> String {
Into::into(&self)
}
fn into(self) -> String {
Into::into(&self)
}
}
impl Into<[u8; 16]> for Uuid {
fn into(self) -> [u8; 16] {
self.0
}
fn into(self) -> [u8; 16] {
self.0
}
}
impl fmt::Display for Uuid {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let s: String = (self as &Uuid).into();
write!(f, "{}", s)
}
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
let s: String = (self as &Uuid).into();
write!(f, "{}", s)
}
}
fn copy_into(from: &str, into: &mut [u8]) -> Result<(), Error> {
let from = from.from_hex().map_err(|_| Error::InvalidUuid)?;
let from = from.from_hex().map_err(|_| Error::InvalidUuid)?;
if from.len() != into.len() {
return Err(Error::InvalidUuid);
}
if from.len() != into.len() {
return Err(Error::InvalidUuid);
}
into.copy_from_slice(&from);
Ok(())
into.copy_from_slice(&from);
Ok(())
}
impl str::FromStr for Uuid {
type Err = Error;
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split("-").collect();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let parts: Vec<&str> = s.split("-").collect();
if parts.len() != 5 {
return Err(Error::InvalidUuid);
}
if parts.len() != 5 {
return Err(Error::InvalidUuid);
}
let mut uuid = [0u8; 16];
let mut uuid = [0u8; 16];
copy_into(parts[0], &mut uuid[0..4])?;
copy_into(parts[1], &mut uuid[4..6])?;
copy_into(parts[2], &mut uuid[6..8])?;
copy_into(parts[3], &mut uuid[8..10])?;
copy_into(parts[4], &mut uuid[10..16])?;
copy_into(parts[0], &mut uuid[0..4])?;
copy_into(parts[1], &mut uuid[4..6])?;
copy_into(parts[2], &mut uuid[6..8])?;
copy_into(parts[3], &mut uuid[8..10])?;
copy_into(parts[4], &mut uuid[10..16])?;
Ok(Uuid(uuid))
}
Ok(Uuid(uuid))
}
}
impl From<&'static str> for Uuid {
fn from(s: &'static str) -> Self {
s.parse().expect(&format!(
"invalid string literal for {}: '{}'",
stringify!(Self),
s
))
}
fn from(s: &'static str) -> Self {
s.parse().expect(&format!("invalid string literal for {}: '{}'", stringify!(Self), s))
}
}
impl Serialize for Uuid {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s: String = self.into();
serializer.serialize_str(&s)
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
let s: String = self.into();
serializer.serialize_str(&s)
}
}
impl<'a> Deserialize<'a> for Uuid {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(UuidVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(UuidVisitor)
}
}
struct UuidVisitor;
impl<'a> Visitor<'a> for UuidVisitor {
type Value = Uuid;
type Value = Uuid;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid hex-encoded UUID")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid hex-encoded UUID")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: SerdeError,
{
value.parse().map_err(SerdeError::custom)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: SerdeError {
value.parse().map_err(SerdeError::custom)
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: SerdeError,
{
self.visit_str(value.as_ref())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: SerdeError {
self.visit_str(value.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::Uuid;
use super::Uuid;
#[test]
fn uuid_from_str() {
let uuid: Uuid = "3198bc9c-6672-5ab3-d995-4942343ae5b6".into();
assert_eq!(
uuid,
Uuid::from([
0x31, 0x98, 0xbc, 0x9c, 0x66, 0x72, 0x5a, 0xb3, 0xd9, 0x95, 0x49, 0x42, 0x34, 0x3a,
0xe5, 0xb6
])
);
}
#[test]
fn uuid_from_str() {
let uuid: Uuid = "3198bc9c-6672-5ab3-d995-4942343ae5b6".into();
assert_eq!(uuid, Uuid::from([0x31, 0x98, 0xbc, 0x9c, 0x66, 0x72, 0x5a, 0xb3, 0xd9, 0x95, 0x49, 0x42, 0x34, 0x3a, 0xe5, 0xb6]));
}
#[test]
fn uuid_from_and_to_str() {
let from = "3198bc9c-6672-5ab3-d995-4942343ae5b6";
let uuid: Uuid = from.into();
let to: String = uuid.into();
assert_eq!(from, &to);
}
#[test]
fn uuid_from_and_to_str() {
let from = "3198bc9c-6672-5ab3-d995-4942343ae5b6";
let uuid: Uuid = from.into();
let to: String = uuid.into();
assert_eq!(from, &to);
}
}

View File

@@ -1,186 +1,159 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Bytes, Error};
use serde::{
de::{Error as SerdeError, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, num::NonZeroU32};
use std::fmt;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Visitor, Error as SerdeError};
use super::{Error, Bytes};
#[derive(Debug, PartialEq)]
pub enum KdfSer {
Pbkdf2,
Scrypt,
Pbkdf2,
Scrypt,
}
impl Serialize for KdfSer {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
KdfSer::Pbkdf2 => serializer.serialize_str("pbkdf2"),
KdfSer::Scrypt => serializer.serialize_str("scrypt"),
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
match *self {
KdfSer::Pbkdf2 => serializer.serialize_str("pbkdf2"),
KdfSer::Scrypt => serializer.serialize_str("scrypt"),
}
}
}
impl<'a> Deserialize<'a> for KdfSer {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(KdfSerVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(KdfSerVisitor)
}
}
struct KdfSerVisitor;
impl<'a> Visitor<'a> for KdfSerVisitor {
type Value = KdfSer;
type Value = KdfSer;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a kdf algorithm identifier")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a kdf algorithm identifier")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: SerdeError,
{
match value {
"pbkdf2" => Ok(KdfSer::Pbkdf2),
"scrypt" => Ok(KdfSer::Scrypt),
_ => Err(SerdeError::custom(Error::UnsupportedKdf)),
}
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: SerdeError {
match value {
"pbkdf2" => Ok(KdfSer::Pbkdf2),
"scrypt" => Ok(KdfSer::Scrypt),
_ => Err(SerdeError::custom(Error::UnsupportedKdf))
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: SerdeError,
{
self.visit_str(value.as_ref())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: SerdeError {
self.visit_str(value.as_ref())
}
}
#[derive(Debug, PartialEq)]
pub enum Prf {
HmacSha256,
HmacSha256,
}
impl Serialize for Prf {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Prf::HmacSha256 => serializer.serialize_str("hmac-sha256"),
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
match *self {
Prf::HmacSha256 => serializer.serialize_str("hmac-sha256"),
}
}
}
impl<'a> Deserialize<'a> for Prf {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(PrfVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(PrfVisitor)
}
}
struct PrfVisitor;
impl<'a> Visitor<'a> for PrfVisitor {
type Value = Prf;
type Value = Prf;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a prf algorithm identifier")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a prf algorithm identifier")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: SerdeError,
{
match value {
"hmac-sha256" => Ok(Prf::HmacSha256),
_ => Err(SerdeError::custom(Error::InvalidPrf)),
}
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E> where E: SerdeError {
match value {
"hmac-sha256" => Ok(Prf::HmacSha256),
_ => Err(SerdeError::custom(Error::InvalidPrf)),
}
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: SerdeError,
{
self.visit_str(value.as_ref())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E> where E: SerdeError {
self.visit_str(value.as_ref())
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Pbkdf2 {
pub c: NonZeroU32,
pub dklen: u32,
pub prf: Prf,
pub salt: Bytes,
pub c: u32,
pub dklen: u32,
pub prf: Prf,
pub salt: Bytes,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Scrypt {
pub dklen: u32,
pub p: u32,
pub n: u32,
pub r: u32,
pub salt: Bytes,
pub dklen: u32,
pub p: u32,
pub n: u32,
pub r: u32,
pub salt: Bytes,
}
#[derive(Debug, PartialEq)]
pub enum KdfSerParams {
Pbkdf2(Pbkdf2),
Scrypt(Scrypt),
Pbkdf2(Pbkdf2),
Scrypt(Scrypt),
}
impl Serialize for KdfSerParams {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
KdfSerParams::Pbkdf2(ref params) => params.serialize(serializer),
KdfSerParams::Scrypt(ref params) => params.serialize(serializer),
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
match *self {
KdfSerParams::Pbkdf2(ref params) => params.serialize(serializer),
KdfSerParams::Scrypt(ref params) => params.serialize(serializer),
}
}
}
impl<'a> Deserialize<'a> for KdfSerParams {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
use serde_json::{from_value, Value};
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'a> {
use serde_json::{Value, from_value};
let v: Value = Deserialize::deserialize(deserializer)?;
let v: Value = Deserialize::deserialize(deserializer)?;
from_value(v.clone())
.map(KdfSerParams::Pbkdf2)
.or_else(|_| from_value(v).map(KdfSerParams::Scrypt))
.map_err(|_| D::Error::custom("Invalid KDF algorithm"))
}
from_value(v.clone()).map(KdfSerParams::Pbkdf2)
.or_else(|_| from_value(v).map(KdfSerParams::Scrypt))
.map_err(|_| D::Error::custom("Invalid KDF algorithm"))
}
}
#[derive(Debug, PartialEq)]
pub enum Kdf {
Pbkdf2(Pbkdf2),
Scrypt(Scrypt),
Pbkdf2(Pbkdf2),
Scrypt(Scrypt),
}

View File

@@ -1,227 +1,195 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Crypto, Uuid, Version, H160};
use serde::{
de::{DeserializeOwned, Error, MapAccess, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt;
use std::io::{Read, Write};
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Error, Visitor, MapAccess, DeserializeOwned};
use serde_json;
use std::{
fmt,
io::{Read, Write},
};
use super::{Uuid, Version, Crypto, H160};
/// Public opaque type representing serializable `KeyFile`.
#[derive(Debug, PartialEq)]
pub struct OpaqueKeyFile {
key_file: KeyFile,
key_file: KeyFile
}
impl Serialize for OpaqueKeyFile {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.key_file.serialize(serializer)
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where
S: Serializer,
{
self.key_file.serialize(serializer)
}
}
impl<T> From<T> for OpaqueKeyFile
where
T: Into<KeyFile>,
{
fn from(val: T) -> Self {
OpaqueKeyFile {
key_file: val.into(),
}
}
impl<T> From<T> for OpaqueKeyFile where T: Into<KeyFile> {
fn from(val: T) -> Self {
OpaqueKeyFile { key_file: val.into() }
}
}
#[derive(Debug, PartialEq, Serialize)]
pub struct KeyFile {
pub id: Uuid,
pub version: Version,
pub crypto: Crypto,
pub address: Option<H160>,
pub name: Option<String>,
pub meta: Option<String>,
pub id: Uuid,
pub version: Version,
pub crypto: Crypto,
pub address: Option<H160>,
pub name: Option<String>,
pub meta: Option<String>,
}
enum KeyFileField {
Id,
Version,
Crypto,
Address,
Name,
Meta,
Id,
Version,
Crypto,
Address,
Name,
Meta,
}
impl<'a> Deserialize<'a> for KeyFileField {
fn deserialize<D>(deserializer: D) -> Result<KeyFileField, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(KeyFileFieldVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<KeyFileField, D::Error>
where D: Deserializer<'a>
{
deserializer.deserialize_any(KeyFileFieldVisitor)
}
}
struct KeyFileFieldVisitor;
impl<'a> Visitor<'a> for KeyFileFieldVisitor {
type Value = KeyFileField;
type Value = KeyFileField;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid key file field")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid key file field")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
match value {
"id" => Ok(KeyFileField::Id),
"version" => Ok(KeyFileField::Version),
"crypto" => Ok(KeyFileField::Crypto),
"Crypto" => Ok(KeyFileField::Crypto),
"address" => Ok(KeyFileField::Address),
"name" => Ok(KeyFileField::Name),
"meta" => Ok(KeyFileField::Meta),
_ => Err(Error::custom(format!("Unknown field: '{}'", value))),
}
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where E: Error
{
match value {
"id" => Ok(KeyFileField::Id),
"version" => Ok(KeyFileField::Version),
"crypto" => Ok(KeyFileField::Crypto),
"Crypto" => Ok(KeyFileField::Crypto),
"address" => Ok(KeyFileField::Address),
"name" => Ok(KeyFileField::Name),
"meta" => Ok(KeyFileField::Meta),
_ => Err(Error::custom(format!("Unknown field: '{}'", value))),
}
}
}
impl<'a> Deserialize<'a> for KeyFile {
fn deserialize<D>(deserializer: D) -> Result<KeyFile, D::Error>
where
D: Deserializer<'a>,
{
static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"];
deserializer.deserialize_struct("KeyFile", FIELDS, KeyFileVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<KeyFile, D::Error>
where D: Deserializer<'a>
{
static FIELDS: &'static [&'static str] = &["id", "version", "crypto", "Crypto", "address"];
deserializer.deserialize_struct("KeyFile", FIELDS, KeyFileVisitor)
}
}
fn none_if_empty<'a, T>(v: Option<serde_json::Value>) -> Option<T>
where
T: DeserializeOwned,
fn none_if_empty<'a, T>(v: Option<serde_json::Value>) -> Option<T> where
T: DeserializeOwned
{
v.and_then(|v| {
if v.is_null() {
None
} else {
serde_json::from_value(v).ok()
}
})
v.and_then(|v| if v.is_null() {
None
} else {
serde_json::from_value(v).ok()
})
}
struct KeyFileVisitor;
impl<'a> Visitor<'a> for KeyFileVisitor {
type Value = KeyFile;
type Value = KeyFile;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid key object")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid key object")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'a>,
{
let mut id = None;
let mut version = None;
let mut crypto = None;
let mut address = None;
let mut name = None;
let mut meta = None;
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where V: MapAccess<'a>
{
let mut id = None;
let mut version = None;
let mut crypto = None;
let mut address = None;
let mut name = None;
let mut meta = None;
loop {
match visitor.next_key()? {
Some(KeyFileField::Id) => {
id = Some(visitor.next_value()?);
}
Some(KeyFileField::Version) => {
version = Some(visitor.next_value()?);
}
Some(KeyFileField::Crypto) => {
crypto = Some(visitor.next_value()?);
}
Some(KeyFileField::Address) => {
address = Some(visitor.next_value()?);
}
Some(KeyFileField::Name) => name = none_if_empty(visitor.next_value().ok()),
Some(KeyFileField::Meta) => meta = none_if_empty(visitor.next_value().ok()),
None => {
break;
}
}
}
loop {
match visitor.next_key()? {
Some(KeyFileField::Id) => { id = Some(visitor.next_value()?); }
Some(KeyFileField::Version) => { version = Some(visitor.next_value()?); }
Some(KeyFileField::Crypto) => { crypto = Some(visitor.next_value()?); }
Some(KeyFileField::Address) => { address = Some(visitor.next_value()?); }
Some(KeyFileField::Name) => { name = none_if_empty(visitor.next_value().ok()) }
Some(KeyFileField::Meta) => { meta = none_if_empty(visitor.next_value().ok()) }
None => { break; }
}
}
let id = match id {
Some(id) => id,
None => return Err(V::Error::missing_field("id")),
};
let id = match id {
Some(id) => id,
None => return Err(V::Error::missing_field("id")),
};
let version = match version {
Some(version) => version,
None => return Err(V::Error::missing_field("version")),
};
let version = match version {
Some(version) => version,
None => return Err(V::Error::missing_field("version")),
};
let crypto = match crypto {
Some(crypto) => crypto,
None => return Err(V::Error::missing_field("crypto")),
};
let crypto = match crypto {
Some(crypto) => crypto,
None => return Err(V::Error::missing_field("crypto")),
};
let result = KeyFile {
id: id,
version: version,
crypto: crypto,
address: address,
name: name,
meta: meta,
};
let result = KeyFile {
id: id,
version: version,
crypto: crypto,
address: address,
name: name,
meta: meta,
};
Ok(result)
}
Ok(result)
}
}
impl KeyFile {
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error> where R: Read {
serde_json::from_reader(reader)
}
pub fn write<W>(&self, writer: &mut W) -> Result<(), serde_json::Error>
where
W: Write,
{
serde_json::to_writer(writer, self)
}
pub fn write<W>(&self, writer: &mut W) -> Result<(), serde_json::Error> where W: Write {
serde_json::to_writer(writer, self)
}
}
#[cfg(test)]
mod tests {
use json::{Aes128Ctr, Cipher, Crypto, Kdf, KeyFile, Scrypt, Uuid, Version};
use serde_json;
use std::str::FromStr;
use std::str::FromStr;
use serde_json;
use json::{KeyFile, Uuid, Version, Crypto, Cipher, Aes128Ctr, Kdf, Scrypt};
#[test]
fn basic_keyfile() {
let json = r#"
#[test]
fn basic_keyfile() {
let json = r#"
{
"address": "6edddfc6349aff20bc6467ccf276c5b52487f7a8",
"crypto": {
@@ -246,36 +214,35 @@ mod tests {
"meta": "{}"
}"#;
let expected = KeyFile {
id: Uuid::from_str("8777d9f6-7860-4b9b-88b7-0b57ee6b3a73").unwrap(),
version: Version::V3,
address: Some("6edddfc6349aff20bc6467ccf276c5b52487f7a8".into()),
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "b5a7ec855ec9e2c405371356855fec83".into(),
}),
ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc"
.into(),
kdf: Kdf::Scrypt(Scrypt {
n: 262144,
dklen: 32,
p: 1,
r: 8,
salt: "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209".into(),
}),
mac: "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f".into(),
},
name: Some("Test".to_owned()),
meta: Some("{}".to_owned()),
};
let expected = KeyFile {
id: Uuid::from_str("8777d9f6-7860-4b9b-88b7-0b57ee6b3a73").unwrap(),
version: Version::V3,
address: Some("6edddfc6349aff20bc6467ccf276c5b52487f7a8".into()),
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "b5a7ec855ec9e2c405371356855fec83".into(),
}),
ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc".into(),
kdf: Kdf::Scrypt(Scrypt {
n: 262144,
dklen: 32,
p: 1,
r: 8,
salt: "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209".into(),
}),
mac: "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f".into(),
},
name: Some("Test".to_owned()),
meta: Some("{}".to_owned()),
};
let keyfile: KeyFile = serde_json::from_str(json).unwrap();
assert_eq!(keyfile, expected);
}
let keyfile: KeyFile = serde_json::from_str(json).unwrap();
assert_eq!(keyfile, expected);
}
#[test]
fn capital_crypto_keyfile() {
let json = r#"
#[test]
fn capital_crypto_keyfile() {
let json = r#"
{
"address": "6edddfc6349aff20bc6467ccf276c5b52487f7a8",
"Crypto": {
@@ -298,62 +265,60 @@ mod tests {
"version": 3
}"#;
let expected = KeyFile {
id: "8777d9f6-7860-4b9b-88b7-0b57ee6b3a73".into(),
version: Version::V3,
address: Some("6edddfc6349aff20bc6467ccf276c5b52487f7a8".into()),
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "b5a7ec855ec9e2c405371356855fec83".into(),
}),
ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc"
.into(),
kdf: Kdf::Scrypt(Scrypt {
n: 262144,
dklen: 32,
p: 1,
r: 8,
salt: "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209".into(),
}),
mac: "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f".into(),
},
name: None,
meta: None,
};
let expected = KeyFile {
id: "8777d9f6-7860-4b9b-88b7-0b57ee6b3a73".into(),
version: Version::V3,
address: Some("6edddfc6349aff20bc6467ccf276c5b52487f7a8".into()),
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "b5a7ec855ec9e2c405371356855fec83".into(),
}),
ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc".into(),
kdf: Kdf::Scrypt(Scrypt {
n: 262144,
dklen: 32,
p: 1,
r: 8,
salt: "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209".into(),
}),
mac: "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f".into(),
},
name: None,
meta: None,
};
let keyfile: KeyFile = serde_json::from_str(json).unwrap();
assert_eq!(keyfile, expected);
}
let keyfile: KeyFile = serde_json::from_str(json).unwrap();
assert_eq!(keyfile, expected);
}
#[test]
fn to_and_from_json() {
let file = KeyFile {
id: "8777d9f6-7860-4b9b-88b7-0b57ee6b3a73".into(),
version: Version::V3,
address: Some("6edddfc6349aff20bc6467ccf276c5b52487f7a8".into()),
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "b5a7ec855ec9e2c405371356855fec83".into(),
}),
ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc"
.into(),
kdf: Kdf::Scrypt(Scrypt {
n: 262144,
dklen: 32,
p: 1,
r: 8,
salt: "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209".into(),
}),
mac: "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f".into(),
},
name: Some("Test".to_owned()),
meta: None,
};
#[test]
fn to_and_from_json() {
let file = KeyFile {
id: "8777d9f6-7860-4b9b-88b7-0b57ee6b3a73".into(),
version: Version::V3,
address: Some("6edddfc6349aff20bc6467ccf276c5b52487f7a8".into()),
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "b5a7ec855ec9e2c405371356855fec83".into(),
}),
ciphertext: "7203da0676d141b138cd7f8e1a4365f59cc1aa6978dc5443f364ca943d7cb4bc".into(),
kdf: Kdf::Scrypt(Scrypt {
n: 262144,
dklen: 32,
p: 1,
r: 8,
salt: "1e8642fdf1f87172492c1412fc62f8db75d796cdfa9c53c3f2b11e44a2a1b209".into(),
}),
mac: "46325c5d4e8c991ad2683d525c7854da387138b6ca45068985aa4959fa2b8c8f".into(),
},
name: Some("Test".to_owned()),
meta: None,
};
let serialized = serde_json::to_string(&file).unwrap();
println!("{}", serialized);
let deserialized = serde_json::from_str(&serialized).unwrap();
let serialized = serde_json::to_string(&file).unwrap();
println!("{}", serialized);
let deserialized = serde_json::from_str(&serialized).unwrap();
assert_eq!(file, deserialized);
}
assert_eq!(file, deserialized);
}
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Contract interface specification.
@@ -29,20 +29,15 @@ mod vault_file;
mod vault_key_file;
mod version;
pub use self::{
bytes::Bytes,
cipher::{Aes128Ctr, Cipher, CipherSer, CipherSerParams},
crypto::{CipherText, Crypto},
error::Error,
hash::{H128, H160, H256},
id::Uuid,
kdf::{Kdf, KdfSer, KdfSerParams, Pbkdf2, Prf, Scrypt},
key_file::{KeyFile, OpaqueKeyFile},
presale::{Encseed, PresaleWallet},
vault_file::VaultFile,
vault_key_file::{
insert_vault_name_to_json_meta, remove_vault_name_from_json_meta, VaultKeyFile,
VaultKeyMeta,
},
version::Version,
};
pub use self::bytes::Bytes;
pub use self::cipher::{Cipher, CipherSer, CipherSerParams, Aes128Ctr};
pub use self::crypto::{Crypto, CipherText};
pub use self::error::Error;
pub use self::hash::{H128, H160, H256};
pub use self::id::Uuid;
pub use self::kdf::{Kdf, KdfSer, Prf, Pbkdf2, Scrypt, KdfSerParams};
pub use self::key_file::{KeyFile, OpaqueKeyFile};
pub use self::presale::{PresaleWallet, Encseed};
pub use self::vault_file::VaultFile;
pub use self::vault_key_file::{VaultKeyFile, VaultKeyMeta, insert_vault_name_to_json_meta, remove_vault_name_from_json_meta};
pub use self::version::Version;

View File

@@ -1,50 +1,47 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Bytes, H160};
use serde_json;
use std::io::Read;
use serde_json;
use super::{H160, Bytes};
pub type Encseed = Bytes;
#[derive(Debug, PartialEq, Deserialize)]
pub struct PresaleWallet {
pub encseed: Encseed,
#[serde(rename = "ethaddr")]
pub address: H160,
pub encseed: Encseed,
#[serde(rename = "ethaddr")]
pub address: H160,
}
impl PresaleWallet {
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error> where R: Read {
serde_json::from_reader(reader)
}
}
#[cfg(test)]
mod tests {
use json::{PresaleWallet, H160};
use serde_json;
use std::str::FromStr;
use std::str::FromStr;
use serde_json;
use json::{PresaleWallet, H160};
#[test]
fn presale_wallet() {
let json = r#"
#[test]
fn presale_wallet() {
let json = r#"
{
"encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066",
"ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1",
@@ -52,18 +49,18 @@ mod tests {
"btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH"
} "#;
let expected = PresaleWallet {
let expected = PresaleWallet {
encseed: "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066".into(),
address: H160::from_str("ede84640d1a1d3e06902048e67aa7db8d52c2ce1").unwrap(),
};
let wallet: PresaleWallet = serde_json::from_str(json).unwrap();
assert_eq!(expected, wallet);
}
let wallet: PresaleWallet = serde_json::from_str(json).unwrap();
assert_eq!(expected, wallet);
}
#[test]
fn long_presale_wallet() {
let json = r#"
#[test]
fn long_presale_wallet() {
let json = r#"
{
"encseed":
"137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0d",
@@ -72,12 +69,12 @@ mod tests {
"btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH"
} "#;
let expected = PresaleWallet {
let expected = PresaleWallet {
encseed: "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0dcf0d".into(),
address: H160::from_str("ede84640d1a1d3e06902048e67aa7db8d52c2ce1").unwrap(),
};
let wallet: PresaleWallet = serde_json::from_str(json).unwrap();
assert_eq!(expected, wallet);
}
let wallet: PresaleWallet = serde_json::from_str(json).unwrap();
assert_eq!(expected, wallet);
}
}

View File

@@ -1,105 +1,94 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::Crypto;
use serde_json;
use std::io::{Read, Write};
use serde_json;
use super::Crypto;
/// Vault meta file
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct VaultFile {
/// Vault password, encrypted with vault password
pub crypto: Crypto,
/// Vault metadata string
pub meta: Option<String>,
/// Vault password, encrypted with vault password
pub crypto: Crypto,
/// Vault metadata string
pub meta: Option<String>,
}
impl VaultFile {
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error> where R: Read {
serde_json::from_reader(reader)
}
pub fn write<W>(&self, writer: &mut W) -> Result<(), serde_json::Error>
where
W: Write,
{
serde_json::to_writer(writer, self)
}
pub fn write<W>(&self, writer: &mut W) -> Result<(), serde_json::Error> where W: Write {
serde_json::to_writer(writer, self)
}
}
#[cfg(test)]
mod test {
use json::{Aes128Ctr, Cipher, Crypto, Kdf, Pbkdf2, Prf, VaultFile};
use serde_json;
use std::num::NonZeroU32;
use serde_json;
use json::{VaultFile, Crypto, Cipher, Aes128Ctr, Kdf, Pbkdf2, Prf};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(1024).expect("1024 > 0; qed");
}
#[test]
fn to_and_from_json() {
let file = VaultFile {
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "0155e3690be19fbfbecabcd440aa284b".into(),
}),
ciphertext: "4d6938a1f49b7782".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: 1024,
dklen: 32,
prf: Prf::HmacSha256,
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
}),
mac: "16381463ea11c6eb2239a9f339c2e780516d29d234ce30ac5f166f9080b5a262".into(),
},
meta: Some("{}".into()),
};
#[test]
fn to_and_from_json() {
let file = VaultFile {
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "0155e3690be19fbfbecabcd440aa284b".into(),
}),
ciphertext: "4d6938a1f49b7782".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
dklen: 32,
prf: Prf::HmacSha256,
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
}),
mac: "16381463ea11c6eb2239a9f339c2e780516d29d234ce30ac5f166f9080b5a262".into(),
},
meta: Some("{}".into()),
};
let serialized = serde_json::to_string(&file).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();
let serialized = serde_json::to_string(&file).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();
assert_eq!(file, deserialized);
}
assert_eq!(file, deserialized);
}
#[test]
fn to_and_from_json_no_meta() {
let file = VaultFile {
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "0155e3690be19fbfbecabcd440aa284b".into(),
}),
ciphertext: "4d6938a1f49b7782".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: 1024,
dklen: 32,
prf: Prf::HmacSha256,
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
}),
mac: "16381463ea11c6eb2239a9f339c2e780516d29d234ce30ac5f166f9080b5a262".into(),
},
meta: None,
};
#[test]
fn to_and_from_json_no_meta() {
let file = VaultFile {
crypto: Crypto {
cipher: Cipher::Aes128Ctr(Aes128Ctr {
iv: "0155e3690be19fbfbecabcd440aa284b".into(),
}),
ciphertext: "4d6938a1f49b7782".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
dklen: 32,
prf: Prf::HmacSha256,
salt: "b6a9338a7ccd39288a86dba73bfecd9101b4f3db9c9830e7c76afdbd4f6872e5".into(),
}),
mac: "16381463ea11c6eb2239a9f339c2e780516d29d234ce30ac5f166f9080b5a262".into(),
},
meta: None,
};
let serialized = serde_json::to_string(&file).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();
let serialized = serde_json::to_string(&file).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();
assert_eq!(file, deserialized);
}
assert_eq!(file, deserialized);
}
}

View File

@@ -1,23 +1,25 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::{Crypto, Uuid, Version, H160};
use serde::de::Error;
use serde_json::{self, error, value::Value};
use std::io::{Read, Write};
use serde::de::Error;
use serde_json;
use serde_json::value::Value;
use serde_json::error;
use super::{Uuid, Version, Crypto, H160};
/// Meta key name for vault field
const VAULT_NAME_META_KEY: &'static str = "vault";
@@ -25,112 +27,89 @@ const VAULT_NAME_META_KEY: &'static str = "vault";
/// Key file as stored in vaults
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct VaultKeyFile {
/// Key id
pub id: Uuid,
/// Key version
pub version: Version,
/// Secret, encrypted with account password
pub crypto: Crypto,
/// Serialized `VaultKeyMeta`, encrypted with vault password
pub metacrypto: Crypto,
/// Key id
pub id: Uuid,
/// Key version
pub version: Version,
/// Secret, encrypted with account password
pub crypto: Crypto,
/// Serialized `VaultKeyMeta`, encrypted with vault password
pub metacrypto: Crypto,
}
/// Data, stored in `VaultKeyFile::metacrypto`
#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct VaultKeyMeta {
/// Key address
pub address: H160,
/// Key name
pub name: Option<String>,
/// Key metadata
pub meta: Option<String>,
/// Key address
pub address: H160,
/// Key name
pub name: Option<String>,
/// Key metadata
pub meta: Option<String>,
}
/// Insert vault name to the JSON meta field
pub fn insert_vault_name_to_json_meta(
meta: &str,
vault_name: &str,
) -> Result<String, error::Error> {
let mut meta = if meta.is_empty() {
Value::Object(serde_json::Map::new())
} else {
serde_json::from_str(meta)?
};
pub fn insert_vault_name_to_json_meta(meta: &str, vault_name: &str) -> Result<String, error::Error> {
let mut meta = if meta.is_empty() {
Value::Object(serde_json::Map::new())
} else {
serde_json::from_str(meta)?
};
if let Some(meta_obj) = meta.as_object_mut() {
meta_obj.insert(
VAULT_NAME_META_KEY.to_owned(),
Value::String(vault_name.to_owned()),
);
serde_json::to_string(meta_obj)
} else {
Err(error::Error::custom(
"Meta is expected to be a serialized JSON object",
))
}
if let Some(meta_obj) = meta.as_object_mut() {
meta_obj.insert(VAULT_NAME_META_KEY.to_owned(), Value::String(vault_name.to_owned()));
serde_json::to_string(meta_obj)
} else {
Err(error::Error::custom("Meta is expected to be a serialized JSON object"))
}
}
/// Remove vault name from the JSON meta field
pub fn remove_vault_name_from_json_meta(meta: &str) -> Result<String, error::Error> {
let mut meta = if meta.is_empty() {
Value::Object(serde_json::Map::new())
} else {
serde_json::from_str(meta)?
};
let mut meta = if meta.is_empty() {
Value::Object(serde_json::Map::new())
} else {
serde_json::from_str(meta)?
};
if let Some(meta_obj) = meta.as_object_mut() {
meta_obj.remove(VAULT_NAME_META_KEY);
serde_json::to_string(meta_obj)
} else {
Err(error::Error::custom(
"Meta is expected to be a serialized JSON object",
))
}
if let Some(meta_obj) = meta.as_object_mut() {
meta_obj.remove(VAULT_NAME_META_KEY);
serde_json::to_string(meta_obj)
} else {
Err(error::Error::custom("Meta is expected to be a serialized JSON object"))
}
}
impl VaultKeyFile {
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error> where R: Read {
serde_json::from_reader(reader)
}
pub fn write<W>(&self, writer: &mut W) -> Result<(), serde_json::Error>
where
W: Write,
{
serde_json::to_writer(writer, self)
}
pub fn write<W>(&self, writer: &mut W) -> Result<(), serde_json::Error> where W: Write {
serde_json::to_writer(writer, self)
}
}
impl VaultKeyMeta {
pub fn load(bytes: &[u8]) -> Result<Self, serde_json::Error> {
serde_json::from_slice(&bytes)
}
pub fn load(bytes: &[u8]) -> Result<Self, serde_json::Error> {
serde_json::from_slice(&bytes)
}
pub fn write(&self) -> Result<Vec<u8>, serde_json::Error> {
let s = serde_json::to_string(self)?;
Ok(s.as_bytes().into())
}
pub fn write(&self) -> Result<Vec<u8>, serde_json::Error> {
let s = serde_json::to_string(self)?;
Ok(s.as_bytes().into())
}
}
#[cfg(test)]
mod test {
use json::{
insert_vault_name_to_json_meta, remove_vault_name_from_json_meta, Aes128Ctr, Cipher,
Crypto, Kdf, Pbkdf2, Prf, VaultKeyFile, Version,
};
use serde_json;
use std::num::NonZeroU32;
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};
lazy_static! {
static ref ITERATIONS: NonZeroU32 = NonZeroU32::new(10240).expect("10240 > 0; qed");
}
#[test]
fn to_and_from_json() {
let file = VaultKeyFile {
#[test]
fn to_and_from_json() {
let file = VaultKeyFile {
id: "08d82c39-88e3-7a71-6abb-89c8f36c3ceb".into(),
version: Version::V3,
crypto: Crypto {
@@ -139,7 +118,7 @@ mod test {
}),
ciphertext: "4befe0a66d9a4b6fec8e39eb5c90ac5dafdeaab005fff1af665fd1f9af925c91".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
c: 10240,
dklen: 32,
prf: Prf::HmacSha256,
salt: "f17731e84ecac390546692dbd4ccf6a3a2720dc9652984978381e61c28a471b2".into(),
@@ -152,7 +131,7 @@ mod test {
}),
ciphertext: "fef0d113d7576c1702daf380ad6f4c5408389e57991cae2a174facd74bd549338e1014850bddbab7eb486ff5f5c9c5532800c6a6d4db2be2212cd5cd3769244ab230e1f369e8382a9e6d7c0a".into(),
kdf: Kdf::Pbkdf2(Pbkdf2 {
c: *ITERATIONS,
c: 10240,
dklen: 32,
prf: Prf::HmacSha256,
salt: "aca82865174a82249a198814b263f43a631f272cbf7ed329d0f0839d259c652a".into(),
@@ -161,45 +140,33 @@ mod test {
}
};
let serialized = serde_json::to_string(&file).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();
let serialized = serde_json::to_string(&file).unwrap();
let deserialized = serde_json::from_str(&serialized).unwrap();
assert_eq!(file, deserialized);
}
assert_eq!(file, deserialized);
}
#[test]
fn vault_name_inserted_to_json_meta() {
assert_eq!(
insert_vault_name_to_json_meta(r#""#, "MyVault").unwrap(),
r#"{"vault":"MyVault"}"#
);
assert_eq!(
insert_vault_name_to_json_meta(r#"{"tags":["kalabala"]}"#, "MyVault").unwrap(),
r#"{"tags":["kalabala"],"vault":"MyVault"}"#
);
}
#[test]
fn vault_name_inserted_to_json_meta() {
assert_eq!(insert_vault_name_to_json_meta(r#""#, "MyVault").unwrap(), r#"{"vault":"MyVault"}"#);
assert_eq!(insert_vault_name_to_json_meta(r#"{"tags":["kalabala"]}"#, "MyVault").unwrap(), r#"{"tags":["kalabala"],"vault":"MyVault"}"#);
}
#[test]
fn vault_name_not_inserted_to_json_meta() {
assert!(insert_vault_name_to_json_meta(r#"///3533"#, "MyVault").is_err());
assert!(insert_vault_name_to_json_meta(r#""string""#, "MyVault").is_err());
}
#[test]
fn vault_name_not_inserted_to_json_meta() {
assert!(insert_vault_name_to_json_meta(r#"///3533"#, "MyVault").is_err());
assert!(insert_vault_name_to_json_meta(r#""string""#, "MyVault").is_err());
}
#[test]
fn vault_name_removed_from_json_meta() {
assert_eq!(
remove_vault_name_from_json_meta(r#"{"vault":"MyVault"}"#).unwrap(),
r#"{}"#
);
assert_eq!(
remove_vault_name_from_json_meta(r#"{"tags":["kalabala"],"vault":"MyVault"}"#).unwrap(),
r#"{"tags":["kalabala"]}"#
);
}
#[test]
fn vault_name_removed_from_json_meta() {
assert_eq!(remove_vault_name_from_json_meta(r#"{"vault":"MyVault"}"#).unwrap(), r#"{}"#);
assert_eq!(remove_vault_name_from_json_meta(r#"{"tags":["kalabala"],"vault":"MyVault"}"#).unwrap(), r#"{"tags":["kalabala"]}"#);
}
#[test]
fn vault_name_not_removed_from_json_meta() {
assert!(remove_vault_name_from_json_meta(r#"///3533"#).is_err());
assert!(remove_vault_name_from_json_meta(r#""string""#).is_err());
}
#[test]
fn vault_name_not_removed_from_json_meta() {
assert!(remove_vault_name_from_json_meta(r#"///3533"#).is_err());
assert!(remove_vault_name_from_json_meta(r#""string""#).is_err());
}
}

View File

@@ -1,67 +1,58 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use super::Error;
use serde::{
de::{Error as SerdeError, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::fmt;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Error as SerdeError, Visitor};
use super::Error;
#[derive(Debug, PartialEq)]
pub enum Version {
V3,
V3,
}
impl Serialize for Version {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Version::V3 => serializer.serialize_u64(3),
}
}
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: Serializer {
match *self {
Version::V3 => serializer.serialize_u64(3)
}
}
}
impl<'a> Deserialize<'a> for Version {
fn deserialize<D>(deserializer: D) -> Result<Version, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(VersionVisitor)
}
fn deserialize<D>(deserializer: D) -> Result<Version, D::Error>
where D: Deserializer<'a> {
deserializer.deserialize_any(VersionVisitor)
}
}
struct VersionVisitor;
impl<'a> Visitor<'a> for VersionVisitor {
type Value = Version;
type Value = Version;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid key version identifier")
}
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a valid key version identifier")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: SerdeError,
{
match value {
3 => Ok(Version::V3),
_ => Err(SerdeError::custom(Error::UnsupportedVersion)),
}
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> where E: SerdeError {
match value {
3 => Ok(Version::V3),
_ => Err(SerdeError::custom(Error::UnsupportedVersion))
}
}
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Ethereum key-management.
@@ -27,17 +27,15 @@ extern crate rustc_hex;
extern crate serde;
extern crate serde_json;
extern crate smallvec;
extern crate tempdir;
extern crate time;
extern crate tiny_keccak;
extern crate tempdir;
extern crate ethereum_types;
extern crate ethkey as _ethkey;
extern crate parity_crypto as crypto;
extern crate ethereum_types;
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;
@@ -60,20 +57,44 @@ mod presale;
mod random;
mod secret_store;
pub use self::{
account::{Crypto, SafeAccount},
error::Error,
ethstore::{EthMultiStore, EthStore},
import::{import_account, import_accounts},
json::OpaqueKeyFile as KeyFile,
parity_wordlist::random_phrase,
presale::PresaleWallet,
random::random_string,
secret_store::{
Derivation, IndexDerivation, SecretStore, SecretVaultRef, SimpleSecretStore,
StoreAccountRef,
},
pub use self::account::{SafeAccount, Crypto};
pub use self::error::Error;
pub use self::ethstore::{EthStore, EthMultiStore};
pub use self::import::{import_account, import_accounts, read_geth_accounts};
pub use self::json::OpaqueKeyFile as KeyFile;
pub use self::presale::PresaleWallet;
pub use self::secret_store::{
SecretVaultRef, StoreAccountRef, SimpleSecretStore, SecretStore,
Derivation, IndexDerivation,
};
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)
}
}

View File

@@ -1,93 +1,90 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use crypto::{self, pbkdf2, Keccak256};
use ethkey::{Address, KeyPair, Password, Secret};
use std::fs;
use std::path::Path;
use json;
use std::{fs, num::NonZeroU32, path::Path};
use Error;
use crypto::publickey::{Address, Secret, KeyPair};
use ethkey::Password;
use crypto::{Keccak256, pbkdf2};
use {crypto, Error};
/// Pre-sale wallet.
pub struct PresaleWallet {
iv: [u8; 16],
ciphertext: Vec<u8>,
address: Address,
iv: [u8; 16],
ciphertext: Vec<u8>,
address: Address,
}
impl From<json::PresaleWallet> for PresaleWallet {
fn from(wallet: json::PresaleWallet) -> Self {
let mut iv = [0u8; 16];
iv.copy_from_slice(&wallet.encseed[..16]);
fn from(wallet: json::PresaleWallet) -> Self {
let mut iv = [0u8; 16];
iv.copy_from_slice(&wallet.encseed[..16]);
let mut ciphertext = vec![];
ciphertext.extend_from_slice(&wallet.encseed[16..]);
let mut ciphertext = vec![];
ciphertext.extend_from_slice(&wallet.encseed[16..]);
PresaleWallet {
iv: iv,
ciphertext: ciphertext,
address: Address::from(wallet.address),
}
}
PresaleWallet {
iv: iv,
ciphertext: ciphertext,
address: Address::from(wallet.address),
}
}
}
impl PresaleWallet {
/// Open a pre-sale wallet.
pub fn open<P>(path: P) -> Result<Self, Error>
where
P: AsRef<Path>,
{
let file = fs::File::open(path)?;
let presale =
json::PresaleWallet::load(file).map_err(|e| Error::InvalidKeyFile(format!("{}", e)))?;
Ok(PresaleWallet::from(presale))
}
/// Open a pre-sale wallet.
pub fn open<P>(path: P) -> Result<Self, Error> where P: AsRef<Path> {
let file = fs::File::open(path)?;
let presale = json::PresaleWallet::load(file)
.map_err(|e| Error::InvalidKeyFile(format!("{}", e)))?;
Ok(PresaleWallet::from(presale))
}
/// Decrypt the wallet.
pub fn decrypt(&self, password: &Password) -> Result<KeyPair, Error> {
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);
/// Decrypt the wallet.
pub fn decrypt(&self, password: &Password) -> Result<KeyPair, Error> {
let mut derived_key = [0u8; 32];
let salt = pbkdf2::Salt(password.as_bytes());
let sec = pbkdf2::Secret(password.as_bytes());
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 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())?;
if let Ok(kp) = KeyPair::from_secret(secret) {
if kp.address() == self.address {
return Ok(kp);
}
}
let secret = Secret::import_key(&unpadded.keccak256())?;
if let Ok(kp) = KeyPair::from_secret(secret) {
if kp.address() == self.address {
return Ok(kp)
}
}
Err(Error::InvalidPassword)
}
Err(Error::InvalidPassword)
}
}
#[cfg(test)]
mod tests {
use super::PresaleWallet;
use json;
use super::PresaleWallet;
use json;
#[test]
fn test() {
let json = r#"
#[test]
fn test() {
let json = r#"
{
"encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066",
"ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1",
@@ -95,9 +92,9 @@ mod tests {
"btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH"
} "#;
let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap();
let wallet = PresaleWallet::from(wallet);
assert!(wallet.decrypt(&"123".into()).is_ok());
assert!(wallet.decrypt(&"124".into()).is_err());
}
let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap();
let wallet = PresaleWallet::from(wallet);
assert!(wallet.decrypt(&"123".into()).is_ok());
assert!(wallet.decrypt(&"124".into()).is_err());
}
}

View File

@@ -1,47 +1,45 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use rand::{OsRng, Rng};
use rand::{Rng, RngCore, rngs::OsRng, distributions::Alphanumeric};
pub trait Random {
fn random() -> Self
where
Self: Sized;
fn random() -> Self where Self: Sized;
}
impl Random for [u8; 16] {
fn random() -> Self {
let mut result = [0u8; 16];
let mut rng = OsRng::new().unwrap();
rng.fill_bytes(&mut result);
result
}
fn random() -> Self {
let mut result = [0u8; 16];
let mut rng = OsRng;
rng.fill_bytes(&mut result);
result
}
}
impl Random for [u8; 32] {
fn random() -> Self {
let mut result = [0u8; 32];
let mut rng = OsRng::new().unwrap();
rng.fill_bytes(&mut result);
result
}
fn random() -> Self {
let mut result = [0u8; 32];
let mut rng = OsRng;
rng.fill_bytes(&mut result);
result
}
}
/// 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()
}

View File

@@ -1,268 +1,191 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use ethereum_types::H256;
use ethkey::{Address, Message, Password, Public, Secret, Signature};
use json::{OpaqueKeyFile, Uuid};
use std::{
cmp::Ordering,
hash::{Hash, Hasher},
path::PathBuf,
};
use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::cmp::Ordering;
use crypto::publickey::{Address, Message, Signature, Secret, Public};
use ethkey::Password;
use Error;
use json::{Uuid, OpaqueKeyFile};
use ethereum_types::H256;
use OpaqueSecret;
/// Key directory reference
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum SecretVaultRef {
/// Reference to key in root directory
Root,
/// Referenc to key in specific vault
Vault(String),
/// Reference to key in root directory
Root,
/// Referenc to key in specific vault
Vault(String),
}
/// Stored account reference
#[derive(Debug, Clone, PartialEq, Eq, Ord)]
pub struct StoreAccountRef {
/// Account address
pub address: Address,
/// Vault reference
pub vault: SecretVaultRef,
/// Account address
pub address: Address,
/// Vault reference
pub vault: SecretVaultRef,
}
impl PartialOrd for StoreAccountRef {
fn partial_cmp(&self, other: &StoreAccountRef) -> Option<Ordering> {
Some(
self.address
.cmp(&other.address)
.then_with(|| self.vault.cmp(&other.vault)),
)
}
fn partial_cmp(&self, other: &StoreAccountRef) -> Option<Ordering> {
Some(self.address.cmp(&other.address).then_with(|| self.vault.cmp(&other.vault)))
}
}
impl ::std::borrow::Borrow<Address> for StoreAccountRef {
fn borrow(&self) -> &Address {
&self.address
}
fn borrow(&self) -> &Address {
&self.address
}
}
/// Simple Secret Store API
pub trait SimpleSecretStore: Send + Sync {
/// Inserts new accounts to the store (or vault) with given password.
fn insert_account(
&self,
vault: SecretVaultRef,
secret: Secret,
password: &Password,
) -> Result<StoreAccountRef, Error>;
/// Inserts new derived account to the store (or vault) with given password.
fn insert_derived(
&self,
vault: SecretVaultRef,
account_ref: &StoreAccountRef,
password: &Password,
derivation: Derivation,
) -> Result<StoreAccountRef, Error>;
/// Changes accounts password.
fn change_password(
&self,
account: &StoreAccountRef,
old_password: &Password,
new_password: &Password,
) -> Result<(), Error>;
/// Exports key details for account.
fn export_account(
&self,
account: &StoreAccountRef,
password: &Password,
) -> Result<OpaqueKeyFile, Error>;
/// Entirely removes account from the store and underlying storage.
fn remove_account(&self, account: &StoreAccountRef, password: &Password) -> Result<(), Error>;
/// Generates new derived account.
fn generate_derived(
&self,
account_ref: &StoreAccountRef,
password: &Password,
derivation: Derivation,
) -> Result<Address, Error>;
/// Sign a message with given account.
fn sign(
&self,
account: &StoreAccountRef,
password: &Password,
message: &Message,
) -> Result<Signature, Error>;
/// Sign a message with derived account.
fn sign_derived(
&self,
account_ref: &StoreAccountRef,
password: &Password,
derivation: Derivation,
message: &Message,
) -> Result<Signature, Error>;
/// Decrypt a messages with given account.
fn decrypt(
&self,
account: &StoreAccountRef,
password: &Password,
shared_mac: &[u8],
message: &[u8],
) -> Result<Vec<u8>, Error>;
/// Agree on shared key.
fn agree(
&self,
account: &StoreAccountRef,
password: &Password,
other: &Public,
) -> Result<Secret, Error>;
/// Inserts new accounts to the store (or vault) with given password.
fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result<StoreAccountRef, Error>;
/// Inserts new derived account to the store (or vault) with given password.
fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result<StoreAccountRef, Error>;
/// Changes accounts password.
fn change_password(&self, account: &StoreAccountRef, old_password: &Password, new_password: &Password) -> Result<(), Error>;
/// Exports key details for account.
fn export_account(&self, account: &StoreAccountRef, password: &Password) -> Result<OpaqueKeyFile, Error>;
/// Entirely removes account from the store and underlying storage.
fn remove_account(&self, account: &StoreAccountRef, password: &Password) -> Result<(), Error>;
/// Generates new derived account.
fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result<Address, Error>;
/// Sign a message with given account.
fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result<Signature, Error>;
/// Sign a message with derived account.
fn sign_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation, message: &Message) -> Result<Signature, Error>;
/// Decrypt a messages with given account.
fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error>;
/// Agree on shared key.
fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result<Secret, Error>;
/// Returns all accounts in this secret store.
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error>;
/// Get reference to some account with given address.
/// This method could be removed if we will guarantee that there is max(1) account for given address.
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error>;
/// Returns all accounts in this secret store.
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error>;
/// Get reference to some account with given address.
/// This method could be removed if we will guarantee that there is max(1) account for given address.
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error>;
/// Create new vault with given password
fn create_vault(&self, name: &str, password: &Password) -> Result<(), Error>;
/// Open vault with given password
fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error>;
/// Close vault
fn close_vault(&self, name: &str) -> Result<(), Error>;
/// List all vaults
fn list_vaults(&self) -> Result<Vec<String>, Error>;
/// List all currently opened vaults
fn list_opened_vaults(&self) -> Result<Vec<String>, Error>;
/// Change vault password
fn change_vault_password(&self, name: &str, new_password: &Password) -> Result<(), Error>;
/// Cnage account' vault
fn change_account_vault(
&self,
vault: SecretVaultRef,
account: StoreAccountRef,
) -> Result<StoreAccountRef, Error>;
/// Get vault metadata string.
fn get_vault_meta(&self, name: &str) -> Result<String, Error>;
/// Set vault metadata string.
fn set_vault_meta(&self, name: &str, meta: &str) -> Result<(), Error>;
/// Create new vault with given password
fn create_vault(&self, name: &str, password: &Password) -> Result<(), Error>;
/// Open vault with given password
fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error>;
/// Close vault
fn close_vault(&self, name: &str) -> Result<(), Error>;
/// List all vaults
fn list_vaults(&self) -> Result<Vec<String>, Error>;
/// List all currently opened vaults
fn list_opened_vaults(&self) -> Result<Vec<String>, Error>;
/// Change vault password
fn change_vault_password(&self, name: &str, new_password: &Password) -> Result<(), Error>;
/// Cnage account' vault
fn change_account_vault(&self, vault: SecretVaultRef, account: StoreAccountRef) -> Result<StoreAccountRef, Error>;
/// Get vault metadata string.
fn get_vault_meta(&self, name: &str) -> Result<String, Error>;
/// Set vault metadata string.
fn set_vault_meta(&self, name: &str, meta: &str) -> Result<(), Error>;
}
/// Secret Store API
pub trait SecretStore: SimpleSecretStore {
/// Returns a raw opaque Secret that can be later used to sign a message.
fn raw_secret(
&self,
account: &StoreAccountRef,
password: &Password,
) -> Result<OpaqueSecret, Error>;
/// Signs a message with raw secret.
fn sign_with_secret(
&self,
secret: &OpaqueSecret,
message: &Message,
) -> Result<Signature, Error> {
Ok(::ethkey::sign(&secret.0, message)?)
}
/// Returns a raw opaque Secret that can be later used to sign a message.
fn raw_secret(&self, account: &StoreAccountRef, password: &Password) -> Result<OpaqueSecret, Error>;
/// Imports presale wallet
fn import_presale(
&self,
vault: SecretVaultRef,
json: &[u8],
password: &Password,
) -> Result<StoreAccountRef, Error>;
/// 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: &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>;
/// Signs a message with raw secret.
fn sign_with_secret(&self, secret: &OpaqueSecret, message: &Message) -> Result<Signature, Error> {
Ok(crypto::publickey::sign(&secret.0, message)?)
}
/// Returns a public key for given account.
fn public(&self, account: &StoreAccountRef, password: &Password) -> Result<Public, Error>;
/// Imports presale wallet
fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &Password) -> Result<StoreAccountRef, Error>;
/// 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: &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>;
/// Returns uuid of an account.
fn uuid(&self, account: &StoreAccountRef) -> Result<Uuid, Error>;
/// Returns account's name.
fn name(&self, account: &StoreAccountRef) -> Result<String, Error>;
/// Returns account's metadata.
fn meta(&self, account: &StoreAccountRef) -> Result<String, Error>;
/// Returns a public key for given account.
fn public(&self, account: &StoreAccountRef, password: &Password) -> Result<Public, Error>;
/// Modifies account metadata.
fn set_name(&self, account: &StoreAccountRef, name: String) -> Result<(), Error>;
/// Modifies account name.
fn set_meta(&self, account: &StoreAccountRef, meta: String) -> Result<(), Error>;
/// Returns uuid of an account.
fn uuid(&self, account: &StoreAccountRef) -> Result<Uuid, Error>;
/// Returns account's name.
fn name(&self, account: &StoreAccountRef) -> Result<String, Error>;
/// Returns account's metadata.
fn meta(&self, account: &StoreAccountRef) -> Result<String, Error>;
/// Returns local path of the store.
fn local_path(&self) -> PathBuf;
/// Modifies account metadata.
fn set_name(&self, account: &StoreAccountRef, name: String) -> Result<(), Error>;
/// Modifies account name.
fn set_meta(&self, account: &StoreAccountRef, meta: String) -> Result<(), Error>;
/// Returns local path of the store.
fn local_path(&self) -> PathBuf;
/// Lists all found geth accounts.
fn list_geth_accounts(&self, testnet: bool) -> Vec<Address>;
/// Imports geth accounts to the store/vault.
fn import_geth_accounts(&self, vault: SecretVaultRef, desired: Vec<Address>, testnet: bool) -> Result<Vec<StoreAccountRef>, Error>;
}
impl StoreAccountRef {
/// Create reference to root account with given address
pub fn root(address: Address) -> Self {
StoreAccountRef::new(SecretVaultRef::Root, address)
}
/// Create reference to root account with given address
pub fn root(address: Address) -> Self {
StoreAccountRef::new(SecretVaultRef::Root, address)
}
/// Create reference to vault account with given address
pub fn vault(vault_name: &str, address: Address) -> Self {
StoreAccountRef::new(SecretVaultRef::Vault(vault_name.to_owned()), address)
}
/// Create reference to vault account with given address
pub fn vault(vault_name: &str, address: Address) -> Self {
StoreAccountRef::new(SecretVaultRef::Vault(vault_name.to_owned()), address)
}
/// Create new account reference
pub fn new(vault_ref: SecretVaultRef, address: Address) -> Self {
StoreAccountRef {
vault: vault_ref,
address: address,
}
}
/// Create new account reference
pub fn new(vault_ref: SecretVaultRef, address: Address) -> Self {
StoreAccountRef {
vault: vault_ref,
address: address,
}
}
}
impl Hash for StoreAccountRef {
fn hash<H: Hasher>(&self, state: &mut H) {
self.address.hash(state);
}
fn hash<H: Hasher>(&self, state: &mut H) {
self.address.hash(state);
}
}
/// Node in hierarchical derivation.
pub struct IndexDerivation {
/// Node is soft (allows proof of parent from parent node).
pub soft: bool,
/// Index sequence of the node.
pub index: u32,
/// Node is soft (allows proof of parent from parent node).
pub soft: bool,
/// Index sequence of the node.
pub index: u32,
}
/// Derivation scheme for keys
pub enum Derivation {
/// Hierarchical derivation
Hierarchical(Vec<IndexDerivation>),
/// Hash derivation, soft.
SoftHash(H256),
/// Hash derivation, hard.
HardHash(H256),
/// Hierarchical derivation
Hierarchical(Vec<IndexDerivation>),
/// Hash derivation, soft.
SoftHash(H256),
/// Hash derivation, hard.
HardHash(H256),
}

View File

@@ -1,197 +1,158 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethstore;
extern crate rand;
extern crate ethstore;
extern crate ethereum_types;
extern crate parity_crypto;
mod util;
use ethstore::{
accounts_dir::RootDiskDirectory,
ethkey::{verify_address, Generator, KeyPair, Random, Secret},
EthStore, SecretVaultRef, SimpleSecretStore, StoreAccountRef,
};
use ethstore::{EthStore, SimpleSecretStore, SecretVaultRef, StoreAccountRef};
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() {
let dir = TransientDir::create().unwrap();
let _ = EthStore::open(Box::new(dir)).unwrap();
let dir = TransientDir::create().unwrap();
let _ = EthStore::open(Box::new(dir)).unwrap();
}
#[test]
#[should_panic]
fn secret_store_open_not_existing() {
let dir = TransientDir::open();
let _ = EthStore::open(Box::new(dir)).unwrap();
let dir = TransientDir::open();
let _ = EthStore::open(Box::new(dir)).unwrap();
}
fn random_secret() -> Secret {
Random.generate().unwrap().secret().clone()
Random.generate().unwrap().secret().clone()
}
#[test]
fn secret_store_create_account() {
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert_eq!(store.accounts().unwrap().len(), 0);
assert!(store
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
assert_eq!(store.accounts().unwrap().len(), 1);
assert!(store
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
assert_eq!(store.accounts().unwrap().len(), 2);
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert_eq!(store.accounts().unwrap().len(), 0);
assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok());
assert_eq!(store.accounts().unwrap().len(), 1);
assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok());
assert_eq!(store.accounts().unwrap().len(), 2);
}
#[test]
fn secret_store_sign() {
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert!(store
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 1);
assert!(store
.sign(&accounts[0], &"".into(), &Default::default())
.is_ok());
assert!(store
.sign(&accounts[0], &"1".into(), &Default::default())
.is_err());
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok());
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 1);
assert!(store.sign(&accounts[0], &"".into(), &Default::default()).is_ok());
assert!(store.sign(&accounts[0], &"1".into(), &Default::default()).is_err());
}
#[test]
fn secret_store_change_password() {
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert!(store
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 1);
assert!(store
.sign(&accounts[0], &"".into(), &Default::default())
.is_ok());
assert!(store
.change_password(&accounts[0], &"".into(), &"1".into())
.is_ok());
assert!(store
.sign(&accounts[0], &"".into(), &Default::default())
.is_err());
assert!(store
.sign(&accounts[0], &"1".into(), &Default::default())
.is_ok());
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok());
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 1);
assert!(store.sign(&accounts[0], &"".into(), &Default::default()).is_ok());
assert!(store.change_password(&accounts[0], &"".into(), &"1".into()).is_ok());
assert!(store.sign(&accounts[0], &"".into(), &Default::default()).is_err());
assert!(store.sign(&accounts[0], &"1".into(), &Default::default()).is_ok());
}
#[test]
fn secret_store_remove_account() {
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert!(store
.insert_account(SecretVaultRef::Root, random_secret(), &"".into())
.is_ok());
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 1);
assert!(store.remove_account(&accounts[0], &"".into()).is_ok());
assert_eq!(store.accounts().unwrap().len(), 0);
assert!(store.remove_account(&accounts[0], &"".into()).is_err());
let dir = TransientDir::create().unwrap();
let store = EthStore::open(Box::new(dir)).unwrap();
assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok());
let accounts = store.accounts().unwrap();
assert_eq!(accounts.len(), 1);
assert!(store.remove_account(&accounts[0], &"".into()).is_ok());
assert_eq!(store.accounts().unwrap().len(), 0);
assert!(store.remove_account(&accounts[0], &"".into()).is_err());
}
fn test_path() -> &'static str {
match ::std::fs::metadata("ethstore") {
Ok(_) => "ethstore/tests/res/geth_keystore",
Err(_) => "tests/res/geth_keystore",
}
match ::std::fs::metadata("ethstore") {
Ok(_) => "ethstore/tests/res/geth_keystore",
Err(_) => "tests/res/geth_keystore",
}
}
fn pat_path() -> &'static str {
match ::std::fs::metadata("ethstore") {
Ok(_) => "ethstore/tests/res/pat",
Err(_) => "tests/res/pat",
}
match ::std::fs::metadata("ethstore") {
Ok(_) => "ethstore/tests/res/pat",
Err(_) => "tests/res/pat",
}
}
fn ciphertext_path() -> &'static str {
match ::std::fs::metadata("ethstore") {
Ok(_) => "ethstore/tests/res/ciphertext",
Err(_) => "tests/res/ciphertext",
}
match ::std::fs::metadata("ethstore") {
Ok(_) => "ethstore/tests/res/ciphertext",
Err(_) => "tests/res/ciphertext",
}
}
#[test]
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()),
]
);
let dir = RootDiskDirectory::at(test_path());
let store = EthStore::open(Box::new(dir)).unwrap();
assert_eq!(store.accounts().unwrap(), vec![
StoreAccountRef::root(Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()),
StoreAccountRef::root(Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()),
StoreAccountRef::root(Address::from_str("63121b431a52f8043c16fcf0d1df9cb7b5f66649").unwrap()),
]);
}
#[test]
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()),
]
);
let dir = RootDiskDirectory::at(pat_path());
let store = EthStore::open(Box::new(dir)).unwrap();
assert_eq!(store.accounts().unwrap(), vec![
StoreAccountRef::root(Address::from_str("3f49624084b67849c7b4e805c5988c21a430f9d9").unwrap()),
StoreAccountRef::root(Address::from_str("5ba4dcf897e97c2bdf8315b9ef26c13c085988cf").unwrap()),
]);
}
#[test]
fn test_decrypting_files_with_short_ciphertext() {
// 31e9d1e6d844bd3a536800ef8d8be6a9975db509, 30
let kp1 = KeyPair::from_secret(
"000081c29e8142bb6a81bef5a92bda7a8328a5c85bb2f9542e76f9b0f94fc018"
.parse()
.unwrap(),
)
.unwrap();
// d1e64e5480bfaf733ba7d48712decb8227797a4e , 31
let kp2 = KeyPair::from_secret(
"00fa7b3db73dc7dfdf8c5fbdb796d741e4488628c41fc4febd9160a866ba0f35"
.parse()
.unwrap(),
)
.unwrap();
let dir = RootDiskDirectory::at(ciphertext_path());
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()),
]
);
// 31e9d1e6d844bd3a536800ef8d8be6a9975db509, 30
let kp1 = KeyPair::from_secret("000081c29e8142bb6a81bef5a92bda7a8328a5c85bb2f9542e76f9b0f94fc018".parse().unwrap()).unwrap();
// d1e64e5480bfaf733ba7d48712decb8227797a4e , 31
let kp2 = KeyPair::from_secret("00fa7b3db73dc7dfdf8c5fbdb796d741e4488628c41fc4febd9160a866ba0f35".parse().unwrap()).unwrap();
let dir = RootDiskDirectory::at(ciphertext_path());
let store = EthStore::open(Box::new(dir)).unwrap();
let accounts = store.accounts().unwrap();
assert_eq!(accounts, vec![
StoreAccountRef::root(Address::from_str("31e9d1e6d844bd3a536800ef8d8be6a9975db509").unwrap()),
StoreAccountRef::root(Address::from_str("d1e64e5480bfaf733ba7d48712decb8227797a4e").unwrap()),
]);
let message = Default::default();
let message = Default::default();
let s1 = store.sign(&accounts[0], &"foo".into(), &message).unwrap();
let s2 = store.sign(&accounts[1], &"foo".into(), &message).unwrap();
assert!(verify_address(&accounts[0].address, &s1, &message).unwrap());
assert!(verify_address(&kp1.address(), &s1, &message).unwrap());
assert!(verify_address(&kp2.address(), &s2, &message).unwrap());
let s1 = store.sign(&accounts[0], &"foo".into(), &message).unwrap();
let s2 = store.sign(&accounts[1], &"foo".into(), &message).unwrap();
assert!(verify_address(&accounts[0].address, &s1, &message).unwrap());
assert!(verify_address(&kp1.address(), &s1, &message).unwrap());
assert!(verify_address(&kp2.address(), &s2, &message).unwrap());
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
mod transient_dir;

View File

@@ -1,82 +1,81 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use ethstore::{
accounts_dir::{KeyDirectory, RootDiskDirectory},
Error, SafeAccount,
};
use rand::{OsRng, Rng};
use std::{env, fs, path::PathBuf};
use std::path::PathBuf;
use std::{env, fs};
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 dir = env::temp_dir();
dir.push(format!("{:x}-{:x}", rng.next_u64(), rng.next_u64()));
dir
let mut rng = OsRng;
let mut dir = env::temp_dir();
dir.push(format!("{:x}-{:x}", rng.next_u64(), rng.next_u64()));
dir
}
pub struct TransientDir {
dir: RootDiskDirectory,
path: PathBuf,
dir: RootDiskDirectory,
path: PathBuf,
}
impl TransientDir {
pub fn create() -> Result<Self, Error> {
let path = random_dir();
let result = TransientDir {
dir: RootDiskDirectory::create(&path)?,
path: path,
};
pub fn create() -> Result<Self, Error> {
let path = random_dir();
let result = TransientDir {
dir: RootDiskDirectory::create(&path)?,
path: path,
};
Ok(result)
}
Ok(result)
}
pub fn open() -> Self {
let path = random_dir();
TransientDir {
dir: RootDiskDirectory::at(&path),
path: path,
}
}
pub fn open() -> Self {
let path = random_dir();
TransientDir {
dir: RootDiskDirectory::at(&path),
path: path,
}
}
}
impl Drop for TransientDir {
fn drop(&mut self) {
fs::remove_dir_all(&self.path).expect("Expected to remove temp dir");
}
fn drop(&mut self) {
fs::remove_dir_all(&self.path).expect("Expected to remove temp dir");
}
}
impl KeyDirectory for TransientDir {
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
self.dir.load()
}
fn load(&self) -> Result<Vec<SafeAccount>, Error> {
self.dir.load()
}
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
self.dir.update(account)
}
fn update(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
self.dir.update(account)
}
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
self.dir.insert(account)
}
fn insert(&self, account: SafeAccount) -> Result<SafeAccount, Error> {
self.dir.insert(account)
}
fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
self.dir.remove(account)
}
fn remove(&self, account: &SafeAccount) -> Result<(), Error> {
self.dir.remove(account)
}
fn unique_repr(&self) -> Result<u64, Error> {
self.dir.unique_repr()
}
fn unique_repr(&self) -> Result<u64, Error> {
self.dir.unique_repr()
}
}

View File

@@ -1,71 +1,74 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Account Metadata
use std::{collections::HashMap, time::Instant};
use std::{
collections::HashMap,
time::Instant,
};
use ethkey::{Address, Password};
use serde_derive::{Deserialize, Serialize};
use parity_crypto::publickey::Address;
use ethkey::Password;
use serde_derive::{Serialize, Deserialize};
use serde_json;
/// Type of unlock.
#[derive(Clone, PartialEq)]
pub enum Unlock {
/// If account is unlocked temporarily, it should be locked after first usage.
OneTime,
/// Account unlocked permanently can always sign message.
/// Use with caution.
Perm,
/// Account unlocked with a timeout
Timed(Instant),
/// If account is unlocked temporarily, it should be locked after first usage.
OneTime,
/// Account unlocked permanently can always sign message.
/// Use with caution.
Perm,
/// Account unlocked with a timeout
Timed(Instant),
}
/// Data associated with account.
#[derive(Clone)]
pub struct AccountData {
pub unlock: Unlock,
pub password: Password,
pub unlock: Unlock,
pub password: Password,
}
/// Collected account metadata
#[derive(Default, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct AccountMeta {
/// The name of the account.
pub name: String,
/// The rest of the metadata of the account.
pub meta: String,
/// The 128-bit Uuid of the account, if it has one (brain-wallets don't).
pub uuid: Option<String>,
/// The name of the account.
pub name: String,
/// The rest of the metadata of the account.
pub meta: String,
/// The 128-bit Uuid of the account, if it has one (brain-wallets don't).
pub uuid: Option<String>,
}
impl AccountMeta {
/// Read a hash map of Address -> AccountMeta
pub fn read<R>(reader: R) -> Result<HashMap<Address, Self>, serde_json::Error>
where
R: ::std::io::Read,
{
serde_json::from_reader(reader)
}
/// Read a hash map of Address -> AccountMeta
pub fn read<R>(reader: R) -> Result<HashMap<Address, Self>, serde_json::Error> where
R: ::std::io::Read,
{
serde_json::from_reader(reader)
}
/// Write a hash map of Address -> AccountMeta
pub fn write<W>(m: &HashMap<Address, Self>, writer: &mut W) -> Result<(), serde_json::Error>
where
W: ::std::io::Write,
{
serde_json::to_writer(writer, m)
}
/// Write a hash map of Address -> AccountMeta
pub fn write<W>(m: &HashMap<Address, Self>, writer: &mut W) -> Result<(), serde_json::Error> where
W: ::std::io::Write,
{
serde_json::to_writer(writer, m)
}
}

View File

@@ -1,46 +1,46 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity.
// OpenEthereum is free software: you can redistribute it and/or modify
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// OpenEthereum is distributed in the hope that it will be useful,
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::fmt;
use ethstore::Error as SSError;
use ethstore::{Error as SSError};
/// Signing error
#[derive(Debug)]
pub enum SignError {
/// Account is not unlocked
NotUnlocked,
/// Account does not exist.
NotFound,
/// Low-level error from store
SStore(SSError),
/// Account is not unlocked
NotUnlocked,
/// Account does not exist.
NotFound,
/// Low-level error from store
SStore(SSError),
}
impl fmt::Display for SignError {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
SignError::NotUnlocked => write!(f, "Account is locked"),
SignError::NotFound => write!(f, "Account does not exist"),
SignError::SStore(ref e) => write!(f, "{}", e),
}
}
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
SignError::NotUnlocked => write!(f, "Account is locked"),
SignError::NotFound => write!(f, "Account does not exist"),
SignError::SStore(ref e) => write!(f, "{}", e),
}
}
}
impl From<SSError> for SignError {
fn from(e: SSError) -> Self {
SignError::SStore(e)
}
fn from(e: SSError) -> Self {
SignError::SStore(e)
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,237 +1,189 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Address Book Store
use std::{
collections::HashMap,
fmt, fs, hash, ops,
path::{Path, PathBuf},
};
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;
/// Disk-backed map from Address to String. Uses JSON.
pub struct AddressBook {
cache: DiskMap<Address, AccountMeta>,
cache: DiskMap<Address, AccountMeta>,
}
impl AddressBook {
/// Creates new address book at given directory.
pub fn new(path: &Path) -> Self {
let mut r = AddressBook {
cache: DiskMap::new(path, "address_book.json"),
};
r.cache.revert(AccountMeta::read);
r
}
/// Creates new address book at given directory.
pub fn new(path: &Path) -> Self {
let mut r = AddressBook {
cache: DiskMap::new(path, "address_book.json")
};
r.cache.revert(AccountMeta::read);
r
}
/// Creates transient address book (no changes are saved to disk).
pub fn transient() -> Self {
AddressBook {
cache: DiskMap::transient(),
}
}
/// Creates transient address book (no changes are saved to disk).
pub fn transient() -> Self {
AddressBook {
cache: DiskMap::transient()
}
}
/// Get the address book.
pub fn get(&self) -> HashMap<Address, AccountMeta> {
self.cache.clone()
}
/// Get the address book.
pub fn get(&self) -> HashMap<Address, AccountMeta> {
self.cache.clone()
}
fn save(&self) {
self.cache.save(AccountMeta::write)
}
fn save(&self) {
self.cache.save(AccountMeta::write)
}
/// Sets new name for given address.
pub fn set_name(&mut self, a: Address, name: String) {
{
let x = self.cache.entry(a).or_insert_with(|| AccountMeta {
name: Default::default(),
meta: "{}".to_owned(),
uuid: None,
});
x.name = name;
}
self.save();
}
/// Sets new name for given address.
pub fn set_name(&mut self, a: Address, name: String) {
{
let x = self.cache.entry(a)
.or_insert_with(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None});
x.name = name;
}
self.save();
}
/// Sets new meta for given address.
pub fn set_meta(&mut self, a: Address, meta: String) {
{
let x = self.cache.entry(a).or_insert_with(|| AccountMeta {
name: "Anonymous".to_owned(),
meta: Default::default(),
uuid: None,
});
x.meta = meta;
}
self.save();
}
/// Sets new meta for given address.
pub fn set_meta(&mut self, a: Address, meta: String) {
{
let x = self.cache.entry(a)
.or_insert_with(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None});
x.meta = meta;
}
self.save();
}
/// Removes an entry
pub fn remove(&mut self, a: Address) {
self.cache.remove(&a);
self.save();
}
/// Removes an entry
pub fn remove(&mut self, a: Address) {
self.cache.remove(&a);
self.save();
}
}
/// Disk-serializable HashMap
#[derive(Debug)]
struct DiskMap<K: hash::Hash + Eq, V> {
path: PathBuf,
cache: HashMap<K, V>,
transient: bool,
path: PathBuf,
cache: HashMap<K, V>,
transient: bool,
}
impl<K: hash::Hash + Eq, V> ops::Deref for DiskMap<K, V> {
type Target = HashMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.cache
}
type Target = HashMap<K, V>;
fn deref(&self) -> &Self::Target {
&self.cache
}
}
impl<K: hash::Hash + Eq, V> ops::DerefMut for DiskMap<K, V> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.cache
}
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.cache
}
}
impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
pub fn new(path: &Path, file_name: &str) -> Self {
let mut path = path.to_owned();
path.push(file_name);
trace!(target: "diskmap", "path={:?}", path);
DiskMap {
path: path,
cache: HashMap::new(),
transient: false,
}
}
pub fn new(path: &Path, file_name: &str) -> Self {
let mut path = path.to_owned();
path.push(file_name);
trace!(target: "diskmap", "path={:?}", path);
DiskMap {
path: path,
cache: HashMap::new(),
transient: false,
}
}
pub fn transient() -> Self {
let mut map = DiskMap::new(&PathBuf::new(), "diskmap.json".into());
map.transient = true;
map
}
pub fn transient() -> Self {
let mut map = DiskMap::new(&PathBuf::new(), "diskmap.json".into());
map.transient = true;
map
}
fn revert<F, E>(&mut self, read: F)
where
F: Fn(fs::File) -> Result<HashMap<K, V>, E>,
E: fmt::Display,
{
if self.transient {
return;
}
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(|m| {
self.cache = m;
Ok(())
});
}
fn revert<F, E>(&mut self, read: F) where
F: Fn(fs::File) -> Result<HashMap<K, V>, E>,
E: fmt::Display,
{
if self.transient { return; }
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 at: {:?} {}", self.path, e)))
.and_then(|m| {
self.cache = m;
Ok(())
});
}
fn save<F, E>(&self, write: F)
where
F: Fn(&HashMap<K, V>, &mut fs::File) -> Result<(), E>,
E: fmt::Display,
{
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))
.and_then(|mut f| {
write(&self.cache, &mut f)
.map_err(|e| warn!(target: "diskmap", "Couldn't write to disk map: {}", e))
});
}
fn save<F, E>(&self, write: F) where
F: Fn(&HashMap<K, V>, &mut fs::File) -> Result<(), E>,
E: fmt::Display,
{
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 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 at: {:?} {}", self.path, e))
});
}
}
#[cfg(test)]
mod tests {
use super::AddressBook;
use crate::account_data::AccountMeta;
use std::collections::HashMap;
use tempdir::TempDir;
use super::{AddressBook, Address};
use std::collections::HashMap;
use tempdir::TempDir;
use crate::account_data::AccountMeta;
#[test]
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());
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<_, _>>()
);
}
#[test]
fn should_save_and_reload_address_book() {
let tempdir = TempDir::new("").unwrap();
let mut b = AddressBook::new(tempdir.path());
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![
(Address::from_low_u64_be(1), AccountMeta {name: "One".to_owned(), meta: "{1:1}".to_owned(), uuid: None})
].into_iter().collect::<HashMap<_, _>>());
}
#[test]
fn should_remove_address() {
let tempdir = TempDir::new("").unwrap();
let mut b = AddressBook::new(tempdir.path());
#[test]
fn should_remove_address() {
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<_, _>>()
);
}
let b = AddressBook::new(tempdir.path());
assert_eq!(b.get(), vec![
(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<_, _>>());
}
}

View File

@@ -1,51 +1,49 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethjson;
extern crate serde_json;
extern crate ethjson;
use std::{fs, env, process};
use ethjson::spec::Spec;
use std::{env, fs, process};
fn quit(s: &str) -> ! {
println!("{}", s);
process::exit(1);
println!("{}", s);
process::exit(1);
}
fn main() {
let mut args = env::args();
if args.len() != 2 {
quit(
"You need to specify chainspec.json\n\
let mut args = env::args();
if args.len() != 2 {
quit("You need to specify chainspec.json\n\
\n\
./chainspec <chainspec.json>",
);
}
./chainspec <chainspec.json>");
}
let path = args.nth(1).expect("args.len() == 2; qed");
let file = match fs::File::open(&path) {
Ok(file) => file,
Err(_) => quit(&format!("{} could not be opened", path)),
};
let path = args.nth(1).expect("args.len() == 2; qed");
let file = match fs::File::open(&path) {
Ok(file) => file,
Err(_) => quit(&format!("{} could not be opened", path)),
};
let spec: Result<Spec, _> = serde_json::from_reader(file);
let spec: Result<Spec, _> = serde_json::from_reader(file);
if let Err(err) = spec {
quit(&format!("{} {}", path, err.to_string()));
}
if let Err(err) = spec {
quit(&format!("{} {}", path, err.to_string()));
}
println!("{} is valid", path);
println!("{} is valid", path);
}

View File

@@ -1,13 +1,13 @@
[package]
description = "OpenEthereum CLI Signer Tool"
homepage = "https://github.com/openethereum/openethereum"
description = "Parity Ethereum CLI Signer Tool"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "cli-signer"
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" }

View File

@@ -1,21 +1,21 @@
[package]
description = "OpenEthereum RPC Client"
homepage = "https://github.com/openethereum/openethereum"
description = "Parity Ethereum RPC Client"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "parity-rpc-client"
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 = "15.0.0"
jsonrpc-ws-server = "15.0.0"
jsonrpc-core = "14.0.3"
jsonrpc-ws-server = "14.0.3"
parity-rpc = { path = "../../rpc" }
keccak-hash = "0.1"
keccak-hash = "0.4.0"

View File

@@ -1,327 +1,347 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use std::{
collections::BTreeMap,
fmt::{Debug, Error as FmtError, Formatter},
io::{BufRead, BufReader},
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
thread, time,
};
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::io::{BufReader, BufRead};
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::collections::BTreeMap;
use std::thread;
use std::time;
use std::path::PathBuf;
use hash::keccak;
use parking_lot::Mutex;
use std::{fs::File, path::PathBuf};
use url::Url;
use std::fs::File;
use ws::ws::{
self, Error as WsError, ErrorKind as WsErrorKind, Handler, Handshake, Message, Request,
Result as WsResult, Sender,
self,
Request,
Handler,
Sender,
Handshake,
Error as WsError,
ErrorKind as WsErrorKind,
Message,
Result as WsResult,
};
use serde::de::DeserializeOwned;
use serde_json::{self as json, Error as JsonError, Value as JsonValue};
use futures::{done, oneshot, Canceled, Complete, Future};
use jsonrpc_core::{
request::MethodCall,
response::{Failure, Output, Success},
Error as JsonRpcError, Id, Params, Version,
use serde_json::{
self as json,
Value as JsonValue,
Error as JsonError,
};
use futures::{Canceled, Complete, Future, oneshot, done};
use jsonrpc_core::{Id, Version, Params, Error as JsonRpcError};
use jsonrpc_core::request::MethodCall;
use jsonrpc_core::response::{Output, Success, Failure};
use BoxFuture;
/// The actual websocket connection handler, passed into the
/// event loop of ws-rs
struct RpcHandler {
pending: Pending,
// Option is used here as temporary storage until connection
// is setup and the values are moved into the new `Rpc`
complete: Option<Complete<Result<Rpc, RpcError>>>,
auth_code: String,
out: Option<Sender>,
pending: Pending,
// Option is used here as temporary storage until connection
// is setup and the values are moved into the new `Rpc`
complete: Option<Complete<Result<Rpc, RpcError>>>,
auth_code: String,
out: Option<Sender>,
}
impl RpcHandler {
fn new(out: Sender, auth_code: String, complete: Complete<Result<Rpc, RpcError>>) -> Self {
RpcHandler {
out: Some(out),
auth_code: auth_code,
pending: Pending::new(),
complete: Some(complete),
}
}
fn new(
out: Sender,
auth_code: String,
complete: Complete<Result<Rpc, RpcError>>
) -> Self {
RpcHandler {
out: Some(out),
auth_code: auth_code,
pending: Pending::new(),
complete: Some(complete),
}
}
}
impl Handler for RpcHandler {
fn build_request(&mut self, url: &Url) -> WsResult<Request> {
match Request::from_url(url) {
Ok(mut r) => {
let timestamp = time::UNIX_EPOCH
.elapsed()
.map_err(|err| WsError::new(WsErrorKind::Internal, format!("{}", err)))?;
let secs = timestamp.as_secs();
let hashed = keccak(format!("{}:{}", self.auth_code, secs));
let proto = format!("{:x}_{}", hashed, secs);
r.add_protocol(&proto);
Ok(r)
}
Err(e) => Err(WsError::new(WsErrorKind::Internal, format!("{}", e))),
}
}
fn on_error(&mut self, err: WsError) {
match self.complete.take() {
Some(c) => match c.send(Err(RpcError::WsError(err))) {
Ok(_) => {}
Err(_) => warn!(target: "rpc-client", "Unable to notify about error."),
},
None => warn!(target: "rpc-client", "unexpected error: {}", err),
}
}
fn on_open(&mut self, _: Handshake) -> WsResult<()> {
match (self.complete.take(), self.out.take()) {
(Some(c), Some(out)) => {
let res = c.send(Ok(Rpc {
out: out,
counter: AtomicUsize::new(0),
pending: self.pending.clone(),
}));
if let Err(_) = res {
warn!(target: "rpc-client", "Unable to open a connection.")
}
Ok(())
}
_ => {
let msg = format!("on_open called twice");
Err(WsError::new(WsErrorKind::Internal, msg))
}
}
}
fn on_message(&mut self, msg: Message) -> WsResult<()> {
let ret: Result<JsonValue, JsonRpcError>;
let response_id;
let string = &msg.to_string();
match json::from_str::<Output>(&string) {
Ok(Output::Success(Success {
result,
id: Id::Num(id),
..
})) => {
ret = Ok(result);
response_id = id as usize;
}
Ok(Output::Failure(Failure {
error,
id: Id::Num(id),
..
})) => {
ret = Err(error);
response_id = id as usize;
}
Err(e) => {
warn!(
target: "rpc-client",
"recieved invalid message: {}\n {:?}",
string,
e
);
return Ok(());
}
_ => {
warn!(
target: "rpc-client",
"recieved invalid message: {}",
string
);
return Ok(());
}
}
fn build_request(&mut self, url: &Url) -> WsResult<Request> {
match Request::from_url(url) {
Ok(mut r) => {
let timestamp = time::UNIX_EPOCH.elapsed().map_err(|err| {
WsError::new(WsErrorKind::Internal, format!("{}", err))
})?;
let secs = timestamp.as_secs();
let hashed = keccak(format!("{}:{}", self.auth_code, secs));
let proto = format!("{:x}_{}", hashed, secs);
r.add_protocol(&proto);
Ok(r)
},
Err(e) =>
Err(WsError::new(WsErrorKind::Internal, format!("{}", e))),
}
}
fn on_error(&mut self, err: WsError) {
match self.complete.take() {
Some(c) => match c.send(Err(RpcError::WsError(err))) {
Ok(_) => {},
Err(_) => warn!(target: "rpc-client", "Unable to notify about error."),
},
None => warn!(target: "rpc-client", "unexpected error: {}", err),
}
}
fn on_open(&mut self, _: Handshake) -> WsResult<()> {
match (self.complete.take(), self.out.take()) {
(Some(c), Some(out)) => {
let res = c.send(Ok(Rpc {
out: out,
counter: AtomicUsize::new(0),
pending: self.pending.clone(),
}));
if let Err(_) = res {
warn!(target: "rpc-client", "Unable to open a connection.")
}
Ok(())
},
_ => {
let msg = format!("on_open called twice");
Err(WsError::new(WsErrorKind::Internal, msg))
}
}
}
fn on_message(&mut self, msg: Message) -> WsResult<()> {
let ret: Result<JsonValue, JsonRpcError>;
let response_id;
let string = &msg.to_string();
match json::from_str::<Output>(&string) {
Ok(Output::Success(Success { result, id: Id::Num(id), .. })) =>
{
ret = Ok(result);
response_id = id as usize;
}
Ok(Output::Failure(Failure { error, id: Id::Num(id), .. })) => {
ret = Err(error);
response_id = id as usize;
}
Err(e) => {
warn!(
target: "rpc-client",
"recieved invalid message: {}\n {:?}",
string,
e
);
return Ok(())
},
_ => {
warn!(
target: "rpc-client",
"recieved invalid message: {}",
string
);
return Ok(())
}
}
match self.pending.remove(response_id) {
Some(c) => {
if let Err(_) = c.send(ret.map_err(|err| RpcError::JsonRpc(err))) {
warn!(target: "rpc-client", "Unable to send response.")
}
}
None => warn!(
target: "rpc-client",
"warning: unexpected id: {}",
response_id
),
}
Ok(())
}
match self.pending.remove(response_id) {
Some(c) => if let Err(_) = c.send(ret.map_err(|err| RpcError::JsonRpc(err))) {
warn!(target: "rpc-client", "Unable to send response.")
},
None => warn!(
target: "rpc-client",
"warning: unexpected id: {}",
response_id
),
}
Ok(())
}
}
/// Keeping track of issued requests to be matched up with responses
#[derive(Clone)]
struct Pending(Arc<Mutex<BTreeMap<usize, Complete<Result<JsonValue, RpcError>>>>>);
struct Pending(
Arc<Mutex<BTreeMap<usize, Complete<Result<JsonValue, RpcError>>>>>
);
impl Pending {
fn new() -> Self {
Pending(Arc::new(Mutex::new(BTreeMap::new())))
}
fn insert(&mut self, k: usize, v: Complete<Result<JsonValue, RpcError>>) {
self.0.lock().insert(k, v);
}
fn remove(&mut self, k: usize) -> Option<Complete<Result<JsonValue, RpcError>>> {
self.0.lock().remove(&k)
}
fn new() -> Self {
Pending(Arc::new(Mutex::new(BTreeMap::new())))
}
fn insert(&mut self, k: usize, v: Complete<Result<JsonValue, RpcError>>) {
self.0.lock().insert(k, v);
}
fn remove(
&mut self,
k: usize
) -> Option<Complete<Result<JsonValue, RpcError>>> {
self.0.lock().remove(&k)
}
}
fn get_authcode(path: &PathBuf) -> Result<String, RpcError> {
if let Ok(fd) = File::open(path) {
if let Some(Ok(line)) = BufReader::new(fd).lines().next() {
let mut parts = line.split(';');
let token = parts.next();
if let Ok(fd) = File::open(path) {
if let Some(Ok(line)) = BufReader::new(fd).lines().next() {
let mut parts = line.split(';');
let token = parts.next();
if let Some(code) = token {
return Ok(code.into());
}
}
}
Err(RpcError::NoAuthCode)
if let Some(code) = token {
return Ok(code.into());
}
}
}
Err(RpcError::NoAuthCode)
}
/// The handle to the connection
pub struct Rpc {
out: Sender,
counter: AtomicUsize,
pending: Pending,
out: Sender,
counter: AtomicUsize,
pending: Pending,
}
impl Rpc {
/// Blocking, returns a new initialized connection or RpcError
pub fn new(url: &str, authpath: &PathBuf) -> Result<Self, RpcError> {
let rpc = Self::connect(url, authpath).map(|rpc| rpc).wait()?;
rpc
}
/// Blocking, returns a new initialized connection or RpcError
pub fn new(url: &str, authpath: &PathBuf) -> Result<Self, RpcError> {
let rpc = Self::connect(url, authpath).map(|rpc| rpc).wait()?;
rpc
}
/// Non-blocking, returns a future
pub fn connect(url: &str, authpath: &PathBuf) -> BoxFuture<Result<Self, RpcError>, Canceled> {
let (c, p) = oneshot::<Result<Self, RpcError>>();
match get_authcode(authpath) {
Err(e) => return Box::new(done(Ok(Err(e)))),
Ok(code) => {
let url = String::from(url);
// The ws::connect takes a FnMut closure, which means c cannot
// be moved into it, since it's consumed on complete.
// Therefore we wrap it in an option and pick it out once.
let mut once = Some(c);
thread::spawn(move || {
let conn = ws::connect(url, |out| {
// this will panic if the closure is called twice,
// which it should never be.
let c = once.take().expect("connection closure called only once");
RpcHandler::new(out, code.clone(), c)
});
match conn {
Err(err) => {
// since ws::connect is only called once, it cannot
// both fail and succeed.
let c = once.take().expect("connection closure called only once");
let _ = c.send(Err(RpcError::WsError(err)));
}
// c will complete on the `on_open` event in the Handler
_ => (),
}
});
Box::new(p)
}
}
}
/// Non-blocking, returns a future
pub fn connect(
url: &str, authpath: &PathBuf
) -> BoxFuture<Result<Self, RpcError>, Canceled> {
let (c, p) = oneshot::<Result<Self, RpcError>>();
match get_authcode(authpath) {
Err(e) => return Box::new(done(Ok(Err(e)))),
Ok(code) => {
let url = String::from(url);
// The ws::connect takes a FnMut closure, which means c cannot
// be moved into it, since it's consumed on complete.
// Therefore we wrap it in an option and pick it out once.
let mut once = Some(c);
thread::spawn(move || {
let conn = ws::connect(url, |out| {
// this will panic if the closure is called twice,
// which it should never be.
let c = once.take()
.expect("connection closure called only once");
RpcHandler::new(out, code.clone(), c)
});
match conn {
Err(err) => {
// since ws::connect is only called once, it cannot
// both fail and succeed.
let c = once.take()
.expect("connection closure called only once");
let _ = c.send(Err(RpcError::WsError(err)));
},
// c will complete on the `on_open` event in the Handler
_ => ()
}
});
Box::new(p)
}
}
}
/// Non-blocking, returns a future of the request response
pub fn request<T>(
&mut self,
method: &'static str,
params: Vec<JsonValue>,
) -> BoxFuture<Result<T, RpcError>, Canceled>
where
T: DeserializeOwned + Send + Sized,
{
let (c, p) = oneshot::<Result<JsonValue, RpcError>>();
/// Non-blocking, returns a future of the request response
pub fn request<T>(
&mut self, method: &'static str, params: Vec<JsonValue>
) -> BoxFuture<Result<T, RpcError>, Canceled>
where T: DeserializeOwned + Send + Sized {
let id = self.counter.fetch_add(1, Ordering::Relaxed);
self.pending.insert(id, c);
let (c, p) = oneshot::<Result<JsonValue, RpcError>>();
let request = MethodCall {
jsonrpc: Some(Version::V2),
method: method.to_owned(),
params: Params::Array(params),
id: Id::Num(id as u64),
};
let id = self.counter.fetch_add(1, Ordering::Relaxed);
self.pending.insert(id, c);
let serialized = json::to_string(&request).expect("request is serializable");
let _ = self.out.send(serialized);
let request = MethodCall {
jsonrpc: Some(Version::V2),
method: method.to_owned(),
params: Params::Array(params),
id: Id::Num(id as u64),
};
Box::new(p.map(|result| match result {
Ok(json) => {
let t: T = json::from_value(json)?;
Ok(t)
}
Err(err) => Err(err),
}))
}
let serialized = json::to_string(&request)
.expect("request is serializable");
let _ = self.out.send(serialized);
Box::new(p.map(|result| {
match result {
Ok(json) => {
let t: T = json::from_value(json)?;
Ok(t)
},
Err(err) => Err(err)
}
}))
}
}
pub enum RpcError {
WrongVersion(String),
ParseError(JsonError),
MalformedResponse(String),
JsonRpc(JsonRpcError),
WsError(WsError),
Canceled(Canceled),
UnexpectedId,
NoAuthCode,
WrongVersion(String),
ParseError(JsonError),
MalformedResponse(String),
JsonRpc(JsonRpcError),
WsError(WsError),
Canceled(Canceled),
UnexpectedId,
NoAuthCode,
}
impl Debug for RpcError {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self {
RpcError::WrongVersion(ref s) => write!(f, "Expected version 2.0, got {}", s),
RpcError::ParseError(ref err) => write!(f, "ParseError: {}", err),
RpcError::MalformedResponse(ref s) => write!(f, "Malformed response: {}", s),
RpcError::JsonRpc(ref json) => write!(f, "JsonRpc error: {:?}", json),
RpcError::WsError(ref s) => write!(f, "Websocket error: {}", s),
RpcError::Canceled(ref s) => write!(f, "Futures error: {:?}", s),
RpcError::UnexpectedId => write!(f, "Unexpected response id"),
RpcError::NoAuthCode => write!(f, "No authcodes available"),
}
}
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
match *self {
RpcError::WrongVersion(ref s)
=> write!(f, "Expected version 2.0, got {}", s),
RpcError::ParseError(ref err)
=> write!(f, "ParseError: {}", err),
RpcError::MalformedResponse(ref s)
=> write!(f, "Malformed response: {}", s),
RpcError::JsonRpc(ref json)
=> write!(f, "JsonRpc error: {:?}", json),
RpcError::WsError(ref s)
=> write!(f, "Websocket error: {}", s),
RpcError::Canceled(ref s)
=> write!(f, "Futures error: {:?}", s),
RpcError::UnexpectedId
=> write!(f, "Unexpected response id"),
RpcError::NoAuthCode
=> write!(f, "No authcodes available"),
}
}
}
impl From<JsonError> for RpcError {
fn from(err: JsonError) -> RpcError {
RpcError::ParseError(err)
}
fn from(err: JsonError) -> RpcError {
RpcError::ParseError(err)
}
}
impl From<WsError> for RpcError {
fn from(err: WsError) -> RpcError {
RpcError::WsError(err)
}
fn from(err: WsError) -> RpcError {
RpcError::WsError(err)
}
}
impl From<Canceled> for RpcError {
fn from(err: Canceled) -> RpcError {
RpcError::Canceled(err)
}
fn from(err: Canceled) -> RpcError {
RpcError::Canceled(err)
}
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
pub mod client;
pub mod signer_client;
@@ -21,12 +21,12 @@ extern crate ethereum_types;
extern crate futures;
extern crate jsonrpc_core;
extern crate jsonrpc_ws_server as ws;
extern crate keccak_hash as hash;
extern crate parity_rpc as rpc;
extern crate parking_lot;
extern crate serde;
extern crate serde_json;
extern crate url;
extern crate keccak_hash as hash;
#[macro_use]
extern crate log;
@@ -36,55 +36,56 @@ extern crate log;
extern crate matches;
/// Boxed future response.
pub type BoxFuture<T, E> = Box<dyn 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 {
use client::{Rpc, RpcError};
use futures::Future;
use rpc;
use std::path::PathBuf;
use futures::Future;
use std::path::PathBuf;
use client::{Rpc, RpcError};
use rpc;
#[test]
fn test_connection_refused() {
let (_srv, port, mut authcodes) = rpc::tests::ws::serve();
#[test]
fn test_connection_refused() {
let (_srv, port, mut authcodes) = rpc::tests::ws::serve();
let _ = authcodes.generate_new();
authcodes.to_file(&authcodes.path).unwrap();
let _ = authcodes.generate_new();
authcodes.to_file(&authcodes.path).unwrap();
let connect = Rpc::connect(&format!("ws://127.0.0.1:{}", port - 1), &authcodes.path);
let connect = Rpc::connect(&format!("ws://127.0.0.1:{}", port - 1),
&authcodes.path);
let _ = connect
.map(|conn| {
assert!(matches!(&conn, &Err(RpcError::WsError(_))));
})
.wait();
}
let _ = connect.map(|conn| {
assert!(matches!(&conn, &Err(RpcError::WsError(_))));
}).wait();
}
#[test]
fn test_authcode_fail() {
let (_srv, port, _) = rpc::tests::ws::serve();
let path = PathBuf::from("nonexist");
#[test]
fn test_authcode_fail() {
let (_srv, port, _) = rpc::tests::ws::serve();
let path = PathBuf::from("nonexist");
let connect = Rpc::connect(&format!("ws://127.0.0.1:{}", port), &path);
let connect = Rpc::connect(&format!("ws://127.0.0.1:{}", port), &path);
let _ = connect
.map(|conn| {
assert!(matches!(&conn, &Err(RpcError::NoAuthCode)));
})
.wait();
}
let _ = connect.map(|conn| {
assert!(matches!(&conn, &Err(RpcError::NoAuthCode)));
}).wait();
}
#[test]
fn test_authcode_correct() {
let (_srv, port, mut authcodes) = rpc::tests::ws::serve();
#[test]
fn test_authcode_correct() {
let (_srv, port, mut authcodes) = rpc::tests::ws::serve();
let _ = authcodes.generate_new();
authcodes.to_file(&authcodes.path).unwrap();
let _ = authcodes.generate_new();
authcodes.to_file(&authcodes.path).unwrap();
let connect = Rpc::connect(&format!("ws://127.0.0.1:{}", port), &authcodes.path);
let connect = Rpc::connect(&format!("ws://127.0.0.1:{}", port),
&authcodes.path);
let _ = connect.map(|conn| {
assert!(conn.is_ok())
}).wait();
}
let _ = connect.map(|conn| assert!(conn.is_ok())).wait();
}
}

View File

@@ -1,76 +1,63 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use client::{Rpc, RpcError};
use ethereum_types::U256;
use futures::Canceled;
use rpc::signer::{ConfirmationRequest, TransactionCondition, TransactionModification};
use rpc::signer::{ConfirmationRequest, TransactionModification, TransactionCondition};
use serde;
use serde_json::{to_value, Value as JsonValue};
use serde_json::{Value as JsonValue, to_value};
use std::path::PathBuf;
use BoxFuture;
use futures::{Canceled};
use {BoxFuture};
pub struct SignerRpc {
rpc: Rpc,
rpc: Rpc,
}
impl SignerRpc {
pub fn new(url: &str, authfile: &PathBuf) -> Result<Self, RpcError> {
Ok(SignerRpc {
rpc: Rpc::new(&url, authfile)?,
})
}
pub fn new(url: &str, authfile: &PathBuf) -> Result<Self, RpcError> {
Ok(SignerRpc { rpc: Rpc::new(&url, authfile)? })
}
pub fn requests_to_confirm(
&mut self,
) -> BoxFuture<Result<Vec<ConfirmationRequest>, RpcError>, Canceled> {
self.rpc.request("signer_requestsToConfirm", vec![])
}
pub fn requests_to_confirm(&mut self) -> BoxFuture<Result<Vec<ConfirmationRequest>, RpcError>, Canceled> {
self.rpc.request("signer_requestsToConfirm", vec![])
}
pub fn confirm_request(
&mut self,
id: U256,
new_gas: Option<U256>,
new_gas_price: Option<U256>,
new_condition: Option<Option<TransactionCondition>>,
pwd: &str,
) -> BoxFuture<Result<U256, RpcError>, Canceled> {
self.rpc.request(
"signer_confirmRequest",
vec![
Self::to_value(&format!("{:#x}", id)),
Self::to_value(&TransactionModification {
sender: None,
gas_price: new_gas_price,
gas: new_gas,
condition: new_condition,
}),
Self::to_value(&pwd),
],
)
}
pub fn confirm_request(
&mut self,
id: U256,
new_gas: Option<U256>,
new_gas_price: Option<U256>,
new_condition: Option<Option<TransactionCondition>>,
pwd: &str
) -> BoxFuture<Result<U256, RpcError>, Canceled> {
self.rpc.request("signer_confirmRequest", vec![
Self::to_value(&format!("{:#x}", id)),
Self::to_value(&TransactionModification { sender: None, gas_price: new_gas_price, gas: new_gas, condition: new_condition }),
Self::to_value(&pwd),
])
}
pub fn reject_request(&mut self, id: U256) -> BoxFuture<Result<bool, RpcError>, Canceled> {
self.rpc.request(
"signer_rejectRequest",
vec![JsonValue::String(format!("{:#x}", id))],
)
}
pub fn reject_request(&mut self, id: U256) -> BoxFuture<Result<bool, RpcError>, Canceled> {
self.rpc.request("signer_rejectRequest", vec![
JsonValue::String(format!("{:#x}", id))
])
}
fn to_value<T: serde::Serialize>(v: &T) -> JsonValue {
to_value(v).expect("Our types are always serializable; qed")
}
fn to_value<T: serde::Serialize>(v: &T) -> JsonValue {
to_value(v).expect("Our types are always serializable; qed")
}
}

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethereum_types;
extern crate futures;
@@ -21,142 +21,177 @@ extern crate rpassword;
extern crate parity_rpc as rpc;
extern crate parity_rpc_client as client;
use client::signer_client::SignerRpc;
use ethereum_types::U256;
use rpc::signer::ConfirmationRequest;
use std::{
fs::File,
io::{stdin, stdout, BufRead, BufReader, Write},
path::PathBuf,
};
use client::signer_client::SignerRpc;
use std::io::{Write, BufRead, BufReader, stdout, stdin};
use std::path::PathBuf;
use std::fs::File;
use futures::Future;
fn sign_interactive(signer: &mut SignerRpc, password: &str, request: ConfirmationRequest) {
print!(
"\n{}\nSign this transaction? (y)es/(N)o/(r)eject: ",
request
);
let _ = stdout().flush();
match BufReader::new(stdin()).lines().next() {
Some(Ok(line)) => match line.to_lowercase().chars().nth(0) {
Some('y') => match sign_transaction(signer, request.id, password) {
Ok(s) | Err(s) => println!("{}", s),
},
Some('r') => match reject_transaction(signer, request.id) {
Ok(s) | Err(s) => println!("{}", s),
},
_ => (),
},
_ => println!("Could not read from stdin"),
}
fn sign_interactive(
signer: &mut SignerRpc,
password: &str,
request: ConfirmationRequest
) {
print!("\n{}\nSign this transaction? (y)es/(N)o/(r)eject: ", request);
let _ = stdout().flush();
match BufReader::new(stdin()).lines().next() {
Some(Ok(line)) => {
match line.to_lowercase().chars().nth(0) {
Some('y') => {
match sign_transaction(signer, request.id, password) {
Ok(s) | Err(s) => println!("{}", s),
}
}
Some('r') => {
match reject_transaction(signer, request.id) {
Ok(s) | Err(s) => println!("{}", s),
}
}
_ => ()
}
}
_ => println!("Could not read from stdin")
}
}
fn sign_transactions(signer: &mut SignerRpc, password: String) -> Result<String, String> {
signer
.requests_to_confirm()
.map(|reqs| match reqs {
Ok(ref reqs) if reqs.is_empty() => Ok("No transactions in signing queue".to_owned()),
Ok(reqs) => {
for r in reqs {
sign_interactive(signer, &password, r)
}
Ok("".to_owned())
}
Err(err) => Err(format!("error: {:?}", err)),
})
.map_err(|err| format!("{:?}", err))
.wait()?
fn sign_transactions(
signer: &mut SignerRpc,
password: String
) -> Result<String, String> {
signer.requests_to_confirm().map(|reqs| {
match reqs {
Ok(ref reqs) if reqs.is_empty() => {
Ok("No transactions in signing queue".to_owned())
}
Ok(reqs) => {
for r in reqs {
sign_interactive(signer, &password, r)
}
Ok("".to_owned())
}
Err(err) => {
Err(format!("error: {:?}", err))
}
}
}).map_err(|err| {
format!("{:?}", err)
}).wait()?
}
fn list_transactions(signer: &mut SignerRpc) -> Result<String, String> {
signer
.requests_to_confirm()
.map(|reqs| match reqs {
Ok(ref reqs) if reqs.is_empty() => Ok("No transactions in signing queue".to_owned()),
Ok(ref reqs) => Ok(format!(
"Transaction queue:\n{}",
reqs.iter()
.map(|r| format!("{}", r))
.collect::<Vec<String>>()
.join("\n")
)),
Err(err) => Err(format!("error: {:?}", err)),
})
.map_err(|err| format!("{:?}", err))
.wait()?
signer.requests_to_confirm().map(|reqs| {
match reqs {
Ok(ref reqs) if reqs.is_empty() => {
Ok("No transactions in signing queue".to_owned())
}
Ok(ref reqs) => {
Ok(format!("Transaction queue:\n{}", reqs
.iter()
.map(|r| format!("{}", r))
.collect::<Vec<String>>()
.join("\n")))
}
Err(err) => {
Err(format!("error: {:?}", err))
}
}
}).map_err(|err| {
format!("{:?}", err)
}).wait()?
}
fn sign_transaction(signer: &mut SignerRpc, id: U256, password: &str) -> Result<String, String> {
signer
.confirm_request(id, None, None, None, password)
.map(|res| match res {
Ok(u) => Ok(format!("Signed transaction id: {:#x}", u)),
Err(e) => Err(format!("{:?}", e)),
})
.map_err(|err| format!("{:?}", err))
.wait()?
fn sign_transaction(
signer: &mut SignerRpc, id: U256, password: &str
) -> Result<String, String> {
signer.confirm_request(id, None, None, None, password).map(|res| {
match res {
Ok(u) => Ok(format!("Signed transaction id: {:#x}", u)),
Err(e) => Err(format!("{:?}", e)),
}
}).map_err(|err| {
format!("{:?}", err)
}).wait()?
}
fn reject_transaction(signer: &mut SignerRpc, id: U256) -> Result<String, String> {
signer
.reject_request(id)
.map(|res| match res {
Ok(true) => Ok(format!("Rejected transaction id {:#x}", id)),
Ok(false) => Err(format!("No such request")),
Err(e) => Err(format!("{:?}", e)),
})
.map_err(|err| format!("{:?}", err))
.wait()?
fn reject_transaction(
signer: &mut SignerRpc, id: U256) -> Result<String, String>
{
signer.reject_request(id).map(|res| {
match res {
Ok(true) => Ok(format!("Rejected transaction id {:#x}", id)),
Ok(false) => Err(format!("No such request")),
Err(e) => Err(format!("{:?}", e)),
}
}).map_err(|err| {
format!("{:?}", err)
}).wait()?
}
// cmds
pub fn signer_list(signerport: u16, authfile: PathBuf) -> Result<String, String> {
let addr = &format!("ws://127.0.0.1:{}", signerport);
let mut signer = SignerRpc::new(addr, &authfile).map_err(|err| format!("{:?}", err))?;
list_transactions(&mut signer)
pub fn signer_list(
signerport: u16, authfile: PathBuf
) -> Result<String, String> {
let addr = &format!("ws://127.0.0.1:{}", signerport);
let mut signer = SignerRpc::new(addr, &authfile).map_err(|err| {
format!("{:?}", err)
})?;
list_transactions(&mut signer)
}
pub fn signer_reject(
id: Option<usize>,
signerport: u16,
authfile: PathBuf,
id: Option<usize>, signerport: u16, authfile: PathBuf
) -> Result<String, String> {
let id = id.ok_or(format!("id required for signer reject"))?;
let addr = &format!("ws://127.0.0.1:{}", signerport);
let mut signer = SignerRpc::new(addr, &authfile).map_err(|err| format!("{:?}", err))?;
reject_transaction(&mut signer, U256::from(id))
let id = id.ok_or(format!("id required for signer reject"))?;
let addr = &format!("ws://127.0.0.1:{}", signerport);
let mut signer = SignerRpc::new(addr, &authfile).map_err(|err| {
format!("{:?}", err)
})?;
reject_transaction(&mut signer, U256::from(id))
}
pub fn signer_sign(
id: Option<usize>,
pwfile: Option<PathBuf>,
signerport: u16,
authfile: PathBuf,
id: Option<usize>,
pwfile: Option<PathBuf>,
signerport: u16,
authfile: PathBuf
) -> Result<String, String> {
let password;
match pwfile {
Some(pwfile) => match File::open(pwfile) {
Ok(fd) => match BufReader::new(fd).lines().next() {
Some(Ok(line)) => password = line,
_ => return Err(format!("No password in file")),
},
Err(e) => return Err(format!("Could not open password file: {}", e)),
},
None => {
password = match rpassword::prompt_password_stdout("Password: ") {
Ok(p) => p,
Err(e) => return Err(format!("{}", e)),
}
}
}
let password;
match pwfile {
Some(pwfile) => {
match File::open(pwfile) {
Ok(fd) => {
match BufReader::new(fd).lines().next() {
Some(Ok(line)) => password = line,
_ => return Err(format!("No password in file"))
}
},
Err(e) =>
return Err(format!("Could not open password file: {}", e))
}
}
None => {
password = match rpassword::prompt_password_stdout("Password: ") {
Ok(p) => p,
Err(e) => return Err(format!("{}", e)),
}
}
}
let addr = &format!("ws://127.0.0.1:{}", signerport);
let mut signer = SignerRpc::new(addr, &authfile).map_err(|err| format!("{:?}", err))?;
let addr = &format!("ws://127.0.0.1:{}", signerport);
let mut signer = SignerRpc::new(addr, &authfile).map_err(|err| {
format!("{:?}", err)
})?;
match id {
Some(id) => sign_transaction(&mut signer, U256::from(id), &password),
None => sign_transactions(&mut signer, password),
}
match id {
Some(id) => {
sign_transaction(&mut signer, U256::from(id), &password)
},
None => {
sign_transactions(&mut signer, password)
}
}
}

View File

@@ -27,7 +27,7 @@ Parity 1.4.10 is a first stable release of 1.4.x series. It includes a few minor
- Gas_limit for blocks, mined by Parity will be divisible by 37 (#4154) [#4179](https://github.com/paritytech/parity/pull/4179)
- gas_limit for new blocks will divide evenly by 13
- increased GAS_LIMIT_DETERMINANT to 37
- increased PARITY_GAS_LIMIT_DETERMINANT to 37
- separate method for marking mined block
- debug_asserts(gas_limit within protocol range)
- round_block_gas_limit method is now static

View File

@@ -421,7 +421,7 @@ Full changes:
- Prevent duplicate incoming connections ([#4180](https://github.com/paritytech/parity/pull/4180))
- Gas_limit for blocks, mined by Parity will be divisible by 37 ([#4154](https://github.com/paritytech/parity/pull/4154)) [#4176](https://github.com/paritytech/parity/pull/4176)
- gas_limit for new blocks will divide evenly by 13
- increased GAS_LIMIT_DETERMINANT to 37
- increased PARITY_GAS_LIMIT_DETERMINANT to 37
- separate method for marking mined block
- debug_asserts(gas_limit within protocol range)
- round_block_gas_limit method is now static

View File

@@ -1,11 +1,11 @@
## Parity-Ethereum [v2.5.13](https://github.com/openethereum/openethereum/releases/tag/v2.5.13)
## 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/openethereum/openethereum/releases/tag/v2.5.12)
## 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
@@ -22,7 +22,7 @@ The full list of included changes:
* Disallow EIP-86 style null signatures for transactions outside tests (#11335)
## Parity-Ethereum [v2.5.11](https://github.com/openethereum/openethereum/releases/tag/v2.5.11)
## 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
@@ -31,7 +31,7 @@ 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/openethereum/openethereum/releases/tag/2.5.10)
## 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
@@ -79,7 +79,7 @@ The full list of included changes:
* Upgrade to jsonrpc v14 (#11151)
* SecretStore: expose restore_key_public in HTTP API (#10241)
## Parity-Ethereum [v2.5.9](https://github.com/openethereum/openethereum/releases/tag/v2.5.9)
## 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.
@@ -88,7 +88,7 @@ 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/openethereum/openethereum/releases/tag/v2.5.8)
## 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.
@@ -119,11 +119,11 @@ The full list of included changes:
* 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/openethereum/openethereum/releases/tag/v2.5.7)
## 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/openethereum/openethereum/releases/tag/v2.5.6)
## 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.
@@ -143,7 +143,7 @@ The full list of included changes:
* 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/openethereum/openethereum/releases/tag/v2.5.5)
## 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.
@@ -151,15 +151,15 @@ 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/openethereum/openethereum/releases/tag/v2.5.4)
## 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/openethereum/openethereum/pull/10822))
* cargo update -p smallvec ([#10822](https://github.com/paritytech/parity-ethereum/pull/10822))
## Parity-Ethereum [v2.5.3](https://github.com/openethereum/openethereum/releases/tag/v2.5.3)
## 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.
@@ -171,14 +171,14 @@ Parity-Ethereum 2.5.3-beta is a bugfix release that improves performance and sta
The full list of included changes:
* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/openethereum/openethereum/pull/10766))
* fix docker tags for publishing ([#10741](https://github.com/openethereum/openethereum/pull/10741))
* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/openethereum/openethereum/pull/10720))
* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/openethereum/openethereum/pull/10775))
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/openethereum/openethereum/pull/10705))
* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/openethereum/openethereum/pull/10744))
* 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/openethereum/openethereum/releases/tag/v2.5.2)
## 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.
@@ -186,15 +186,15 @@ Among others, it enables the _Atlantis_ hardfork on **Morden** and **Kotti** Cla
The full list of included changes:
* [CI] allow cargo audit to fail ([#10676](https://github.com/openethereum/openethereum/pull/10676))
* Reset blockchain properly ([#10669](https://github.com/openethereum/openethereum/pull/10669))
* new image ([#10673](https://github.com/openethereum/openethereum/pull/10673))
* Update publishing ([#10644](https://github.com/openethereum/openethereum/pull/10644))
* enable lto for release builds ([#10717](https://github.com/openethereum/openethereum/pull/10717))
* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/openethereum/openethereum/pull/10719))
* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/openethereum/openethereum/pull/10731))
* [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/openethereum/openethereum/releases/tag/v2.5.1)
## 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.
@@ -202,19 +202,19 @@ Among others, it enables the Petersburg hardfork on **Rinkeby** and **POA-Core**
The full list of included changes:
* ci: publish docs debug ([#10638](https://github.com/openethereum/openethereum/pull/10638))
* ci: publish docs debug ([#10638](https://github.com/paritytech/parity-ethereum/pull/10638))
## Parity-Ethereum [v2.5.0](https://github.com/openethereum/openethereum/releases/tag/v2.5.0)
## 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/openethereum/openethereum/pull/9981))
- 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/openethereum/openethereum/pull/10531))
- 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/openethereum/openethereum/pull/10559))
* fix(light cull): poll light cull instead of timer ([#10559](https://github.com/paritytech/parity-ethereum/pull/10559))

View File

@@ -1,11 +1,11 @@
## Parity-Ethereum [v2.6.8](https://github.com/openethereum/openethereum/releases/tag/v2.6.8)
## 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/openethereum/openethereum/releases/tag/v2.6.7)
## 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
@@ -22,7 +22,7 @@ The full list of included changes:
* 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/openethereum/openethereum/releases/tag/v2.6.6)
## 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
@@ -31,7 +31,7 @@ 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/openethereum/openethereum/releases/tag/v2.6.5)
## 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.
@@ -76,7 +76,7 @@ The full list of included changes:
* Filter out some bad ropsten warp snapshots (#11247)
* Allow default block parameter to be blockHash (#10932)
## Parity-Ethereum [v2.6.4](https://github.com/openethereum/openethereum/releases/tag/v2.6.4)
## 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.
@@ -87,7 +87,7 @@ A full list of included changes:
* [json-spec] make blake2 pricing spec more readable (#11034)
* Update JSON tests to d4f86ecf4aa7c (#11054)
## Parity-Ethereum [v2.6.3](https://github.com/openethereum/openethereum/releases/tag/v2.6.3)
## 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.
@@ -116,11 +116,11 @@ The full list of included changes:
* 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/openethereum/openethereum/releases/tag/v2.6.2)
## 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/openethereum/openethereum/releases/tag/v2.6.1)
## 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.
@@ -141,7 +141,7 @@ The full list of included changes:
* 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/openethereum/openethereum/releases/tag/v2.6.0)
## 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.
@@ -158,131 +158,131 @@ This release includes:
encouraged to upgrade.
The full list of included changes:
* update jsonrpc to 12.0 ([#10841](https://github.com/openethereum/openethereum/pull/10841))
* Move more code into state-account ([#10840](https://github.com/openethereum/openethereum/pull/10840))
* Extract AccountDB to account-db ([#10839](https://github.com/openethereum/openethereum/pull/10839))
* Extricate PodAccount and state Account to own crates ([#10838](https://github.com/openethereum/openethereum/pull/10838))
* Fix fork choice ([#10837](https://github.com/openethereum/openethereum/pull/10837))
* tests: Relates to #10655: Test instructions for Readme ([#10835](https://github.com/openethereum/openethereum/pull/10835))
* idiomatic changes to PodState ([#10834](https://github.com/openethereum/openethereum/pull/10834))
* Break circular dependency between Client and Engine (part 1) ([#10833](https://github.com/openethereum/openethereum/pull/10833))
* Remove excessive warning ([#10831](https://github.com/openethereum/openethereum/pull/10831))
* Allow --nat extip:your.host.here.org ([#10830](https://github.com/openethereum/openethereum/pull/10830))
* ethcore does not use byteorder ([#10829](https://github.com/openethereum/openethereum/pull/10829))
* Fix typo in README.md ([#10828](https://github.com/openethereum/openethereum/pull/10828))
* Update wordlist to v1.3 ([#10823](https://github.com/openethereum/openethereum/pull/10823))
* bump `smallvec 0.6.10` to fix vulnerability ([#10822](https://github.com/openethereum/openethereum/pull/10822))
* removed additional_params method ([#10818](https://github.com/openethereum/openethereum/pull/10818))
* Improve logging when remote peer is unknown ([#10817](https://github.com/openethereum/openethereum/pull/10817))
* replace memzero with zeroize crate ([#10816](https://github.com/openethereum/openethereum/pull/10816))
* When updating the client or when called from RPC, sleep should mean sleep ([#10814](https://github.com/openethereum/openethereum/pull/10814))
* Don't reimplement the logic from the Default impl ([#10813](https://github.com/openethereum/openethereum/pull/10813))
* refactor: whisper: Add type aliases and update rustdocs in message.rs ([#10812](https://github.com/openethereum/openethereum/pull/10812))
* test: whisper/cli `add invalid pool size test depending on processor` ([#10811](https://github.com/openethereum/openethereum/pull/10811))
* Add Constantinople EIPs to the dev (instant_seal) config ([#10809](https://github.com/openethereum/openethereum/pull/10809))
* fix spurious test failure ([#10808](https://github.com/openethereum/openethereum/pull/10808))
* revert temp changes to .gitlab-ci.yml ([#10807](https://github.com/openethereum/openethereum/pull/10807))
* removed redundant fmt::Display implementations ([#10806](https://github.com/openethereum/openethereum/pull/10806))
* removed EthEngine alias ([#10805](https://github.com/openethereum/openethereum/pull/10805))
* ethcore-bloom-journal updated to 2018 ([#10804](https://github.com/openethereum/openethereum/pull/10804))
* Fix a few typos and unused warnings. ([#10803](https://github.com/openethereum/openethereum/pull/10803))
* updated price-info to edition 2018 ([#10801](https://github.com/openethereum/openethereum/pull/10801))
* updated parity-local-store to edition 2018 ([#10800](https://github.com/openethereum/openethereum/pull/10800))
* updated project to ansi_term 0.11 ([#10799](https://github.com/openethereum/openethereum/pull/10799))
* ethcore-light uses bincode 1.1 ([#10798](https://github.com/openethereum/openethereum/pull/10798))
* ethcore-network-devp2p uses igd 0.9 ([#10797](https://github.com/openethereum/openethereum/pull/10797))
* Better logging when backfilling ancient blocks fail ([#10796](https://github.com/openethereum/openethereum/pull/10796))
* added new ropsten-bootnode and removed old one ([#10794](https://github.com/openethereum/openethereum/pull/10794))
* Removed machine abstraction from ethcore ([#10791](https://github.com/openethereum/openethereum/pull/10791))
* Removed redundant ethcore-service error type ([#10788](https://github.com/openethereum/openethereum/pull/10788))
* Cleanup unused vm dependencies ([#10787](https://github.com/openethereum/openethereum/pull/10787))
* ethkey no longer uses byteorder ([#10786](https://github.com/openethereum/openethereum/pull/10786))
* Updated blooms-db to rust 2018 and removed redundant deps ([#10785](https://github.com/openethereum/openethereum/pull/10785))
* Treat empty account the same as non-exist accounts in EIP-1052 ([#10775](https://github.com/openethereum/openethereum/pull/10775))
* Do not drop the peer with None difficulty ([#10772](https://github.com/openethereum/openethereum/pull/10772))
* EIP-1702: Generalized Account Versioning Scheme ([#10771](https://github.com/openethereum/openethereum/pull/10771))
* Move Engine::register_client to be before other I/O handler registration ([#10767](https://github.com/openethereum/openethereum/pull/10767))
* ethcore/res: activate atlantis classic hf on block 8772000 ([#10766](https://github.com/openethereum/openethereum/pull/10766))
* Updated Bn128PairingImpl to use optimized batch pairing ([#10765](https://github.com/openethereum/openethereum/pull/10765))
* Remove unused code ([#10762](https://github.com/openethereum/openethereum/pull/10762))
* Initialize private tx logger only if private tx functionality is enabled ([#10758](https://github.com/openethereum/openethereum/pull/10758))
* SecretStore: remove support of old database formats ([#10757](https://github.com/openethereum/openethereum/pull/10757))
* Enable aesni ([#10756](https://github.com/openethereum/openethereum/pull/10756))
* updater: fix static id hashes initialization ([#10755](https://github.com/openethereum/openethereum/pull/10755))
* Use fewer threads for snapshotting ([#10752](https://github.com/openethereum/openethereum/pull/10752))
* Die error_chain, die ([#10747](https://github.com/openethereum/openethereum/pull/10747))
* Fix deprectation warnings on nightly ([#10746](https://github.com/openethereum/openethereum/pull/10746))
* Improve logging and cleanup in miner around block sealing ([#10745](https://github.com/openethereum/openethereum/pull/10745))
* Add a way to signal shutdown to snapshotting threads ([#10744](https://github.com/openethereum/openethereum/pull/10744))
* fix docker tags for publishing ([#10741](https://github.com/openethereum/openethereum/pull/10741))
* refactor: Fix indentation in ethjson ([#10740](https://github.com/openethereum/openethereum/pull/10740))
* Log validator set changes in EpochManager ([#10734](https://github.com/openethereum/openethereum/pull/10734))
* Print warnings when using dangerous settings for ValidatorSet ([#10733](https://github.com/openethereum/openethereum/pull/10733))
* ethcore: enable ECIP-1054 for classic ([#10731](https://github.com/openethereum/openethereum/pull/10731))
* Stop breaking out of loop if a non-canonical hash is found ([#10729](https://github.com/openethereum/openethereum/pull/10729))
* Removed secret_store folder ([#10722](https://github.com/openethereum/openethereum/pull/10722))
* Revert "enable lto for release builds (#10717)" ([#10721](https://github.com/openethereum/openethereum/pull/10721))
* fix: aura don't add `SystemTime::now()` ([#10720](https://github.com/openethereum/openethereum/pull/10720))
* Use RUSTFLAGS to set the optimization level ([#10719](https://github.com/openethereum/openethereum/pull/10719))
* enable lto for release builds ([#10717](https://github.com/openethereum/openethereum/pull/10717))
* [devp2p] Update to 2018 edition ([#10716](https://github.com/openethereum/openethereum/pull/10716))
* [devp2p] Don't use `rust-crypto` ([#10714](https://github.com/openethereum/openethereum/pull/10714))
* [devp2p] Fix warnings and re-org imports ([#10710](https://github.com/openethereum/openethereum/pull/10710))
* DevP2p: Get node IP address and udp port from Socket, if not included in PING packet ([#10705](https://github.com/openethereum/openethereum/pull/10705))
* introduce MissingParent Error, fixes #10699 ([#10700](https://github.com/openethereum/openethereum/pull/10700))
* Refactor Clique stepping ([#10691](https://github.com/openethereum/openethereum/pull/10691))
* add_sync_notifier in EthPubSubClient holds on to a Client for too long ([#10689](https://github.com/openethereum/openethereum/pull/10689))
* Fix compiler warning (that will become an error) ([#10683](https://github.com/openethereum/openethereum/pull/10683))
* Don't panic if extra_data is longer than VANITY_LENGTH ([#10682](https://github.com/openethereum/openethereum/pull/10682))
* Remove annoying compiler warnings ([#10679](https://github.com/openethereum/openethereum/pull/10679))
* Remove support for hardware wallets ([#10678](https://github.com/openethereum/openethereum/pull/10678))
* [CI] allow cargo audit to fail ([#10676](https://github.com/openethereum/openethereum/pull/10676))
* new image ([#10673](https://github.com/openethereum/openethereum/pull/10673))
* Upgrade ethereum types ([#10670](https://github.com/openethereum/openethereum/pull/10670))
* Reset blockchain properly ([#10669](https://github.com/openethereum/openethereum/pull/10669))
* fix: Move PR template into .github/ folder ([#10663](https://github.com/openethereum/openethereum/pull/10663))
* docs: evmbin - Update Rust docs ([#10658](https://github.com/openethereum/openethereum/pull/10658))
* refactor: Related #9459 - evmbin: replace untyped json! macro with fully typed serde serialization using Rust structs ([#10657](https://github.com/openethereum/openethereum/pull/10657))
* docs: Add PR template ([#10654](https://github.com/openethereum/openethereum/pull/10654))
* docs: Add ProgPoW Rust docs to ethash module ([#10653](https://github.com/openethereum/openethereum/pull/10653))
* docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions ([#10652](https://github.com/openethereum/openethereum/pull/10652))
* Upgrade to parity-crypto 0.4 ([#10650](https://github.com/openethereum/openethereum/pull/10650))
* fix(compilation warnings) ([#10649](https://github.com/openethereum/openethereum/pull/10649))
* [whisper] Move needed aes_gcm crypto in-crate ([#10647](https://github.com/openethereum/openethereum/pull/10647))
* Update publishing ([#10644](https://github.com/openethereum/openethereum/pull/10644))
* ci: publish docs debug ([#10638](https://github.com/openethereum/openethereum/pull/10638))
* Fix publish docs ([#10635](https://github.com/openethereum/openethereum/pull/10635))
* Fix rinkeby petersburg fork ([#10632](https://github.com/openethereum/openethereum/pull/10632))
* Update kovan.json to switch Kovan validator set to POA Consensus Contracts ([#10628](https://github.com/openethereum/openethereum/pull/10628))
* [ethcore] remove error_chain ([#10616](https://github.com/openethereum/openethereum/pull/10616))
* Remove unused import ([#10615](https://github.com/openethereum/openethereum/pull/10615))
* Adds parity_getRawBlockByNumber, parity_submitRawBlock ([#10609](https://github.com/openethereum/openethereum/pull/10609))
* adds rpc error message for --no-ancient-blocks ([#10608](https://github.com/openethereum/openethereum/pull/10608))
* Constantinople HF on POA Core ([#10606](https://github.com/openethereum/openethereum/pull/10606))
* Clique: zero-fill extradata when the supplied value is less than 32 bytes in length ([#10605](https://github.com/openethereum/openethereum/pull/10605))
* evm: add some mulmod benches ([#10600](https://github.com/openethereum/openethereum/pull/10600))
* sccache logs to stdout ([#10596](https://github.com/openethereum/openethereum/pull/10596))
* update bootnodes ([#10595](https://github.com/openethereum/openethereum/pull/10595))
* Merge `Notifier` and `TransactionsPoolNotifier` ([#10591](https://github.com/openethereum/openethereum/pull/10591))
* fix(whisper): change expiry `unix_time + ttl + work` ([#10587](https://github.com/openethereum/openethereum/pull/10587))
* fix(evmbin): make benches compile again ([#10586](https://github.com/openethereum/openethereum/pull/10586))
* fix issue with compilation when 'slow-blocks' feature enabled ([#10585](https://github.com/openethereum/openethereum/pull/10585))
* Allow CORS requests in Secret Store API ([#10584](https://github.com/openethereum/openethereum/pull/10584))
* CI improvements ([#10579](https://github.com/openethereum/openethereum/pull/10579))
* ethcore: improve timestamp handling ([#10574](https://github.com/openethereum/openethereum/pull/10574))
* Update Issue Template to direct security issue to email ([#10562](https://github.com/openethereum/openethereum/pull/10562))
* version: bump master to 2.6 ([#10560](https://github.com/openethereum/openethereum/pull/10560))
* fix(light cull): poll light cull instead of timer ([#10559](https://github.com/openethereum/openethereum/pull/10559))
* Watch transactions pool ([#10558](https://github.com/openethereum/openethereum/pull/10558))
* Add SealingState; don't prepare block when not ready. ([#10529](https://github.com/openethereum/openethereum/pull/10529))
* Explicitly enable or disable Stratum in config file (Issue 9785) ([#10521](https://github.com/openethereum/openethereum/pull/10521))
* Add filtering capability to `parity_pendingTransactions` (issue 8269) ([#10506](https://github.com/openethereum/openethereum/pull/10506))
* Remove calls to heapsize ([#10432](https://github.com/openethereum/openethereum/pull/10432))
* RPC: Implements eth_subscribe("syncing") ([#10311](https://github.com/openethereum/openethereum/pull/10311))
* SecretStore: non-blocking wait of session completion ([#10303](https://github.com/openethereum/openethereum/pull/10303))
* Node table limiting and cache for node filter ([#10288](https://github.com/openethereum/openethereum/pull/10288))
* SecretStore: expose restore_key_public in HTTP API ([#10241](https://github.com/openethereum/openethereum/pull/10241))
* Trivial journal for private transactions ([#10056](https://github.com/openethereum/openethereum/pull/10056))
* 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

View File

@@ -1,383 +0,0 @@
## Parity-Ethereum [v2.7.2](https://github.com/openethereum/openethereum/releases/tag/v2.7.2)
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:
* [eth classic chainspec]: remove balance = 1 (#11458)
* 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/openethereum/openethereum/releases/tag/v2.7.1)
* Revert #11311 (#11427)
## Parity-Ethereum [v2.7.0](https://github.com/openethereum/openethereum/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):
* 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)
* [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)
* 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)
* Insert explicit warning into the panic hook (#11225)
* Snapshot restoration overhaul (#11219)
* Fix docker centos build (#11226)
* retry on gitlab system failures (#11222)
* Update bootnodes. (#11203)
* Use provided usd-per-eth value if an endpoint is specified (#11209)
* 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)
* [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)
* 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)
* [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)
* 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)
* [trace] check mem diff within range (#11002)
* EIP-1344 Add CHAINID op-code (#10983)
* Make ClientIoMessage generic over the Client (#10981)
* bump spin to 0.5.2 (#10996)
* fix compile warnings (#10993)
* Fix compilation on recent nightlies (#10991)
* [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)
* 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)
* 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)
* 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)

View File

@@ -1,122 +0,0 @@
## OpenEthereum [v3.0.1](https://github.com/openethereum/openethereum/releases/tag/v3.0.1)
- Add missing forks to fork ID (#11747)
## OpenEthereum [v3.0.0](https://github.com/openethereum/openethereum/releases/tag/v3.0.0)
OpenEthereum v3.0.0 is the first release of OpenEthereum client as part of OpenEthereum project, divested from Parity Technologies.
This release marks the transition from Parity Technologies infrastructure and bootnodes to the one managed by OpenEthereum project.
Parity-Ethereum v2.7 users can continue using their existing data folders. Command-line interface has also stayed identical.
Unless specified otherwise, OpenEthereum v3.0.0 will detect if the user's database in the old Parity-Ethereum default path,
and only if it's not found will write to the new default location.
This release includes several major improvements to network and database stack:
- Support for `eth/64` protocol and Node Discovery v4 `Ethereum Node Records` extension.
- Accounts bloom is removed which should decrease the database size.
**Due to database changes this is a one-way upgrade. Please back up your database if you plan to continue using Parity-Ethereum v2.7.2.**
Note that this release drops support for IPFS and `eth/62` protocol. Additionally, it marks light client, private transactions and updater as deprecated features which may be removed in a future release.
The full list of included changes:
- Add deprecation warnings (#11682)
- Add Curl to Docker image (#11687)
- v3 release version strings and track stable (#11680)
- Fix sccache server errors (#11675)
- Don't delete old db after migration (#11662)
- rename inject to drain_transaction_overlay (#11657)
- Drain the transaction overlay (#11654)
- vergen library seems to depend not only on the .git folder content but also on the git binary (#11651)
- New default paths (#11641)
- Update EWF's chains with Istanbul transition block numbers (#11482)
- add openethereum supplementary bootnodes, those are not active right now, but will be in case the network needs more power (#11650)
- Remove Parity bootnodes (#11644)
- Remove accounts bloom (#11589)
- Deploy docker images on master (#11640)
- Fix some compiler warnings (#11632)
- Add support for non-fork side of Phoenix (#11627)
- validate mainnet specs against all forks (#11625)
- Fix ecrecover builtin (#11623)
- Update .gitmodules (#11628)
- ethcore/res: activate ecip-1088 phoenix on classic (#11598)
- Upgrade parity-common deps to latest (#11620)
- Fix Goerli syncing (#11604)
- deps: switch to upstream ctrlc (#11617)
- Deduplicating crate dependencies (part 3 of n) (#11614)
- Deduplicating crate dependencies (part 2 of n, `slab`) (#11613)
- Actually save ENR on creation and modification (#11602)
- Activate POSDAO on xDai chain and update bootnodes (#11610)
- Activate on-chain randomness in POA Core (#11609)
- Deduplicating crate dependencies (part 1 of n) (#11606)
- Update enodes for POA Sokol (#11611)
- Remove .git folder from dogerignore file so vergen library can get build date and commit hash in the binary generatio vergen library can get build date and commit hash in the binary generation (#11608)
- Reduced gas cost for static calls made to precompiles EIP2046/1352 (#11583)
- `ethcore-bloom-journal` was renamed to `accounts-bloom` (#11605)
- Use serde_json to export hardcoded sync (#11601)
- Node Discovery v4 ENR Extension (EIP-868) (#11540)
- Fix compile warnings (#11595)
- Update version to 3.0.0-alpha.1 (#11592)
- ethcore/res: bump canon fork hash for mordor and kotti testnets (#11584)
- Update on push tags (#11590)
- Replace deprecated tempdir dependency with tempfile (#11588)
- Fix project name, links, rename the binaries (#11580)
- Update Cargo.lock (#11573)
- ci: workaround for the cache bug on Linux (#11568)
- Increase the default pruning parameters (#11558)
- Add Docker build and push to github actions (#11555)
- Update README (#11578)
- informant: display I/O stats (#11523)
- [devp2p discovery]: remove `deprecated_echo_hash` (#11564)
- [secretstore] create db_version file when database doesn't exist (#11570)
- Remove Parity's Security Policy (#11565)
- ethcore/res: enable ecip-1088 phoenix upgrade for kotti and mordor testnets (#11529)
- Misc docs and renames …and one less clone (#11556)
- [secretstore]: don't sign message with only zeroes (#11561)
- [devp2p discovery]: cleanup (#11547)
- Code cleanup in the sync module (#11552)
- initial cleanup (#11542)
- Warn if genesis constructor revert (#11550)
- ethcore: cleanup after #11531 (#11546)
- license update (#11543)
- Less cloning when importing blocks (#11531)
- Github Actions (#11528)
- Fix Alpine Dockerfile (#11538)
- Remove AuxiliaryData/AuxiliaryRequest (#11533)
- [journaldb]: cleanup (#11534)
- Remove references to parity-ethereum (#11525)
- Drop IPFS support (#11532)
- chain-supplier: fix warning reporting for GetNodeData request (#11530)
- Faster kill_garbage (#11514)
- [EngineSigner]: don't sign message with only zeroes (#11524)
- fix compilation warnings (#11522)
- [ethcore cleanup]: various unrelated fixes from `#11493` (#11507)
- Add benchmark for transaction execution (#11509)
- Add Smart Contract License v1.0
- Misc fixes (#11510)
- [dependencies]: unify `rustc-hex` (#11506)
- Activate on-chain randomness in POA Sokol (#11505)
- Grab bag of cleanup (#11504)
- Implement eth/64 (EIP-2364) and drop support for eth/62 (#11472)
- [dependencies]: remove `util/macros` (#11501)
- OpenEthereum bootnodes are added (#11499)
- [ci benches]: use `all-features` (#11496)
- [verification]: make test-build compile standalone (#11495)
- complete null-signatures removal (#11491)
- Include the seal when populating the header for a new block (#11475)
- fix compilation warnings (#11492)
- cargo update -p cmake (#11490)
- update to published rlp-derive (#11489)
- Switch usage of Secret Store to the external lib (#11487)
- Switch from the internal runtime lib to external one from crates.io (#11480)
- Update params.rs (#11474)
- weak_counts has been stabilized (#11476)
- sync: remove broken eth_protocol_version method (#11473)
- Use parity-crypto updated to use upstream rust-secp256k1 (#11406)
- Cleanup some code in Aura (#11466)
- upgrade some of the dependencies (#11467)
- Some more release track changes to README.md (#11465)
- Update simple one-line installer due to switching to a single stable release track (#11463)
- update Dockerfile (#11461)
- Implement EIP-2124 (#11456)
- [eth classic chainspec]: remove `balance = 1` (#11459)

View File

@@ -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"

View File

@@ -1,126 +1,152 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
#[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,
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;
use std::env;
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let light = builder.light(&env::temp_dir(), 486382);
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, 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_memmap", move |b| b.iter(|| light.compute(&HASH, NONCE, u64::max_value())));
}
fn bench_light_compute_memory(b: &mut Criterion) {
use std::env;
use std::env;
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let light = builder.light(&env::temp_dir(), 486382);
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;
use std::env;
b.bench_function("bench_light_compute_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());
})
});
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());
}));
}
fn bench_light_new_round_trip_memory(b: &mut Criterion) {
use std::env;
use std::env;
b.bench_function("bench_light_compute_memmap", 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());
})
});
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());
}));
}
fn bench_light_from_file_round_trip_memory(b: &mut Criterion) {
use std::env;
use std::env;
let dir = env::temp_dir();
let height = 486382;
{
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let mut dummy = builder.light(&dir, height);
dummy.to_file().unwrap();
}
let dir = env::temp_dir();
let height = 486382;
{
let builder = NodeCacheBuilder::new(OptimizeFor::Cpu, u64::max_value());
let mut dummy = builder.light(&dir, height);
dummy.to_file().unwrap();
}
b.bench_function("bench_light_compute_memmap", 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());
})
});
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());
}));
}
fn bench_light_from_file_round_trip_memmap(b: &mut Criterion) {
use std::env;
use std::env;
let dir = env::temp_dir();
let height = 486382;
let dir = env::temp_dir();
let height = 486382;
{
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let mut dummy = builder.light(&dir, height);
dummy.to_file().unwrap();
}
{
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let mut dummy = builder.light(&dir, height);
dummy.to_file().unwrap();
}
b.bench_function("bench_light_compute_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());
})
});
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[..]);
}));
}

View File

@@ -3,75 +3,86 @@ extern crate criterion;
extern crate ethash;
extern crate rustc_hex;
extern crate tempdir;
extern crate common_types;
use criterion::Criterion;
use ethash::progpow;
use ethash::{compute::light_compute, NodeCacheBuilder, OptimizeFor};
use rustc_hex::FromHex;
use tempdir::TempDir;
use rustc_hex::FromHex;
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());
let tempdir = TempDir::new("").unwrap();
let light = builder.light(&tempdir.path(), 1);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f")
.unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let light = builder.light(&tempdir.path(), 1);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
c.bench_function("hashimoto_light", move |b| {
b.iter(|| light_compute(&light, &hash, 0))
});
c.bench_function("hashimoto_light", move |b| {
b.iter(|| light_compute(&light, &hash, 0))
});
}
fn bench_progpow_light(c: &mut Criterion) {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f")
.unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
c.bench_function("progpow_light", move |b| {
b.iter(|| {
let c_dag = progpow::generate_cdag(cache.as_ref());
progpow::progpow(hash, 0, 0, cache.as_ref(), &c_dag);
})
});
c.bench_function("progpow_light", move |b| {
b.iter(|| {
let c_dag = progpow::generate_cdag(cache.as_ref());
progpow::progpow(
hash,
0,
0,
cache.as_ref(),
&c_dag,
);
})
});
}
fn bench_progpow_optimal_light(c: &mut Criterion) {
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let c_dag = progpow::generate_cdag(cache.as_ref());
let builder = NodeCacheBuilder::new(OptimizeFor::Memory, u64::max_value());
let tempdir = TempDir::new("").unwrap();
let cache = builder.new_cache(tempdir.into_path(), 0);
let c_dag = progpow::generate_cdag(cache.as_ref());
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f")
.unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
let h = FromHex::from_hex("c9149cc0386e689d789a1c2f3d5d169a61a6218ed30e74414dc736e442ef3d1f").unwrap();
let mut hash = [0; 32];
hash.copy_from_slice(&h);
c.bench_function("progpow_optimal_light", move |b| {
b.iter(|| {
progpow::progpow(hash, 0, 0, cache.as_ref(), &c_dag);
})
});
c.bench_function("progpow_optimal_light", move |b| {
b.iter(|| {
progpow::progpow(
hash,
0,
0,
cache.as_ref(),
&c_dag,
);
})
});
}
fn bench_keccak_f800_long(c: &mut Criterion) {
c.bench_function("keccak_f800_long(0, 0, 0)", |b| {
b.iter(|| progpow::keccak_f800_long([0; 32], 0, [0; 8]))
});
c.bench_function("keccak_f800_long(0, 0, 0)", |b| {
b.iter(|| progpow::keccak_f800_long([0; 32], 0, [0; 8]))
});
}
criterion_group!(
benches,
bench_hashimoto_light,
bench_progpow_light,
bench_progpow_optimal_light,
bench_keccak_f800_long,
criterion_group!(benches,
bench_hashimoto_light,
bench_progpow_light,
bench_progpow_optimal_light,
bench_keccak_f800_long,
);
criterion_main!(benches);

View File

@@ -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"
]
]

View File

@@ -1,313 +1,296 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// This file is part of Parity Ethereum.
// OpenEthereum is free software: you can redistribute it and/or modify
// 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.
// OpenEthereum is distributed in the hope that it will be useful,
// 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.
use compute::Light;
use either::Either;
use keccak::{keccak_512, H256};
use keccak::{H256, keccak_512};
use memmap::MmapMut;
use parking_lot::Mutex;
use seed_compute::SeedHashCompute;
use shared::{epoch, get_cache_size, to_hex, Node, ETHASH_CACHE_ROUNDS, NODE_BYTES, NODE_DWORDS};
use shared::{ETHASH_CACHE_ROUNDS, NODE_BYTES, Node, epoch, get_cache_size, to_hex};
use std::{
borrow::Cow,
fs,
io::{self, Read, Write},
path::{Path, PathBuf},
slice,
sync::Arc,
};
use std::borrow::Cow;
use std::fs;
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
use std::slice;
use std::sync::Arc;
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};
use self::Either::{Left, Right};
match *cache {
Left(ref vec) => vec.len() * NODE_BYTES,
Right(ref mmap) => mmap.len(),
}
match *cache {
Left(ref vec) => vec.len() * NODE_BYTES,
Right(ref mmap) => mmap.len(),
}
}
fn new_buffer(path: &Path, num_nodes: usize, ident: &H256, optimize_for: OptimizeFor) -> Cache {
let memmap = match optimize_for {
OptimizeFor::Cpu => None,
OptimizeFor::Memory => make_memmapped_cache(path, num_nodes, ident).ok(),
};
let memmap = match optimize_for {
OptimizeFor::Cpu => None,
OptimizeFor::Memory => make_memmapped_cache(path, num_nodes, ident).ok(),
};
memmap
.map(Either::Right)
.unwrap_or_else(|| Either::Left(make_memory_cache(num_nodes, ident)))
memmap.map(Either::Right).unwrap_or_else(|| {
Either::Left(make_memory_cache(num_nodes, ident))
})
}
#[derive(Clone)]
pub struct NodeCacheBuilder {
// TODO: Remove this locking and just use an `Rc`?
seedhash: Arc<Mutex<SeedHashCompute>>,
optimize_for: OptimizeFor,
progpow_transition: u64,
// TODO: Remove this locking and just use an `Rc`?
seedhash: Arc<Mutex<SeedHashCompute>>,
optimize_for: OptimizeFor,
progpow_transition: u64,
}
// TODO: Abstract the "optimize for" logic
pub struct NodeCache {
builder: NodeCacheBuilder,
cache_dir: Cow<'static, Path>,
cache_path: PathBuf,
epoch: u64,
cache: Cache,
builder: NodeCacheBuilder,
cache_dir: Cow<'static, Path>,
cache_path: PathBuf,
epoch: u64,
cache: Cache,
}
impl NodeCacheBuilder {
pub fn light(&self, cache_dir: &Path, block_number: u64) -> Light {
Light::new_with_builder(self, cache_dir, block_number, self.progpow_transition)
}
pub fn light(&self, cache_dir: &Path, block_number: u64) -> Light {
Light::new_with_builder(self, cache_dir, block_number, self.progpow_transition)
}
pub fn light_from_file(&self, cache_dir: &Path, block_number: u64) -> io::Result<Light> {
Light::from_file_with_builder(self, cache_dir, block_number, self.progpow_transition)
}
pub fn light_from_file(&self, cache_dir: &Path, block_number: u64) -> io::Result<Light> {
Light::from_file_with_builder(self, cache_dir, block_number, self.progpow_transition)
}
pub fn new<T: Into<Option<OptimizeFor>>>(optimize_for: T, progpow_transition: u64) -> Self {
NodeCacheBuilder {
seedhash: Arc::new(Mutex::new(SeedHashCompute::default())),
optimize_for: optimize_for.into().unwrap_or_default(),
progpow_transition,
}
}
pub fn new<T: Into<Option<OptimizeFor>>>(optimize_for: T, progpow_transition: u64) -> Self {
NodeCacheBuilder {
seedhash: Arc::new(Mutex::new(SeedHashCompute::default())),
optimize_for: optimize_for.into().unwrap_or_default(),
progpow_transition
}
}
fn block_number_to_ident(&self, block_number: u64) -> H256 {
self.seedhash.lock().hash_block_number(block_number)
}
fn block_number_to_ident(&self, block_number: u64) -> H256 {
self.seedhash.lock().hash_block_number(block_number)
}
fn epoch_to_ident(&self, epoch: u64) -> H256 {
self.seedhash.lock().hash_epoch(epoch)
}
fn epoch_to_ident(&self, epoch: u64) -> H256 {
self.seedhash.lock().hash_epoch(epoch)
}
pub fn from_file<P: Into<Cow<'static, Path>>>(
&self,
cache_dir: P,
block_number: u64,
) -> io::Result<NodeCache> {
let cache_dir = cache_dir.into();
let ident = self.block_number_to_ident(block_number);
pub fn from_file<P: Into<Cow<'static, Path>>>(
&self,
cache_dir: P,
block_number: u64,
) -> io::Result<NodeCache> {
let cache_dir = cache_dir.into();
let ident = self.block_number_to_ident(block_number);
let path = cache_path(cache_dir.as_ref(), &ident);
let path = cache_path(cache_dir.as_ref(), &ident);
let cache = cache_from_path(&path, self.optimize_for)?;
let expected_cache_size = get_cache_size(block_number);
let cache = cache_from_path(&path, self.optimize_for)?;
let expected_cache_size = get_cache_size(block_number);
if byte_size(&cache) == expected_cache_size {
Ok(NodeCache {
builder: self.clone(),
epoch: epoch(block_number),
cache_dir: cache_dir,
cache_path: path,
cache: cache,
})
} else {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"Node cache is of incorrect size",
))
}
}
if byte_size(&cache) == expected_cache_size {
Ok(NodeCache {
builder: self.clone(),
epoch: epoch(block_number),
cache_dir: cache_dir,
cache_path: path,
cache: cache,
})
} else {
Err(io::Error::new(
io::ErrorKind::InvalidData,
"Node cache is of incorrect size",
))
}
}
pub fn new_cache<P: Into<Cow<'static, Path>>>(
&self,
cache_dir: P,
block_number: u64,
) -> NodeCache {
let cache_dir = cache_dir.into();
let ident = self.block_number_to_ident(block_number);
pub fn new_cache<P: Into<Cow<'static, Path>>>(
&self,
cache_dir: P,
block_number: u64,
) -> NodeCache {
let cache_dir = cache_dir.into();
let ident = self.block_number_to_ident(block_number);
let cache_size = get_cache_size(block_number);
let cache_size = get_cache_size(block_number);
// We use `debug_assert` since it is impossible for `get_cache_size` to return an unaligned
// value with the current implementation. If the implementation changes, CI will catch it.
debug_assert!(cache_size % NODE_BYTES == 0, "Unaligned cache size");
let num_nodes = cache_size / NODE_BYTES;
// We use `debug_assert` since it is impossible for `get_cache_size` to return an unaligned
// value with the current implementation. If the implementation changes, CI will catch it.
debug_assert!(cache_size % NODE_BYTES == 0, "Unaligned cache size");
let num_nodes = cache_size / NODE_BYTES;
let path = cache_path(cache_dir.as_ref(), &ident);
let nodes = new_buffer(&path, num_nodes, &ident, self.optimize_for);
let path = cache_path(cache_dir.as_ref(), &ident);
let nodes = new_buffer(&path, num_nodes, &ident, self.optimize_for);
NodeCache {
builder: self.clone(),
epoch: epoch(block_number),
cache_dir: cache_dir.into(),
cache_path: path,
cache: nodes,
}
}
NodeCache {
builder: self.clone(),
epoch: epoch(block_number),
cache_dir: cache_dir.into(),
cache_path: path,
cache: nodes,
}
}
}
impl NodeCache {
pub fn cache_path(&self) -> &Path {
&self.cache_path
}
pub fn cache_path(&self) -> &Path {
&self.cache_path
}
pub fn flush(&mut self) -> io::Result<()> {
if let Some(last) = self
.epoch
.checked_sub(2)
.map(|ep| cache_path(self.cache_dir.as_ref(), &self.builder.epoch_to_ident(ep)))
{
fs::remove_file(last).unwrap_or_else(|error| match error.kind() {
io::ErrorKind::NotFound => (),
_ => warn!("Error removing stale DAG cache: {:?}", error),
});
}
pub fn flush(&mut self) -> io::Result<()> {
if let Some(last) = self.epoch.checked_sub(2).map(|ep| {
cache_path(self.cache_dir.as_ref(), &self.builder.epoch_to_ident(ep))
})
{
fs::remove_file(last).unwrap_or_else(|error| match error.kind() {
io::ErrorKind::NotFound => (),
_ => warn!("Error removing stale DAG cache: {:?}", error),
});
}
consume_cache(&mut self.cache, &self.cache_path)
}
consume_cache(&mut self.cache, &self.cache_path)
}
}
fn make_memmapped_cache(path: &Path, num_nodes: usize, ident: &H256) -> io::Result<MmapMut> {
use std::fs::OpenOptions;
use std::fs::OpenOptions;
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)?;
file.set_len((num_nodes * NODE_BYTES) as _)?;
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)?;
file.set_len((num_nodes * NODE_BYTES) as _)?;
let mut memmap = unsafe { MmapMut::map_mut(&file)? };
let mut memmap = unsafe { MmapMut::map_mut(&file)? };
unsafe { initialize_memory(memmap.as_mut_ptr() as *mut Node, num_nodes, ident) };
unsafe { initialize_memory(memmap.as_mut_ptr() as *mut Node, num_nodes, ident) };
Ok(memmap)
Ok(memmap)
}
fn make_memory_cache(num_nodes: usize, ident: &H256) -> Vec<Node> {
let mut nodes: Vec<Node> = Vec::with_capacity(num_nodes);
// Use uninit instead of unnecessarily writing `size_of::<Node>() * num_nodes` 0s
unsafe {
initialize_memory(nodes.as_mut_ptr(), num_nodes, ident);
nodes.set_len(num_nodes);
}
let mut nodes: Vec<Node> = Vec::with_capacity(num_nodes);
// Use uninit instead of unnecessarily writing `size_of::<Node>() * num_nodes` 0s
unsafe {
initialize_memory(nodes.as_mut_ptr(), num_nodes, ident);
nodes.set_len(num_nodes);
}
nodes
nodes
}
fn cache_path<'a, P: Into<Cow<'a, Path>>>(path: P, ident: &H256) -> PathBuf {
let mut buf = path.into().into_owned();
buf.push(to_hex(ident));
buf
let mut buf = path.into().into_owned();
buf.push(to_hex(ident));
buf
}
fn consume_cache(cache: &mut Cache, path: &Path) -> io::Result<()> {
use std::fs::OpenOptions;
use std::fs::OpenOptions;
match *cache {
Either::Left(ref mut vec) => {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)?;
match *cache {
Either::Left(ref mut vec) => {
let mut file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&path)?;
let buf = unsafe {
slice::from_raw_parts_mut(vec.as_mut_ptr() as *mut u8, vec.len() * NODE_BYTES)
};
let buf = unsafe {
slice::from_raw_parts_mut(vec.as_mut_ptr() as *mut u8, vec.len() * NODE_BYTES)
};
file.write_all(buf).map(|_| ())
}
Either::Right(ref mmap) => mmap.flush(),
}
file.write_all(buf).map(|_| ())
}
Either::Right(ref mmap) => {
mmap.flush()
}
}
}
fn cache_from_path(path: &Path, optimize_for: OptimizeFor) -> io::Result<Cache> {
let memmap = match optimize_for {
OptimizeFor::Cpu => None,
OptimizeFor::Memory => {
let file = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(path)?;
unsafe { MmapMut::map_mut(&file).ok() }
}
};
let memmap = match optimize_for {
OptimizeFor::Cpu => None,
OptimizeFor::Memory => {
let file = fs::OpenOptions::new().read(true).write(true).create(true).open(path)?;
unsafe { MmapMut::map_mut(&file).ok() }
},
};
memmap
.map(Either::Right)
.ok_or(())
.or_else(|_| read_from_path(path).map(Either::Left))
memmap.map(Either::Right).ok_or(()).or_else(|_| {
read_from_path(path).map(Either::Left)
})
}
fn read_from_path(path: &Path) -> io::Result<Vec<Node>> {
use std::{fs::File, mem};
use std::fs::File;
use std::mem;
let mut file = File::open(path)?;
let mut file = File::open(path)?;
let mut nodes: Vec<u8> = Vec::with_capacity(
file.metadata()
.map(|m| m.len() as _)
.unwrap_or(NODE_BYTES * 1_000_000),
);
file.read_to_end(&mut nodes)?;
let mut nodes: Vec<u8> = Vec::with_capacity(file.metadata().map(|m| m.len() as _).unwrap_or(
NODE_BYTES * 1_000_000,
));
file.read_to_end(&mut nodes)?;
nodes.shrink_to_fit();
nodes.shrink_to_fit();
if nodes.len() % NODE_BYTES != 0 || nodes.capacity() % NODE_BYTES != 0 {
return Err(io::Error::new(
io::ErrorKind::Other,
"Node cache is not a multiple of node size",
));
}
if nodes.len() % NODE_BYTES != 0 || nodes.capacity() % NODE_BYTES != 0 {
return Err(io::Error::new(
io::ErrorKind::Other,
"Node cache is not a multiple of node size",
));
}
let out: Vec<Node> = unsafe {
Vec::from_raw_parts(
nodes.as_mut_ptr() as *mut _,
nodes.len() / NODE_BYTES,
nodes.capacity() / NODE_BYTES,
)
};
let out: Vec<Node> = unsafe {
Vec::from_raw_parts(
nodes.as_mut_ptr() as *mut _,
nodes.len() / NODE_BYTES,
nodes.capacity() / NODE_BYTES,
)
};
mem::forget(nodes);
mem::forget(nodes);
Ok(out)
Ok(out)
}
impl AsRef<[Node]> for NodeCache {
fn as_ref(&self) -> &[Node] {
match self.cache {
Either::Left(ref vec) => vec,
Either::Right(ref mmap) => unsafe {
let bytes = mmap.as_ptr();
// This isn't a safety issue, so we can keep this a debug lint. We don't care about
// people manually messing with the files unless it can cause unsafety, but if we're
// generating incorrect files then we want to catch that in CI.
debug_assert_eq!(mmap.len() % NODE_BYTES, 0);
slice::from_raw_parts(bytes as _, mmap.len() / NODE_BYTES)
},
}
}
fn as_ref(&self) -> &[Node] {
match self.cache {
Either::Left(ref vec) => vec,
Either::Right(ref mmap) => unsafe {
let bytes = mmap.as_ptr();
// This isn't a safety issue, so we can keep this a debug lint. We don't care about
// people manually messing with the files unless it can cause unsafety, but if we're
// generating incorrect files then we want to catch that in CI.
debug_assert_eq!(mmap.len() % NODE_BYTES, 0);
slice::from_raw_parts(bytes as _, mmap.len() / NODE_BYTES)
},
}
}
}
// This takes a raw pointer and a counter because `memory` may be uninitialized. `memory` _must_ be
@@ -318,47 +301,39 @@ impl AsRef<[Node]> for NodeCache {
// out. It counts as a read and causes all writes afterwards to be elided. Yes, really. I know, I
// want to refactor this to use less `unsafe` as much as the next rustacean.
unsafe fn initialize_memory(memory: *mut Node, num_nodes: usize, ident: &H256) {
let dst = memory as *mut u8;
let dst = memory as *mut u8;
debug_assert_eq!(ident.len(), 32);
keccak_512::unchecked(dst, NODE_BYTES, ident.as_ptr(), ident.len());
debug_assert_eq!(ident.len(), 32);
keccak_512::unchecked(dst, NODE_BYTES, ident.as_ptr(), ident.len());
for i in 1..num_nodes {
// We use raw pointers here, see above
let dst = memory.offset(i as _) as *mut u8;
let src = memory.offset(i as isize - 1) as *mut u8;
for i in 1..num_nodes {
// We use raw pointers here, see above
let dst = memory.offset(i as _) as *mut u8;
let src = memory.offset(i as isize - 1) as *mut u8;
keccak_512::unchecked(dst, NODE_BYTES, src, NODE_BYTES);
}
keccak_512::unchecked(dst, NODE_BYTES, src, NODE_BYTES);
}
// Now this is initialized, we can treat it as a slice.
let nodes: &mut [Node] = slice::from_raw_parts_mut(memory, num_nodes);
// 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);
for _ in 0..ETHASH_CACHE_ROUNDS {
for i in 0..num_nodes {
let data_idx = (num_nodes - 1 + i) % num_nodes;
let idx = nodes.get_unchecked_mut(i).as_words()[0] as usize % num_nodes;
// This _should_ get unrolled by the compiler, since it's not using the loop variable.
for _ in 0..ETHASH_CACHE_ROUNDS {
for i in 0..num_nodes {
let data_idx = (num_nodes - 1 + i) % num_nodes;
let idx = nodes.get_unchecked_mut(i).as_words()[0] as usize % num_nodes;
let data = {
let mut data: Node = nodes.get_unchecked(data_idx).clone();
let rhs: &Node = nodes.get_unchecked(idx);
let data = {
let mut data: Node = nodes.get_unchecked(data_idx).clone();
let rhs: &Node = nodes.get_unchecked(idx);
for (a, b) in data.as_dwords_mut().iter_mut().zip(rhs.as_dwords()) {
*a ^= *b;
}
unroll! {
for w in 0..8 {
*data.as_dwords_mut().get_unchecked_mut(w) ^=
*rhs.as_dwords().get_unchecked(w);
}
}
data
};
data
};
keccak_512::write(&data.bytes, &mut nodes.get_unchecked_mut(i).bytes);
}
}
keccak_512::write(&data.bytes, &mut nodes.get_unchecked_mut(i).bytes);
}
}
}

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