Compare commits

...

541 Commits
v2.2.4 ... main

Author SHA1 Message Date
POA
6e06824c23 Bump to v3.3.3 2022-01-13 12:34:02 +03:00
Rim Rakhimov
43d6da6b52
Made nodes data concatenate as RLP sequences instead of bytes (#598)
* Made nodes data concatenate as RLP sequences instead of bytes

* Add test for getNodeData dispatch

* Update getNodeData to return data for non-aura networks
2022-01-13 12:26:33 +03:00
Rim Rakhimov
412d797a3b
Implements eip-3607 (#593)
* implements eip-3607

* Tests fixed

* Added tests for eip3607 functionality

* rast fmt
2022-01-10 18:01:46 +03:00
Rim Rakhimov
63bab44e3c
Makes eth_mining to return False if not is not allowed to seal (#581) 2021-12-10 14:25:39 +03:00
Rim Rakhimov
f703d01f23
Add type field for legacy transactions in RPC calls (#580)
* Added type field for legacy transactions when returned as rpc call response

* Remove invalid test
2021-12-09 11:17:42 +03:00
POA
f13fa10b8a Bump to v3.3.2, London on Sokol, effective_gas_price function enhancement 2021-12-07 14:03:48 +03:00
POA
657100cebc Bump to v3.3.1 2021-11-30 10:55:54 +03:00
POA
d2d19ec8c2 Merge branch 'dev' of https://github.com/openethereum/openethereum into dev 2021-11-30 10:39:06 +03:00
POA
0f872aff78 Add a bootnode for Kovan 2021-11-30 10:38:55 +03:00
Rim Rakhimov
405738c791
Fix for modexp overflow in debug mode (#578)
* fix modexp overflow panic in debug mode

* Added one more unit test for modexp

* Remove redundant bytes from modexp unit test

Co-authored-by: POA <33550681+poa@users.noreply.github.com>
2021-11-30 10:33:40 +03:00
Rim Rakhimov
3b19a79c37
Adds eth_maxPriorityFeePerGas implementaiton (#570)
* added eth_maxPriorityFeePerGas rpc call

* cargo fmt

* moved block_base_fee implementation into the trait

* added basic test for eth_maxPriorityFeePerGas

* added test for eth_maxPriorityFeePerGas calculation

* Added support for zero-cost transactions

* Added 'eip1559_not_activated' error

* Fixes 'chain::supplier::test::return_nodes' test

* cargo fmt

* cargo fmt

* made calculation of fallback priority fee to ignore zero-cost transactions

* cargo fmt

* made use of 'saturating_sub' instead of minus
2021-11-25 10:43:00 +03:00
POA
64a1614769 Bump to v3.3.0 2021-11-17 12:05:58 +03:00
POA
b981f7beef Add validateServiceTransactionsTransition spec option 2021-11-12 13:06:19 +03:00
POA
caa210107e Add additional service transactions checking to block verifier 2021-11-10 16:36:17 +03:00
POA
88eb7d3257 Revert eip1559BaseFeeMinValue activation on xDai 2021-11-04 15:50:48 +03:00
POA
73895aae88 Set eip1559BaseFeeMinValue for POA Core 2021-11-02 10:29:54 +03:00
POA
c5719983b2 Set eip1559BaseFeeInitialValue equal to eip1559BaseFeeMinValue for xDai 2021-11-02 09:34:53 +03:00
POA
f9b2db206a Replace eip1559BaseFeeFixedValue* spec options with eip1559BaseFeeMinValue and eip1559BaseFeeMinValueTransition 2021-11-01 13:20:58 +03:00
POA
437ba9b044 Add eip1559BaseFeeFixedValue and eip1559BaseFeeFixedValueTransition spec options and bump to v3.3.0-rc.14 2021-11-01 10:53:50 +03:00
uink45
98873fc0c0
EIP-4345 enabled (#561)
* EIP-4345 enabled

Co-authored-by: varasev <33550681+varasev@users.noreply.github.com>
2021-11-01 07:14:52 +03:00
POA
415a522429 POA Core London hard fork and bump to v3.3.0-rc.13 2021-10-29 16:37:12 +03:00
POA
646f49fdd0 xDai London hard fork and bump to v3.3.0-rc.12 2021-10-22 09:44:16 +03:00
POA
25ce4b2ec8 Enable GetNodeData for AuRa chains and bump to v3.3.0-rc.11 2021-10-19 11:25:32 +03:00
POA
ac30783c82 Add eip1559FeeCollector and eip1559FeeCollectorTransition spec options and bump to v3.3.0-rc.10 2021-10-14 16:14:38 +03:00
POA
5e9b4c58ae Bump to v3.3.0-rc.9 2021-10-04 10:43:30 +03:00
POA
74e709fd55 Fix MinGasPrice config option 2021-09-29 10:30:28 +03:00
POA
3413343caa Add service transactions support for EIP-1559 2021-09-29 10:30:28 +03:00
sunce86
8bb02dd479 small fixes 2021-09-29 10:30:27 +03:00
sunce86
79be8f1ab8 min_gas_price becomes min_effective_priority_fee (effective_gas_price - base_fee) 2021-09-29 10:30:27 +03:00
sunce86
a049baf6b2 added version 4 for TxPermission contract 2021-09-29 10:30:27 +03:00
sunce86
d8305c52ea Bump to v3.3.0-rc.8 2021-09-03 17:07:40 +02:00
Jochen Müller
239d790df1
Ignore GetNodeData requests (#519) 2021-09-03 16:43:33 +02:00
Jochen Müller
298a1a0ecc Bump to v3.3.0-rc.7 2021-08-23 14:03:36 +02:00
Jochen Müller
36b3f125a4
Fix wrong sync packet id (#514) 2021-08-23 13:54:25 +02:00
sunce86
5d9ff63043 Bump to v3.3.0-rc.6 2021-08-04 18:15:06 +02:00
sunce86
01996c8867 Merge branch 'dev' 2021-08-04 18:05:31 +02:00
varasev
2ae294990a
London HF on Kovan (#502)
* London HF on Kovan

Block number 26741100

* Set wasmDisableTransition for Kovan

Co-authored-by: Dusan Stanivukovic <dusan.stanivukovic@gmail.com>
2021-08-03 14:02:37 +02:00
sunce86
745c4bd00c Revert "Sunce86/eip1559 for x dai (#499)"
This reverts commit 87ae05d99e.
2021-08-03 11:49:51 +02:00
sunce86
ecae5f1c47 Revert "Sunce86/eip1559 for x dai (#499)"
This reverts commit 87ae05d99e.
2021-08-03 11:47:01 +02:00
Dusan Stanivukovic
87ae05d99e
Sunce86/eip1559 for x dai (#499)
* added version 4 for TxPermission contract
* min_gas_price becomes min_effective_priority_fee (effective_gas_price - base_fee)
2021-08-02 19:47:39 +02:00
sunce86
a92e5e761b Bump to v3.3.0-rc.4 2021-07-14 21:46:58 +02:00
Dusan Stanivukovic
87603926b5
feeHistory implementation (#484)
* feeHistory implementation

* code review fix
2021-07-14 21:21:28 +02:00
Dusan Stanivukovic
eb42f0c5d9
gasPrice is required field for Transaction object (#481) 2021-07-12 15:22:27 +02:00
Dusan Stanivukovic
33908e8361
fix state test for openethereum-evm (#480)
* fix state test for openethereum-evm
2021-07-10 08:53:53 +02:00
Dusan Stanivukovic
aa09846200
bump ethereum tests 9.0.3 (#478) 2021-07-09 16:47:02 +02:00
Dusan Stanivukovic
67ab600bc9
Sunce86/effective gas price not omitting (#477)
* no omit effectiveGasPrice in receipts
2021-07-09 14:56:37 +02:00
Dusan Stanivukovic
4b437428bd
define london block at 12965000 (#476)
* define london block at 12965000
2021-07-08 22:55:53 +02:00
Jochen Müller
38e40f649c
Restore GetNodeData (#469)
* Accept GetNodeData requests

* Implement blockchain client method for node data requests

* Reuse old database read methods for node data

* fmt

* Copy & paste old tests...

* ... and make them work

* fmt
2021-07-05 17:06:35 +02:00
Jochen Müller
43ee520904
Implement eth/66 (#467)
* Allow eth/66

* Add eth/66 request ids

* fmt

* Remove some leftovers

* fmt

* Change behaviour in case of missing peer info

- Assume eth/66 protocol, not earlier one
- Log just a trace, not an error
2021-07-05 15:59:22 +02:00
sunce86
fdaee51ca0 Bump to v3.3.0-rc.3 2021-06-29 22:56:40 +02:00
Dusan Stanivukovic
eec38b30e3
forcing base fee to zero if gas pricing is omitted (#460)
* forcing base fee to zero if gas pricing is omitted

* force base fee to zero for estimate_gas
2021-06-29 22:17:00 +02:00
Dusan Stanivukovic
287409f9f5
gasPrice substituted with effective_gas_price (#458) 2021-06-28 19:15:37 +02:00
Dusan Stanivukovic
e5ae846de4
added effectiveGasPrice to eth_getTransactionReceipt return structure (#450) 2021-06-28 19:04:52 +02:00
Dusan Stanivukovic
e6f3794dd4
rust version reverted to 1.52.1 (#454) 2021-06-28 16:39:18 +02:00
sunce86
5920f232d0 Bump to v3.3.0-rc.2 2021-06-17 11:32:11 +02:00
sunce86
3bce814090 Update changelog 2021-06-17 11:31:33 +02:00
sunce86
118051696e Merge branch 'dev' 2021-06-16 21:18:02 +02:00
Dusan Stanivukovic
17057eeedc
bump ethereum tests 9.0.2, revert london mainnet block (#435)
* bump ethereum tests 9.0.2
* london mainnet block removed
2021-06-16 20:48:23 +02:00
Dusan Stanivukovic
7aa1e987de
Update CHANGELOG.md 2021-06-16 09:33:16 +02:00
Jochen Müller
193b25a22d Bump to v3.3.0-rc.1 2021-06-15 13:25:26 +02:00
Jochen Müller
99a8ddae41 Update changelog 2021-06-15 13:00:45 +02:00
Dusan Stanivukovic
93b39df02d
Eip 3554 enabled, London blocks defined (#433)
* Eip 3554 enabled
* london hard fork blocks
2021-06-15 11:18:56 +02:00
Dusan Stanivukovic
5dec58ba9f
Sunce86/fix tx pool locals for 1559 (#431)
* fixed handling of local txs after 1559 activation
2021-06-11 10:19:08 +02:00
Dusan Stanivukovic
b928380b64
test update (#429)
support for 9.0.1 ethereum tests
2021-06-10 15:01:48 +02:00
Dusan Stanivukovic
5e7086d54c
Sunce86/eip 1559 (#393)
* eip1559 hard fork activation

* eip1559 hard fork activation 2

* added new transaction type for eip1559

* added base fee field to block header

* fmt fix

* added base fee calculation. added block header validation against base fee

* fmt

* temporarily added modified transaction pool

* tx pool fix of PendingIterator

* tx pool fix of UnorderedIterator

* tx pool added test for set_scoring

* transaction pool changes

* added tests for eip1559 transaction and eip1559 receipt

* added test for eip1559 transaction execution

* block gas limit / block gas target handling

* base fee verification moved out of engine

* calculate_base_fee moved to EthereumMachine

* handling of base_fee_per_gas as part of seal

* handling of base_fee_per_gas changed. Different encoding/decoding of block header

* eip1559 transaction execution - gas price handling

* eip1559 transaction execution - verification, fee burning

* effectiveGasPrice removed from the receipt payload (specs)

* added support for 1559 txs in tx pool verification

* added Aleut test network configuration

* effective_tip_scaled replaced by typed_gas_price

* eip 3198 - Basefee opcode

* rpc - updated structs Block and Header

* rpc changes for 1559

* variable renaming according to spec

* - typed_gas_price renamed to effective_gas_price
- elasticity_multiplier definition moved to update_schedule()

* calculate_base_fee simplified

* Evm environment context temporary fix for gas limit

* fmt fix

* fixed fake_sign::sign_call

* temporary fix for GASLIMIT opcode to provide gas_target actually

* gas_target removed from block header according to spec change: https://github.com/ethereum/EIPs/pull/3566

* tx pool verification fix

* env_info base fee changed to Option

* fmt fix

* pretty format

* updated ethereum tests

* cache_pending refresh on each update of score

* code review fixes

* fmt fix

* code review fix - changed handling of eip1559_base_fee_max_change_denominator

* code review fix - modification.gas_price

* Skip gas_limit_bump for Aura

* gas_limit calculation changed to target ceil

* gas_limit calculation will target ceil on 1559 activation block

* transaction verification updated according spec: https://github.com/ethereum/EIPs/pull/3594

* updated json tests

* ethereum json tests fix for base_fee
2021-06-04 12:12:24 +02:00
Jochen Müller
144b2293a2
EIP 3541 (#422)
* Add EIP-3541 transition block parameter

* Implement EIP-3541

* Add a unit test for EIP-3541

* Add error type for attempt to deploy invalid code

* fmt
2021-05-31 14:37:23 +02:00
Jochen Müller
f14d3e5a5c
EIP-3529: Reduction in gas refunds (#406)
* Implement changed gas refund rules according to EIP-3529

* Add a unit test for changed gas refunds

* Add missing comment

* Add fork block to spec.hard_forks
2021-05-19 17:18:01 +02:00
Jochen Müller
f9f492638c Bump to v3.2.6 2021-05-14 09:39:01 +02:00
varasev
fe198ddf7d
Berlin HF on POA Core and Sokol (#398)
Co-authored-by: POA <33550681+poa@users.noreply.github.com>
2021-05-11 11:10:51 +02:00
Jochen Müller
32d8b5487a Bump to v3.2.5 2021-05-05 15:14:10 +02:00
rakita
6835ec53ad
Remove windows build artifacts (#385)
Remove windows build artifacts that were added by mistake
2021-05-05 13:33:48 +02:00
Jochen Müller
09ab40b956
Mention v3.2.2 changes in v3.2.5 changelog (#386)
Since the two hotfix releases, v3.2.3 and v3.2.4, did not include the
changes from v3.2.2-rc.1, they should be mentioned in the changelog for
v3.2.5-rc.1 again.
2021-05-05 12:19:45 +02:00
Jochen Müller
2df74c26dd Bump to v3.2.5-rc.1 2021-04-28 15:08:33 +02:00
varasev
ed12fffeef
Berlin HF on xDai (#384)
* Berlin HF on xDai

* Update enodes for xDai

Co-authored-by: rakita <rakita@users.noreply.github.com>
2021-04-28 14:07:24 +02:00
Jochen Müller
c03cc15468
Implement eth/65 (#352)
* EIP-2464: eth/65: transaction announcements and retrievals

* Updates to eth-65 implementatiom

- Replace deprecated syntax and method name
- Replace call to removed method
- Reimplement rlp::Encodable for SignedTransaction

* fmt

* More updates

- Replace calls to removed methods
- More dyns

* Apply requested changes

- Avoid unused variable warnings
- Avoid implementing Encodable trait for Transaction
- Update message encoding to EIP-2718 transaction format

* Update sync stats of eth-65 peers properly

* fmt & fix error propagation

* Fix: Add correct subset of transactions to stats.

* Update list of last sent transactions correctly.

Co-authored-by: Artem Vorotnikov <artem@vorotnikov.me>
Co-authored-by: Karim Agha <karim.dev@gmail.com>
Co-authored-by: rakita <rakita@users.noreply.github.com>
2021-04-27 15:33:40 +02:00
rakita
3b3ecf6676
Bump eth tests to 8.0.3 (#349) 2021-04-27 14:36:50 +02:00
rakita
be9b16ab67
Bump parking_lot to 0.11.1. Revert std mutex from #277 (#350) 2021-04-27 13:12:19 +02:00
varasev
392a909cb7
Berlin HF in Kovan (#380)
* Berlin HF in Kovan

According to https://github.com/poanetwork/poa-chain-spec/pull/171

* Update nodes for Kovan
2021-04-26 10:21:01 +02:00
Jochen Müller
6f5a00a642 Merge branch 'main' into dev 2021-04-21 15:42:43 +02:00
Jochen Müller
2453f1a803 Merge branch 'release/v3.2.x' into main 2021-04-21 15:27:39 +02:00
rakita
09967329af Bump to v3.2.4 2021-04-15 21:49:20 +02:00
rakita
459a1a02a4 Fix broadcast for typed tx 2021-04-15 21:47:50 +02:00
Wei Tang
a716eb3871 EIP-2929: only add params.address to access list 2021-04-15 18:15:40 +02:00
Wei Tang
0fd7c59724 EIP-2929: add tx sender and address into the access list 2021-04-15 18:02:24 +02:00
rakita
aa41520dd1 Bump to v3.2.3 2021-04-15 18:02:24 +02:00
Wei Tang
4bffab6715 Fix compile 2021-04-15 18:02:24 +02:00
Wei Tang
5709dbc3e0 EIP2929: only add builtin to warm address if they are active 2021-04-15 18:02:24 +02:00
Wei Tang
6ce6666cbb
EIP-2929: add tx sender and address into the access list (#360) 2021-04-15 17:41:33 +02:00
rakita
582bca385f Bump to v3.2.2-rc.1. Changelog 2021-03-31 15:07:27 +02:00
rakita
9037ad0ea7 Bump eth/tests to v8.0.2 2021-03-31 13:44:14 +02:00
rakita
c9190a39ed
Executable queue for ancient blocks inclusion (#208)
* Executable queue for ancient blocks inclusion
* Add drop trait for client
* Added shutdown to tests
* Remove doubled call
* Use reth-util from reth repo
2021-03-25 16:04:32 +01:00
rakita
85391f99ac
Backport AuRa commits for xdai (#330)
* Add SealingState; don't prepare block when not ready. (#10529)
* Fix a few typos and unused warnings. #10803
* Configuration map of block reward contract addresses (#10875)
* Step duration map configuration parameter ported from the POA Network fork (#10902)
* Add a 2/3 quorum option to Authority Round. (#10909)
* Additional arithmetic EVM opcode benchmarks (#10916)
* RPC method for clearing the engine signer (#10920)
* authority_round: Fix next_step_time_duration. (#11379)
* Aura: Report malice on sibling blocks from the same validator (#11160)
* TxPermissions ver 3: gas price & data (#11170)
* Add randomness contract support to AuthorityRound. (#10946)
* Set the block gas limit to the value returned by a contract call (#10928)
* AuthorityEngine: Minor cleanups. (#11408)
* Add POSDAO transition and malice report queue. (#11245)
* PoA call validators on_close_block
* Actualize spec files for POA Networks
* Some fixes after merge
* Crypto error desc
* AuRa on_close_block Error::Old fix

Co-authored-by: POA <33550681+poa@users.noreply.github.com>
2021-03-25 14:37:01 +01:00
rakita
561ed8df3c fix miner_author by adding dummy msg 2021-03-24 17:50:36 +01:00
rakita
5eacff59e8 Revert "Remove eth/63 protocol version (#252)"
This reverts commit bbecb0415e.
2021-03-23 11:59:33 +01:00
rakita
d030870220 Merge remote-tracking branch 'origin/main' into dev 2021-03-21 21:58:13 +01:00
Karim Agha
ee88247e71 Fixing outdated readme links (#322) 2021-03-21 21:58:02 +01:00
Jochen Müller
37f5291538
Add Nethermind to clients that accept service transactions (#324)
* Add Nethermind to clients that accept service transactions

* fmt
2021-03-18 14:00:05 +01:00
rakita
5fdedf0858 Bump to v3.2.1. Changelog 2021-03-17 09:46:36 +01:00
Jochen Müller
504777e879
Implement the filter argument in parity_pendingTransactions (#295)
* Add filters for pending transactions to RPC API

Allow filtering results in the parity_pendingTransaction endpoint as described in the API docs.

* Make arguments in parity_pendingTransactions work together

filter and limit

* fmt

* Requested changes

- filter in ethcore to avoid unneccessary copying
- rename gas_price to gasPrice
- implement requesting contract creation txs with "action"

* Some beautifying

Remove missing import and unneccessary dependency entry, add a comment
and set right lint level on new module

* fixed broken build after merge

* fmt

* fixing CI errors: type conversion

Co-authored-by: Karim Agha <karim.dev@gmail.com>
2021-03-16 13:39:42 +01:00
rakita
3317797285 Initial sync block stuck. Block import logs (#318) 2021-03-16 12:08:22 +01:00
rakita
33a3a9deec
Initial sync block stuck. Block import logs (#318)
Co-authored-by: Karim Agha <karim.dev@gmail.com>
2021-03-14 11:18:38 +01:00
Karim Agha
327c4bcb14
Fixing outdated readme links (#322) 2021-03-14 10:25:45 +01:00
Karim Agha
b6b5129058
Following up on PR #316, removing unused conversions that are now deadcode (#321) 2021-03-14 10:25:14 +01:00
Karim Agha
29dc10c446
Updating ethcore and ethjson crates to Rust Edition 2018 (#316)
* Migrating use crate::Type imports to Rust 2018 edition

* import name fixes

* fmt

* removing diff leftover

* catching up with latest developments on dev

* fmt

* removing another diff leftover
2021-03-12 14:55:49 +01:00
Simon KP
48e7d6cee4
Send SIGTERM instead of SIGHUP to OE daemon (#317)
* Send SIGTERM instead of SIGHUP to OE daemon

* Address comments
2021-03-12 13:00:09 +01:00
rakita
a0f406e26b
Ethereum-types and various libs upgrade (#315)
* Upgrade Eth types

ethereum-types -> 0.9.2
rlp -> 0.4.6
keccak-hash -> 0.5.0
parity-crypto -> 0.6.2
ethabi -> 0.12.0
ethabi-derive -> 0.12.0
ethabi-contract -> 0.11.0
ethbloom -> 0.9.1
rand -> 0.7.3
trie-standardmap -> 0.15.2
triehash -> 0.5.0

* backport #10714. Small changes, merge fixes

Co-authored-by: mdben1247 <mdben1247@users.noreply.github.com>
2021-03-12 10:12:42 +01:00
rakita
3f8e0cfec4 Merge remote-tracking branch 'origin/main' into dev 2021-03-11 16:30:47 +01:00
rakita
f143ddb75a [devops] Upgrade docker alpine to v1.13.2 2021-03-11 08:42:23 +01:00
rakita
32fd2b484c Merge remote-tracking branch 'origin/main' into dev 2021-03-10 17:23:00 +01:00
rakita
187c81b3f1 Upgrade ethereum/tests to v8.0.1 (#301) 2021-03-10 17:18:17 +01:00
rakita
d7a958129f
[evmbin] Omit storage output, now for std-json (#311)
* [evmbin] Omit storage output, now for std-json
* fix tests
2021-03-10 16:39:32 +01:00
rakita
eca8fb74ae
Strict memory order (#306)
* Make MemoryOrdering more strict

* fmt

* Strict mem order for priority_tasks_gate
2021-03-10 12:36:23 +01:00
Karim Agha
e2024c4b81
Fixing a compilation warning (#308)
* Fixing a compilation warning
2021-03-10 09:46:34 +01:00
rakita
5b904476cd
Backport: Block sync stopped without any errors. #277 (#286)
* Backport: Block sync stopped without any errors. #277
* fmt
2021-03-09 11:20:32 +01:00
rakita
7ea5707904
Freeze pruning while creating snapshot (#205)
* Freeze pruning while creating snapshot
* Use scopeguard for snapshot generation
* Snapshot 1k blocks
* Snapshot number correction
2021-03-09 09:47:49 +01:00
rakita
458d55559e Bump to v3.2.0 2021-03-08 17:49:59 +01:00
rakita
6f50061f0c
AuRa multi block reward (#290)
* Multi block reward for AuRa
* Added test
* Better error on wrong config
2021-03-08 11:59:04 +01:00
gakada
dbc5f94241
Migrate compare_and_swap to compare_exchange (#291) 2021-03-06 11:30:52 +01:00
rakita
0cf0cdbb86 Disable CI on tag for windows2019 machine"
This reverts commit efb80e1032.
2021-03-05 19:27:01 +01:00
rakita
91e57c803d Disable EIP-2315 2021-03-05 18:01:27 +01:00
adria0.eth
0fcb102f03
Improved metrics (#240)
Added db metrics (kvdb_bytes_read, kvdb_bytes_written, kvdb_reads, kvdb_writes)
Added --metrics-prefix=[prefix]
2021-03-03 22:44:35 +01:00
Dusan Stanivukovic
973a5a594b
Sunce86/add support eip2930 ethereum tests runner (#288)
* added support for eip2930 tests

Co-authored-by: sunce86 <dusan.stanivukovic@gmail.pm>
2021-03-03 15:57:25 +01:00
rakita
ba011eba15
Send RLPx auth in EIP-8 format (#287) 2021-03-03 12:58:10 +01:00
Anonymous
7c9eed8d65 ethcore/snapshot: fix double-lock in Service::feed_chunk (#289) 2021-03-02 14:44:58 +01:00
Anonymous
63fdad8d86
ethcore/snapshot: fix double-lock in Service::feed_chunk (#289) 2021-03-02 14:27:28 +01:00
Dusan Stanivukovic
0947261cf2
Sunce86/rpc module reverted for RPC JSON api (#284)
* rpc module reverted for RPC JSON api

Co-authored-by: Dusan Stanivukovic <dusan.stanivukovic@gnosis.pm>
2021-02-26 15:23:29 +01:00
Giacomo
efb80e1032
Enable CI on windows2019 machine (#283)
Enable CI on windows2019 machine

* Add -y for choco install
2021-02-26 10:35:17 +01:00
draganrakita
f0fd88aa12 Github action path for folder structure 2021-02-25 17:21:02 +01:00
draganrakita
142b63a4f9 Backport github actions from old main 2021-02-25 17:05:24 +01:00
rakita
1d2b640834 chocolate -y confirmation steps 2021-02-25 11:11:31 +01:00
draganrakita
f1dc682168 Bump to 3.2.0-rc.1 2021-02-24 13:00:50 +01:00
draganrakita
0bb2f8f6b8 Berlin hardfork blocks 2021-02-24 13:00:50 +01:00
rakita
d5c2a0fbe2
Fix for TypedTx enabling and hash generation. Tweak sig V in RPC. (#272)
* Fix for TypedTx hash generation from RlpView
* Tweaks on sig V field in RPC
* Fix for eip2930 incomming tx
2021-02-23 13:46:08 +01:00
rakita
98563b0a45
Change ProtocolId to U64. yolo3x spec (#271)
* Change ProtocolId to U64 and make it support variable subprotocol names* 
* Add yolo3x testnet
2021-02-19 12:52:24 +01:00
adria0.eth
d8ce175846
Fix modexp, update tests, update berlin chainspec (#267) 2021-02-17 19:43:09 +01:00
rakita
fb9699d8e1
EIP-2930 remove type from legacy JSONRPC (#265)
* EIP-2930 remove type from legacy JSONRPC
* fmt
2021-02-17 16:52:51 +01:00
rakita
dbf9a1cd98
EIP-2930 spec change for signature hash (#261)
* EIP-2930 spec change for signature hash
* Removing eip2930 test blocks
2021-02-10 15:58:35 +01:00
rakita
6b4e56b214
AccessList in JSONRPC. And enabling github action tests (#255)
* Enabling github action tests
* Fix failing tests
* AccessList to Option in json
* failing rust example removed
* AccessList for jsonrpc
* Tx type as sequence, AccessList as type
2021-02-08 14:55:03 +01:00
Jochen Müller
f40e198eb7
Give IoService a consistent interface (#257)
The start() method had two different signatures depending on configuration. Since ethcore is built with either config depending on the build target, this resulted in compiler errors for either evmbin or oe.
2021-02-05 13:33:39 +01:00
rakita
bbecb0415e
Remove eth/63 protocol version (#252)
* Remove eth/63 protocol
2021-02-04 14:10:48 +01:00
rakita
6d81fce451
Update EWF's chains with Istanbul transition block numbers (#11482) (#254)
Co-authored-by: Artem Vorotnikov <artem@vorotnikov.me>
2021-02-04 11:39:10 +01:00
rakita
65c5e6dfd3
EIP-2930 RPC and TypedTransactionView support (#245)
* TypedTransactionView for EIP-2930
* Enable EIP-2930 in RPC calls
* type field added to TypedTransactionView
2021-02-02 16:26:55 +01:00
adria0.eth
2e23ca353f
Use berlin chainspec for unit test, yolo3 for testnet (#244)
* Fix yolo+berlin specs
* fix yolo3 maximumExtraDataSize
* fmt
2021-02-01 16:40:00 +01:00
rakita
a831379ad8
Yolo3 spec (#241)
Update Yolo3
2021-02-01 08:34:44 +01:00
rakita
cfc6439f2e
Local EIP2930 and EN/DE block tests (#237) 2021-01-28 17:23:01 +01:00
François Garillot
52d966ccaa
Cleans up a number of Option / Result patterns and warts (#226) 2021-01-21 18:27:35 +01:00
rakita
59d891edf4
Snapshot manifest block added to prometheus (#232)
Co-authored-by: adria0.eth <5526331+adria0@users.noreply.github.com>
2021-01-21 17:23:15 +01:00
draganrakita
f3bdc0da3c Bump to 3.1.1 2021-01-19 14:49:25 +01:00
Denis Granha
a55799d523
Set alpine version to 3.12.3
Alpine version is changed in order to prevent Cmake errors. Reference: https://gitlab.alpinelinux.org/alpine/aports/-/issues/12321.

Intends to solve https://github.com/openethereum/openethereum/issues/230
2021-01-19 10:59:40 +01:00
draganrakita
1d07c4c06b fix Supplied instant is later than self 2021-01-18 09:34:48 +01:00
rakita
ea25ffd79d
Added additional Sg-1,Ca-2,Ca-3 OE bootnodes (#222) 2021-01-17 23:15:33 +01:00
Adria Massanet
eb876cb2d7 CI fix 2021-01-14 15:30:57 +01:00
Adria Massanet
814526a248 Fix CI 2021-01-14 15:30:57 +01:00
Adria Massanet
d3ba83405c fmt 2021-01-14 15:30:57 +01:00
Adria Massanet
c46fe330dc Big folder refactor 2021-01-14 15:30:57 +01:00
draganrakita
0e5d6944b7 Add eip2929,eip2930 to ForkId list 2021-01-11 15:21:16 +01:00
adria0.eth
b0a1e3da03
Update ethereum/tests to f55f344 (#220) 2021-01-11 14:14:41 +01:00
rakita
0706e5468d
EIP-1898: Allow default block parameter to be blockHash (#203)
* Allow default block parameter to be blockHash

Backport to 3.1 of https://github.com/openethereum/openethereum/pull/10932

Co-authored-by: Richard Patel <me@terorie.dev>

* Request canonical with BlockHash

Co-authored-by: Seun LanLege <seunlanlege@gmail.com>
Co-authored-by: Richard Patel <me@terorie.dev>
2021-01-11 11:00:27 +01:00
rakita
f286597d10
Update link to issue (#202) 2021-01-08 15:56:53 +01:00
Giacomo
e2f665e9cf
Enable Windows2019 CI on main/dev (#213)
* Revert "Disable windows2019, remove tagged windows artifact"

This reverts commit 08e6cca3e5.

* Allow running CI on windows only when pushing to main/dev

* Remove unneeded block code
2020-12-30 15:07:20 +01:00
draganrakita
eab41b49cf test cfg 2020-12-23 15:31:13 +01:00
draganrakita
8d3e0582a8 fmt 2020-12-23 15:31:13 +01:00
draganrakita
705bc71593 Payload limit for test 2020-12-23 15:31:13 +01:00
draganrakita
f723e288c3 Cleanup devp2p unused interface fn 2020-12-23 15:31:13 +01:00
Justin Beaurone
a6bd3516e0 OpenEthereum rebranding 2020-12-21 13:34:05 +01:00
draganrakita
08e6cca3e5 Disable windows2019, remove tagged windows artifact 2020-12-21 11:54:53 +01:00
draganrakita
8a9d14141a Revert "Fix CI problems (#127)" and Remove sscache
This reverts commit 12afb13e9b.
2020-12-21 11:45:52 +01:00
draganrakita
832fc444b6 Tweaks in informer log 2020-12-15 17:07:49 +01:00
adria0.eth
612a71ecb2 Update ISSUE_TEMPLATE.md (#124)
Tell users to ask questions in discord instead of opening an issue.
2020-12-15 11:39:34 +01:00
Giacomo
06fc61d7c5
Add custom windows runner (#162) 2020-12-11 11:18:18 +01:00
rakita
837e8b8725
Ancient target set. InvalidStateRoot bug (#69) (#149) 2020-12-10 17:57:26 +01:00
rakita
ea3efd926e
TypedTransaction (EIP-2718) and Optional access list (EIP-2930) (#135) 2020-12-10 16:42:05 +01:00
rakita
3f01b69084
Fix broken doc comments (#151) 2020-12-09 12:43:32 +01:00
rakita
647ff31942
Add ws-max-paxload (#155) 2020-12-09 11:48:27 +01:00
rakita
56131b6d92
Trace comment on new block inclusion (#100) 2020-12-02 11:31:11 +01:00
rakita
51d824fbdc
Remove sscache (#138) 2020-12-01 16:40:06 +01:00
rakita
1225ff2c5a
Add flag to disable storage output in openethereum-evm tool #97 (#115) 2020-11-26 08:31:44 +01:00
adria0.eth
cb91b7e828
Fix CI problems (#127)
* Temporally Fix CI compilation
2020-11-25 18:28:17 +01:00
Adria Massanet
233bab2ee7 Update linked-hash-map to 0.5.3 2020-11-24 18:11:29 +00:00
Lachezar Lechev
fed80cc075
ethstore - remove unnecessary dir & tiny-keccak dependencies from the lib (#107)
* ethstore - remove unnecessary dir & tiny-keccak dependencies
2020-11-23 13:49:32 +01:00
Giacomo
26ab00b6c7
Fix deprecated set-env declaration (#106)
* Fix deprecated set-env declaration

* Fix add-path and set-env in install-sscache.ps1
2020-11-17 11:16:24 +01:00
Giacomo
01e72efb80 Feature/improve dockerhub deployment (#98)
* Add docker deployment for Github actions

* Add docker specs for the release of tagged and latest versions, also add specs for nightly builds

Co-authored-by: Denis Granha <denis@gnosis.pm>
2020-11-16 18:30:13 +01:00
adria0.eth
81ae80b7f1
EIP2565 impl (#82)
EIP2565 implementation
2020-11-12 14:31:24 +01:00
adria0.eth
910bb78f0d
Downgrade sccache to 1.1.2 (#93) 2020-11-12 12:57:35 +01:00
adria0.eth
6078eeaed7
EIP2929 with journaling + Yolov3 (#79) 2020-11-04 19:11:05 +01:00
rakita
50a4d5fa57
Sync block verification (#74)
* Synchronize block verification
* max_round_blocks_to_import set to 1
* Fixed test that rely on 12block batches

Co-authored-by: adria0.eth <5526331+adria0@users.noreply.github.com>
2020-10-27 10:45:48 +01:00
Adria Massanet
410853e280 Update gitactions for dev branch, deprecate stable branch 2020-10-26 09:27:44 +00:00
Denis Granha
bf5830f766
revert actions/cache to version 1.1.2 (#80) 2020-10-23 22:59:18 +02:00
rakita
d811f6e3ce
Use ubuntu-16.04 for glibc compatibility (#11888) (#73) 2020-10-23 10:43:18 +02:00
adria0.eth
9110b1d9e4
Update gitactions master->main (#72) 2020-10-12 10:55:21 +02:00
varasev
cb0513a8b1
Add wasmDisableTransition spec option (#60)
* Add wasmDisableTransition spec option
2020-10-08 22:37:48 +02:00
adria0.eth
84f675021c
Fix warnings (#64) 2020-09-30 13:10:54 +02:00
rakita
03bfb012a1
Change wiki links (#68) 2020-09-30 13:10:18 +02:00
Denis Granha
16542bd355
fix CD env param 2020-09-29 13:04:59 +02:00
Giacomo
24cff45334
Set AWS_REGION as a global env variable (#67) 2020-09-28 17:07:36 +02:00
adria0.eth
51817baecd
Bump to 3.1rc1 (#58) 2020-09-25 10:49:22 +02:00
rakita
15ebc98877
Drain the transaction overlay (#11654) (#59) 2020-09-25 10:46:51 +02:00
claveros
b6a25ba30a
Update CHANGELOG to 3.1 (#56)
* Update CHANGELOG.md

Backport 3.1 Changelog

* Update CHANGELOG.md

3.0.0, 3.0.1, 3.1 changelog

* Update CHANGELOG.md

* Update CHANGELOG.md

* Update CHANGELOG.md

* Update CHANGELOG.md

* Added 3.0.x changelog

Co-authored-by: draganrakita <dragan0rakita@gmail.com>
2020-09-24 17:36:53 +03:00
rakita
abceaf3832
fix migration check when version_db file does no exist (#57) 2020-09-23 19:57:52 +02:00
rakita
25c2f7e7fd
Dont upgrade for old versions of DB (#54) 2020-09-23 13:49:25 +02:00
rakita
27a0142af1
OpenEthereum rebranding (#31) 2020-09-22 14:53:52 +02:00
adria0.eth
698fa6e8f6
Remove classic, kotti, mordor, expanse (#52) 2020-09-22 13:45:38 +02:00
rakita
ae312bcb01
Added bad block header hash for ropsten (#49)
* Added bad block header hash for ropsten
2020-09-22 13:29:03 +02:00
Artem Vorotnikov
d17ee979b8
Remove accounts bloom (#33) 2020-09-22 12:41:04 +02:00
draganrakita
4fb4ef6d24 Bump jsonrpc-* to v15 2020-09-21 16:11:29 +00:00
adria0.eth
1c82a0733f
Implement eth/64, remove eth/62 (#46)
Co-authored-by: Artem Vorotnikov <artem@vorotnikov.me>
2020-09-21 14:48:14 +02:00
adria0.eth
b54ddd027d
No snapshotting by default (#11814) 2020-09-15 17:51:49 +03:00
Artem Vorotnikov
61e56aba41
Update Ellaism chainspec 2020-09-15 17:34:51 +03:00
rakita
aecc6fc862
Prometheus, heavy memory calls removed (#27) 2020-09-14 16:08:57 +02:00
adria0.eth
dd38573a28
Update ethereum/tests 2020-09-10 09:04:14 +03:00
adria0.eth
c84d82580a
Implement JSON test suite (#11801) 2020-09-10 05:54:38 +03:00
rakita
506cee52e8
Fix issues during block sync (#11265) 2020-09-10 05:54:37 +03:00
rakita
c58b52c21c
verification: fix race same block (#11400) 2020-09-10 05:54:37 +03:00
adria0.eth
f8326b6e27
EIP-2537: Precompile for BLS12-381 curve operations (#11707) 2020-09-10 05:54:37 +03:00
Artem Vorotnikov
ea0c13c0a4
Remove private transactions 2020-09-10 05:54:37 +03:00
rakita
a8668b371c
Remove GetNodeData 2020-09-10 05:54:36 +03:00
Artem Vorotnikov
32ea4d69a3
Remove IPFS integration (#11532) 2020-09-10 05:54:36 +03:00
Artem Vorotnikov
defd24c40e
Remove updater 2020-09-10 05:54:36 +03:00
Artem Vorotnikov
194101ed00
Remove light client 2020-09-10 05:54:36 +03:00
Artem Vorotnikov
2ab8c72ce3
Correct internal par protocol nomenclature 2020-09-10 05:54:30 +03:00
Artem Vorotnikov
a75ba3620c
Remove C and Java bindings (#11346) 2020-09-10 05:54:10 +03:00
Artem Vorotnikov
54afb33333
Remove whisper (#10855) 2020-09-10 05:53:41 +03:00
Artem Vorotnikov
3f42b6178f
Remove security audit workflow for now 2020-09-10 05:53:41 +03:00
adria0.eth
1460f6cc27
EIP-2315: Simple Subroutines for the EVM (#11629) 2020-09-10 05:53:41 +03:00
Artem Vorotnikov
751210c963
Remove deprecated flags 2020-09-10 05:53:41 +03:00
Artem Vorotnikov
7dfa57999b
Remove failing test 2020-09-10 05:53:41 +03:00
Artem Vorotnikov
11fb967c6a
Remove support for hardware wallets (#10678) 2020-09-10 05:53:29 +03:00
Artem Vorotnikov
c270599a23
Fix warnings: other 2020-08-07 20:47:14 +03:00
adria0
412d0307cb
Fix warnings: try/? in whisper 2020-08-07 20:47:14 +03:00
adria0
33b5b36f44
Fix warnings: single tuples 2020-08-07 20:47:14 +03:00
adria0
ef7a82835a
Fix warnings: future name collisions 2020-08-07 20:47:14 +03:00
adria0
ac8f65dbbf
Fix warnings: iter 2020-08-07 20:47:13 +03:00
adria0
725073a683
Fix warnings: docs 2020-08-07 20:47:13 +03:00
adria0
c5aed5bab1
Fix warnings: unnecessary mut 2020-08-07 20:47:13 +03:00
adria0
cacbf256fe
Fix warnings: unused 2020-08-07 20:47:13 +03:00
adria0
0cd972326c
Fix warnings: mem::uninitialized 2020-08-07 20:47:13 +03:00
adria0
239cf91594
Fix warnings: range patterns 2020-08-07 20:47:13 +03:00
adria0
1700873f48
Fix warnings: dyn 2020-08-07 20:47:12 +03:00
adria0
4adb44155d
Update bootnodes 2020-08-07 20:47:12 +03:00
adria0
82b37bfa0d
Add github actions 2020-08-07 20:47:12 +03:00
adria0
544725a018
Fix compilation errors 2020-08-07 20:47:12 +03:00
Artem Vorotnikov
26e253e554
Ignore reformat commit in git blame 2020-08-07 20:47:09 +03:00
Artem Vorotnikov
610d9baba4
Reformat the source code 2020-08-07 20:46:52 +03:00
s3krit
253ff3f37b
Update version and changelog (#11360) 2019-12-31 00:47:57 +01:00
Tomasz Drwięga
54c2d6167f Make sure to not mark block header hash as invalid if only the body is wrong. (#11356)
* Patch invalid transaction root.

* Add raw hash to bad and include fix for uncles too.

* Fix submodules.
2019-12-30 13:15:11 -08:00
David
29ebddc64f V2.5.12 stable (#11336)
* Enable EIP-2384 for ice age hard fork (#11281)
* ethcore/res: activate agharta on classic 9573000 (#11331)
* Istanbul HF in xDai (2019-12-12) (#11299)
* Istanbul HF in POA Core (2019-12-19) (#11298)
* Istanbul HF in POA Sokol (2019-12-05) (#11282)
* Activate ecip-1061 on kotti and mordor (#11338)
* Enable basic verification of local transactions (#11332)
* Disallow EIP-86 style null signatures for transactions outside tests (#11335)
2019-12-16 14:53:34 +01:00
Niklas Adolfsson
fc129b4a26 [stable backport]: add eip1344_transition for istanbul (#11301) (#11303)
* [chainspec]: add `eip1344_transition` for istanbul (#11301)

* Update version and CHANGELOG.md
2019-12-05 14:11:55 +01:00
s3krit
a071d81fe9
update CHANGELOG.md (#11263) 2019-11-14 17:42:49 +01:00
Denis S. Soldatov aka General-Beck
9f94473eaf sccache --stop-server -> sccache --show-stats (#11255) 2019-11-12 18:23:08 +01:00
s3krit
42437fbc57
fix windows libusb builds (#11251)
* fix libusb on Windows
2019-11-12 16:52:34 +01:00
Talha Cross
f3cdd7bf21 v2.5.10 stable (#11239)
* ropsten #6631425 foundation #8798209 (#11201)
* [stable] builtin, istanbul and mordor testnet backports (#11234)
  * ethcore-builtin (#10850)
  * [builtin]: support `multiple prices and activations` in chain spec (#11039)
  * [chain specs]: activate `Istanbul` on mainnet (#11228)
  * ethcore/res: add mordor testnet configuration (#11200)
* Update list of bootnodes for xDai chain (#11236)
* ethcore: remove `test-helper feat` from build (#11047)
* Secret store: fix Instant::now() related race in net_keep_alive (#11155) (#11159)
* [stable]: backport #10691 and #10683 (#11143)
  * Fix compiler warning (that will become an error) (#10683)
  * Refactor Clique stepping (#10691)
* Add Constantinople eips to the dev (instant_seal) config (#10809)
* Add cargo-remote dir to .gitignore (?)
* Insert explicit warning into the panic hook (#11225)
* Fix docker centos build (#11226)
* Update MIX bootnodes. (#11203)
* Use provided usd-per-eth value if an endpoint is specified (#11209)
* Add new line after writing block to hex file. (#10984)
* Type annotation for next_key() matching of json filter options (#11192) (but no `FilterOption` in 2.5 so…)
* Upgrade jsonrpc to latest (#11206)
* [CI] check evmbin build (#11096)
* Correct EIP-712 encoding (#11092)
* [client]: Fix for incorrectly dropped consensus messages (#11086)
* Fix block detail updating (#11015)
* Switching sccache from local to Redis (#10971)
* Made ecrecover implementation trait public (#11188)
* [dependencies]: jsonrpc `14.0.1` (#11183)
* [receipt]: add `sender` & `receiver` to `RichReceipts` (#11179)
* [ethcore/builtin]: do not panic in blake2pricer on short input (#11180)
* util Host: fix a double Read Lock bug in fn Host::session_readable() (#11175)
* ethcore client: fix a double Read Lock bug in fn Client::logs() (#11172)
* Change how RPCs eth_call and eth_estimateGas handle "Pending" (#11127)
* Cleanup stratum a bit (#11161)
* Upgrade to jsonrpc v14 (#11151)
* SecretStore: expose restore_key_public in HTTP API (#10241)
2019-11-11 21:57:38 +01:00
Niklas Adolfsson
5ee54b7298 [stable]: backports (#11114)
* [spec] fix rinkeby spec (#11108)

* use images from our registry (#11105)
2019-10-02 12:23:20 +02:00
s3krit
06c7096054
Update CHANGELOG.md and version (#11093)
* Update CHANGELOG.md and version
2019-09-26 12:38:49 +02:00
s3krit
b2277f65e4
v2.5.9-stable (#11089)
* 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

* [json-spec] make blake2 pricing spec more readable (#11034)

* [json-spec] make blake2 pricing spec more readable

* [ethcore] fix compilation

* Manual backport of #11033
2019-09-26 11:03:39 +02:00
s3krit
c52a6c8fb7
update CHANGELOG.md (#11057) 2019-09-16 12:00:04 +02:00
s3krit
7c7b181ca0
v2.5.8-stable (rev2) (#11051)
* EIP 1884 Re-pricing of trie-size dependent operations  (#10992)
* Implement EIP-1283 reenable transition, EIP-1706 and EIP-2200  (#10191)
2019-09-13 15:46:03 +02:00
David
24a4fdf405
Don't build rpc with ethcore test-helpers (#11048) 2019-09-13 11:53:49 +02:00
s3krit
45f27cec34
v2.5.8-stable (#11041)
* add more tx tests (#11038)
* Fix parallel transactions race-condition (#10995)
* Add blake2_f precompile (#11017)
* [trace] introduce trace failed to Ext (#11019)
* Edit publish-onchain.sh to use https (#11016)
* Fix deadlock in network-devp2p (#11013)
* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
* xDai chain support and nodes list update (#10989)
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
* EIP-1344 Add CHAINID op-code (#10983)
* manual publish jobs for releases, no changes for nightlies (#10977)
* [blooms-db] Fix benchmarks (#10974)
* Verify transaction against its block during import (#10954)
* Better error message for rpc gas price errors (#10931)
* tx-pool: accept local tx with higher gas price when pool full (#10901)
* Fix fork choice (#10837)
* Cleanup unused vm dependencies (#10787)
* Fix compilation on recent nightlies (#10991)
2019-09-12 18:43:53 +02:00
s3krit
6bd7db96fe
v2.5.7 stable (#11006)
* [trace] check mem diff within range (#11002)

* Update version (v2.5.7-stable)
2019-08-29 12:06:49 +02:00
s3krit
ff398fe7ff
V2.5.6 stable (#10961)
-  Fix cargo audit (#10921)
  - Add support for Energy Web Foundation's new chains (#10957)
  - Kaspersky AV whitelisting (#10919)
  - Avast whitelist script (#10900)
  - Docker images renaming (#10863)
  - Remove excessive warning (#10831)
  - Allow --nat extip:your.host.here.org (#10830)
  - When updating the client or when called from RPC, sleep should mean sleep (#10814)
  - added new ropsten-bootnode and removed old one (#10794)
  - ethkey no longer uses byteorder (#10786)
  - Do not drop the peer with None difficulty (#10772)
  - docs: Update Readme with TOC, Contributor Guideline. Update Cargo package descriptions (#10652)
2019-08-12 18:55:11 +02:00
s3krit
3ebc769757
version: stabilise v2.5 (#10857) 2019-07-08 12:30:14 +02:00
s3krit
d60e6384d7
Beta 2.5.4 (#10827)
* cargo update -p smallvec (#10822)

Fixes https://github.com/servo/rust-smallvec/issues/148

* Update version to v2.5.3

Signed-off-by: Martin Pugh <pugh@s3kr.it>
2019-07-01 12:33:35 +02:00
s3krit
3fd58bdcbd
Beta 2.5.3 (#10776)
* ethcore/res: activate atlantis classic hf on block 8772000 (#10766)

* fix docker tags for publishing (#10741)

* 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

* Update version

* Treat empty account the same as non-exist accounts in EIP-1052 (#10775)

* 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>

* 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

* revert .as_bytes() change

* fix build

* fix build maybe
2019-06-25 13:38:29 +00:00
Talha Cross
ecbafb2390
backports for beta 2.5.2 (#10737)
* version: bump beta to 2.5.2

* [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

* Reset blockchain properly (#10669)

* delete BlockDetails from COL_EXTRA

* better proofs

* added tests

* PR suggestions

* new image (#10673)

* 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

* enable lto for release builds (#10717)

* 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

* 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 20:56:03 +02:00
Talha Cross
adabd8198c
beta ci: backport missing diff from master (#10661)
* ci: publish docs debug (#10638)

* ci: backport missing diff from master
2019-05-14 15:03:29 +02:00
Talha Cross
c2487cfe07
ci: publish docs debug (#10638) (#10660) 2019-05-14 14:04:54 +02:00
Talha Cross
e0141f8324
beta 2.5.1 (#10643)
* version: bump beta to 2.5.1

* fix(whisper expiry): current time + work + ttl (#10587)

* update bootnodes (#10595)

* config: update goerli bootnodes

* config: update kotti bootnodes

* 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>

* 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

* evm: add some mulmod benches (#10600)

* evm: add blockhash_mulmod bench

* evm: use num-bigint for mod ops

* Clique: zero-fill extradata when the supplied value is less than 32 bytes in length (#10605)

* Update kovan.json to switch validator set to POA Consensus Contracts (#10628)

* 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

* Fix rinkeby petersburg fork (#10632)
2019-05-10 13:48:52 +02:00
Talha Cross
b52ac20660
beta backports (#10576)
* Reject crazy timestamps instead of truncating.

* 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-08 11:44:10 +02:00
soc1c
3c85f29f11
version: betalize 2.5 2019-04-02 09:37:43 +02:00
Andrew Jones
d9673b0d6b tx-pool: check transaction readiness before replacing (#10526)
* Update to vanilla tx pool error

* Prevent a non ready tx replacing a ready tx

* Make tests compile

* Test ready tx not replaced by future tx

* Transaction indirection

* Use StateReadiness to calculate Ready in `should_replace`

* Test existing txs from same sender are used to compute Readiness

* private-tx: Wire up ShouldReplace

* Revert "Use StateReadiness to calculate Ready in `should_replace`"

This reverts commit af9e69c8

* Make replace generic so it works with private-tx

* Rename Replace and add missing docs

* ShouldReplace no longer mutable

* tx-pool: update to transaction-pool 2.0 from crates.io

* tx-pool: generic error type alias

* Exit early for first unmatching nonce

* Fix private-tx test, use existing write lock

* Use read lock for pool scoring
2019-04-01 10:48:51 +02:00
Niklas Adolfsson
89f828be1c fix(light account response): update tx_queue (#10545) 2019-03-31 11:54:19 +02:00
Thibaut Sardan
ec56b1f09d Update light client harcoded headers (#10547)
* kovan #10643457

* ropsten #5296129

* foundation #7460865

* classic #7747585

* indentation

* morden #3973121
2019-03-31 11:46:36 +02:00
Niklas Adolfsson
95236d25b2 fix(light eth_gasPrice): ask network if not in cache (#10535)
* fix(light eth_gasPrice): ask N/W if not in cache

* fix(bad rebase)
2019-03-31 10:40:33 +02:00
Vladyslav Lupashevskyi
7b2afdfc8c Implement caching for service transactions checker (#10088)
* Tx permission contract improvement

* Take in account zero gas price certification when doing transact_contract

* DRY in ServiceTransactionChecker

* Fix typos and regroup mod

* Introduce CertifiedAddressesCache

* Introduce refresh_cache for CertifiedAddressesCache

* Add CertifiedAddressesCache read and write on checking

* Refresh CertifiedAddressesCache on new imported block

* Separate ChainInfo trait and fix errors after merge

* Do not fire an error when service txes contract does not exist

* WIP: Shared certified addresses cache between miner and client + use HashMap instead of BTreeMap

* Refactor refresh_cache for ServiceTransactionChecker

* Refresh cache fixes

* Add cache read in check_address + log when cache is used + improve code

* Remove ChainInfo from ServiceTransaction dependencies

* DRY ServiceTransactionChecker

* Fix Client and Miner in tests

* Fix node_filter test

* Fix Client::new in add_peer_with_private_config

* WIP: Separated ChainNotify from ethcore trait and implemented ChainNotify for ServiceTransactionChecker

* Fix watcher test

* Revert "Merge branch 'master' into master"

This reverts commit 4e7371dc109d022efe3087defc33d827998ce648, reversing
changes made to bffd73e5fd58a516bbf404281b51cf26422e181e.

* Revert "Fix watcher test"

This reverts commit bffd73e5fd58a516bbf404281b51cf26422e181e.

* Revert "WIP: Separated ChainNotify from ethcore trait and implemented ChainNotify for ServiceTransactionChecker"

This reverts commit 6e73d1e61fa15dc10ffd4fab63df29eabe9c3b3a.

* Revert "Fix Client::new in add_peer_with_private_config"

This reverts commit ec610a30bee95588d58b79edcc9e43c2ff90f1ad.

* Revert "Fix node_filter test"

This reverts commit 06a4b2de86317c902f579e912b40de0b0fbf6d78.

* Revert "Fix Client and Miner in tests"

This reverts commit 51bbad330ea6e7bdfc1516208cc8705d5d11516d.

* Implement ServiceTransactionChecker in miner and delegate it to client + revert unnecessary changes

* Merge master

* Code improvements

* Merge branch 'master' of https://github.com/paritytech/parity-ethereum

# Conflicts:
#	Cargo.lock
#	ethcore/private-tx/src/lib.rs
#	ethcore/src/miner/miner.rs
#	ethcore/src/miner/pool_client.rs
2019-03-31 10:39:38 +02:00
TriplEight
440e52f410 build android with cache, win fixes (#10546)
* build android with cache!

* windows fixes

* windows fixes 2

* windows fixes 3

* windows fixes 4

* windows should have sccache variables in env variables
2019-03-30 20:29:08 +01:00
jwasinger
8840a293dd clique: make state backfill time measurement more accurate (#10551) 2019-03-30 20:28:32 +01:00
Marek Kotewicz
89d627769e updated lru-cache to 0.1.2 (#10542) 2019-03-29 12:25:15 +00:00
TriplEight
4e2e88a620
separate docker image to build docs (#10543) 2019-03-28 17:19:00 +01:00
Niklas Adolfsson
ebf51c0be0 fix(bump dependencies) (#10540)
* cargo update -p log:0.4.5

* cargo update -p regex:1.0.5

* cargo update -p parking_lot

* cargo update -p serde_derive

* cargo update -p serde_json

* cargo update -p serde

* cargo update -p lazy_static

* cargo update -p num_cpus

* cargo update -p toml
2019-03-28 15:31:06 +00:00
Wei Tang
04c6867660 Fix max_gas (#10537)
Fix max_gas
2019-03-27 15:53:06 -04:00
soc1c
0199acbece
ethcore: remove eth social and easthub chain configs (#10531) 2019-03-27 15:07:38 +01:00
Denis S. Soldatov aka General-Beck
e4c2fe9e72 Initial support sccache for windows build (#10520)
* Initial support sccache for win build

* show sccache stats

* cache paths for shared runners

* sccache status is in the script.

* removed windows test for now
2019-03-27 14:47:08 +01:00
Niklas Adolfsson
407de5e8c4 fix(light): make OnDemand generic instead of using the concrete type (#10514)
* ethcore: add clique engine (#9981)

* fix broken sync

* correct seal fields

* ethcore: fix comment

* parity: remove duplicate params

* clique: fix whitespaces

* ethcore: fix goerli chain spec

* refactor signer_snapshot into pending/finalized state

* move close_block_extra_data after seal is applied

* refactor most of the logic into the signer_snapshot

* clique: refactor locking logic out of the consensus engine interface

* Fix jsonspec and add an unittest

* Replace space with tabs

* Unbroke sync

* Fix broken sync

* 1/2 state tracking without votes

* 2/2 implement vote tracking

* ci: use travis for goerli

* ci: setup a clique network

* ci: sync a görli node

* add clique deploy script

* ci: fix paths in clique deploy script

* ci: use docker compose

* ci: fix travis job names

* ci: fix build deps

* ci: massively reduce tests

* Revert "ci: massively reduce tests"

This reverts commit 6369f0b069ed2607a7e9f2e1d85489bacdc43384.

* ci: run cargo test directly

* ci: separate build and test stages

* ci: cache rust installation

* ci: simplify ci stages

* ci: make clique deploy script executable

* ci: shutdown goerli sync after 20min

* ci: remove slow sync stage

* ci: use timeout to finish jobs

* ci: fix build path

* ci: use absolute paths to end this confusion

* ci: add geth and parity to path

* ci: be more verbose

* ci: allow for more relaxed caching timeout

* ci: update repositories for custom ppa

* ci: fix typo in file name

* ci: fix docker compose file

* ci: add ethkey to docker

* ci: make sure deploy script is up to date with upstream

* ci: stop docker container after certain time

* ci: force superuser to update permissions on docker files

* ci: reduce run time of script to ~30 min

* ci: remove duplicate caching in travis

* remove trace statements

* clique: add more validation involving the recent signer list

* ethcore: enable constantinople for rinkeby

* ethcore: fix whitespaces in rinkeby spec

* ethcore: reformat goerli.json

* Revert "ci: remove duplicate caching in travis"

This reverts commit a562838d3d194d37f9871dcbe00b783637978f89.

* tmp commit

* another tmp commit

* it builds!

* add sealing capabilities

* add seal_header hook to allow separation of block seal/importing code paths

* clique: remove populate_from_parent.

* add panic

* make turn delay random

* initialize OpenBlock properly in 'enact'

* misc: remove duplicate lines

* misc: fix license headers

* misc: convert spaces to tabs

* misc: fix tabs

* Update Cargo.toml

* Update Cargo.toml

* Update Cargo.toml

* clique: ensure validator restores state before trying to seal

* clique: make 'state' return an Error.  Make some error messages more clear

* Fix compile error after rebase & toolchain upgrade

* fix a bunch of import warnings

* Refactor code

* Fix permissions

* Refactoring syncing

* Implement full validator checks

* Refactor util functions to seperate file

* mining 1

* ethcore: add chainspec for kotti

* ethcore: rename pre-goerli configs

* ethcore: load kotti chain spec

* cli: add kotti to params

* Implement working local sealing

* making sealing & syncing work together

* Relax timestamp checking

* ethcore: prepare for the real goerli to launch

* Implement NOTURN wiggle properly & cleanupnup warnings

* Implement vote casting

* Update docs & skip signing if no signer

* Optimize step-service interval

* Record state on local sealed block

* Fix script filemode

* Cleaning up codebase

* restore enact trace logging

* Delete clique.sh and move sync.sh

* remove travis.yml

* Remove dead code

* Cleanup compile warning

* address review comments

* adding more comments and removing unwrap()

* ci: remove sync script

* Address review comments

* fix compile error

* adding better debugging for timing

* Implement an dedicated thread for sealing timing

* fix(add helper for timestamp overflows) (#10330)

* fix(add helper timestamp overflows)

* fix(simplify code)

* fix(make helper private)

* snap: official image / test (#10168)

* official image / test

* fix / test

* bit more necromancy

* fix paths

* add source bin/df /test

* add source bin/df /test2

* something w paths /test

* something w paths /test

* add source-type /test

* show paths /test

* copy plugin /test

* plugin -> nil

* install rhash

* no questions while installing rhash

* publish snap only for release

* fix(docker): fix not receives SIGINT (#10059)

* fix(docker): fix not receives SIGINT

* fix: update with reviews

* update with review

* update

* update

* Don't add discovery initiators to the node table (#10305)

* Don't add discovery initiators to the node table

* Use enums for tracking state of the nodes in discovery

* Dont try to ping ourselves

* Fix minor nits

* Update timeouts when observing an outdated node

* Extracted update_bucket_record from update_node

* Fixed typo

* Fix two final nits from @todr

* change docker image based on debian instead of ubuntu due to the chan… (#10336)

* change docker image based on debian instead of ubuntu due to the changes of the build container

* role back docker build image and docker deploy image to ubuntu:xenial based (#10338)

* Bundle protocol and packet_id together in chain sync (#10315)

Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object.

* snap: prefix version and populate candidate channel (#10343)

* snap: populate candidate releases with beta snaps to avoid stale channel

* snap: prefix version with v*

* addressing review comments

* engine: fix copyright header

* scripts: restore permissions on sign command

* ethcore: enforce tabs

* ethcore: enforce tabs

* ethcore: enforce tabs

* addressing comments

* addressing comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* json-spec: fix clique epoch to non-zero u64

* ci: enable travis for parity goerli

* ci: don't separate build and test step

* ci: don't run c++ tests on travis

* ci: simplify cargo test to squeeze into travis timeout

* ci: don't run tests on travis at all

* style(fixes)

* fix(add tests)

* fix(recent_signer bug)

* fix(complete all tests)

* fix(nits)

* fix(simplify asserts)

* fix(cliqueState): simplify code

* fix(nits)

* docs(comments what's need to fixed)

* fix(revert unintended changes)

* fix(tests)

* fix(logs): voting logs

* fix(readability + more logs)

* fix(sync)

* docs(add missing licens header)

* fix(log): info! -> trace!

* docs(fix nits) + fix(remove assert)

* perf(use counter instead of vec)

* fix(remove needless block in match)

* fix(faulty comment)

* grumbles(docs for tests)

* fix(nits)

* fix(revert_vote): only remove vote when votes == 0

* fix(vote counter): checked arithmetics

* fix(simplify tests)

* fix(nits)

* fix(clique): err types

* fix(clique utils): make use of errors

* fix(cleanup nits)

* fix(clique sealing): don't read state no signer

* fix(replace Vec<Signers> with BTreeSet<Signers>)

* fix(tests): BTreeSet and more generic helpers

* fix(nits)

* fix(ethcore_block_seal): remove needless `Box`

* fix(faulty log): info -> trace

* fix(checked SystemTime): prevent SystemTime panics

* style(chain cfg): space after `:`

* style(fn enact): fix whitespace

* docs(clique): StepService

* docs(nit): fix faulty comment

* docs(fix typo)

* style(fix bad indentation)

* fix(bad regex match)

* grumble(on_seal_block): make `&mut` to avoid clone

* docs(on_seal_block): fix faulty documentation

* Delete .travis.yml

* docs: remove eth hf references in spec

* Update client.rs

* fix(nits)

* fix(clique step): `RwLock` -> `AtomicBool`

* fix(clique): use `Duration::as_millis`

* Clean up some Clique documentation

* Add trace information to eth_estimateGas (#10519)

* Add trace information to eth_estimateGas

* replace unwrap better version

* change vm::Error formatter to more user-friendly

* remove extra error format

* use map_or instead sequence of map/unwrap_or

* fix(light/on_demand): extract as a trait

* fix(grumble): OnDemand remove needless trait bound
2019-03-27 14:46:20 +01:00
Andrew Jones
7d26a82232 private-tx: replace error_chain (#10510)
* Update to vanilla tx pool error

* private-tx: remove error-chain, implement Error, derive Display

* private-tx: replace ErrorKind and bail!

* private-tx: add missing From impls and other compiler errors

* private-tx: use original tx-pool error

* Don't be silly cargo
2019-03-27 14:46:05 +01:00
Kirill Fomichev
3b23817936
Add trace information to eth_estimateGas (#10519)
* Add trace information to eth_estimateGas

* replace unwrap better version

* change vm::Error formatter to more user-friendly

* remove extra error format

* use map_or instead sequence of map/unwrap_or
2019-03-27 14:21:08 +01:00
5chdn
aa8487c1d0
ethcore: add clique engine (#9981)
* fix broken sync

* correct seal fields

* ethcore: fix comment

* parity: remove duplicate params

* clique: fix whitespaces

* ethcore: fix goerli chain spec

* refactor signer_snapshot into pending/finalized state

* move close_block_extra_data after seal is applied

* refactor most of the logic into the signer_snapshot

* clique: refactor locking logic out of the consensus engine interface

* Fix jsonspec and add an unittest

* Replace space with tabs

* Unbroke sync

* Fix broken sync

* 1/2 state tracking without votes

* 2/2 implement vote tracking

* ci: use travis for goerli

* ci: setup a clique network

* ci: sync a görli node

* add clique deploy script

* ci: fix paths in clique deploy script

* ci: use docker compose

* ci: fix travis job names

* ci: fix build deps

* ci: massively reduce tests

* Revert "ci: massively reduce tests"

This reverts commit 6369f0b069ed2607a7e9f2e1d85489bacdc43384.

* ci: run cargo test directly

* ci: separate build and test stages

* ci: cache rust installation

* ci: simplify ci stages

* ci: make clique deploy script executable

* ci: shutdown goerli sync after 20min

* ci: remove slow sync stage

* ci: use timeout to finish jobs

* ci: fix build path

* ci: use absolute paths to end this confusion

* ci: add geth and parity to path

* ci: be more verbose

* ci: allow for more relaxed caching timeout

* ci: update repositories for custom ppa

* ci: fix typo in file name

* ci: fix docker compose file

* ci: add ethkey to docker

* ci: make sure deploy script is up to date with upstream

* ci: stop docker container after certain time

* ci: force superuser to update permissions on docker files

* ci: reduce run time of script to ~30 min

* ci: remove duplicate caching in travis

* remove trace statements

* clique: add more validation involving the recent signer list

* ethcore: enable constantinople for rinkeby

* ethcore: fix whitespaces in rinkeby spec

* ethcore: reformat goerli.json

* Revert "ci: remove duplicate caching in travis"

This reverts commit a562838d3d194d37f9871dcbe00b783637978f89.

* tmp commit

* another tmp commit

* it builds!

* add sealing capabilities

* add seal_header hook to allow separation of block seal/importing code paths

* clique: remove populate_from_parent.

* add panic

* make turn delay random

* initialize OpenBlock properly in 'enact'

* misc: remove duplicate lines

* misc: fix license headers

* misc: convert spaces to tabs

* misc: fix tabs

* Update Cargo.toml

* Update Cargo.toml

* Update Cargo.toml

* clique: ensure validator restores state before trying to seal

* clique: make 'state' return an Error.  Make some error messages more clear

* Fix compile error after rebase & toolchain upgrade

* fix a bunch of import warnings

* Refactor code

* Fix permissions

* Refactoring syncing

* Implement full validator checks

* Refactor util functions to seperate file

* mining 1

* ethcore: add chainspec for kotti

* ethcore: rename pre-goerli configs

* ethcore: load kotti chain spec

* cli: add kotti to params

* Implement working local sealing

* making sealing & syncing work together

* Relax timestamp checking

* ethcore: prepare for the real goerli to launch

* Implement NOTURN wiggle properly & cleanupnup warnings

* Implement vote casting

* Update docs & skip signing if no signer

* Optimize step-service interval

* Record state on local sealed block

* Fix script filemode

* Cleaning up codebase

* restore enact trace logging

* Delete clique.sh and move sync.sh

* remove travis.yml

* Remove dead code

* Cleanup compile warning

* address review comments

* adding more comments and removing unwrap()

* ci: remove sync script

* Address review comments

* fix compile error

* adding better debugging for timing

* Implement an dedicated thread for sealing timing

* fix(add helper for timestamp overflows) (#10330)

* fix(add helper timestamp overflows)

* fix(simplify code)

* fix(make helper private)

* snap: official image / test (#10168)

* official image / test

* fix / test

* bit more necromancy

* fix paths

* add source bin/df /test

* add source bin/df /test2

* something w paths /test

* something w paths /test

* add source-type /test

* show paths /test

* copy plugin /test

* plugin -> nil

* install rhash

* no questions while installing rhash

* publish snap only for release

* fix(docker): fix not receives SIGINT (#10059)

* fix(docker): fix not receives SIGINT

* fix: update with reviews

* update with review

* update

* update

* Don't add discovery initiators to the node table (#10305)

* Don't add discovery initiators to the node table

* Use enums for tracking state of the nodes in discovery

* Dont try to ping ourselves

* Fix minor nits

* Update timeouts when observing an outdated node

* Extracted update_bucket_record from update_node

* Fixed typo

* Fix two final nits from @todr

* change docker image based on debian instead of ubuntu due to the chan… (#10336)

* change docker image based on debian instead of ubuntu due to the changes of the build container

* role back docker build image and docker deploy image to ubuntu:xenial based (#10338)

* Bundle protocol and packet_id together in chain sync (#10315)

Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object.

* snap: prefix version and populate candidate channel (#10343)

* snap: populate candidate releases with beta snaps to avoid stale channel

* snap: prefix version with v*

* addressing review comments

* engine: fix copyright header

* scripts: restore permissions on sign command

* ethcore: enforce tabs

* ethcore: enforce tabs

* ethcore: enforce tabs

* addressing comments

* addressing comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* addressing more comments

* json-spec: fix clique epoch to non-zero u64

* ci: enable travis for parity goerli

* ci: don't separate build and test step

* ci: don't run c++ tests on travis

* ci: simplify cargo test to squeeze into travis timeout

* ci: don't run tests on travis at all

* style(fixes)

* fix(add tests)

* fix(recent_signer bug)

* fix(complete all tests)

* fix(nits)

* fix(simplify asserts)

* fix(cliqueState): simplify code

* fix(nits)

* docs(comments what's need to fixed)

* fix(revert unintended changes)

* fix(tests)

* fix(logs): voting logs

* fix(readability + more logs)

* fix(sync)

* docs(add missing licens header)

* fix(log): info! -> trace!

* docs(fix nits) + fix(remove assert)

* perf(use counter instead of vec)

* fix(remove needless block in match)

* fix(faulty comment)

* grumbles(docs for tests)

* fix(nits)

* fix(revert_vote): only remove vote when votes == 0

* fix(vote counter): checked arithmetics

* fix(simplify tests)

* fix(nits)

* fix(clique): err types

* fix(clique utils): make use of errors

* fix(cleanup nits)

* fix(clique sealing): don't read state no signer

* fix(replace Vec<Signers> with BTreeSet<Signers>)

* fix(tests): BTreeSet and more generic helpers

* fix(nits)

* fix(ethcore_block_seal): remove needless `Box`

* fix(faulty log): info -> trace

* fix(checked SystemTime): prevent SystemTime panics

* style(chain cfg): space after `:`

* style(fn enact): fix whitespace

* docs(clique): StepService

* docs(nit): fix faulty comment

* docs(fix typo)

* style(fix bad indentation)

* fix(bad regex match)

* grumble(on_seal_block): make `&mut` to avoid clone

* docs(on_seal_block): fix faulty documentation

* Delete .travis.yml

* docs: remove eth hf references in spec

* Update client.rs

* fix(nits)

* fix(clique step): `RwLock` -> `AtomicBool`

* fix(clique): use `Duration::as_millis`

* Clean up some Clique documentation

Co-authored-by: soc1c <soc1c@users.noreply.github.com>
Co-authored-by: HCastano <HCastano@users.noreply.github.com>
Co-authored-by: niklasad1 <niklasad1@users.noreply.github.com>
Co-authored-by: jwasinger <jwasinger@users.noreply.github.com>
Co-authored-by: ChainSafe <ChainSafe@users.noreply.github.com>
Co-authored-by: thefallentree <thefallentree@users.noreply.github.com>
Co-authored-by: 5chdn <5chdn@users.noreply.github.com>
2019-03-27 14:13:24 +01:00
TriplEight
9cb8606103
verbose flag for cpp tests (#10524) 2019-03-26 12:37:45 +01:00
Hernando Castano
6cf3ba7efd
Add a more realistic Batch test (#10511)
* Remove unrealistic tests

* Add test that more closely resembles real usage
2019-03-25 10:42:33 +01:00
Sočik
023e511f83 docs: add changelogs for 2.3.{6,7,8} and 2.4.{1,2,3} (#10494)
* docs: add changelogs for 2.3.{6,7} and 2.4.{1,2}

* docs: add changelogs for 2.4.3 beta and 2.3.8 stable

* Update docs/CHANGELOG-2.3.md

Co-Authored-By: soc1c <47772477+soc1c@users.noreply.github.com>

* Update docs/CHANGELOG-2.3.md

Co-Authored-By: soc1c <47772477+soc1c@users.noreply.github.com>

* docs: remove empty lines
2019-03-22 15:59:20 +01:00
Niklas Adolfsson
17042e9c32 fix(rpc): fix a bunch of clippy lints (#10493)
* fix(rpc): fix a bunch of clippy lints

* fix(rpc clippy): remove unused ignored lints

* fix(clippy): fix all redundant_field_names

This commit fixes all uses of `redundant_field_names` and removes the ignored lint `redundant_field_names`

* fix(brain unwrap): replace with expect
2019-03-22 12:01:11 +01:00
Denis S. Soldatov aka General-Beck
f2c34f7ca2 fix Sha3/keccak256 hash calculation for binaries (#10509)
https://github.com/paritytech/parity-ethereum/issues/10495
2019-03-22 11:46:57 +01:00
Hernando Castano
375a8daeb4
Add additional request tests (#10503) 2019-03-21 17:37:13 +01:00
Guillaume Ballet
b700ff3501 whisper/cli: add p2p port and ip parameters (#10057)
* whisper/cli: add p2p port and ip parameters

This is so that those params don't change randomly and are in sync with the URL that
is displayed.

* feedback: Result instead of panic

Co-Authored-By: gballet <gballet@gmail.com>

* feedback: Map error in port conversion

Co-Authored-By: gballet <gballet@gmail.com>

* whisper/cli: User can specify enode private key

So that the enode doesn't change at every run.

* whipser/cli: finish integrating review feedback.

* Accomodate error API change

* Update rustc-hex version in whisper/cli/Cargo.toml

Co-Authored-By: gballet <gballet@gmail.com>

* Update README with new whisper cli options

* Fix typo in error message

Co-Authored-By: gballet <gballet@gmail.com>

* Fix Cargo.lock and build issue after lib version upgrade

* Fix another typo

Co-Authored-By: gballet <gballet@gmail.com>
2019-03-21 17:45:02 +03:00
Niklas Adolfsson
9519493e32 fix(time-utils): add missing license (#10497) 2019-03-20 16:01:38 +01:00
Niklas Adolfsson
037fd1b309 fix(extract timestamp_checked_add as lib) (#10383)
* fix(extract `timestamp_checked_add` as lib)

* fix(whisper types): remove unused `EmptyTopics`

* fix(time-lib): feature-flag to use time-lib or std

This commit adds conditional compilation checks that falls back to `our time-lib` when
`time_checked_add` is not available in the standard library

Note, `time_checked_add` covers both `checked_add` and `checked_sub`

* fix(grumble): use cfg_attr to define rustc feature
2019-03-19 23:17:05 +01:00
Niklas Adolfsson
78a534633d fix(rpc): lint unused_extern_crates + fix warns (#10489) 2019-03-19 16:37:24 +01:00
Denis S. Soldatov aka General-Beck
effead9ba5 fix win&mac build (#10486)
add CARGO_HOME:                      "${CI_PROJECT_DIR}/.cargo"
2019-03-19 11:39:44 +01:00
TriplEight
a8ee3c97e6 Сaching through docker volume (#10477)
* _old codebase_ before docker update

* before docker update, testing runnr

* docker update, testing the caching

* distributed job cargo homes

* distributed job cargo homes 2

* distributed job cargo homes 3

* dockerfile with gitlab checkout, audit uses template

* dockerfile gets repo in volume

* change builds_dir

* trying docker cache for repo

* repo cached automatically

* after script is not concatenated

* check sccache non-cacheable reasons nature

* watch cache

* log sccache

* log sccache 2

* debug log sccache

* fix debug log sccache

* fix debug log sccache 2

* debug log cache 3

* debug log cache 3

* trace log all sccache

* test wo cargo cache

* test w removed cargo cache

* report non-cacheable reasons, cargo cache is back and empty

* report non-cacheable reasons, cargo cache is back and empty 2

* report non-cacheable reasons, cargo cache is back and empty 3

* wrap into after_script

* restore CI tags

`qa` -> `linux-docker`

* return to main runners, this will fail until config on runners And Dockerfile won't be updated

* typo fix CI lint

* return to docker tag
2019-03-19 03:14:59 +03:00
Marek Kotewicz
fb461659c7
OpenBlock::new take IntoIterator instead of mutable ref to Iterator (#10480) 2019-03-15 15:43:54 +01:00
Marek Kotewicz
a574df3132 simplify block module and usage (#10479)
* removed trait IsBlock and simplify block usage

* removed redundant ClosedBlock::hash function
2019-03-15 12:22:47 +00:00
Marek Kotewicz
d83143d0ba remove unused Engine::maximum_uncle_age (#10476) 2019-03-14 21:34:26 +01:00
Marek Kotewicz
f875175325 remove unused Engine::is_proposal (#10475) 2019-03-14 12:40:59 +00:00
Marek Kotewicz
c9db8ea21d further simplify machine (#10472)
* removed AuxiliaryRequest from Machin trait

* removed AncestryAction from Machine trait

* removed AuxiliaryData from Machine trait

* removed LocalizedMachine trait
2019-03-14 11:28:15 +01:00
Marek Kotewicz
a16bad4175
simplify parity machine (#10469)
* simplify ethcore machine by removing redundant traits

* further ethereum machine simplifications

* removed obsolete todo
2019-03-13 11:36:13 +01:00
Hernando Castano
595dac6c3f
Ensure static validator set changes are recognized (#10467) 2019-03-12 19:16:29 +01:00
TriplEight
82a148a99b
Tests parallelized (#10452)
* tests splitted, phase 1

* typo

* fix wrong launch commands

* typos

* rearrangements

* use `nproc` function for threads

* use nproc for threads

* let theads be auto, build-andriod no more in regular run

* split val chain and cargo check

* renamed some files

* wrong phase

* check rust files before test jobs

* lint error

* rust files modivied var

* test except changes

* add rust_changes except

* lint error

* fixes

* .gitlab-ci.yml can't be excluded

* pipeline shouldn't start

* pipeline must go

* pipeline must go 2

* pipeline must go 3

* pipeline must go 4

* pipeline must go 5

* pipeline must go 6

* pipeline must go 7

* pipeline must not go 1

* pipeline must go 8

* avoid skippng tests yet, reintroducing them after the caching

* test theory

* parallelized cargo check with combusting helicopters

* less uploads

* alias for cargo checks

* nice template
2019-03-11 15:26:35 +01:00
Niklas Adolfsson
4320c9bc4f docs(spec): remove link to obsolete issue (#10464) 2019-03-11 11:48:01 +01:00
Marek Kotewicz
23d977ecce simplify ethcore machine by removing redundant traits (#10454) 2019-03-11 10:37:48 +00:00
5chdn
ab27848dc4 docs: update changelogs for 2.2.{8,9,10,11}, 2.3.{1,2,3,4,5}, and 2.4.0 (#10389)
* docs: move changelog 2-3 to docs/

* docs: fix changelog 2-3 path

* docs: add changelogs for 2.2.{8,9,10,11}

* docs: add changelogs for 2.3.{1,2,3,4}

* Update CHANGELOG.md

* Update CHANGELOG-2.3.md

* Update CHANGELOG.md

* Update CHANGELOG.md
2019-03-07 21:11:58 +01:00
Denis S. Soldatov aka General-Beck
742a6007fe
Revert "CI aws git checkout (#10451)" (#10456)
* Revert "CI aws git checkout (#10451)"

This reverts commit 3e1d73126c.

* Update .gitlab-ci.yml

revert aws script with small fixes

* Delete publish-aws.sh
2019-03-07 14:45:35 +03:00
Niklas Adolfsson
91933d857d perf(ethcore): micro-opt (#10405)
Mostly fixes that changes `eagerly eval` to `lazy eval`
2019-03-06 15:30:35 +01:00
Denis S. Soldatov aka General-Beck
3e1d73126c CI aws git checkout (#10451)
* Updating the CI system with the publication of releases and binary files on github

Signed-off-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>

* move publish aws from gitlab.yml to gitlab scripts

Signed-off-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>

* gitlab.yml cleaning
move publish AWS to gitlab scripts
remove dependencies from android build

Signed-off-by: Denis S. Soldatov aka General-Beck <general.beck@gmail.com>

* Revert "Updating the CI system with the publication of releases and binary files on github"

This reverts commit da87e06f2e4751dbca08a898b52926aef5ad0aba.

* remove no-git for aws

* microfix

* no need in no_git then
2019-03-05 18:33:10 +01:00
Axel Chalon
7014642815 Implement parity_versionInfo & parity_setChain on LC; fix parity_setChain (#10312)
* Light client: implement parity_versionInfo RPC

* Light client: implement set_exit_handler & parity_setChain RPC

* parity_setChain RPC: return an error if failed (instead of `true`)

* Implement eth_subscribe('syncing') RPC for full node & light node

* Fix indentation

* Revert commit: Implement eth_subscribe('syncing')

* Revert change to Cr callback function
2019-03-04 20:24:53 +01:00
Denis S. Soldatov aka General-Beck
1bd4564216
CI publish to aws (#10446)
* move publish aws from gitlab.yml to gitlab scripts

* gitlab.yml cleaning
move publish AWS to gitlab scripts
remove dependencies from android build
2019-03-04 21:59:20 +03:00
Andrew Jones
97cb010df8 Silence Error::cause deprecations (#10438) 2019-03-02 13:18:18 +01:00
Hernando Castano
ed18c7b54c Use correct name for documentation field in Cargo.toml (#10440) 2019-03-01 16:23:40 +00:00
Thibaut Sardan
e71598d876 Update hardcoded headers for Foundation, Ropsten, Kovan and Classic (#10417)
* update foundation to #7262209

* update kovan to #10434561

* update ropsten to #5027841

* update classic to #7555073

* Update Ropsten headers to #5101569
2019-02-27 15:50:45 +01:00
Marek Kotewicz
3d0ce10fa6 panic_hook module uses eprintln instead of raw stderr interface (#10426) 2019-02-27 09:48:40 +00:00
soc1c
cfc8df156b ci: clean up gitlab-ci.yml leftovers from previous merge (#10429) 2019-02-27 10:47:27 +01:00
Marek Kotewicz
94cb3b6e0e
fix underflow in pip, closes #10419 (#10423) 2019-02-27 10:08:04 +01:00
Marek Kotewicz
fefec000fb
remove redundant macro println_stderr from parity/cli/usage.rs (#10425) 2019-02-27 10:07:41 +01:00
Mohanson
c7ded6a785 Remove duplicate test cases (#10385)
Case create_account() is same as new_account()
2019-02-27 10:07:12 +01:00
Marek Kotewicz
2fbb952cdd parity/main.rs uses eprintln instead of raw stderr interface (#10427) 2019-02-27 11:41:03 +03:00
Marek Kotewicz
e2ab3e4f5b fix panic when logging directory does not exist, closes #10420 (#10424) 2019-02-26 18:14:11 +01:00
elferdo
1871275ecd Refactor ethcore::client::TransactResult to use it inside std::result::Result (#10366)
* Refactor TransactResult

* Adapt evmbin and tests
2019-02-26 13:49:33 +01:00
joshua-mir
afc1b72611 10000 > 5000 (#10422)
addresses #10418
2019-02-26 15:35:40 +03:00
Niklas Adolfsson
c5c3fb6a75
fix(rpc-types): replace uint and hash with ethereum_types v0.4 (#10217)
* fix(rpc-types): remove uint and hash wrappers

* fix(tests)

* fix(cleanup)

* grumbles(rpc-api): revert `verify_signature`

* revert change of `U64` -> `u64`

* fix(cleanup after bad merge)

* chore(bump ethereum-types)

* fix(bad merge)

* feat(tests ethereum-types): add tests

* chore(update `ethereum-types` to 0.4.2)

* feat(tests for h256)

* chore(rpc): remove `ethbloom` import

Use re-export from `ethereum-types` instead

* fix(bad merge): remove `DefaultAccount` type

* doc(add TODO with issue link)
2019-02-25 14:27:28 +01:00
5chdn
bceb883d99 snap: reenable i386, arm64, armhf architecture publishing (#10386)
* snap: reenable i386, arm64, armhf architecture publishing

* gitlab: fix indent

* gitlab: fix yml syntax

* Linker for crosscomile

* fix target to linker

* new docker image

* fix lint, add build to this PR

* calc SHA3 using rhash

* add new images for i386, armhf

* show snap target & artifacts

* set CARGO_TARGET for publish snap

* move detect Version to publish snap

* rm libc6 dep from snap-template up pub-snap script

* clean up cargo config before add linker

* move linker config to docker images
2019-02-25 14:56:38 +03:00
Antoine
fcccbf3b75 fix #10390 (#10391) 2019-02-22 15:31:34 +01:00
Wei Tang
9ad71b7baa Fix to_pod storage trie value decoding (#10368) 2019-02-22 14:00:20 +01:00
TriplEight
4311d43497
revert some changes, could be buggy (#10399) 2019-02-21 21:06:49 +01:00
5chdn
0815cc3b83 version: bump nightly to 2.5 (#10392)
* version: bump nightly to 2.5

* revert(rand 0.3.22)
2019-02-21 20:03:34 +01:00
TriplEight
b21844b371 no-git for publish jobs, empty artifacts dir (#10393)
* no-git for publish jobs, empty artifacts dir

* fix syntax

* prettiness

* fix prettiness

* should get rid of git in publishing
2019-02-21 21:14:59 +03:00
Niklas Adolfsson
f825048efa fix(jni): bump to jni to 0.11 & remove unsafe impl (#10394) 2019-02-21 19:26:01 +03:00
Niklas Adolfsson
2cbffe36e2 chore(bump ethereum-types) (#10396)
Fixes a de-serialization bug in `ethereum-tyes`
2019-02-21 15:34:41 +00:00
cheme
6bb106a784 Update to latest mem-db, hash-db and trie-db. (#10314)
* 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>

* Update ethcore/src/snapshot/tests/state.rs

Co-Authored-By: cheme <emericchevalier.pro@gmail.com>
2019-02-20 21:09:34 +03:00
Andrew Jones
4e0ec4e66b
tx pool: always accept local transactions (#10375)
* tx pool: always accept local transactions

* tx pool: `choose` local txs with same sender and nonce
2019-02-20 16:49:39 +00:00
Niklas Adolfsson
b58a3ed0ad fix(trace_main! macro): don't re-export (#10384) 2019-02-20 10:52:28 +01:00
felix
b803f57db6 exchanged old(azure) bootnodes with new(ovh) ones (#10309)
* exchanged old(azure) bootnodes with new(ovh) ones

* Fix indent
2019-02-20 10:06:26 +01:00
André Silva
b457f46c81 ethash: implement Progpow (#9762)
* ethash: initial implementation of progpow

* progpow: use wrapping arithmetic

* progpow: cleanup comments

* progpow: fix keccak_f800

* progpow: reorder definitions

* progpow: general fixing

* progpow: add basic tests from geth

* progpow: generate c_dag and add test

* progpow: fix progpow_init and progpow_loop

* progpow: fix and add new test

* progpow: tabify

* progpow: add shared testvectors from geth and aleth

* progpow: add benchmarks

* progpow: don't read bytes from dag

* ethash: use criterion for progpow benchmarks

* progpow: dont borrow hash on fnv1a_hash

* progpow: don't borrow operand on progpow merge

* progpow: hardcode dag lookup function

we only support light verification anyway

* progpow: read double words directly from the dag

* progpow: inline some small functions

* progpow: remove some bounds checking from the main loop

* progpow: remove unreachable match cases

* progpow: remove bounds check in keccak_f800_round

* progpow: fix ptr::swap

* progpow: force loop unroll in keccak_f800_round

* progpow: remove unnecessary branching in progpow_loop

* progpow: force loop unroll in fill_mix

* progpow: silence unused warning

* progpow: dont run last keccak_f800_round out of the loop

rustc generates the same assembly, it unrolls the loop

* progpow: fix output of keccak_f800_short

* ethcore: support progpow in ethash engine

* ethash: fix typo

* ethcore, ethash: fix tests

* json: fix ethash spec tests

* ethash: update quick_get_difficulty for progpow

* ethash: drop light cache on progpow transition block

* ethash: fix quick_get_difficulty tests

* progpow: update to spec v0.9.0

* progpow: update to spec v0.9.1

* progpow: update to spec v0.9.2

* ethash: rename progpow benchmarks

* fix Cargo.lock bad merge

* ethash: only export modules for benchmarks

* ethash: progpow: remove unsafe unchecked indexing

* ethash: create enum for pow algorithm

* ethash: box the progpow cdag

* ethash: skip slow progpow test vectors on ci

* ethash: don't skip progpow test vectors

they don't take too long when running in release mode which is the case
for CI.

* ethash: progpow: update copyright date

Co-Authored-By: andresilva <andre.beat@gmail.com>

* ethcore: remove verification of ci-skip-tests on non-test builds
2019-02-20 10:05:11 +01:00
Leo Arias
b4520c5886 snap: add the removable-media plug (#10377)
This interface allows the snap to access the directories in /media. This is needed when the storage is in a separate disk, not part of home.
2019-02-20 09:49:54 +01:00
Psilon
ca67dc251f Add message to IO errors (#10324) 2019-02-18 20:39:38 +03:00
Niklas Adolfsson
aea289e79e chore(bump parity-daemonize): require rust >= 1.31 (#10359) 2019-02-18 13:38:46 +01:00
Svyatoslav Nikolsky
ef0eda0c39 SecretStore: use in-memory transport in cluster tests (#9850)
* fixing SS tests

* removed some redundant clones

* fixed grumbles

* replaced hash.clone() with *hash + fixed comment

* lost files
2019-02-18 13:38:19 +01:00
Hernando Castano
af7dc3676b
Add fields to memzero's Cargo.toml (#10362)
* Add fields to Cargo.toml before publishing to crates.io

* Change license from MIT to GPL-3.0

* Add docs page
2019-02-15 12:32:33 +01:00
Afri Schoedon
fa570f297e snap: release untagged versions from branches to the candidate snap channel (#10357) 2019-02-14 17:24:52 +01:00
Niklas Adolfsson
9cce6a47d4 fix(compilation warns): no-default-features (#10346) 2019-02-14 17:54:44 +03:00
TriplEight
bff0bedfa9 no volumes are needed, just run -v volume:/path/in/the/container (#10345) 2019-02-14 12:45:56 +01:00
Dan Acristinii
d6c80c1672 Fixed misstype (#10351)
* Fixed misstype

BadTransactonType => BadTransactionType

* fixed other insances of transacton
2019-02-14 12:25:44 +01:00
Afri Schoedon
512343003d
snap: prefix version and populate candidate channel (#10343)
* snap: populate candidate releases with beta snaps to avoid stale channel

* snap: prefix version with v*
2019-02-13 15:50:02 +01:00
elferdo
3adb640d2b
Bundle protocol and packet_id together in chain sync (#10315)
Define a new `enum` where devp2p subprotocol packet ids (currently eth and par) are defined. Additionally provide functionality to query id value and protocol of a given id object.
2019-02-13 09:20:33 +01:00
gabriel klawitter
ea589a17a4
role back docker build image and docker deploy image to ubuntu:xenial based (#10338) 2019-02-12 20:52:30 +01:00
gabriel klawitter
a3883ca5d9
change docker image based on debian instead of ubuntu due to the chan… (#10336)
* change docker image based on debian instead of ubuntu due to the changes of the build container
2019-02-12 19:00:52 +01:00
Kirill Pimenov
5be0163cde Don't add discovery initiators to the node table (#10305)
* Don't add discovery initiators to the node table

* Use enums for tracking state of the nodes in discovery

* Dont try to ping ourselves

* Fix minor nits

* Update timeouts when observing an outdated node

* Extracted update_bucket_record from update_node

* Fixed typo

* Fix two final nits from @todr
2019-02-12 16:57:53 +01:00
Shude Li
55454b2f2d fix(docker): fix not receives SIGINT (#10059)
* fix(docker): fix not receives SIGINT

* fix: update with reviews

* update with review

* update

* update
2019-02-12 16:57:07 +01:00
TriplEight
a4dc85543b
snap: official image / test (#10168)
* official image / test

* fix / test

* bit more necromancy

* fix paths

* add source bin/df /test

* add source bin/df /test2

* something w paths /test

* something w paths /test

* add source-type /test

* show paths /test

* copy plugin /test

* plugin -> nil

* install rhash

* no questions while installing rhash

* publish snap only for release
2019-02-12 15:37:54 +01:00
Niklas Adolfsson
d8394bded7 fix(add helper for timestamp overflows) (#10330)
* fix(add helper timestamp overflows)

* fix(simplify code)

* fix(make helper private)
2019-02-12 14:16:23 +00:00
cheme
d89b8d904f Additional error for invalid gas (#10327)
* Tag sensible place (ECHECH)

* Additional overflows checks.
2019-02-11 22:20:51 +00:00
Hernando Castano
8e866ee551
Revive parity_setMinGasPrice RPC call (#10294)
* Add function to update minimum gas price

* Update TestMinerService to handle min_gas_price changes

* Place minimum gas price test behind feature flag

* Update check for fixed gas pricer to be more explicit

* Use errors::unsupported instead of errors::request_rejected

* Add test that fails to set minimum gas price

* Fix test that should fail when setting new gas price

* Put dev dependencies behind feature flag

* Fix deadlock in set_minimal_gas_price()

* Update RPC tests with mocked error response

* Remove unnecessary cfg flag

* Remove duplicate crate imports
2019-02-11 18:08:12 +01:00
Hernando Castano
6dfc1bd474 Add Statetest support for Constantinople Fix (#10323)
* Update Ethereum tests repo to v6.0.0-beta.3 tag

* Add spec for St.Peter's / ConstantinopleFix statetests
2019-02-11 17:13:36 +01:00
Niklas Adolfsson
c84e5745fa fix(parity-clib): grumbles that were not addressed in #9920 (#10154)
* fix(remove needless unsafe blocks)

* style(nits)

* fix(parity-clib): eliminate repetitive event loops

* revert(java bindings): safe rust -> unsafe rust

These functions can still end up with `UB` thus should be unsafe

* fix(grumbles): make Callback trait `pub (crate)`
2019-02-11 15:27:46 +01:00
Niklas Adolfsson
751d15e4be fix(light-rpc): Make light_sync generic (#10238)
* fix(light-rpc): Make `light_sync` generic

The motivation behind this change is to easily mock `light-sync` to make it possible to enable `rpc-integration` tests
for the light-client.

Currently the `rpc's` requires the concrete type `sync::LightSync` which makes it very hard to do so

* fix(bad merge)
2019-02-11 10:33:16 +00:00
TriplEight
8b6c5be6a9
fix publish job (#10317)
* fix publish job

* dashes and colonels
2019-02-08 18:22:08 +01:00
Axel Chalon
3502b36232 Secure WS-RPC: grant access to all apis (#10246) 2019-02-08 14:11:55 +01:00
elferdo
046b8bbc8a
Make specification of protocol in SyncRequester::send_request explicit (#10295)
* Make the specification of the protocol to which a packet_id belongs to
  explicit when calling "SyncRequester::send_packet".

* Remove "SyncIO::send" and leave only "SyncIO::send_protocol"

* Adapt tests to new code.

* Strengthen tests to check if packet_id and protocol match when sending
a devp2p packet.
2019-02-08 13:01:29 +01:00
Alexander Arlt
6fa4b2dec5 fix: parity-clib/examples/cpp/CMakeLists.txt (#10313)
* use of ${CMAKE_SHARED_LIBRARY_PREFIX} &
${CMAKE_SHARED_LIBRARY_SUFFIX} to support other operating systems.
2019-02-08 12:01:29 +03:00
TriplEight
83bcb819da
CI optimizations (#10297)
* CI optimizations

* fix stripping

* new dockerfile

* no need n submodule upd

* review

* moved dockerfile

* it becomes large

* onchain update depends on s3

* fix dependency

* fix cache status

* fix cache status

* new cache status
2019-02-07 18:49:50 +01:00
elferdo
b7e8621846 Increase number of requested block bodies in chain sync (#10247)
* Increase the number of block bodies requested during Sync.

* Increase the number of block bodies requested during Sync.

* Check if our peer is an older parity client with the bug
  of not handling large requests properly

* Add a ClientVersion struct and a ClientCapabilites trait

* Make ClientVersion its own module

* Refactor and extend use of ClientVersion

* Replace strings with ClientVersion in PeerInfo

* Group further functionality in ClientCapabilities

* Move parity client version data from tuple to its own struct.

* Implement accessor methods for ParityClientData and remove them
from ClientVersion.

* Minor fixes

* Make functions specific to parity return types specific to parity.

* Test for shorter ID strings

* Fix formatting and remove unneeded dependencies.

* Roll back Cargo.lock

* Commit last Cargo.lock

* Convert from string to ClientVersion

* * When checking if peer accepts service transactions just check
  if it's parity, remove version check.

* Remove dependency on semver in ethcore-sync

* Remove unnecessary String instantiation

* Rename peer_info to peer_version

* Update RPC test helpers

* Simplify From<String>

* Parse static version string only once

* Update RPC tests to new ClientVersion struct

* Document public members

* More robust parsing of ID string

* Minor changes.

* Update version in which large block bodies requests appear.

* Update ethcore/sync/src/block_sync.rs

Co-Authored-By: elferdo <elferdo@gmail.com>

* Update util/network/src/client_version.rs

Co-Authored-By: elferdo <elferdo@gmail.com>

* Update util/network/src/client_version.rs

Co-Authored-By: elferdo <elferdo@gmail.com>

* Update tests.

* Minor fixes.
2019-02-07 15:27:09 +01:00
Tomasz Drwięga
d5c19f8719 Deprecate account management (#10213)
* Extract accounts from ethcore.

* Fix ethcore.

* Get rid of AccountProvider in test_helpers

* Fix rest of the code.

* Re-use EngineSigner, fix tests.

* Simplify EngineSigner to always have an Address.

* Fix RPC tests.

* Add deprecation notice to RPCs.

* Feature to disable accounts.

* extract accounts in RPC

* Run with accounts in tests.

* Fix RPC compilation and tests.

* Fix compilation of the binary.

* Fix compilation of the binary.

* Fix compilation with accounts enabled.

* Fix tests.

* Update submodule.

* Remove android.

* Use derive for Default

* Don't build secretstore by default.

* Add link to issue.

* Refresh Cargo.lock.

* Fix miner tests.

* Update rpc/Cargo.toml

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Fix private tests.
2019-02-07 14:34:24 +01:00
Wei Tang
8fa56add47 Properly handle check_epoch_end_signal errors (#10015)
* Make check_epoch_end_signal to only use immutable data

* Move check_epoch_end_signals out of commit_block

* Make check_epoch_end_signals possible to fail

* Actually return the error from check_epoch_end_signals

* Remove a clone

* Fix import error
2019-02-07 14:34:07 +01:00
Niklas Adolfsson
e45ee6cd72 fix(osx and windows builds): bump parity-daemonize (#10291) 2019-02-07 12:53:12 +01:00
Julien Bouteloup
e344286c32 Add missing step for Using systemd service file (#10175)
* Add missing step for  Using `systemd` service file

Copy Parity release from target folder to bin, write `cp -R ./target/release/parity /usr/bin/` to match `ExecStart=/usr/bin/parity --config /etc/parity/config.toml` from `https://github.com/paritytech/parity-ethereum/blob/master/scripts/parity.service`

* Copy release to bin folder using sudo install

`sudo install ./target/release/parity /usr/bin/parity`
2019-02-07 12:50:15 +01:00
Anton Gavrilov
45d7c60608 Call private contract methods from another private contract (read-only) (#10086)
* Patch available private contracts during private transaction

* Key acl ABI added

* Work with secret store keys moved to the separate struct

* Private tx test refactored

* Revert "Private tx test refactored"

This reverts commit 476c132d692c7a886bc7b7cd7fe47b3d7692bd63.

* Test for calling private contract from another one added

* Test fixed

* Redundant tab removed

* ACL contract processing fixed, test added

* Merge with head

* Expect replaced with closure
2019-02-07 12:39:04 +01:00
Andronik Ordian
a3e39c9858 update ring to 0.14 (#10262)
* cargo upgrade hyper-rustls --all

* cargo upgrade parity-crypto --all

* update Cargo.lock

* propagate NonZeroU32

* use NonZeroU32::new_unchecked for crypto::KEY_ITERATIONS

* update Cargo.lock

* replace unsafe code with lazy_static
2019-02-06 17:53:34 +01:00
Niklas Adolfsson
8ab6d89810 fix(secret-store): deprecation warning (#10301)
use of deprecated item 'core::str::<impl str>::trim_left_matches': superseded by `trim_start_matches`
2019-02-06 16:54:35 +03:00
Andrew Jones
1b3b9b2887
Update to jsonrpc-derive 10.0.2, fixes aliases bug (#10300) 2019-02-05 14:47:25 +00:00
Andrew Jones
89ae0f0ea0 Convert to jsonrpc-derive, use jsonrpc-* from crates.io (#10298)
* Use jsonrpc crates on local path

* Convert all RPC traits to use jsonrpc-derive

* Use local jsonrpc at top level

* Upgrade remaining jsonrpc dependencies

* Checkout Cargo.lock to master HEAD

* Use jsonrpc-* 10.0.1 from crates.io

* Attribute after docs
2019-02-05 14:31:19 +01:00
Pierre Krieger
06cae8a535 Fix Windows build (#10284) 2019-02-03 13:32:06 +01:00
Pierre Krieger
12ac992ffb Don't run the CPP example on CI (#10285)
* Don't run the CPP example on CI

* Add comment
2019-02-03 13:23:07 +01:00
Tomasz Drwięga
3b23c2e86d Additional tests for uint deserialization. (#10279) 2019-02-03 12:26:25 +01:00
Seun LanLege
0f9b2218da prevent silent errors in daemon mode (#10007)
* prevent silent errors in daemon mode

* change author in Cargo.toml, add preamble to pipe.rs

* set the uid and gid on daemon process, fix permission errors when writing to pid file

* call setup_logger before daemonize to prevent crashing when attempting to create logfile

* map_err for calls to splice and ioctl, fix spaces in Cargo.toml

* split out daemonize to own repo

* removed util/daemonize

* renamed dep to parity-daemonize

* fix(parity-clib): enable `logger`

* bump parity-daemonize

* remove obsolete comment

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

* fix(grumbles): docs and log in ParityParams

* Add FIXME comment regarding @tomaka grumbles
* Unify logger with the C-API in ParityParams (less type-safety with more from_raw() conversions)
* Add better documentation in the `parity.h`

* Apply suggestions from code review

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

* docs(parity lib): add link to logging issue

* fix(parity-clib): JNI enable `logger`

* fix(parity-clib): update `Java example`

* Update example to the API changes
* Remove needless printouts which can be controlled via logger instead
2019-02-01 19:31:02 +01:00
Tomasz Drwięga
12c42bce9b Fix join-set test to be deterministic. (#10263) 2019-01-30 12:57:38 +00:00
Gabriel Majoulet
eb3d33ed6f Update CHANGELOG-2.2.md (#10254) 2019-01-29 10:13:21 +01:00
cheme
a139c6d216 Macos heapsize force jemalloc (#10234)
* Switch to non prefixed malloc_size_of on macos

* Fix

* Testing darwin build

* Fix import

* conflict

* switch heapsize deps commit

* switch heapsize commit

* Rename branch

* Restore gitlab ci to origin

* test for mac

* mac tests?

* Switch of macos CI tests.
2019-01-29 09:26:22 +01:00
Andrew Plaza
50f5ccc4f2 Allow specifying local accounts via CLI (#9960)
* Allow specifying local accounts via CLI

 * Add `tx-queue-locals` CLI option
 * ethcore: modify miner to check options vec before importing transaction
 * modify tests (ethcore/parity)
Resolves #9634

* fix formatting

* fixes: Make prefer HashSet over Vec<>, add test, comment formatting

* Update ethcore/src/miner/miner.rs

Co-Authored-By: insipx <aplaza@liquidthink.net>

* Fix comments and add helper for set->vec conversion

* remove blank line from use statement

* fix helper test

* formatting

* fix test to pass on nightly

* revert test fix for nightly
2019-01-28 11:26:11 +01:00
Vladyslav Lupashevskyi
94db961975 Take in account zero gas price certification when doing transact_contract (#10232)
* Tx permission contract improvement

* Take in account zero gas price certification when doing transact_contract

* DRY in ServiceTransactionChecker

* Fix typos and regroup mod

* Fix imports

* Simplify code in struct instantiation

Co-Authored-By: VladLupashevskyi <vlad@lupashevskyi.com>
2019-01-28 10:58:34 +01:00
Yucong Sun
38f3747cde Update CHANGELOG.md (#10249)
change 2018 to 2019
2019-01-28 10:54:07 +01:00
folex
4fec2f2fc2 Fix typo: CHANGELOG-2.1 -> CHANGELOG-2.2 (#10233) 2019-01-23 11:09:40 +01:00
Sho Sawada
c96d8a742b Update copyright year to 2019. (#10181)
* Update copyright year to 2019.

Have a great year.

* add `(UK)`

* 2018-2019
2019-01-23 09:26:36 +00:00
Elder Ryan
c2de31e586 fixed: types::transaction::SignedTransaction; (#10229) 2019-01-22 22:03:31 +03:00
Niklas Adolfsson
4b11d79829
fix(ManageNetwork): replace Range with RangeInclusive (#10209)
* fix(ManageNetwork): replace Range -> RangeIncls

Fixes `TODO: Range should be changed to RangeInclusive once stable (https://github.com/rust-lang/rust/pull/50758)`

* fix(tests)

* fix(grumbles): off-by-one error in debug_asserts

* RangeInclusive::end() is inclusive which means that if start and end is equal the `debug_assert(range.end() >
range.start()` will fail which is shouldn't
2019-01-22 09:51:40 +01:00
Seun LanLege
c35abe4196 import rpc transactions sequentially (#10051)
* import rpc transactions sequentially

* use impl trait in argument position, renamed ProspectiveDispatcher to WithPostSign

* grouped imports

* integrates PostSign with ProspectiveSigner

* fix spaces, removed unnecessary type cast and duplicate polling

* clean up code style

* Apply suggestions from code review
2019-01-22 09:33:56 +01:00
Afri Schoedon
a9a278a6e1
Enable St-Peters-Fork ("Constantinople Fix") (#10223)
* ethcore: disable eip-1283 on kovan block 10255201

* ethcore: disable eip-1283 on ropsten block 4939394

* ethcore: enable st-peters-fork on mainnet block 7280000

* ethcore: fix kovan chain spec

* version: update fork blocks

* ethcore: disable eip-1283 on sokol block 7026400
2019-01-21 22:55:44 +01:00
Wei Tang
fb07ffa676 Add EIP-1283 disable transition (#10214) 2019-01-21 12:22:29 +01:00
Michael Müller
940a88fa4e Echo CORS request headers by default (#10221)
* Echo CORS request headers by default

More details in https://github.com/paritytech/parity-ethereum/issues/6616.

* fixup: Single line
2019-01-21 10:30:24 +00:00
Bryant Eisenbach
708e495c28 Happy New Year! (#10211)
* Happy New Year!

* Happy New Year!

* Update README.md
2019-01-18 14:00:13 +01:00
Denis S. Soldatov aka General-Beck
460681ead9 perform stripping during build (#10208)
* perform stripping during build

* var RUSTFLAGS
2019-01-18 12:03:18 +01:00
Hernando Castano
2a7ed457dc
Remove CallContract and RegistryInfo re-exports from ethcore/client (#10205)
* Remove re-export of `CallContract` and `RegistryInfo` from `ethcore/client`

* Remove CallContract and RegistryInfo re-exports again

This was missed while fixing merge conflicts
2019-01-17 16:43:08 +01:00
Hernando Castano
35bbf11ba5 Extract CallContract and RegistryInfo traits into their own crate (#10178)
* Create call-contract crate

* Add license

* First attempt at using extracted CallContract trait

* Remove unneeded `extern crate` calls

* Move RegistryInfo trait into call-contract crate

* Move service-transaction-checker from ethcore to ethcore-miner

* Update Cargo.lock file

* Re-export call_contract

* Merge CallContract and RegistryInfo imports

* Remove commented code

* Add documentation to call_contract crate

* Add TODO for removal of re-exports

* Update call-contract crate description

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

* Rename call-contract crate to ethcore-call-contract
2019-01-16 19:52:21 +01:00
Afri Schoedon
4f1e1e8870 Update the changelogs for 2.1.11, 2.2.6, 2.2.7, and 2.3.0 (#10197)
* docs: move 2.2 changelog to docs/

* docs: mark parity 2.1 end of life

* docs: add changelog for 2.1.11

* docs: add changelog for 2.2.6

* docs: add changelog for 2.2.7

* docs: add changelog for 2.3.0

* docs: add release notes for 2.3.0
2019-01-16 18:32:53 +01:00
Victor Baranov
cf505139f1 Cancel Constantinople HF on POA Core (#10198) 2019-01-16 18:31:59 +01:00
Seun LanLege
cdba22a2cb Adds cli interface to allow reseting chain to a particular block (#9782)
* added BlockChainReset trait, client impl, and cli interface

* show block hashes to be deleted and new best block, update best block in db, better cli interface

* delete BlockNumber from COL_EXTRA

* add TODO comment

* add BlockReciepts to imports

* refactor block_headers_from_best_block, better cli documentation

* exit gracefully if reset arg isn't supplied

* fix cli usage macro

* removed stray int literals

* use Vec::with_capacity

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

* cast n to usize

* correct imports

* make db reset arg required
2019-01-16 16:37:26 +01:00
Nicolas Gotchac
1df6361753 Run all igd methods in its own thread (#10195) 2019-01-16 16:35:28 +01:00
Afri Schoedon
a6c6c7c070
pull constantinople on ethereum network (#10189)
* ethcore: pull constantinople on ethereum network

* version: mark update as critical

* ethcore: remove constantinople alltogether from chain spec

* version: revert fork block for ethereum
2019-01-15 21:50:41 +01:00
TriplEight
ed6f2877d7
Update for Android cross-compilation. (#10180)
* build-unix update

* .gitlab-ci update

* Update build-unix.sh

add android postprocessing

* path to android lib

libparity.so

* fix path to libparity

* add android lib to artifacts
2019-01-15 17:27:43 +01:00
Afri Schoedon
53c408f549
version: bump fork blocks for kovan and foundation (#10186) 2019-01-15 15:48:50 +01:00
Wei Tang
64704c456f Handle the case for contract creation on an empty but exist account with storage items (#10065)
* Add is_base_storage_root_unchanged

* Fix compile, use a shortcut for check, and remove ignored tests

* Add a warn!

* Update ethereum/tests to v6.0.0-beta.2

* grumble: use {:#x} instead of 0x{:x}

Co-Authored-By: sorpaas <accounts@that.world>
2019-01-15 10:21:44 +01:00
joshua-mir
0edf8e3f1b Align personal_unlockAccount behaviour when permanent unlock is disabled (#10060)
* align with docs

> If permanent unlocking is disabled (the default) then the duration argument will be ignored, and the account will be unlocked for a single signing.

Current behaviour throws an error that is no longer relevant.

* fix test

* Change back to throwing error

* Fix test again

* formatting

* oops

* whitespace fixes
2019-01-15 09:36:55 +01:00
Nicolas Gotchac
53a04e1686 Drop runtime after others (especially ws_server) (#10179) 2019-01-15 09:14:15 +01:00
Afri Schoedon
d356c6640d
version: bump nightly to 2.4 (#10165)
* version: bump nightly to 2.4

* revert rand downgrade
2019-01-14 17:29:17 +01:00
Wei Tang
e8e087fc37 Skip locking in statedb for non-canon blocks (#10141) 2019-01-15 01:33:10 +11:00
shoffmeister
181738a736 Remove reference to ui-interface command-line option (#10170) 2019-01-12 13:12:03 +01:00
Tomasz Drwięga
1ac1224cd3 Fix #9822: trace_filter does not return failed contract creation (#10140)
currently trace_filter can't return failed contract creation transaction
but trace_block can query the failed contract creation transaction.it
because the logic of parity-ethereum/ethcore/src/trace/types/filter.rs
Line 109 in 9982eba
```
 _ => false
```

this patch correct the logic:
```
 _ => self.to_address.matches_all()
```

Signed-off-by: Deshi Xiao <xiaods@gmail.com>
2019-01-11 18:08:58 +01:00
Nicolas Gotchac
3687df8da2 Fix _cannot recursively call into Core_ issue (#10144)
* Change igd to github:maufl/rust-igd

* Run `igd::search_gateway_from_timeout` from own thread
2019-01-11 17:59:05 +01:00
Niklas Adolfsson
67eee6aeb7 fix(whisper): correct PoW calculation (#10166)
* Fix off-by-one error on `leading_zeros` which was used to index in the hash to get leading zeros when not aligned on byte boundary (i.e, all the bits in a byte was not zero such as 0001 1111)
* Fix overflow by shifting with bigger value than 63
2019-01-11 17:48:58 +01:00
Tomasz Drwięga
83ba9df85b Bump JSON-RPC (#10151)
* Bump JSON-RPC

* Fix test casing.
2019-01-11 16:55:03 +01:00
Kirill Pimenov
83f706186f Ping nodes from discovery (#10167) 2019-01-10 20:43:16 +01:00
Niklas Adolfsson
eea5f6f232 fix(android): remove dependency to libusb (#10161) 2019-01-10 13:13:15 +01:00
Niklas Adolfsson
38af7f35fc refactor(trim_right_matches -> trim_end_matches) (#10159) 2019-01-10 13:12:14 +01:00
Pierre Krieger
eea3de00c1 Merge Machine and WithRewards (#10071) 2019-01-10 13:11:39 +01:00
Afri Schoedon
4d66e8d06d
snap: fix path in script (#10157)
* snap: fix path in script

* debug, revert me

* fix

* necromancer awk magic

* awk necromancy and path fixing

* working track selection
2019-01-10 10:58:30 +01:00
Wei Tang
010cfb7d67 Make sure parent block is not in importing queue when importing ancient blocks (#10138)
* Make sure parent block is not in importing queue when importing ancient blocks

* Clear queue when an ancient import fails

* Lock only once in clear

* Add comments why queued check is needed

* Should push the value back to the queue

* Directly check in chain.read()

* Remove extra empty line

* Revert unused verification change
2019-01-09 16:47:14 +03:00
Afri Schoedon
f9a8aac036
ci: re-enable snap publishing (#10142)
* ci: enable snap publishing~

* ci: add publish snap script

* ci: add snapcraft skeleton

* ci: group export statements

* ci: enable snaps on pr branch

* ci: enable snaps on pr branch

* ci: set default BUILD_ARCH

* ci: enable snaps on pr branch

* ci: enable snaps on pr branch

* ci: add libdb to snap

* ci: reinitiate gitlabci

* ci: reinitiate publish-snap script

* ci: fix yaml syntax

* cargo/gitlab env vars

* debug, revert me

* version?

* debug vars

* vars

* vars fix

* vars fix

* revert

* Update scripts/gitlab/publish-snap.sh

Co-Authored-By: 5chdn <5chdn@users.noreply.github.com>

* ci: read track from cargo toml
2019-01-09 14:39:21 +01:00
Vadim Arasev
3d28823be7 HF in POA Core (2019-01-18) - Constantinople (#10155)
https://github.com/poanetwork/poa-chain-spec/pull/100
2019-01-09 12:42:44 +01:00
ETHorHIL
492317abd7 Update EWF's tobalaba chainspec (#10152)
Added some bootnodes and removed some that we have lost access to.
2019-01-09 11:37:28 +01:00
Tomasz Drwięga
ab22d5e278 Replace ethcore-logger with env-logger. (#10102)
* Replace ethcore-logger with env-logger.

* Fix logger initialization in WASM tests.

* uncomment logger initialization in secret store

* Don't use ethcore-logger in whisper.

* Move ethcore-logger within parity dir.

* Uncomment rest from secret-store.

* Use `let _ =` in private_contract for consistency

* `ok()` to `let _ =` fix in service

* Use `let _ = ` for state_db
2019-01-08 15:07:20 +01:00
Andronik Ordian
ce5f704dd5 finality: dont require chain head to be in the chain (#10054) 2019-01-08 11:14:59 +01:00
Anton Gavrilov
696dc05dda Remove caching for node connections (#10143) 2019-01-08 11:31:26 +11:00
cheme
589083ad7a Blooms file iterator empty on out of range position. (#10145) 2019-01-07 17:54:06 +01:00
joshua-mir
1fda997370 Autogen docs for the "Configuring Parity Ethereum" wiki page. (#10067)
* publish docs changes for autogen config docs

* Update publish-docs.sh

adding an environment variable so js knows not to download git master and just grab the local repo

* Update publish-docs.sh

made some changes making this unnecessary

* fix env variable

env variable passes to node properly now

* use yarn

* test pipeline, revert me

* fix test pipeline, revert me

* change runner tag

* change runner tag 2

* change runner tag

* global git config

* supress upload_files output

* Update .gitlab-ci.yml

reverting testing changes

* Replace tag if exists

Very unlikely to be important/useful
2019-01-07 14:47:28 +01:00
Afri Schoedon
7c335e8764
misc: bump license header to 2019 (#10135)
* misc: bump license header to 2019

* misc: remove_duplicate_empty_lines.sh

* misc: run license header script

* commit cargo lock
2019-01-07 11:33:07 +01:00
Tomasz Drwięga
5b1d33d5fa Hide most of the logs from cpp example. (#10139) 2019-01-07 10:23:50 +01:00
Nicolas Gotchac
e435407080 Don't try to send oversized packets (#10042)
* Don't construct oversized packets

* Add test for payload limit

* [eth-sync] Fix wrongly computed data sizes

* Replace `MAX_RECEIPTS_TO_SEND` with overall softlimit
2019-01-04 19:58:21 +01:00
Anton Gavrilov
b180be7526 Private tx enabled flag added into STATUS packet (#9999)
* Add private tx enabled flag into status packet

* Error log added for the case with no peers available

* Add flag only for supported protocol versions

* Work with private handler refactored

* Log target changed

* Cargo.lock updated
2019-01-04 19:57:01 +01:00
Sergei Pepyakin
90fb473d87 Update pwasm-utils to 0.6.1 (#10134) 2019-01-04 16:56:56 +01:00
Tomasz Drwięga
3650f2d51c Extract blockchain from ethcore (#10114)
* Split blockchain & db from ethcore.

* Clean up blockchain deps.

* Missing docs.

* Fix blockchain tests.

* Make other crates compile.

* Remove some re-exports.

* Remove types re-export from ethcore.

* Remove EVM dependency from transaction.

* Merge ethcore-transaction with common-types.

* Clean-up ethcore deps a bit.

* remove ethcore from cargo.toml

* Update ethcore/blockchain/src/lib.rs

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Address review comments.

* Update DB comment.

* Add tracking issue to the TODO and fix typo.

* Common naming for common types.

* Update ethcore/db/src/keys.rs

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Update ethcore/blockchain/src/generator.rs

Co-Authored-By: tomusdrw <tomusdrw@users.noreply.github.com>

* Try to fix beta tests.
2019-01-04 14:05:46 +01:00
Afri Schoedon
3090324366 ethcore: update hardcoded headers (#10123)
* ethcore: update hardcoded headers for foundation

* ethcore: update hardcoded headers for ropsten

* ethcore: update hardcoded headers for kovan

* ethcore: use consistant formatting

* ethcore: restore spaces after colon in chain spec

* ethcore: fix bootnodes in chain specs

* ethcore: fix bootnodes in chain specs

* ethcore: enforce newline at the end of chainspecs
2019-01-04 13:26:18 +01:00
joshua-mir
130901e820 Identity fix (#10128)
* fix #10125

fix service transaction version detection if --identity is enabled, change test to match how --identity actually works

* fix wrong var

* get the index of  v, not /

* idx, not idx.len()

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

Co-Authored-By: joshua-mir <43032097+joshua-mir@users.noreply.github.com>

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

Co-Authored-By: joshua-mir <43032097+joshua-mir@users.noreply.github.com>

* change version prefix to a const

* space

Co-Authored-By: joshua-mir <43032097+joshua-mir@users.noreply.github.com>
2019-01-04 13:23:46 +01:00
Tomasz Drwięga
801b8191ef Use LenCachingMutex to optimize verification. (#10117) 2019-01-03 14:11:07 +01:00
Piotr Chromiec
469f9c26e7 Pyethereum keystore support (#9710)
* support for keystore format produced by pyethereum lib + some debug msgs

* made salt unbound also for Scrypt

* made address optional and skip if its none

* ignore values of any type, not just i32

* WIP: local deps

* cleanup

* enable optional address + more cleanup

* yet another cleanup

* enable keystore wo address import (using passwd)

* cleanup

* doc enchancement

* parity/account fix

* redesign after review

* fix indentation

* ignore just version in json under crypto

* remove unnecessary borrowing within match str

Co-Authored-By: tworec <tworec@golem.network>

* remove another unnecessary borrowing

Co-Authored-By: tworec <tworec@golem.network>

* default derived instead of implementing

* log dependency removed

* [ethstore] warn restored + env_logger initialized in CLI

* applied suggestion from @tomusdrw
2019-01-03 14:07:27 +01:00
Pierre Krieger
b5f510ead7 Bump rocksdb-sys to 0.5.5 (#10124)
* Bump rocksdb-sys to 0.5.5

* Revert rand
2019-01-03 13:13:02 +03:00
Niklas Adolfsson
b4f8bba843 parity-clib: async C bindings to RPC requests + subscribe/unsubscribe to websocket events (#9920)
* feat(parity-clib asynchronous rpc queries)

* feat(seperate bindings for ws and rpc)

* Subscribing to websockets for the full-client works

* feat(c binding unsubscribe_from_websocket)

* fix(tests): tweak CMake build config

* Enforce C+11

* refactor(parity-cpp-example) : `cpp:ify`

* fix(typedefs) : revert typedefs parity-clib

* docs(nits)

* fix(simplify websocket_unsubscribe)

* refactor(cpp example) : more subscriptions

* fix(callback type) : address grumbles on callback

* Use it the example to avoid using global variables

* docs(nits) - don't mention `arc`

* fix(jni bindings): fix compile errors

* feat(java example and updated java bindings)

* fix(java example) : run both full and light client

* fix(Java shutdown) : unsubscribe to sessions

Forgot to pass the JNIEnv environment since it is an instance method

* feat(return valid JString)

* Remove Java dependency by constructing a valid Java String in the callback

* fix(logger) : remove `rpc` trace log

* fix(format)

* fix(parity-clib): remove needless callback `type`

* fix(parity-clib-examples) : update examples

* `cpp` example pass in a struct instead to determines `callback kind`
* `java` add a instance variable the class `Callback` to determine `callback kind`

* fix(review comments): docs and format

* Update parity-clib/src/java.rs

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

* fix(bad merge + spelling)

* fix(move examples to parity-clib/examples)
2019-01-02 16:49:01 +01:00
Niklas Adolfsson
2bb79614f6 refactor (hardware wallet) : reduce the number of threads (#9644)
* refactor(hardware-wallet) - use only one thread

This changes parity to use one thread instead of two to subscribe USB
events via the hardware-wallets.

* Fix logs and tests

* fix(grumbles) : formatting and spelling nits

* Update hw/src/lib.rs

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

* Update hw/src/lib.rs

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

* Update hw/src/ledger.rs

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

* fix(grumbles): clarify docs and use constants

* Clarify bad explaination of `run-to-completion`
* Replace magic numbers with constants
2019-01-02 16:48:45 +01:00
Vadim Arasev
c077dc652d HF in POA Sokol (2019-01-04) (#10077)
* HF in POA Sokol (2019-01-04)

https://github.com/poanetwork/poa-chain-spec/pull/91

* Update POA Core bootnodes
2019-01-02 11:19:24 +01:00
Songtronix
1b6f2a3e92 Fix broken links (#10119)
Due to #10101 new directory structure, some links needed to be fixed.
2019-01-02 11:14:18 +01:00
Pierre Krieger
9136c81f05 Follow-up to #10105 (#10107) 2018-12-28 10:43:03 +01:00
Seun LanLege
912e5599d9 Move EIP-712 crate back to parity-ethereum (#10106)
* move eip-712 crate back to parity-ethereum

* changed license, updated documentation url
2018-12-28 17:36:55 +08:00
Tomasz Drwięga
ff0095ac5e Move a bunch of stuff around (#10101)
* Move devtools.

* Merge stop_guard & rename memzero

* Move price-info to miner.

* Group account management

* Clean up workspace members.

* Move local store closer to miner.

* Move clib examples.

* Move registrar and hash-fetch

* Move rpc_cli/rpc_client

* Move stratum closer to miner.

* Fix naming convention of crates.

* Update Cpp examples path.

* Fix paths for clib-example.

* Fix removing build.
2018-12-28 17:33:49 +08:00
Tomasz Drwięga
bf9fedc4ee Revert "Add --frozen when running cargo (#10081)" (#10105)
* Revert "Add --frozen when running cargo (#10081)"

This reverts commit c90e279ab5.

* Add Cargo.lock modification detection.
2018-12-27 13:42:19 +03:00
Wei Tang
78ba54da6b Fix left over small grumbles on whitespaces (#10084) 2018-12-20 14:28:32 +01:00
Pierre Krieger
c90e279ab5 Add --frozen when running cargo (#10081) 2018-12-19 15:23:26 +03:00
mattrutherford
215602de08
Fix pubsub new_blocks notifications to include all blocks (#9987)
Fix: new blocks notifications sometimes missing in pubsub RPC

Implement new struct to pass to `new_blocks()` with extra parameter - `has_more_blocks_to_import`, which was previously used to determine whether the notification should be sent. Now it's up to each implementation to decide what to do.

Updated all implementations to behave as before, except `eth_pubsub`, which will send notification even when the queue is not empty.

Update tests.
2018-12-19 09:24:14 +00:00
Pierre Krieger
13b832f959 Update some dependencies for compilation with pc-windows-gnu (#10082) 2018-12-18 23:26:01 +03:00
cheme
789bb9c852 Fill transaction hash on ethGetLog of light client. (#9938)
* Fill transaction hash on ethGetLog of light client. This is enifficient
but we keep align with spec.

* Using better variables names.

* Expose old fast light get log as `parity_getLogsLight`.

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

Fix indent.

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

* Factor common code between light_logs and logs.

* Remove useless check

* Rename parity light logs to 'parity_getLogsNoTransactionHash'.
Fix indent and extra white lines.

* Use vec instead of tree map to avoid inner function.

* better loop
2018-12-17 22:40:25 +03:00
Thibaut Sardan
aada1f547b
Update changelog update for 2.2.5-beta and 2.1.10-stable (#10064)
* Update CHANGELOG.md

* Update CHANGELOG-2.1.md

* Update docs/CHANGELOG-2.1.md

Co-Authored-By: Tbaut <33178835+Tbaut@users.noreply.github.com>

* Update docs/CHANGELOG-2.1.md

Co-Authored-By: Tbaut <33178835+Tbaut@users.noreply.github.com>

* Use - instead of *
2018-12-14 16:48:36 +01:00
mattrutherford
60718225ac
Implement len caching for parking_lot RwLock (#10032)
- Refactor (and rename crate) and implement RwLock len cache.

- improve docs

- update ethcore verification queue to new version

- Implement Default, From,  also derive Debug

- update: parking_lot to 0.7
2018-12-13 18:07:56 +00:00
Pierre Krieger
1a2fc03083 Update parking_lot to 0.7 (#10050) 2018-12-11 17:22:55 +01:00
Tomasz Drwięga
61e8baee0c Bump crossbeam. (#10048) 2018-12-11 12:30:21 +00:00
Afri Schoedon
dbc5f55da9 ethcore: enable constantinople on ethereum (#10031)
* ethcore: change blockreward to 2e18 for foundation after constantinople

* ethcore: delay diff bomb by 2e6 blocks for foundation after constantinople

* ethcore: enable eip-{145,1014,1052,1283} for foundation after constantinople
2018-12-11 12:06:04 +08:00
Tomasz Drwięga
81b7698428 Strict empty steps validation (#10041)
* Add two failings tests for strict empty steps.

* Implement strict validation of empty steps.
2018-12-10 18:58:38 +00:00
Lazaridis
4ce4bad383 Center the Subtitle, use some CAPS (#10034) 2018-12-10 21:45:48 +08:00
cheme
23d25a079b Change test miner max memory to malloc reports. (#10024) 2018-12-07 09:11:16 +01:00
Anton Gavrilov
d19bdb642e Sort the storage for private state (#10018) 2018-12-06 13:02:15 +03:00
mattrutherford
2e0246a6c2
Fix: test corpus_inaccessible panic (#10019)
If system uptime is less than the duration in the test, thread
will panic due to: 'overflow when subtracting duration from instant'.

Changed duration to 20 seconds to make it unlikely the test will
fail due to this condition.

Since no operations that carry a similar risk of panic occur outside
of the tests, it doesn't seem warranted to depend on an external crate
to fix this.
2018-12-05 15:38:55 +00:00
Afri Schoedon
349098e7b2
ci: move future releases to ethereum subdir on s3 (#10017)
* ci: move future releases to ethereum subdir on s3

* ci: redesign s3 bucket logic

* ci: use the releases bucket
2018-12-05 15:02:37 +01:00
Andronik Ordian
dc3b1ecdd0 light(on_demand): decrease default time window to 10 secs (#10016)
* light(on_demand): decrease default time window to 10 secs

* light(on_demand): use secs units for cli options
2018-12-05 19:17:26 +08:00
Niklas Adolfsson
7fb33796b1 light client : failsafe crate (circuit breaker) (#9790)
* refactor(light) : N/W calls with `circuit breaker`

* fix(nits) : forgot to commit new files

* Add tests and change CLI args

* Address grumbles

* fix(failsafe-rs) : Santize input to prevent panics

* chore(failsafe) : bump failsafe, (parking_lot)

Bump failsafe to v0.3.0 to enable `parking_lot::Mutex` instead
`spin::Mutex`

* Remove `success_rate`

* feat(circuit_breaker logger)

* feat(CLI): separate CLI args request and response

* Fix tests

* Error response provide request kind

When a reponse `times-out` provide the actual request or requests that failed

* Update ethcore/light/src/on_demand/mod.rs

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

* Update ethcore/light/src/on_demand/mod.rs

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

* fix(grumbles): formatting nit

* fix(grumbles)

* Use second resolution on CLI args
* Use `consecutive failure policy` instead of `timeOverWindow`
* Add a couple of tests for `request_guard`

* fix(request_guard): off-by-one error, update tests
2018-12-05 10:36:53 +01:00
mattrutherford
ec886ddefb
LenCachingMutex (#9988)
New util LenCachingMutex can be used in place of a Mutex, when working
with collections, or other types with a len() method. When
the Guard is dropped, the value returned from len() is stored
into an AtomicUsize and can be queried using load_len() without
needing to lock the Mutex. Implementations for ```Vec``` and
```VecDeque```.

Now used in [Verification](4ded4181a6/ethcore/src/verification/queue/mod.rs (L196)) so that calls to ```VerificationQueue.queue_info()```
no longer require locks.
2018-12-04 14:30:52 +00:00
Anton Gavrilov
4ded4181a6 Version and notification for private contract wrapper added (#9761)
* Version and notification for private contract wrapper added

* Error handling improved

* Style for comments in file fixed

* TODO issue added into comments
2018-12-03 19:44:36 +00:00
Wei Tang
60691d03e0
Handle failing case for update account cache in require (#9989) 2018-12-03 23:26:39 +08:00
Anton Gavrilov
869fa399b1 Add tokio runtime to ethcore io worker (#9979)
* Add tokio runtime to ethcore io worker

* Reworked with block_on_all
2018-12-03 22:35:46 +08:00
Andronik Ordian
7af953fd62
move daemonize before creating account provider (#10003)
* move daemonize before creating account provider

* daemonize: add a future-proofing comment
2018-11-30 17:22:41 +03:00
Afri Schoedon
5acbcb0d57
docs: update changelogs (#9990)
* docs: add changelog for 2.1.7 stable

* docs: add changelog for 2.2.2.2.2.2... :)
2018-11-30 13:30:40 +01:00
Andronik Ordian
7000c394b2 Fix daemonize (#10000)
* Revert "prevent silent errors in daemon mode, closes #9367 (#9946)"

This reverts commit 52d5278a62.

* deps(daemonize): switch back to crates.io
2018-11-30 12:39:30 +01:00
Nicolas Gotchac
7c0d894ccf Fix Bloom migration (#9992)
* Fix wrong block number in blooms migration

* Fix wrong `const` type (usize -> u64) 😬
2018-11-30 12:08:20 +08:00
Wei Tang
f092c10de5
Remove tendermint engine support (#9980)
* Remove tendermint engine support

* Remove tendermint test json spec

* Fix ethcore test compile

* Remove tendermint test in sync
2018-11-29 06:47:11 +08:00
Anton Gavrilov
7f5e6b3a0a Calculate gas for deployment transaction (#9840)
* Calculate gas for deployment transaction

* Space fixed

* ethcore: style fix in public_creation_transaction
2018-11-28 13:14:40 +01:00
Nicolas Gotchac
5e9dc185a5 Fix unstable peers and slowness in sync (#9967)
* Don't sync all peers after each response

* Update formating

* Fix tests: add `continue_sync` to `Sync_step`

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

Co-Authored-By: ngotchac <ngotchac@gmail.com>
2018-11-28 12:19:35 +01:00
Seun LanLege
0e94ac0111 adds parity_verifySignature RPC method (#9507)
* closes #7009

adds parity_verifySignature RPC method

* removed unneccesary into

* adds support for chain replay protected signatures

* corrected chain replay protection check

* corrected possible overflow

* added tests

* use checked_sub to prevent possible overflow

* use saturating_mul to prevent possible overflow

* changed method signature to accept r,s,v components

* added unit tests

* more tests

* refactored tests for better readability
moved verify_signature tests to live in the same file.

* removed unneccesary imports

* fixed PR grumbles

* fixed rsv notation

* fixed rsv notation

* renamed BasicAcount to RecoveredAccount, Support zero chain_id

* fixed compile errors

* fixed tests

* doc comment
2018-11-28 12:18:43 +01:00
Tomasz Drwięga
0b5bbf6048 Improve block and transaction propagation (#9954)
* Refactor sync to add priority tasks.

* Send priority tasks notifications.

* Propagate blocks, optimize transactions.

* Implement transaction propagation. Use sync_channel.

* Tone down info.

* Prevent deadlock by not waiting forever for sync lock.

* Fix lock order.

* Don't use sync_channel to prevent deadlocks.

* Fix tests.
2018-11-28 11:30:05 +01:00
Wei Tang
14c9cbd40e
Deny unknown fields for chainspec (#9972)
* Add deny_unknown_fields to chainspec

* Add tests and fix existing one

* Remove serde_ignored dependency for chainspec

* Fix rpc test eth chain spec

* Fix starting_nonce_test spec
2018-11-28 06:21:31 +08:00
gabriel klawitter
c4466878cf fix docker build (#9971) 2018-11-27 12:51:42 +01:00
Afri Schoedon
c584221fa2
ci: rearrange pipeline by logic (#9970)
* ci: rearrange pipeline by logic

* ci: rename docs script
2018-11-27 12:51:27 +01:00
Afri Schoedon
70ba050c06
Add changelogs for 2.0.9, 2.1.4, 2.1.6, and 2.2.1 (#9963)
* docs: add changelog for parity 2.0.9 stable (eol)

* docs: add changelog for parity 2.1.4 beta and 2.1.6 stable

* docs: add changelogs for 2.2.1 beta

* docs: add releasenotes for 2.2
2018-11-26 20:18:56 +01:00
Seun LanLege
f2281dc38a Add Error message when sync is still in progress. (#9475)
* closes #9188

* check_for_unavailable_block in
eth_getTransactionByHash
eth_getTransactionByBlockHashAndIndex
eth_getTransactionByBlockNumberAndIndex
eth_getTransactionReceipt

* check for unavailable block in eth_getBlockByNumber

* corrected checks for unavailable_block

* check for block gaps in db

* corrected error messages

* corrected error information

* added allow-empty-block-result cli flag

* address grumbles

* --jsonrpc-allow-missing-blocks

* fix tests

* added checks to
    block_transaction_count_by_hash
    block_transaction_count_by_number
    block_uncles_count_by_hash
    block_uncles_count_by_number
    uncle_by_block_hash_and_index
    uncle_by_block_number_and_index
fix PR grumbles

* Update parity/cli/mod.rs

revert config name

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

* Update parity/cli/mod.rs

revert cli arg

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

* Apply suggestions from code review

revert config name

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

* fix PR grumbles

* fix more PR grumbles
2018-11-27 02:58:27 +08:00
Wei Tang
18a2e6265d Make CALLCODE to trace value to be the code address (#9881) 2018-11-26 12:21:55 +01:00
Nicolas Gotchac
0d593199d0 Fix light client informant while syncing (#9932)
* Add `is_idle` to LightSync to check importing status

* Use SyncStateWrapper to make sure is_idle gets updates

* Update is_major_import to use verified queue size as well

* Add comment for `is_idle`

* Add Debug to `SyncStateWrapper`

* `fn get` -> `fn into_inner`
2018-11-26 14:05:02 +03:00
cheme
832c4a7565 Add a optional json dump state to evm-bin (#9706)
* Add a dump of the state at the end of transaction for --json-test.
Also fixes json-test output on finish, and allow to put both on err or
out (--out-only and --err-only).

* Dump state resolution from trie, function behind evm-bin feature to avoid misuse.

* Rename 'slow' method to 'to_pod_full'.
Use cache first in 'to_pod_full', for in between commits case.
Change dump activation to use a function pointer instead.

* Fix tests.

* Query and add storage values to dump.

* Switch to use `require` method, even if less efficient it is better in
this case to reuse existing code.
Reuse of `storage_at` was not easy in this case (could not iterate and
use the method at the same time (refcell mutable borrow panics) so
keeping code as is.

* Switch to returning error.
Use 'base_storage_root' instead of 'storage_root'.
Added a test, it will only execute with json-test in ci, or when launch
with the feature.

* Renaming of command line parameters.
Comments fixes.
Minor code changes.

* Fix evmbin cmd parsing test.

* README update.

* Fix extra space and avoid clone call on copiable address.

* Revert test submodule.

* Revert wasm-test submodule.

* Use map_or instead of map + unwrap_or

* restore tests submodule
2018-11-25 20:12:59 +01:00
Wei Tang
34d22a35dd Disable EIP-98 transition by default (#9955)
* Change eip98Transition default to BlockNumber::max_value

* Remove accidential ethereum/tests submodule change
2018-11-25 19:59:27 +01:00
Nick Sanders
c880716f16 Remove secret_store runtimes. (#9888)
* Remove the independent runtimes from `KeyServerHttpListener` and
  `KeyServerCore` and instead require a `parity_runtime::Executor`
  to be passed upon creation of each.

* Remove the `threads` parameter from both `ClusterConfiguration` structs.

* Implement the `future::Executor` trait for `parity_runtime::Executor`.

* Update tests.
  - Update the `loop_until` function to instead use a oneshot to signal
    completion.
  - Modify the `make_key_servers` function to create and return a runtime.
2018-11-26 01:36:43 +08:00
Nicolas Gotchac
f20f4c74d2 Fix a deadlock (#9952)
* Update informant:
  - decimal in Mgas/s
  - print every 5s (not randomly between 5s and 10s)

* Fix dead-lock in `blockchain.rs`

* Update locks ordering
2018-11-25 15:53:41 +08:00
Niklas Adolfsson
1fdfa1e6c6 chore(eip712): remove unused failure-derive (#9958) 2018-11-23 16:42:44 +00:00
Sebastian Siemssen
4ee49f03df Do not use the home directory as the working dir in docker (#9834)
* Do not create a home directory.

* Re-add -m flag
2018-11-22 14:15:04 +00:00
Seun LanLege
52d5278a62 prevent silent errors in daemon mode, closes #9367 (#9946) 2018-11-22 05:41:23 +08:00
Tomasz Drwięga
35a2b87174 Fix empty steps (#9939)
* Don't send empty step twice or empty step then block.

* Perform basic validation of locally sealed blocks.

* Don't include empty step twice.
2018-11-21 21:30:03 +00:00
Nicolas Gotchac
664bb2becd Adjust requests costs for light client (#9925)
* PIP Table Cost relative to average peers instead of max peers

* Add tracing in PIP new_cost_table

* Update stat peer_count

* Use number of leeching peers for Light serve costs

* Fix test::light_params_load_share_depends_on_max_peers (wrong type)

* Remove (now) useless test

* Remove `load_share` from LightParams.Config
Prevent div. by 0

* Add LEECHER_COUNT_FACTOR

* PR Grumble: u64 to u32 for f64 casting

* Prevent u32 overflow for avg_peer_count

* Add tests for LightSync::Statistics
2018-11-21 20:11:01 +01:00
Simon Jentzsch
8865b95818 EIP-1186: add eth_getProof RPC-Method (#9001)
* added eth_getAccount

* changed to getProof

* implemented storage_proof

* better formatting of storage proof

* fixed imports;2C

* removed spaces

* fixed whitespace

* fixed docker

* added doc

* fixed Compile-error

* expose more ports

* added eth_getAccount

* changed to getProof

* implemented storage_proof

* better formatting of storage proof

* fixed docker

* removed slockit-changes

* fixed Dockerfile

* intend

* spaces

* removed spaces

* fixed whitespace

* fixed docker

* tabs

* fixed Compile-error

* added eth_getAccount

* changed to getProof

* implemented storage_proof

* fixed docker

* removed slockit-changes

* fixed Dockerfile

* intend

* spaces

* removed spaces

* fixed whitespace

* fixed docker

* tabs

* merged changes

* fixed warnings

* added eth_getAccount

* changed to getProof

* implemented storage_proof

* better formatting of storage proof

* Update Dockerfile

* fixed docker

* removed slockit-changes

* fixed Dockerfile

* intend

* spaces

* removed spaces

* fixed whitespace

* fixed docker

* tabs

* added eth_getAccount

* changed to getProof

* implemented storage_proof

* removed spaces

* fixed whitespace

* fixed docker

* added eth_getAccount

* changed to getProof

* implemented storage_proof

* better formatting of storage proof

* fixed docker

* removed slockit-changes

* fixed Dockerfile

* intend

* spaces

* removed spaces

* fixed whitespace

* fixed docker

* tabs

* merged changes

* fixed merge error

* fixed formatting

* fixed rename_all = "camelCase"

* fixed tabs

* fixed spaces

* removed port exposer

* formatting

* fixed comment

* use filter_map

* formatting

* use better variable names

* changed casting

* fixed tabs

* remote into() from address

* remove space

Co-Authored-By: simon-jentzsch <simon@slock.it>

* fixed storage_index

Co-Authored-By: simon-jentzsch <simon@slock.it>

* fixed clone

* fixed format

Co-Authored-By: simon-jentzsch <simon@slock.it>

* fixed empty lines

* removed Option from EthAccount

* fixed storage_index

* implemented test and fixed the struct-spaces

* fixed tests

* added experimental RPCs flag for getProof

* optmized code
2018-11-21 20:09:33 +01:00
mattrutherford
03600dce97
Missing blocks in filter_changes RPC (#9947)
* feat + fix: Missing blocks in filter_changes RPC

 * Implement validity check of reported hashes (in case of re-org) and re-set last_block to the last block reported that is still valid.

* Add const to set history size for validity check (32).

* test: in the case of a re-org we get same block number if hash is different
2018-11-21 15:50:41 +00:00
gabriel klawitter
8b607efc40
allow rust-nightly builds fail in nightly builds (#9944) 2018-11-20 11:17:03 +01:00
Reyk Floeter
9f1af6b3e8 Update eth-secp256k1 to include fix for BSDs (#9935) 2018-11-18 14:22:59 +08:00
Reyk Floeter
c0952ba44b Unbreak build on rust -stable (#9934) 2018-11-17 23:51:35 +00:00
Nicolas Gotchac
9475a2e474 Keep existing blocks when restoring a Snapshot (#8643)
* Rename db_restore => client

* First step: make it compile!

* Second step: working implementation!

* Refactoring

* Fix tests

* PR Grumbles

* PR Grumbles WIP

* Migrate ancient blocks interating backward

* Early return in block migration if snapshot is aborted

* Remove RwLock getter (PR Grumble I)

* Remove dependency on `Client`: only used Traits

* Add test for recovering aborted snapshot recovery

* Add test for migrating old blocks

* Fix build

* PR Grumble I

* PR Grumble II

* PR Grumble III

* PR Grumble IV

* PR Grumble V

* PR Grumble VI

* Fix one test

* Fix test

* PR Grumble

* PR Grumbles

* PR Grumbles II

* Fix tests

* Release RwLock earlier

* Revert Cargo.lock

* Update _update ancient block_ logic: set local in `commit`

* Update typo in ethcore/src/snapshot/service.rs

Co-Authored-By: ngotchac <ngotchac@gmail.com>
2018-11-18 00:06:34 +01:00
Tomasz Drwięga
5baed0c158 Add experimental RPCs flag (#9928)
* WiP

* Enable experimental RPCs.
2018-11-16 14:00:34 +01:00
Tomasz Drwięga
97c259858c Clarify poll lifetime (#9922)
* Clarify poll filter.

* Fix RPC test.
2018-11-16 11:39:29 +00:00
Niklas Adolfsson
0f90696528 docs(require rust 1.30) (#9923)
* docs(require rust 1.30)

* Update README.md

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>
2018-11-15 12:53:11 +01:00
Nicolas Gotchac
ac974a180d Use block header for building finality (#9914) 2018-11-14 13:05:49 +01:00
TriplEight
052380b8de
simplify cargo audit (#9918) 2018-11-14 11:46:10 +01:00
Niklas Adolfsson
23a29439c0 light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure (#9824)
* fix start_gas, handle OOG exceptions & NotEnoughGas

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response

* fix(light-fetch): ensure block_gas_limit is tried

Try the `block_gas_limit` before regard the execution as an error

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

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>
2018-11-14 13:04:33 +03:00
Seun LanLege
a8617e2862
EIP 191 (#9701)
* added sign_191 rpc method

* fixed hash_structured_data return type

* added ConfirmationPayload::SignMessage for non-prefixed signatures, added tests for sign191

* renamed WithValidator -> PresignedTransaction

* rename applicationData to data in test

* adds docs for EIP191Version, renamed SignRequest to EIP191SignRequest
2018-11-14 09:02:40 +01:00
Niklas Adolfsson
6945a6b320 fix(logger): reqwest no longer a dependency (#9908) 2018-11-13 16:19:58 +00:00
Pierre Krieger
b375c9adbf Remove rust-toolchain file (#9906) 2018-11-13 18:23:17 +03:00
Thibaut Sardan
88a727739b
foundation: #6692865, ropsten: #4417537, kovan: #9363457 (#9907) 2018-11-13 14:48:23 +01:00
André Silva
5f3ae4dee3 ethcore: use Machine::verify_transaction on parent block (#9900)
* ethcore: use Machine::verify_transaction on parent block

also fixes off-by-one activation of transaction permission contract

* ethcore: clarify call to verify_transaction
2018-11-13 14:58:53 +03:00
Niklas Adolfsson
5cbe834024 chore(rpc-tests): remove unused rand (#9896) 2018-11-12 13:41:05 +03:00
mattrutherford
eea5b86cc4 fix: Intermittent failing CI due to addr in use (#9885)
Allow OS to set port at runtime
2018-11-11 11:20:04 +01:00
Niklas Adolfsson
09c512abaa chore(bump docopt): 0.8 -> 1.0 (#9889) 2018-11-11 11:19:44 +01:00
zhangyaning
d42d816e7f Use expect (#9883) 2018-11-09 14:54:23 +03:00
Nicolas Gotchac
17effd15ab Use Weak reference in PubSubClient (#9886) 2018-11-09 11:51:49 +00:00
Afri Schoedon
9982eba188 ci: nuke the gitlab caches (#9855)
Will go without cache. Meanwhile have to investigate what was wrong and how to use it effectively.
2018-11-08 19:37:12 +01:00
zhangyaning
aafe527d4a Remove unused code (#9884) 2018-11-08 13:20:02 +01:00
Wei Tang
e4c53a460e
Fix json tracer overflow (#9873)
* Fix json tracer overflow

* Replace trace_executed with a direct trace push

* Remove unused variable

* Add test for 5a51

* Remove duplicate json!
2018-11-08 03:04:36 +08:00
cheme
ca01596a65 Allow to seal work on latest block (#9876)
* Allow to seal work on latest block.

* Test from @todr to check sealing conditions.
2018-11-07 17:59:08 +00:00
Afri Schoedon
4f2415b483 Fix docker script (#9854)
* Dockerfile: change source path of the newly added check_sync.sh (#9869)
2018-11-07 15:53:22 +01:00
Tomasz Drwięga
f680eacdf2 Health endpoint (#9847)
* Health endpoint.

* Fix chain handling.

* Update to latest json-rpc.

* Change dev chain detection.

* Fix test.
2018-11-07 09:30:34 +01:00
gabriel klawitter
f6dcca3ebb
gitlab-ci: make android release build succeed (#9743)
* use docker cargo config file for android builds

* make android build succeed
2018-11-06 20:26:05 +01:00
Wei Tang
1a642fc624
Clean up existing benchmarks (#9839)
* Add FIXME link for a state mod statement

* Remove unused benches feature in ethcore

* Fix evm benches compile

* Fix ethash benches compile

* Switch to criterion
2018-11-06 21:22:44 +08:00
Yohan Graterol
c4469514db Update Callisto block reward code to support HF1 (#9811)
* Add Callisto Mainnet support

* Remove merge failure

* EIP-649 removed

* Remove eip649Reward

* Modify difficultyBombDelays

* Callisto reward smart contract

* Remove ethash params

* Fix merge

* Update bootnodes

* Update block reward to support HF1
2018-11-06 14:07:59 +08:00
Tomasz Drwięga
59daf95859 Option to disable keep alive for JSON-RPC http transport (#9848)
* Keep alive jsonrpc CLI option.

* Update to latest json-rpc.

* Keep alive flag.
2018-11-05 22:39:51 +08:00
Yaz Khoury
3a6e04ba15 Classic.json Bootnode Update (#9828)
* fix: Update bootnodes list to only responsive nodes

* feat: Add more bootnodes to classic.json list

* feat: Add retested bootnodes
2018-11-01 11:30:34 +01:00
Jonathan Brown
b26f86d6ff Support MIX. (#9767)
* Support MIX.

* Re-arrange mix.json so tests pass.

* Add MIX hardfork.

* Fix MIX chain specification.

* Use original MIX datadir.

* Fix MIX Newark enode.
2018-11-01 11:06:53 +01:00
Afri Schoedon
570215acae
ci: remove failing tests for android, windows, and macos (#9788)
* ci: remove failing tests for android, windows, and macos

* ci: restore android build jobs
2018-11-01 11:06:24 +01:00
cheme
a511264433 Implement NoProof for json tests and update tests reference (replaces #9744) (#9814)
* Update test reference.
Block test are really not working so I disabled a few by commenting
directly in source.

* Move ethtest commit cursor.

* Implements 'NoProof' engine from https://github.com/ethereum/tests/issues/464 .

Since tests has been regenerated those one were failing on block
difficulty check.

Update ethereum/tests, waiting for cost fix (block test are still
commented).

* Update tests submodule reference to latest (all test passing except an
identified case).
Fix block reward of constantinople json.

* Restore broken test by using old json tests files.

* Use CanonNoSeal instead of a custom engine, still have to include some
additional tests code.

* Gas upper limit check in json_chain test was bad, moving the test to
verification, the test is running in `verify_header_param`.
Note that test was previously only for ethash, and now for any engine.

* Restore old behavior (gas uper limit only for ethash engine), at the
cost of an additional trait method.

* Proper rpc test fix.

* Update tests submodule, add SStore bug tests.

* Fix json issue tabulation.
Update tests submodule to latest master (lot of new sstore tests
passing)

* Switch ethereum/tests to tag 6.0.0-beta.1 (no tests changes from latest
synch).

* Display hex with separator, use indirection instead of clone for copy
types.
2018-11-01 11:04:32 +01:00
Niklas Adolfsson
06f25d2b27 chore(bump regex) (#9842) 2018-11-01 13:16:02 +08:00
Anton Gavrilov
a3bd355b16 Ignore global cache for patched accounts (#9752)
* Ignore global cache for patched accounts

* Rollback patched account flag

* Store root in checkpoint storage
2018-10-31 15:55:11 +00:00
Wei Tang
1c1cd8b164
Move state root verification before gas used (#9841) 2018-10-31 22:44:46 +08:00
Niklas Adolfsson
a898109522 fix(docker-aarch64) : cross-compile config (#9798) 2018-10-31 12:39:18 +00:00
Afri Schoedon
3694b10e22 version: bump nightly to 2.3.0 (#9819)
* version: bump nightly to 2.3.0

* Revert Cargo.lock
2018-10-31 12:38:47 +00:00
cheme
39f25d20a8 Tests modification for windows CI (#9671)
* Fixing and disabling some tests for windows 10 compatibility.

* Few adjustment for windows in tests (eg bigger timeout for keyserver tests)

* Spaces and temporary single thread ci (to be able to spot the error).
2018-10-31 11:50:38 +01:00
Seun LanLege
61c1646b43 EIP-712 implementation (#9631)
* EIP-712 impl

* added more tests

* removed size parsing unwrap

* corrected TYPE_REGEX to disallow zero sized fixed length arrays, replaced LinkedHashSet with IndexSet, added API spec to docs, fixed Type::Byte encoding branch

* use Option<u64> instead of u64 for Type::Array::Length

* replace `.iter()` with  `.values()`

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

* tabify eip712.rs

* use proper comments for docs

* Cargo.lock: revert unrelated changes

* tabify encode.rs
2018-10-31 00:12:42 +03:00
Niklas Adolfsson
1b9396dcbb Fix typo (#9826) 2018-10-29 21:41:54 +01:00
Wei Tang
05be4b5b0e
Clean up serde rename and use rename_all = camelCase when possible (#9823)
* Clean up serde rename and use rename_all = camelCase when possible

* snake_case for pricing

* Use camelcase for engine

* Use camel case for seal

* Use camel case for validator set

* Use camel case for confirmation payload

* Use camel case for consensus status

* Use camel case for nodekind

* Use kebab case for provenance

* Use camel case for pubsub

* Use lowercase and camelcase for trace

* Use camel case for whisper

* rename Ethash as irregular name
2018-10-29 23:49:04 +08:00
1590 changed files with 226331 additions and 271789 deletions

View File

@ -1,3 +1,3 @@
[target.x86_64-pc-windows-msvc]
# Link the C runtime statically ; https://github.com/paritytech/parity-ethereum/issues/6643
# Link the C runtime statically ; https://github.com/openethereum/parity-ethereum/issues/6643
rustflags = ["-Ctarget-feature=+crt-static"]

2
.git-blame-ignore-revs Normal file
View File

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

View File

@ -2,11 +2,11 @@
## 1. Purpose
A primary goal of Parity is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
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).
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
We invite all those who participate in Parity to help us create safe and positive experiences for everyone.
We invite all those who participate in OpenEthereum 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 Parity 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 OpenEthereum 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 Parity via Email: community@parity.io
You can contact OpenEthereum 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://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/)!
Check out our [Beginner Introduction](https://openethereum.github.io/Beginner-Introduction), [Configuration](https://openethereum.github.io//Configuring-OpenEthereum), and [FAQ](https://openethereum.github.io/FAQ) articles on our [wiki](https://openethereum.github.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/paritytech/parity-ethereum/issues/new) in our repository and state:
Otherwise, just create a [new issue](https://github.com/openethereum/openethereum/issues/new) in our repository and state:
- What's your Parity Ethereum version?
- What's your OpenEthereum version?
- What's your operating system and version?
- How did you install Parity Ethereum?
- How did you install OpenEthereum?
- Is your node fully synchronized?
- Did you try turning it off and on again?
@ -22,9 +22,44 @@ Also, try to include **steps to reproduce** the issue and expand on the **actual
## Contribute!
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).
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).
Please, refer to the [Coding Guide](https://wiki.parity.io/Coding-guide) in our wiki for more details about hacking on Parity.
### 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.
### Rules
There are a few basic ground-rules for contributors (including the maintainer(s) of the project):
* **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.
* All code changed should be formated by running `cargo fmt -- --config=merge_imports=true`
### 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).
* **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).
* 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.
### 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)).
When doing a review, make sure to look for any:
* Buggy behavior.
* Undue maintenance burden.
* Breaking with house coding style.
* Pessimization (i.e. reduction of speed as measured in the projects benchmarks).
* Breaking changes should be carefuly reviewed and tagged as such so they end up in the [changelog](../CHANGELOG.md).
* Uselessness (i.e. it does not strictly add a feature or fix a known issue).
## License.

View File

@ -1,6 +1,8 @@
For questions please use https://discord.io/openethereum, issues are for bugs and feature requests.
_Before filing a new issue, please **provide the following information**._
- **Parity Ethereum version**: 0.0.0
- **OpenEthereum version (>=3.1.0)**: 0.0.0
- **Operating system**: Windows / MacOS / Linux
- **Installation**: homebrew / one-line installer / built from source
- **Fully synchronized**: no / yes

View File

@ -0,0 +1,33 @@
name: Build and Test Suite on Windows
on:
push:
branches:
- main
- dev
jobs:
build-tests:
name: Test and Build
strategy:
matrix:
platform:
- windows2019 # custom runner
toolchain:
- 1.52.1
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: Build tests
uses: actions-rs/cargo@v1
with:
command: test
args: --locked --all --release --features "json-tests" --verbose --no-run

40
.github/workflows/build-test.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Build and Test Suite
on:
pull_request:
push:
branches:
- main
- dev
jobs:
build-tests:
name: Test and Build
strategy:
matrix:
platform:
- ubuntu-16.04
- macos-latest
toolchain:
- 1.52.1
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: 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 }}
uses: actions-rs/cargo@v1
with:
command: test
args: --locked --all --release --features "json-tests" --verbose

285
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,285 @@
name: Build Release Suite
on:
push:
tags:
- v*
# Global vars
env:
AWS_REGION: "us-east-1"
AWS_S3_ARTIFACTS_BUCKET: "openethereum-releases"
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
jobs:
build:
name: Build Release
strategy:
matrix:
platform:
- ubuntu-16.04
- macos-latest
toolchain:
- 1.52.1
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
# ==============================
# Windows Build
# ==============================
# - name: Install LLVM for Windows
# if: matrix.platform == 'windows2019'
# run: choco install llvm
# - name: Build OpenEthereum for Windows
# if: matrix.platform == 'windows2019'
# run: sh scripts/actions/build-windows.sh ${{matrix.platform}}
# - name: Upload Windows build
# uses: actions/upload-artifact@v2
# if: matrix.platform == 'windows2019'
# with:
# name: windows-artifacts
# path: artifacts
# ==============================
# Linux/Macos Build
# ==============================
- name: Build OpenEthereum for ${{matrix.platform}}
if: matrix.platform != 'windows2019'
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
zip-artifacts-creator:
name: Create zip artifacts
needs: build
runs-on: ubuntu-16.04
steps:
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
# ==============================
# 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 "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
# ==============================
# 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

50
.github/workflows/check.yml vendored Normal file
View File

@ -0,0 +1,50 @@
name: Check
on:
pull_request:
push:
branches:
- main
- dev
jobs:
check:
name: Check
runs-on: ubuntu-16.04
steps:
- name: Checkout sources
uses: actions/checkout@main
with:
submodules: true
- name: Install 1.52.1 toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 1.52.1
profile: minimal
override: true
- 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 crates/runtime/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 crates/runtime/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

View File

@ -0,0 +1,29 @@
name: Docker Image Nightly Release
# Run "nightly" build on each commit to "dev" branch.
on:
push:
branches:
- dev
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: 1.52.1
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
tags: "nightly"

30
.github/workflows/deploy-docker-tag.yml vendored Normal file
View File

@ -0,0 +1,30 @@
name: Docker Image Tag and Latest Release
on:
push:
tags:
- v*
jobs:
deploy-docker:
name: Build Release
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@master
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Install toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: 1.52.1
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
tags: "latest,${{ env.RELEASE_VERSION }}"

30
.github/workflows/deploy-docker.yml vendored Normal file
View File

@ -0,0 +1,30 @@
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: 1.52.1
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

20
.github/workflows/fmt.yml vendored Normal file
View File

@ -0,0 +1,20 @@
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: 1.52.1
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,8 +38,10 @@ node_modules
# Build artifacts
out/
parity-clib-examples/cpp/build/
.vscode
rls/
/parity.*
# cargo remote artifacts
remote-target

View File

@ -1,182 +0,0 @@
stages:
- test
- build
- publish
- optional
image: parity/rust:gitlab-ci
variables:
CI_SERVER_NAME: "GitLab CI"
CARGO_HOME: "${CI_PROJECT_DIR}/.cargo"
BUILD_TARGET: ubuntu
BUILD_ARCH: amd64
CARGO_TARGET: x86_64-unknown-linux-gnu
cache:
key: "${CI_JOB_NAME}"
paths:
- ./target
- ./.cargo
.releaseable_branches: # list of git refs for building GitLab artifacts (think "pre-release binaries")
only: &releaseable_branches
- stable
- beta
- 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/
.determine_version: &determine_version
- VERSION="$(sed -r -n '1,/^version/s/^version = "([^"]+)".*$/\1/p' Cargo.toml)"
- DATE_STR="$(date +%Y%m%d)"
- ID_SHORT="$(echo ${CI_COMMIT_SHA} | cut -c 1-7)"
- test "${SCHEDULE_TAG:-${CI_COMMIT_REF_NAME}}" = "nightly" && VERSION="${VERSION}-${ID_SHORT}-${DATE_STR}"
- export VERSION
- echo "Version = ${VERSION}"
test-linux:
stage: test
variables:
RUN_TESTS: all
script:
- scripts/gitlab/test-all.sh stable
tags:
- rust-stable
build-linux:
stage: build
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-unknown-linux-gnu
script:
- scripts/gitlab/build-unix.sh
<<: *collect_artifacts
tags:
- rust-stable
build-darwin:
stage: build
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-apple-darwin
CC: gcc
CXX: g++
script:
- scripts/gitlab/build-unix.sh
tags:
- rust-osx
<<: *collect_artifacts
build-windows:
stage: build
only: *releaseable_branches
variables:
CARGO_TARGET: x86_64-pc-windows-msvc
script:
- sh scripts/gitlab/build-windows.sh
tags:
- rust-windows
<<: *collect_artifacts
publish-docker:
stage: publish
only: *releaseable_branches
cache: {}
dependencies:
- build-linux
tags:
- shell
script:
- scripts/gitlab/publish-docker.sh parity
publish-awss3:
stage: publish
only: *releaseable_branches
cache: {}
dependencies:
- build-linux
- build-darwin
- build-windows
before_script: *determine_version
script:
- scripts/gitlab/publish-awss3.sh
tags:
- shell
docs-jsonrpc:
stage: optional
only:
- tags
except:
- nightly
cache: {}
script:
- scripts/gitlab/docs-jsonrpc.sh
tags:
- shell
cargo-audit:
stage: optional
script:
- scripts/gitlab/cargo-audit.sh
tags:
- rust-stable
test-android:
stage: optional
image: parity/rust-android:gitlab-ci
variables:
CARGO_TARGET: armv7-linux-androideabi
script:
- scripts/gitlab/test-all.sh stable
tags:
- rust-arm
test-darwin:
stage: optional
variables:
CARGO_TARGET: x86_64-apple-darwin
CC: gcc
CXX: g++
RUN_TESTS: cargo
script:
- scripts/gitlab/test-all.sh stable
tags:
- rust-osx
test-windows:
stage: optional
variables:
CARGO_TARGET: x86_64-pc-windows-msvc
RUN_TESTS: cargo
script:
- sh scripts/gitlab/test-all.sh stable
tags:
- rust-windows
test-beta:
stage: optional
variables:
RUN_TESTS: cargo
script:
- scripts/gitlab/test-all.sh beta
tags:
- rust-beta
test-nightly:
stage: optional
variables:
RUN_TESTS: all
script:
- scripts/gitlab/test-all.sh nightly
tags:
- rust-nightly

8
.gitmodules vendored
View File

@ -1,7 +1,3 @@
[submodule "ethcore/res/ethereum/tests"]
path = ethcore/res/ethereum/tests
[submodule "crates/ethcore/res/json_tests"]
path = crates/ethcore/res/json_tests
url = https://github.com/ethereum/tests.git
branch = develop
[submodule "ethcore/res/wasm-tests"]
path = ethcore/res/wasm-tests
url = https://github.com/paritytech/wasm-tests

File diff suppressed because it is too large Load Diff

5835
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,19 @@
[package]
description = "Parity Ethereum client"
name = "parity-ethereum"
description = "OpenEthereum"
name = "openethereum"
# NOTE Make sure to update util/version/Cargo.toml as well
version = "2.2.0"
version = "3.3.3"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]
authors = [
"OpenEthereum developers",
"Parity Technologies <admin@parity.io>"
]
[dependencies]
blooms-db = { path = "util/blooms-db" }
blooms-db = { path = "crates/db/blooms-db" }
log = "0.4"
env_logger = "0.5"
rustc-hex = "1.0"
docopt = "0.8"
docopt = "1.0"
clap = "2"
term_size = "0.3"
textwrap = "0.9"
@ -20,55 +22,56 @@ number_prefix = "0.2"
rpassword = "1.0"
semver = "0.9"
ansi_term = "0.10"
parking_lot = "0.6"
regex = "0.2"
parking_lot = "0.11.1"
regex = "1.0"
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 = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-2.2" }
ethcore = { path = "ethcore", features = ["parity"] }
jsonrpc-core = "15.0.0"
parity-bytes = "0.1"
ethcore-io = { path = "util/io" }
ethcore-light = { path = "ethcore/light" }
ethcore-logger = { path = "logger" }
ethcore-miner = { path = "miner" }
ethcore-network = { path = "util/network" }
ethcore-private-tx = { path = "ethcore/private-tx" }
ethcore-service = { path = "ethcore/service" }
ethcore-sync = { path = "ethcore/sync" }
ethcore-transaction = { path = "ethcore/transaction" }
ethereum-types = "0.4"
node-filter = { path = "ethcore/node_filter" }
ethkey = { path = "ethkey" }
rlp = { version = "0.3.0", features = ["ethereum"] }
rpc-cli = { path = "rpc_cli" }
parity-hash-fetch = { path = "hash-fetch" }
parity-ipfs-api = { path = "ipfs" }
parity-local-store = { path = "local-store" }
parity-runtime = { path = "util/runtime" }
parity-rpc = { path = "rpc" }
parity-rpc-client = { path = "rpc_client" }
parity-updater = { path = "updater" }
parity-version = { path = "util/version" }
parity-whisper = { path = "whisper" }
common-types = { path = "crates/ethcore/types" }
ethcore = { path = "crates/ethcore", features = ["parity"] }
ethcore-accounts = { path = "crates/accounts", optional = true }
ethcore-blockchain = { path = "crates/ethcore/blockchain" }
ethcore-call-contract = { path = "crates/vm/call-contract"}
ethcore-db = { path = "crates/db/db" }
ethcore-io = { path = "crates/runtime/io" }
ethcore-logger = { path = "bin/oe/logger" }
ethcore-miner = { path = "crates/concensus/miner" }
ethcore-network = { path = "crates/net/network" }
ethcore-service = { path = "crates/ethcore/service" }
ethcore-sync = { path = "crates/ethcore/sync" }
ethereum-types = "0.9.2"
ethkey = { path = "crates/accounts/ethkey" }
ethstore = { path = "crates/accounts/ethstore" }
fetch = { path = "crates/net/fetch" }
node-filter = { path = "crates/net/node-filter" }
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
rlp = { version = "0.4.6" }
cli-signer= { path = "crates/util/cli-signer" }
parity-daemonize = "0.3"
parity-local-store = { path = "crates/concensus/miner/local-store" }
parity-runtime = { path = "crates/runtime/runtime" }
parity-rpc = { path = "crates/rpc" }
parity-version = { path = "crates/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" }
dir = { path = "crates/util/dir" }
panic_hook = { path = "crates/util/panic-hook" }
keccak-hash = "0.5.0"
migration-rocksdb = { path = "crates/db/migration-rocksdb" }
kvdb = "0.1"
kvdb-rocksdb = "0.1.3"
journaldb = { path = "util/journaldb" }
mem = { path = "util/mem" }
journaldb = { path = "crates/db/journaldb" }
stats = { path = "crates/util/stats" }
prometheus = "0.9.0"
ethcore-secretstore = { path = "secret_store", optional = true }
registrar = { path = "registrar" }
# ethcore-secretstore = { path = "crates/util/secret-store", optional = true }
[build-dependencies]
rustc_version = "0.2"
@ -77,23 +80,22 @@ rustc_version = "0.2"
pretty_assertions = "0.1"
ipnetwork = "0.12.6"
tempdir = "0.3"
fake-fetch = { path = "util/fake-fetch" }
fake-fetch = { path = "crates/net/fake-fetch" }
lazy_static = "1.2.0"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.4", features = ["winsock2", "winuser", "shellapi"] }
[target.'cfg(not(windows))'.dependencies]
daemonize = { git = "https://github.com/paritytech/daemonize" }
[features]
default = ["accounts"]
accounts = ["ethcore-accounts", "parity-rpc/accounts"]
miner-debug = ["ethcore/miner-debug"]
json-tests = ["ethcore/json-tests"]
ci-skip-issue = ["ethcore/ci-skip-issue"]
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"]
final = ["parity-version/final"]
deadlock_detection = ["parking_lot/deadlock_detection"]
# to create a memory profile (requires nightly rust), use e.g.
@ -103,37 +105,29 @@ 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"
path = "bin/oe/lib.rs"
[[bin]]
path = "parity/main.rs"
name = "parity"
path = "bin/oe/main.rs"
name = "openethereum"
[profile.dev]
[profile.test]
lto = false
opt-level = 3 # makes tests slower to compile, but faster to run
[profile.release]
debug = false
lto = true
[workspace]
# This should only list projects that are not
# in the dependency tree in any other way
# (i.e. pretty much only standalone CLI tools)
members = [
"chainspec",
"ethcore/wasm/run",
"ethcore/types",
"ethkey/cli",
"ethstore/cli",
"evmbin",
"miner",
"parity-clib",
"whisper",
"whisper/cli",
"util/triehash-ethereum",
"util/keccak-hasher",
"util/patricia-trie-ethereum",
"util/fastmap",
]
"bin/ethkey",
"bin/ethstore",
"bin/evmbin",
"bin/chainspec"
]

299
README.md
View File

@ -1,13 +1,38 @@
![Parity Ethereum](docs/logo-parity-ethereum.svg)
# OpenEthereum
## The fastest and most advanced Ethereum client.
Fast and feature-rich multi-network Ethereum client.
<p align="center"><strong><a href="https://github.com/paritytech/parity-ethereum/releases/latest">» Download the latest release «</a></strong></p>
[» Download the latest release «](https://github.com/openethereum/openethereum/releases/latest)
<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>
[![GPL licensed][license-badge]][license-url]
[![Build Status][ci-badge]][ci-url]
[![Discord chat][chat-badge]][chat-url]
**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.
[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
## Table of Contents
1. [Description](#chapter-001)
2. [Technical Overview](#chapter-002)
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)
4. [Testing](#chapter-004)
5. [Documentation](#chapter-005)
6. [Toolchain](#chapter-006)
7. [Contributing](#chapter-008)
8. [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.
- Clean, modular codebase for easy customisation
- Advanced CLI-based client
@ -15,19 +40,21 @@
- Synchronise in hours, not days with Warp Sync
- Modular for light integration into your service or product
## Technical Overview
## 2. Technical Overview <a id="chapter-002"></a>
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.
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.
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.
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.
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).
If you run into problems while using OpenEthereum, check out the [old wiki for documentation](https://openethereum.github.io/), 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!
Parity Ethereum's current beta-release is 2.1. 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.
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.
## Build Dependencies
## 3. Building <a id="chapter-003"></a>
Parity Ethereum requires **Rust version 1.29.x** to build.
### 3.1 Build Dependencies <a id="chapter-0031"></a>
OpenEthereum 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:
@ -36,7 +63,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
$ curl https://sh.rustup.rs -sSf | sh
```
Parity Ethereum also requires `gcc`, `g++`, `libudev-dev`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
OpenEthereum also requires `clang` (>= 9.0), `clang++`, `pkg-config`, `file`, `make`, and `cmake` packages to be installed.
- OSX:
```bash
@ -45,7 +72,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
`clang` is required. It comes with Xcode command line tools or can be installed with homebrew.
- Windows
- Windows:
Make sure you have Visual Studio 2015 with C++ support installed. Next, download and run the `rustup` installer from
https://static.rust-lang.org/rustup/dist/x86_64-pc-windows-msvc/rustup-init.exe, start "VS2015 x64 Native Tools Command Prompt", and use the following command to install and set up the `msvc` toolchain:
```bash
@ -56,14 +83,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 Parity Ethereum from source.
Make sure that these binaries are in your `PATH`. After that, you should be able to build OpenEthereum from source.
## Build from Source Code
### 3.2 Build from Source Code <a id="chapter-0032"></a>
```bash
# download Parity Ethereum code
$ git clone https://github.com/paritytech/parity-ethereum
$ cd parity-ethereum
# download OpenEthereum code
$ git clone https://github.com/openethereum/openethereum
$ cd openethereum
# build in release mode
$ cargo build --release --features final
@ -83,73 +110,209 @@ 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 or beta, do a
This always compiles the latest nightly builds. If you want to build stable, do a
```bash
$ git checkout stable
```
or
### 3.3 Starting OpenEthereum <a id="chapter-0034"></a>
#### Manually
To start OpenEthereum manually, just run
```bash
$ git checkout beta
$ ./target/release/openethereum
```
## Simple One-Line Installer for Mac and Linux
so OpenEthereum begins syncing the Ethereum blockchain.
```bash
bash <(curl https://get.parity.io -L)
```
#### Using `systemd` service file
The one-line installer always defaults to the latest beta release. To install a stable release, run:
To start OpenEthereum as a regular user using `systemd` init:
```bash
bash <(curl https://get.parity.io -L) -r stable
```
## Start Parity Ethereum
### Manually
To start Parity Ethereum manually, just run
```bash
$ ./target/release/parity
```
so Parity Ethereum begins syncing the Ethereum blockchain.
### Using `systemd` service file
To start Parity Ethereum as a regular user using `systemd` init:
1. Copy `./scripts/parity.service` to your
1. Copy `./scripts/openethereum.service` to your
`systemd` user directory (usually `~/.config/systemd/user`).
2. 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.
2. Copy release to bin folder, write `sudo install ./target/release/openethereum /usr/bin/openethereum`
3. To configure OpenEthereum, see [our wiki](https://openethereum.github.io/Configuring-OpenEthereum) for details.
## Parity Ethereum toolchain
## 4. Testing <a id="chapter-004"></a>
In addition to the Parity Ethereum client, there are additional tools in this repository available:
Download the required test files: `git submodule update --init --recursive`. You can run tests with the following commands:
- [evmbin](https://github.com/paritytech/parity-ethereum/blob/master/evmbin/) - EVM implementation for Parity Ethereum.
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding.
- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/ethstore/) - Parity Ethereum key management.
- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/ethkey/) - Parity Ethereum keys generator.
- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC.
* **All** packages
```
cargo test --all
```
## Join the chat!
* Specific package
```
cargo test --package <spec>
```
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)
Replace `<spec>` with one of the packages from the [package list](#package-list) (e.g. `cargo test --package evmbin`).
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)
You can show your logs in the test output by passing `--nocapture` (i.e. `cargo test --package evmbin -- --nocapture`)
## Documentation
## 5. Documentation <a id="chapter-005"></a>
Official website: https://parity.io
Be sure to [check out our wiki](https://openethereum.github.io/) for more information.
Be sure to [check out our wiki](https://wiki.parity.io) for more information.
### Viewing documentation for OpenEthereum packages
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:
* **All** packages
```
cargo doc --document-private-items --open
```
* Specific package
```
cargo doc --package <spec> -- --document-private-items --open
```
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`):
<a id="package-list"></a>
**Package List**
<details><p>
* OpenEthereum Client Application
```bash
openethereum
```
* OpenEthereum Account Management, Key Management Tool, and Keys Generator
```bash
ethcore-accounts, ethkey-cli, ethstore, ethstore-cli
```
* OpenEthereum Chain Specification
```bash
chainspec
```
* OpenEthereum CLI Signer Tool & RPC Client
```bash
cli-signer parity-rpc-client
```
* OpenEthereum Ethash & ProgPoW Implementations
```bash
ethash
```
* EthCore Library
```bash
ethcore
```
* OpenEthereum Blockchain Database, Test Generator, Configuration,
Caching, Importing Blocks, and Block Information
```bash
ethcore-blockchain
```
* OpenEthereum Contract Calls and Blockchain Service & Registry Information
```bash
ethcore-call-contract
```
* OpenEthereum Database Access & Utilities, Database Cache Manager
```bash
ethcore-db
```
* OpenEthereum Virtual Machine (EVM) Rust Implementation
```bash
evm
```
* OpenEthereum Light Client Implementation
```bash
ethcore-light
```
* Smart Contract based Node Filter, Manage Permissions of Network Connections
```bash
node-filter
```
* OpenEthereum Client & Network Service Creation & Registration with the I/O Subsystem
```bash
ethcore-service
```
* OpenEthereum Blockchain Synchronization
```bash
ethcore-sync
```
* OpenEthereum Common Types
```bash
common-types
```
* OpenEthereum Virtual Machines (VM) Support Library
```bash
vm
```
* OpenEthereum WASM Interpreter
```bash
wasm
```
* OpenEthereum WASM Test Runner
```bash
pwasm-run-test
```
* OpenEthereum EVM Implementation
```bash
evmbin
```
* OpenEthereum JSON Deserialization
```bash
ethjson
```
* OpenEthereum State Machine Generalization for Consensus Engines
```bash
parity-machine
```
* OpenEthereum Miner Interface
```bash
ethcore-miner parity-local-store price-info ethcore-stratum using_queue
```
* OpenEthereum Logger Implementation
```bash
ethcore-logger
```
* OpenEthereum JSON-RPC Servers
```bash
parity-rpc
```
* OpenEthereum Updater Service
```bash
parity-updater parity-hash-fetch
```
* OpenEthereum Core Libraries (`util`)
```bash
accounts-bloom blooms-db dir eip-712 fake-fetch fastmap fetch ethcore-io
journaldb keccak-hasher len-caching-lock memory-cache memzero
migration-rocksdb ethcore-network ethcore-network-devp2p panic_hook
patricia-trie-ethereum registrar rlp_compress stats
time-utils triehash-ethereum unexpected parity-version
```
</p></details>
## 6. Toolchain <a id="chapter-006"></a>
In addition to the OpenEthereum client, there are additional tools in this repository available:
- [evmbin](./bin/evmbin) - OpenEthereum EVM Implementation.
- [ethstore](./crates/accounts/ethstore) - OpenEthereum Key Management.
- [ethkey](./crates/accounts/ethkey) - OpenEthereum 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.
## 7. Contributing <a id="chapter-007"></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).
### Contributor Code of Conduct
[CODE_OF_CONDUCT](./.github/CODE_OF_CONDUCT.md)
## 8. License <a id="chapter-008"></a>
[LICENSE](./LICENSE)

View File

@ -1,80 +0,0 @@
# 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-----
mQENBFlyIAwBCACe0keNPjgYzZ1Oy/8t3zj/Qw9bHHqrzx7FWy8NbXnYBM19NqOZ
DIP7Oe0DvCaf/uruBskCS0iVstHlEFQ2AYe0Ei0REt9lQdy61GylU/DEB3879IG+
6FO0SnFeYeerv1/hFI2K6uv8v7PyyVDiiJSW0I1KIs2OBwJicTKmWxLAeQsRgx9G
yRGalrVk4KP+6pWTA7k3DxmDZKZyfYV/Ej10NtuzmsemwDbv98HKeomp/kgFOfSy
3AZjeCpctlsNqpjUuXa0/HudmH2WLxZ0fz8XeoRh8XM9UudNIecjrDqmAFrt/btQ
/3guvlzhFCdhYPVGsUusKMECk/JG+Xx1/1ZjABEBAAG0LFBhcml0eSBTZWN1cml0
eSBDb250YWN0IDxzZWN1cml0eUBwYXJpdHkuaW8+iQFUBBMBCAA+FiEE2uUVYCjP
N6B8aTiDXQ8DAY0H3nMFAllyIAwCGwMFCQPCZwAFCwkIBwIGFQgJCgsCBBYCAwEC
HgECF4AACgkQXQ8DAY0H3nM60wgAkS3A36Zc+upiaxU7tumcGv+an17j7gin0sif
+0ELSjVfrXInM6ovai+NhUdcLkJ7tCrKS90fvlaELK5Sg9CXBWCTFccKN4A/B7ey
rOg2NPXUecnyBB/XqQgKYH7ujYlOlqBDXMfz6z8Hj6WToxg9PPMGGomyMGh8AWxM
3yRPFs5RKt0VKgN++5N00oly5Y8ri5pgCidDvCLYMGTVDHFKwkuc9w6BlWlu1R1e
/hXFWUFAP1ffTAul3QwyKhjPn2iotCdxXjvt48KaU8DN4iL7aMBN/ZBKqGS7yRdF
D/JbJyaaJ0ZRvFSTSXy/sWY3z1B5mtCPBxco8hqqNfRkCwuZ6LkBDQRZciAMAQgA
8BP8xrwe12TOUTqL/Vrbxv/FLdhKh53J6TrPKvC2TEEKOrTNo5ahRq+XOS5E7G2N
x3b+fq8gR9BzFcldAx0XWUtGs/Wv++ulaSNqTBxj13J3G3WGsUfMKxRgj//piCUD
bCFLQfGZdKk0M1o9QkPVARwwmvCNiNB/l++xGqPtfc44H5jWj3GoGvL2MkShPzrN
yN/bJ+m+R5gtFGdInqa5KXBuxxuW25eDKJ+LzjbgUgeC76wNcfOiQHTdMkcupjdO
bbGFwo10hcbRAOcZEv6//Zrlmk/6nPxEd2hN20St2bSN0+FqfZ267mWEu3ejsgF8
ArdCpv5h4fBvJyNwiTZwIQARAQABiQE8BBgBCAAmFiEE2uUVYCjPN6B8aTiDXQ8D
AY0H3nMFAllyIAwCGwwFCQPCZwAACgkQXQ8DAY0H3nNisggAl4fqhRlA34wIb190
sqXHVxiCuzPaqS6krE9xAa1+gncX485OtcJNqnjugHm2rFE48lv7oasviuPXuInE
/OgVFnXYv9d/Xx2JUeDs+bFTLouCDRY2Unh7KJZasfqnMcCHWcxHx5FvRNZRssaB
WTZVo6sizPurGUtbpYe4/OLFhadBqAE0EUmVRFEUMc1YTnu4eLaRBzoWN4d2UWwi
LN25RSrVSke7LTSFbgn9ntQrQ2smXSR+cdNkkfRCjFcpUaecvFl9HwIqoyVbT4Ym
0hbpbbX/cJdc91tKa+psa29uMeGL/cgL9fAu19yNFRyOTMxjZnvql1X/WE1pLmoP
ETBD1Q==
=K9Qw
-----END PGP PUBLIC KEY BLOCK-----
```

View File

@ -1,9 +1,9 @@
[package]
description = "Parity Ethereum Chain Specification"
name = "chainspec"
version = "0.1.0"
authors = ["Marek Kotewicz <marek@parity.io>"]
[dependencies]
ethjson = { path = "../json" }
ethjson = { path = "../../crates/ethjson" }
serde_json = "1.0"
serde_ignored = "0.0.4"

51
bin/chainspec/src/main.rs Normal file
View File

@ -0,0 +1,51 @@
// 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/>.
extern crate ethjson;
extern crate serde_json;
use ethjson::spec::Spec;
use std::{env, fs, process};
fn quit(s: &str) -> ! {
println!("{}", s);
process::exit(1);
}
fn main() {
let mut args = env::args();
if args.len() != 2 {
quit(
"You need to specify chainspec.json\n\
\n\
./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 spec: Result<Spec, _> = serde_json::from_reader(file);
if let Err(err) = spec {
quit(&format!("{} {}", path, err.to_string()));
}
println!("{} is valid", path);
}

View File

@ -1,14 +1,16 @@
[package]
description = "Parity Ethereum Keys Generator CLI"
name = "ethkey-cli"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
docopt = "0.8"
docopt = "1.0"
env_logger = "0.5"
ethkey = { path = "../" }
panic_hook = { path = "../../util/panic_hook" }
parity-wordlist="1.2"
ethkey = { path = "../../crates/accounts/ethkey" }
panic_hook = { path = "../../crates/util/panic-hook" }
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parity-wordlist="1.3"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"

493
bin/ethkey/src/main.rs Normal file
View File

@ -0,0 +1,493 @@
// 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/>.
extern crate docopt;
extern crate env_logger;
extern crate ethkey;
extern crate panic_hook;
extern crate parity_crypto as crypto;
extern crate parity_wordlist;
extern crate rustc_hex;
extern crate serde;
extern crate threadpool;
#[macro_use]
extern crate serde_derive;
use std::{env, fmt, io, num::ParseIntError, process, sync};
use crypto::publickey::{
sign, verify_address, verify_public, Error as EthkeyError, Generator, KeyPair, Random,
};
use docopt::Docopt;
use ethkey::{brain_recover, Brain, BrainPrefix, Prefix};
use rustc_hex::{FromHex, FromHexError};
const USAGE: &'static str = r#"
Parity Ethereum keys generator.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Usage:
ethkey info <secret-or-phrase> [options]
ethkey generate random [options]
ethkey generate prefix <prefix> [options]
ethkey sign <secret> <message>
ethkey verify public <public> <signature> <message>
ethkey verify address <address> <signature> <message>
ethkey recover <address> <known-phrase>
ethkey [-h | --help]
Options:
-h, --help Display this message and exit.
-s, --secret Display only the secret key.
-p, --public Display only the public key.
-a, --address Display only the address.
-b, --brain Use parity brain wallet algorithm. Not recommended.
Commands:
info Display public key and address of the secret.
generate random Generates new random Ethereum key.
generate prefix Random generation, but address must start with a prefix ("vanity address").
sign Sign message using a secret key.
verify Verify signer of the signature by public key or address.
recover Try to find brain phrase matching given address from partial phrase.
"#;
#[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,
}
#[derive(Debug)]
enum 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)
}
}
impl From<FromHexError> for Error {
fn from(err: FromHexError) -> Self {
Error::FromHex(err)
}
}
impl From<ParseIntError> for Error {
fn from(err: ParseIntError) -> Self {
Error::ParseInt(err)
}
}
impl From<docopt::Error> for Error {
fn from(err: docopt::Error) -> Self {
Error::Docopt(err)
}
}
impl From<io::Error> for Error {
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),
}
}
}
enum DisplayMode {
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 main() {
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);
}
}
}
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()),
}
}
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);
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();
(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::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();
if keypair.address() == address {
return Ok(Some((phrase, keypair)));
}
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))
};
}
const BRAIN_WORDS: usize = 12;
fn validate_phrase(phrase: &str) -> String {
match Brain::validate_phrase(phrase, BRAIN_WORDS) {
Ok(()) => format!("The recovery phrase looks correct.\n"),
Err(err) => format!("The recover phrase was not generated by Parity: {}", err),
}
}
fn in_threads<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 (tx, rx) = sync::mpsc::sync_channel(1);
let is_done = sync::Arc::new(sync::atomic::AtomicBool::default());
for _ in 0..pool.max_count() {
let is_done = is_done.clone();
let tx = tx.clone();
let mut task = prepare();
pool.execute(move || {
loop {
if is_done.load(sync::atomic::Ordering::SeqCst) {
return;
}
let res = match task() {
Ok(None) => continue,
Ok(Some(v)) => Ok(v),
Err(err) => Err(err),
};
// We are interested only in the first response.
let _ = tx.send(res);
}
});
}
if let Ok(solution) = rx.recv() {
is_done.store(true, sync::atomic::Ordering::SeqCst);
return solution;
}
Err(EthkeyError::Custom("No results found.".into()))
}
#[cfg(test)]
mod tests {
use super::execute;
#[test]
fn info() {
let command = vec![
"ethkey",
"info",
"17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55",
]
.into_iter()
.map(Into::into)
.collect::<Vec<String>>();
let expected =
"secret: 17d08f5fe8c77af811caa0c9a187e668ce3b74a99acc3f6d976f075fa8e0be55
public: 689268c0ff57a20cd299fa60d3fb374862aff565b20b5f1767906a99e6e09f3ff04ca2b2a5cd22f62941db103c0356df1a8ed20ce322cab2483db67685afd124
address: 26d1ec50b4e62c1d1a40d16e7cacc6a6580757d5".to_owned();
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>>();
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);
}
#[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"]
.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);
}
}

25
bin/ethstore/Cargo.toml Normal file
View File

@ -0,0 +1,25 @@
[package]
description = "Parity Ethereum Key Management CLI"
name = "ethstore-cli"
version = "0.1.1"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
docopt = "1.0"
env_logger = "0.5"
num_cpus = "1.6"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"
parking_lot = "0.11.1"
ethstore = { path = "../../crates/accounts/ethstore" }
dir = { path = '../../crates/util/dir' }
panic_hook = { path = "../../crates/util/panic-hook" }
[[bin]]
name = "ethstore"
path = "src/main.rs"
doc = false
[dev-dependencies]
tempdir = "0.3.5"

66
bin/ethstore/src/crack.rs Normal file
View File

@ -0,0 +1,66 @@
// 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 parking_lot::Mutex;
use std::{cmp, collections::VecDeque, sync::Arc, thread};
use ethstore::{ethkey::Password, Error, PresaleWallet};
use num_cpus;
pub fn run(passwords: VecDeque<Password>, wallet_path: &str) -> Result<(), Error> {
let passwords = Arc::new(Mutex::new(passwords));
let mut handles = Vec::new();
for _ in 0..num_cpus::get() {
let passwords = passwords.clone();
let wallet = PresaleWallet::open(&wallet_path)?;
handles.push(thread::spawn(move || {
look_for_password(passwords, wallet);
}));
}
for handle in handles {
handle
.join()
.map_err(|err| Error::Custom(format!("Error finishing thread: {:?}", err)))?;
}
Ok(())
}
fn look_for_password(passwords: Arc<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!("."),
_ => {}
}
}
}
}

363
bin/ethstore/src/main.rs Normal file
View File

@ -0,0 +1,363 @@
// 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/>.
extern crate dir;
extern crate docopt;
extern crate ethstore;
extern crate num_cpus;
extern crate panic_hook;
extern crate parking_lot;
extern crate rustc_hex;
extern crate serde;
extern crate env_logger;
#[macro_use]
extern crate serde_derive;
use std::{collections::VecDeque, env, fmt, fs, io::Read, process};
use docopt::Docopt;
use ethstore::{
accounts_dir::{KeyDirectory, RootDiskDirectory},
ethkey::{Address, Password},
import_accounts, EthStore, PresaleWallet, SecretStore, SecretVaultRef, SimpleSecretStore,
StoreAccountRef,
};
mod crack;
pub const USAGE: &'static str = r#"
Parity Ethereum key management tool.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Usage:
ethstore insert <secret> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore change-pwd <address> <old-pwd> <new-pwd> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore list [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore import [<password>] [--src DIR] [--dir DIR]
ethstore import-wallet <path> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore find-wallet-pass <path> <password>
ethstore remove <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore sign <address> <password> <message> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore public <address> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore list-vaults [--dir DIR]
ethstore create-vault <vault> <password> [--dir DIR]
ethstore change-vault-pwd <vault> <old-pwd> <new-pwd> [--dir DIR]
ethstore move-to-vault <address> <vault> <password> [--dir DIR] [--vault VAULT] [--vault-pwd VAULTPWD]
ethstore move-from-vault <address> <vault> <password> [--dir DIR]
ethstore [-h | --help]
Options:
-h, --help Display this message and exit.
--dir DIR Specify the secret store directory. It may be either
parity, parity-(chain), geth, geth-test
or a path [default: parity].
--vault VAULT Specify vault to use in this operation.
--vault-pwd VAULTPWD Specify vault password to use in this operation. Please note
that this option is required when vault option is set.
Otherwise it is ignored.
--src DIR Specify import source. It may be either
parity, parity-(chain), geth, geth-test
or a path [default: geth].
Commands:
insert Save account with password.
change-pwd Change password.
list List accounts.
import Import accounts from src.
import-wallet Import presale wallet.
find-wallet-pass Tries to open a wallet with list of passwords given.
remove Remove account.
sign Sign message.
public Displays public key for an address.
list-vaults List vaults.
create-vault Create new vault.
change-vault-pwd Change vault password.
move-to-vault Move account to vault from another vault/root directory.
move-from-vault Move account to root directory from given vault.
"#;
#[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,
}
enum Error {
Ethstore(ethstore::Error),
Docopt(docopt::Error),
}
impl From<ethstore::Error> for Error {
fn from(err: ethstore::Error) -> Self {
Error::Ethstore(err)
}
}
impl From<docopt::Error> for Error {
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 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.");
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)?,
};
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);
}
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 format_accounts(accounts: &[Address]) -> String {
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")
}
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())
}
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)?)?;
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))
};
}

33
bin/evmbin/Cargo.toml Normal file
View File

@ -0,0 +1,33 @@
[package]
description = "Parity EVM Implementation"
name = "evmbin"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[[bin]]
name = "openethereum-evm"
path = "./src/main.rs"
[dependencies]
common-types = { path = "../../crates/ethcore/types", features = ["test-helpers"] }
docopt = "1.0"
env_logger = "0.5"
ethcore = { path = "../../crates/ethcore", features = ["test-helpers", "json-tests", "to-pod-full"] }
ethereum-types = "0.9.2"
ethjson = { path = "../../crates/ethjson" }
evm = { path = "../../crates/vm/evm" }
panic_hook = { path = "../../crates/util/panic-hook" }
parity-bytes = "0.1"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
vm = { path = "../../crates/vm/vm" }
[dev-dependencies]
criterion = "0.3.0"
pretty_assertions = "0.1"
tempdir = "0.3"
[features]
evm-debug = ["ethcore/evm-debug-tests"]

60
bin/evmbin/README.md Normal file
View File

@ -0,0 +1,60 @@
## evmbin
EVM implementation for OpenEthereum.
### Usage
```
EVM implementation for Parity.
Copyright 2015-2020 Parity Technologies (UK) Ltd.
Usage:
openethereum-evm state-test <file> [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only --omit-storage-output --omit-memory-output]
openethereum-evm stats [options]
openethereum-evm stats-jsontests-vm <file>
openethereum-evm [options]
openethereum-evm [-h | --help]
Commands:
state-test Run a state test from a json file.
stats Execute EVM runtime code and return the statistics.
stats-jsontests-vm Execute standard json-tests format VMTests and return
timing statistics in tsv format.
Transaction options:
--code CODE Contract code as hex (without 0x).
--to ADDRESS Recipient address (without 0x).
--from ADDRESS Sender address (without 0x).
--input DATA Input data as hex (without 0x).
--gas GAS Supplied gas as hex (without 0x).
--gas-price WEI Supplied gas price as hex (without 0x).
State test options:
--chain CHAIN Run only from specific chain name (i.e. one of EIP150, EIP158,
Frontier, Homestead, Byzantium, Constantinople,
ConstantinopleFix, Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5,
HomesteadToDaoAt5, HomesteadToEIP150At5, Berlin, Yolo3).
--only NAME Runs only a single test matching the name.
General options:
--json Display verbose results in JSON.
--std-json Display results in standardized JSON format.
--std-err-only With --std-json redirect to err output only.
--std-out-only With --std-json redirect to out output only.
--omit-storage-output With --std-json omit storage output.
--omit-memory-output With --std-json omit memory output.
--std-dump-json Display results in standardized JSON format
with additional state dump.
Display result state dump in standardized JSON format.
--chain CHAIN Chain spec file path.
-h, --help Display this message and exit.
```
## OpenEthereum toolchain
_This project is a part of the OpenEthereum toolchain._
- [evmbin](https://github.com/openethereum/openethereum/blob/master/evmbin/) - EVM implementation for OpenEthereum
- [ethabi](https://github.com/openethereum/ethabi) - OpenEthereum function calls encoding.
- [ethstore](https://github.com/openethereum/openethereum/blob/master/accounts/ethstore) - OpenEthereum key management.
- [ethkey](https://github.com/openethereum/openethereum/blob/master/accounts/ethkey) - OpenEthereum keys generator.

98
bin/evmbin/benches/mod.rs Normal file
View File

@ -0,0 +1,98 @@
// 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/>.
//! benchmarking for EVM
//! should be started with:
//! ```bash
//! cargo bench
//! ```
#[macro_use]
extern crate criterion;
extern crate ethcore;
extern crate ethereum_types;
extern crate evm;
extern crate rustc_hex;
extern crate vm;
use criterion::{black_box, Criterion};
use std::sync::Arc;
use ethereum_types::U256;
use evm::Factory;
use rustc_hex::FromHex;
use vm::{tests::FakeExt, ActionParams, Ext};
criterion_group!(
evmbin,
bench_simple_loop_usize,
bench_simple_loop_u256,
bench_rng_usize,
bench_rng_u256
);
criterion_main!(evmbin);
fn bench_simple_loop_usize(c: &mut Criterion) {
simple_loop(U256::from(::std::usize::MAX), c, "simple_loop_usize")
}
fn bench_simple_loop_u256(c: &mut Criterion) {
simple_loop(!U256::zero(), c, "simple_loop_u256")
}
fn simple_loop(gas: U256, c: &mut Criterion, bench_id: &str) {
let code = black_box(
"606060405260005b620042408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200".from_hex().unwrap()
);
c.bench_function(bench_id, move |b| {
b.iter(|| {
let mut params = ActionParams::default();
params.gas = gas;
params.code = Some(Arc::new(code.clone()));
let mut ext = FakeExt::new();
let evm = Factory::default().create(params, ext.schedule(), ext.depth());
let _ = evm.exec(&mut ext);
})
});
}
fn bench_rng_usize(c: &mut Criterion) {
rng(U256::from(::std::usize::MAX), c, "rng_usize")
}
fn bench_rng_u256(c: &mut Criterion) {
rng(!U256::zero(), c, "rng_u256")
}
fn rng(gas: U256, c: &mut Criterion, bench_id: &str) {
let code = black_box(
"6060604052600360056007600b60005b62004240811215607f5767ffe7649d5eca84179490940267f47ed85c4b9a6379019367f8e5dd9a5c994bba9390930267f91d87e4b8b74e55019267ff97f6f3b29cda529290920267f393ada8dd75c938019167fe8d437c45bb3735830267f47d9a7b5428ffec019150600101600f565b838518831882186000555050505050600680609a6000396000f3606060405200".from_hex().unwrap()
);
c.bench_function(bench_id, move |b| {
b.iter(|| {
let mut params = ActionParams::default();
params.gas = gas;
params.code = Some(Arc::new(code.clone()));
let mut ext = FakeExt::new();
let evm = Factory::default().create(params, ext.schedule(), ext.depth());
let _ = evm.exec(&mut ext);
})
});
}

View File

@ -0,0 +1,40 @@
// 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/>.
//! Config used by display informants
#[derive(Default, Copy, Clone, Debug)]
pub struct Config {
omit_storage_output: bool,
omit_memory_output: bool,
}
impl Config {
pub fn new(omit_storage_output: bool, omit_memory_output: bool) -> Config {
Config {
omit_storage_output,
omit_memory_output,
}
}
pub fn omit_storage_output(&self) -> bool {
self.omit_storage_output
}
pub fn omit_memory_output(&self) -> bool {
self.omit_memory_output
}
}

View File

@ -0,0 +1,425 @@
// 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/>.
//! JSON VM output.
use std::{collections::HashMap, mem};
use super::config::Config;
use bytes::ToPretty;
use display;
use ethcore::trace;
use ethereum_types::{BigEndianHash, H256, U256};
use info as vm;
/// JSON formatting informant.
#[derive(Default)]
pub struct Informant {
code: Vec<u8>,
depth: usize,
pc: usize,
instruction: u8,
gas_cost: U256,
gas_used: U256,
mem_written: Option<(usize, usize)>,
store_written: Option<(U256, U256)>,
stack: Vec<U256>,
memory: Vec<u8>,
storage: HashMap<H256, H256>,
traces: Vec<String>,
subtraces: Vec<String>,
subinfos: Vec<Informant>,
subdepth: usize,
unmatched: bool,
config: Config,
}
impl Informant {
pub fn new(config: Config) -> Informant {
let mut def = Informant::default();
def.config = config;
def
}
fn with_informant_in_depth<F: Fn(&mut Informant)>(
informant: &mut Informant,
depth: usize,
f: F,
) {
if depth == 0 {
f(informant);
} else {
Self::with_informant_in_depth(
informant
.subinfos
.last_mut()
.expect("prepare/done_trace are not balanced"),
depth - 1,
f,
);
}
}
fn informant_trace(informant: &Informant, gas_used: U256) -> String {
let memory = if informant.config.omit_memory_output() {
"".to_string()
} else {
format!("0x{}", informant.memory.to_hex())
};
let storage = if informant.config.omit_storage_output() {
None
} else {
Some(&informant.storage)
};
let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info());
json!({
"pc": informant.pc,
"op": informant.instruction,
"opName": info.map(|i| i.name).unwrap_or(""),
"gas": format!("{:#x}", gas_used.saturating_add(informant.gas_cost)),
"gasCost": format!("{:#x}", informant.gas_cost),
"memory": memory,
"stack": informant.stack,
"storage": storage,
"depth": informant.depth,
})
.to_string()
}
}
impl vm::Informant for Informant {
type Sink = Config;
fn before_test(&mut self, name: &str, action: &str) {
println!("{}", json!({"action": action, "test": name}));
}
fn set_gas(&mut self, gas: U256) {
self.gas_used = gas;
}
fn clone_sink(&self) -> Self::Sink {
self.config
}
fn finish(result: vm::RunResult<Self::Output>, config: &mut Self::Sink) {
match result {
Ok(success) => {
for trace in success.traces.unwrap_or_else(Vec::new) {
println!("{}", trace);
}
let success_msg = json!({
"output": format!("0x{}", success.output.to_hex()),
"gasUsed": format!("{:#x}", success.gas_used),
"time": display::as_micros(&success.time),
});
println!("{}", success_msg)
}
Err(failure) => {
if !config.omit_storage_output() {
for trace in failure.traces.unwrap_or_else(Vec::new) {
println!("{}", trace);
}
}
let failure_msg = json!({
"error": &failure.error.to_string(),
"gasUsed": format!("{:#x}", failure.gas_used),
"time": display::as_micros(&failure.time),
});
println!("{}", failure_msg)
}
}
}
}
impl trace::VMTracer for Informant {
type Output = Vec<String>;
fn trace_next_instruction(&mut self, pc: usize, instruction: u8, _current_gas: U256) -> bool {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| {
informant.pc = pc;
informant.instruction = instruction;
informant.unmatched = true;
});
true
}
fn trace_prepare_execute(
&mut self,
pc: usize,
instruction: u8,
gas_cost: U256,
mem_written: Option<(usize, usize)>,
store_written: Option<(U256, U256)>,
) {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| {
informant.pc = pc;
informant.instruction = instruction;
informant.gas_cost = gas_cost;
informant.mem_written = mem_written;
informant.store_written = store_written;
});
}
fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem: &[u8]) {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| {
let store_diff = informant.store_written.clone();
let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info());
let trace = Self::informant_trace(informant, gas_used);
informant.traces.push(trace);
informant.unmatched = false;
informant.gas_used = gas_used;
let len = informant.stack.len();
let info_args = info.map(|i| i.args).unwrap_or(0);
informant
.stack
.truncate(if len > info_args { len - info_args } else { 0 });
informant.stack.extend_from_slice(stack_push);
// TODO [ToDr] Align memory?
if let Some((pos, size)) = informant.mem_written.clone() {
if informant.memory.len() < (pos + size) {
informant.memory.resize(pos + size, 0);
}
informant.memory[pos..(pos + size)].copy_from_slice(&mem[pos..(pos + size)]);
}
if let Some((pos, val)) = store_diff {
informant.storage.insert(
BigEndianHash::from_uint(&pos),
BigEndianHash::from_uint(&val),
);
}
if !informant.subtraces.is_empty() {
informant
.traces
.extend(mem::replace(&mut informant.subtraces, vec![]));
}
});
}
fn prepare_subtrace(&mut self, code: &[u8]) {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| {
let mut vm = Informant::default();
vm.config = informant.config;
vm.depth = informant.depth + 1;
vm.code = code.to_vec();
vm.gas_used = informant.gas_used;
informant.subinfos.push(vm);
});
self.subdepth += 1;
}
fn done_subtrace(&mut self) {
self.subdepth -= 1;
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant| {
if let Some(subtraces) = informant
.subinfos
.pop()
.expect("prepare/done_subtrace are not balanced")
.drain()
{
informant.subtraces.extend(subtraces);
}
});
}
fn drain(mut self) -> Option<Self::Output> {
if self.unmatched {
// print last line with final state:
self.gas_cost = 0.into();
let gas_used = self.gas_used;
let subdepth = self.subdepth;
Self::with_informant_in_depth(&mut self, subdepth, |informant: &mut Informant| {
let trace = Self::informant_trace(informant, gas_used);
informant.traces.push(trace);
});
} else if !self.subtraces.is_empty() {
self.traces
.extend(mem::replace(&mut self.subtraces, vec![]));
}
Some(self.traces)
}
}
#[cfg(test)]
mod tests {
use super::*;
use info::tests::run_test;
use serde_json;
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(rename_all = "camelCase")]
struct TestTrace {
pc: usize,
#[serde(rename = "op")]
instruction: u8,
op_name: String,
#[serde(rename = "gas")]
gas_used: U256,
gas_cost: U256,
memory: String,
stack: Vec<U256>,
storage: Option<HashMap<H256, H256>>,
depth: usize,
}
fn assert_traces_eq(a: &[String], b: &[String]) {
let mut ita = a.iter();
let mut itb = b.iter();
loop {
match (ita.next(), itb.next()) {
(Some(a), Some(b)) => {
// Compare both without worrying about the order of the fields
let actual: TestTrace = serde_json::from_str(a).unwrap();
let expected: TestTrace = serde_json::from_str(b).unwrap();
assert_eq!(actual, expected);
println!("{}", a);
}
(None, None) => return,
e => {
panic!("Traces mismatch: {:?}", e);
}
}
}
}
fn compare_json(traces: Option<Vec<String>>, expected: &str) {
let expected = expected
.split("\n")
.map(|x| x.trim())
.map(|x| x.to_owned())
.filter(|x| !x.is_empty())
.collect::<Vec<_>>();
assert_traces_eq(&traces.unwrap(), &expected);
}
#[test]
fn should_trace_failure() {
run_test(
Informant::default(),
&compare_json,
"60F8d6",
0xffff,
r#"
{"pc":0,"op":96,"opName":"PUSH1","gas":"0xffff","gasCost":"0x3","memory":"0x","stack":[],"storage":{},"depth":1}
{"pc":2,"op":214,"opName":"","gas":"0xfffc","gasCost":"0x0","memory":"0x","stack":["0xf8"],"storage":{},"depth":1}
"#,
);
run_test(
Informant::default(),
&compare_json,
"F8d6",
0xffff,
r#"
{"pc":0,"op":248,"opName":"","gas":"0xffff","gasCost":"0x0","memory":"0x","stack":[],"storage":{},"depth":1}
"#,
);
run_test(
Informant::default(),
&compare_json,
"5A51",
0xfffff,
r#"
{"depth":1,"gas":"0xfffff","gasCost":"0x2","memory":"0x","op":90,"opName":"GAS","pc":0,"stack":[],"storage":{}}
{"depth":1,"gas":"0xffffd","gasCost":"0x0","memory":"0x","op":81,"opName":"MLOAD","pc":1,"stack":["0xffffd"],"storage":{}}
"#,
);
}
#[test]
fn should_trace_create_correctly() {
run_test(
Informant::default(),
&compare_json,
"32343434345830f138343438323439f0",
0xffff,
r#"
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":1}
{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0xfffd","gasCost":"0x2","memory":"0x","stack":["0x0"],"storage":{},"depth":1}
{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0xfffb","gasCost":"0x2","memory":"0x","stack":["0x0","0x0"],"storage":{},"depth":1}
{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0xfff9","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0"],"storage":{},"depth":1}
{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0xfff7","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
{"pc":5,"op":88,"opName":"PC","gas":"0xfff5","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":1}
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0xfff3","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":1}
{"pc":7,"op":241,"opName":"CALL","gas":"0xfff1","gasCost":"0x61d0","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{},"depth":1}
{"pc":8,"op":56,"opName":"CODESIZE","gas":"0x9e21","gasCost":"0x2","memory":"0x","stack":["0x1"],"storage":{},"depth":1}
{"pc":9,"op":52,"opName":"CALLVALUE","gas":"0x9e1f","gasCost":"0x2","memory":"0x","stack":["0x1","0x10"],"storage":{},"depth":1}
{"pc":10,"op":52,"opName":"CALLVALUE","gas":"0x9e1d","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0"],"storage":{},"depth":1}
{"pc":11,"op":56,"opName":"CODESIZE","gas":"0x9e1b","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
{"pc":12,"op":50,"opName":"ORIGIN","gas":"0x9e19","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{},"depth":1}
{"pc":13,"op":52,"opName":"CALLVALUE","gas":"0x9e17","gasCost":"0x2","memory":"0x","stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{},"depth":1}
{"pc":14,"op":57,"opName":"CODECOPY","gas":"0x9e15","gasCost":"0x9","memory":"0x","stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{},"depth":1}
{"pc":15,"op":240,"opName":"CREATE","gas":"0x9e0c","gasCost":"0x9e0c","memory":"0x32343434345830f138343438323439f0","stack":["0x1","0x10","0x0","0x0"],"storage":{},"depth":1}
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0x210c","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":2}
{"pc":1,"op":52,"opName":"CALLVALUE","gas":"0x210a","gasCost":"0x2","memory":"0x","stack":["0x0"],"storage":{},"depth":2}
{"pc":2,"op":52,"opName":"CALLVALUE","gas":"0x2108","gasCost":"0x2","memory":"0x","stack":["0x0","0x0"],"storage":{},"depth":2}
{"pc":3,"op":52,"opName":"CALLVALUE","gas":"0x2106","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0"],"storage":{},"depth":2}
{"pc":4,"op":52,"opName":"CALLVALUE","gas":"0x2104","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
{"pc":5,"op":88,"opName":"PC","gas":"0x2102","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{},"depth":2}
{"pc":6,"op":48,"opName":"ADDRESS","gas":"0x2100","gasCost":"0x2","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{},"depth":2}
{"pc":7,"op":241,"opName":"CALL","gas":"0x20fe","gasCost":"0x0","memory":"0x","stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{},"depth":2}
"#,
);
run_test(
Informant::default(),
&compare_json,
"3260D85554",
0xffff,
r#"
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"0x","stack":[],"storage":{},"depth":1}
{"pc":1,"op":96,"opName":"PUSH1","gas":"0xfffd","gasCost":"0x3","memory":"0x","stack":["0x0"],"storage":{},"depth":1}
{"pc":3,"op":85,"opName":"SSTORE","gas":"0xfffa","gasCost":"0x1388","memory":"0x","stack":["0x0","0xd8"],"storage":{},"depth":1}
{"pc":4,"op":84,"opName":"SLOAD","gas":"0xec72","gasCost":"0x0","memory":"0x","stack":[],"storage":{"0x00000000000000000000000000000000000000000000000000000000000000d8":"0x0000000000000000000000000000000000000000000000000000000000000000"},"depth":1}
"#,
);
}
#[test]
fn should_omit_storage_and_memory_flag() {
// should omit storage
run_test(
Informant::new(Config::new(true, true)),
&compare_json,
"3260D85554",
0xffff,
r#"
{"pc":0,"op":50,"opName":"ORIGIN","gas":"0xffff","gasCost":"0x2","memory":"","stack":[],"storage":null,"depth":1}
{"pc":1,"op":96,"opName":"PUSH1","gas":"0xfffd","gasCost":"0x3","memory":"","stack":["0x0"],"storage":null,"depth":1}
{"pc":3,"op":85,"opName":"SSTORE","gas":"0xfffa","gasCost":"0x1388","memory":"","stack":["0x0","0xd8"],"storage":null,"depth":1}
{"pc":4,"op":84,"opName":"SLOAD","gas":"0xec72","gasCost":"0x0","memory":"","stack":[],"storage":null,"depth":1}
"#,
)
}
}

View File

@ -1,33 +1,34 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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 Parity. If not, see <http://www.gnu.org/licenses/>.
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! VM Output display utils.
use std::time::Duration;
pub mod config;
pub mod json;
pub mod std_json;
pub mod simple;
pub mod std_json;
/// Formats duration into human readable format.
pub fn format_time(time: &Duration) -> String {
format!("{}.{:.9}s", time.as_secs(), time.subsec_nanos())
format!("{}.{:.9}s", time.as_secs(), time.subsec_nanos())
}
/// Formats the time as microseconds.
pub fn as_micros(time: &Duration) -> u64 {
time.as_secs() * 1_000_000 + time.subsec_nanos() as u64 / 1_000
time.as_secs() * 1_000_000 + time.subsec_nanos() as u64 / 1_000
}

View File

@ -0,0 +1,74 @@
// 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/>.
//! Simple VM output.
use super::config::Config;
use bytes::ToPretty;
use ethcore::trace;
use display;
use info as vm;
/// Simple formatting informant.
#[derive(Default)]
pub struct Informant {
config: Config,
}
impl Informant {
pub fn new(config: Config) -> Informant {
Informant { config }
}
}
impl vm::Informant for Informant {
type Sink = Config;
fn before_test(&mut self, name: &str, action: &str) {
println!("Test: {} ({})", name, action);
}
fn clone_sink(&self) -> Self::Sink {
self.config
}
fn finish(result: vm::RunResult<Self::Output>, _sink: &mut Self::Sink) {
match result {
Ok(success) => {
println!("Output: 0x{}", success.output.to_hex());
println!("Gas used: {:x}", success.gas_used);
println!("Time: {}", display::format_time(&success.time));
}
Err(failure) => {
println!("Error: {}", failure.error);
println!("Time: {}", display::format_time(&failure.time));
}
}
}
}
impl trace::VMTracer for Informant {
type Output = ();
fn prepare_subtrace(&mut self, _code: &[u8]) {
Default::default()
}
fn done_subtrace(&mut self) {}
fn drain(self) -> Option<()> {
None
}
}

View File

@ -0,0 +1,413 @@
// 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/>.
//! Standardized JSON VM output.
use std::{collections::HashMap, io};
use super::config::Config;
use bytes::ToPretty;
use display;
use ethcore::{pod_state, trace};
use ethereum_types::{BigEndianHash, H256, U256};
use info as vm;
pub trait Writer: io::Write + Send + Sized {
fn clone(&self) -> Self;
fn default() -> Self;
}
impl Writer for io::Stdout {
fn clone(&self) -> Self {
io::stdout()
}
fn default() -> Self {
io::stdout()
}
}
impl Writer for io::Stderr {
fn clone(&self) -> Self {
io::stderr()
}
fn default() -> Self {
io::stderr()
}
}
/// JSON formatting informant.
pub struct Informant<Trace, Out> {
code: Vec<u8>,
instruction: u8,
depth: usize,
stack: Vec<U256>,
storage: HashMap<H256, H256>,
subinfos: Vec<Informant<Trace, Out>>,
subdepth: usize,
trace_sink: Trace,
out_sink: Out,
config: Config,
}
impl Default for Informant<io::Stderr, io::Stdout> {
fn default() -> Self {
Self::new(io::stderr(), io::stdout(), Config::default())
}
}
impl Informant<io::Stdout, io::Stdout> {
/// std json informant using out only.
pub fn out_only(config: Config) -> Self {
Self::new(io::stdout(), io::stdout(), config)
}
}
impl Informant<io::Stderr, io::Stderr> {
/// std json informant using err only.
pub fn err_only(config: Config) -> Self {
Self::new(io::stderr(), io::stderr(), config)
}
}
impl Informant<io::Stderr, io::Stdout> {
pub fn new_default(config: Config) -> Self {
let mut informant = Self::default();
informant.config = config;
informant
}
}
impl<Trace: Writer, Out: Writer> Informant<Trace, Out> {
pub fn new(trace_sink: Trace, out_sink: Out, config: Config) -> Self {
Informant {
code: Default::default(),
instruction: Default::default(),
depth: Default::default(),
stack: Default::default(),
storage: Default::default(),
subinfos: Default::default(),
subdepth: 0,
trace_sink,
out_sink,
config,
}
}
fn with_informant_in_depth<F: Fn(&mut Informant<Trace, Out>)>(
informant: &mut Informant<Trace, Out>,
depth: usize,
f: F,
) {
if depth == 0 {
f(informant);
} else {
Self::with_informant_in_depth(
informant
.subinfos
.last_mut()
.expect("prepare/done_trace are not balanced"),
depth - 1,
f,
);
}
}
fn dump_state_into(
trace_sink: &mut Trace,
root: H256,
end_state: &Option<pod_state::PodState>,
) {
if let Some(ref end_state) = end_state {
let dump_data = json!({
"root": root,
"accounts": end_state,
});
writeln!(trace_sink, "{}", dump_data).expect("The sink must be writeable.");
}
}
}
impl<Trace: Writer, Out: Writer> vm::Informant for Informant<Trace, Out> {
type Sink = (Trace, Out, Config);
fn before_test(&mut self, name: &str, action: &str) {
let out_data = json!({
"action": action,
"test": name,
});
writeln!(&mut self.out_sink, "{}", out_data).expect("The sink must be writeable.");
}
fn set_gas(&mut self, _gas: U256) {}
fn clone_sink(&self) -> Self::Sink {
(
self.trace_sink.clone(),
self.out_sink.clone(),
self.config.clone(),
)
}
fn finish(
result: vm::RunResult<<Self as trace::VMTracer>::Output>,
(ref mut trace_sink, ref mut out_sink, _): &mut Self::Sink,
) {
match result {
Ok(success) => {
let trace_data = json!({"stateRoot": success.state_root});
writeln!(trace_sink, "{}", trace_data).expect("The sink must be writeable.");
Self::dump_state_into(trace_sink, success.state_root, &success.end_state);
let out_data = json!({
"output": format!("0x{}", success.output.to_hex()),
"gasUsed": format!("{:#x}", success.gas_used),
"time": display::as_micros(&success.time),
});
writeln!(out_sink, "{}", out_data).expect("The sink must be writeable.");
}
Err(failure) => {
let out_data = json!({
"error": &failure.error.to_string(),
"gasUsed": format!("{:#x}", failure.gas_used),
"time": display::as_micros(&failure.time),
});
Self::dump_state_into(trace_sink, failure.state_root, &failure.end_state);
writeln!(out_sink, "{}", out_data).expect("The sink must be writeable.");
}
}
}
}
impl<Trace: Writer, Out: Writer> trace::VMTracer for Informant<Trace, Out> {
type Output = ();
fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
let storage = if informant.config.omit_storage_output() {
None
} else {
Some(&informant.storage)
};
let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info());
informant.instruction = instruction;
let trace_data = json!({
"pc": pc,
"op": instruction,
"opName": info.map(|i| i.name).unwrap_or(""),
"gas": format!("{:#x}", current_gas),
"stack": informant.stack,
"storage": storage,
"depth": informant.depth,
});
writeln!(&mut informant.trace_sink, "{}", trace_data)
.expect("The sink must be writeable.");
});
true
}
fn trace_prepare_execute(
&mut self,
_pc: usize,
_instruction: u8,
_gas_cost: U256,
_mem_written: Option<(usize, usize)>,
store_written: Option<(U256, U256)>,
) {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
if let Some((pos, val)) = store_written {
informant.storage.insert(
BigEndianHash::from_uint(&pos),
BigEndianHash::from_uint(&val),
);
}
});
}
fn trace_executed(&mut self, _gas_used: U256, stack_push: &[U256], _mem: &[u8]) {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
let info = ::evm::Instruction::from_u8(informant.instruction).map(|i| i.info());
let len = informant.stack.len();
let info_args = info.map(|i| i.args).unwrap_or(0);
informant
.stack
.truncate(if len > info_args { len - info_args } else { 0 });
informant.stack.extend_from_slice(stack_push);
});
}
fn prepare_subtrace(&mut self, code: &[u8]) {
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
let mut vm = Informant::new(
informant.trace_sink.clone(),
informant.out_sink.clone(),
informant.config,
);
vm.depth = informant.depth + 1;
vm.code = code.to_vec();
informant.subinfos.push(vm);
});
self.subdepth += 1;
}
fn done_subtrace(&mut self) {
self.subdepth -= 1;
let subdepth = self.subdepth;
Self::with_informant_in_depth(self, subdepth, |informant: &mut Informant<Trace, Out>| {
informant.subinfos.pop();
});
}
fn drain(self) -> Option<Self::Output> {
None
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use info::tests::run_test;
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone, Default)]
pub struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
impl Writer for TestWriter {
fn clone(&self) -> Self {
Clone::clone(self)
}
fn default() -> Self {
Default::default()
}
}
impl io::Write for TestWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.0.lock().unwrap().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.0.lock().unwrap().flush()
}
}
pub fn informant(config: Config) -> (Informant<TestWriter, TestWriter>, Arc<Mutex<Vec<u8>>>) {
let trace_writer: TestWriter = Default::default();
let out_writer: TestWriter = Default::default();
let res = trace_writer.0.clone();
(Informant::new(trace_writer, out_writer, config), res)
}
#[test]
fn should_trace_failure() {
let (inf, res) = informant(Config::default());
run_test(
inf,
move |_, expected| {
let bytes = res.lock().unwrap();
assert_eq!(expected, &String::from_utf8_lossy(&**bytes))
},
"60F8d6",
0xffff,
r#"{"depth":1,"gas":"0xffff","op":96,"opName":"PUSH1","pc":0,"stack":[],"storage":{}}
{"depth":1,"gas":"0xfffc","op":214,"opName":"","pc":2,"stack":["0xf8"],"storage":{}}
"#,
);
let (inf, res) = informant(Config::default());
run_test(
inf,
move |_, expected| {
let bytes = res.lock().unwrap();
assert_eq!(expected, &String::from_utf8_lossy(&**bytes))
},
"F8d6",
0xffff,
r#"{"depth":1,"gas":"0xffff","op":248,"opName":"","pc":0,"stack":[],"storage":{}}
"#,
);
}
#[test]
fn should_trace_create_correctly() {
let (informant, res) = informant(Config::default());
run_test(
informant,
move |_, expected| {
let bytes = res.lock().unwrap();
assert_eq!(expected, &String::from_utf8_lossy(&**bytes))
},
"32343434345830f138343438323439f0",
0xffff,
r#"{"depth":1,"gas":"0xffff","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}}
{"depth":1,"gas":"0xfffd","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}}
{"depth":1,"gas":"0xfffb","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}}
{"depth":1,"gas":"0xfff9","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}}
{"depth":1,"gas":"0xfff7","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}}
{"depth":1,"gas":"0xfff5","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}}
{"depth":1,"gas":"0xfff3","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}}
{"depth":1,"gas":"0xfff1","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0x0"],"storage":{}}
{"depth":1,"gas":"0x9e21","op":56,"opName":"CODESIZE","pc":8,"stack":["0x1"],"storage":{}}
{"depth":1,"gas":"0x9e1f","op":52,"opName":"CALLVALUE","pc":9,"stack":["0x1","0x10"],"storage":{}}
{"depth":1,"gas":"0x9e1d","op":52,"opName":"CALLVALUE","pc":10,"stack":["0x1","0x10","0x0"],"storage":{}}
{"depth":1,"gas":"0x9e1b","op":56,"opName":"CODESIZE","pc":11,"stack":["0x1","0x10","0x0","0x0"],"storage":{}}
{"depth":1,"gas":"0x9e19","op":50,"opName":"ORIGIN","pc":12,"stack":["0x1","0x10","0x0","0x0","0x10"],"storage":{}}
{"depth":1,"gas":"0x9e17","op":52,"opName":"CALLVALUE","pc":13,"stack":["0x1","0x10","0x0","0x0","0x10","0x0"],"storage":{}}
{"depth":1,"gas":"0x9e15","op":57,"opName":"CODECOPY","pc":14,"stack":["0x1","0x10","0x0","0x0","0x10","0x0","0x0"],"storage":{}}
{"depth":1,"gas":"0x9e0c","op":240,"opName":"CREATE","pc":15,"stack":["0x1","0x10","0x0","0x0"],"storage":{}}
{"depth":2,"gas":"0x210c","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":{}}
{"depth":2,"gas":"0x210a","op":52,"opName":"CALLVALUE","pc":1,"stack":["0x0"],"storage":{}}
{"depth":2,"gas":"0x2108","op":52,"opName":"CALLVALUE","pc":2,"stack":["0x0","0x0"],"storage":{}}
{"depth":2,"gas":"0x2106","op":52,"opName":"CALLVALUE","pc":3,"stack":["0x0","0x0","0x0"],"storage":{}}
{"depth":2,"gas":"0x2104","op":52,"opName":"CALLVALUE","pc":4,"stack":["0x0","0x0","0x0","0x0"],"storage":{}}
{"depth":2,"gas":"0x2102","op":88,"opName":"PC","pc":5,"stack":["0x0","0x0","0x0","0x0","0x0"],"storage":{}}
{"depth":2,"gas":"0x2100","op":48,"opName":"ADDRESS","pc":6,"stack":["0x0","0x0","0x0","0x0","0x0","0x5"],"storage":{}}
{"depth":2,"gas":"0x20fe","op":241,"opName":"CALL","pc":7,"stack":["0x0","0x0","0x0","0x0","0x0","0x5","0xbd770416a3345f91e4b34576cb804a576fa48eb1"],"storage":{}}
"#,
)
}
#[test]
fn should_omit_storage_and_memory_flag() {
// should omit storage
let (informant, res) = informant(Config::new(true, true));
run_test(
informant,
move |_, expected| {
let bytes = res.lock().unwrap();
assert_eq!(expected, &String::from_utf8_lossy(&**bytes))
},
"3260D85554",
0xffff,
r#"{"depth":1,"gas":"0xffff","op":50,"opName":"ORIGIN","pc":0,"stack":[],"storage":null}
{"depth":1,"gas":"0xfffd","op":96,"opName":"PUSH1","pc":1,"stack":["0x0"],"storage":null}
{"depth":1,"gas":"0xfffa","op":85,"opName":"SSTORE","pc":3,"stack":["0x0","0xd8"],"storage":null}
{"depth":1,"gas":"0xec72","op":84,"opName":"SLOAD","pc":4,"stack":[],"storage":null}
"#,
)
}
}

316
bin/evmbin/src/info.rs Normal file
View File

@ -0,0 +1,316 @@
// 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/>.
//! VM runner.
use ethcore::{
client::{self, EvmTestClient, EvmTestError, TransactErr, TransactSuccess},
pod_state, spec, state, state_db, trace, TrieSpec,
};
use ethereum_types::{H256, U256};
use ethjson;
use std::time::{Duration, Instant};
use types::transaction;
use vm::ActionParams;
/// VM execution informant
pub trait Informant: trace::VMTracer {
/// Sink to use with finish
type Sink;
/// Display a single run init message
fn before_test(&mut self, test: &str, action: &str);
/// Set initial gas.
fn set_gas(&mut self, _gas: U256) {}
/// Clone sink.
fn clone_sink(&self) -> Self::Sink;
/// Display final result.
fn finish(result: RunResult<Self::Output>, &mut Self::Sink);
}
/// Execution finished correctly
#[derive(Debug)]
pub struct Success<T> {
/// State root
pub state_root: H256,
/// Used gas
pub gas_used: U256,
/// Output as bytes
pub output: Vec<u8>,
/// Time Taken
pub time: Duration,
/// Traces
pub traces: Option<T>,
/// Optional end state dump
pub end_state: Option<pod_state::PodState>,
}
/// Execution failed
#[derive(Debug)]
pub struct Failure<T> {
/// State root
pub state_root: H256,
/// Used gas
pub gas_used: U256,
/// Internal error
pub error: EvmTestError,
/// Duration
pub time: Duration,
/// Traces
pub traces: Option<T>,
/// Optional end state dump
pub end_state: Option<pod_state::PodState>,
}
/// EVM Execution result
pub type RunResult<T> = Result<Success<T>, Failure<T>>;
/// Execute given `ActionParams` and return the result.
pub fn run_action<T: Informant>(
spec: &spec::Spec,
mut params: ActionParams,
mut informant: T,
trie_spec: TrieSpec,
) -> RunResult<T::Output> {
informant.set_gas(params.gas);
// if the code is not overwritten from CLI, use code from spec file.
if params.code.is_none() {
if let Some(acc) = spec.genesis_state().get().get(&params.code_address) {
params.code = acc.code.clone().map(::std::sync::Arc::new);
params.code_hash = None;
}
}
run(
spec,
trie_spec,
params.gas,
spec.genesis_state(),
|mut client| {
let result = match client.call(params, &mut trace::NoopTracer, &mut informant) {
Ok(r) => (Ok(r.return_data.to_vec()), Some(r.gas_left)),
Err(err) => (Err(err), None),
};
(result.0, H256::zero(), None, result.1, informant.drain())
},
)
}
/// Execute given Transaction and verify resulting state root.
pub fn run_transaction<T: Informant>(
name: &str,
idx: usize,
spec: &ethjson::spec::ForkSpec,
pre_state: &pod_state::PodState,
post_root: H256,
env_info: &client::EnvInfo,
transaction: transaction::SignedTransaction,
mut informant: T,
trie_spec: TrieSpec,
) {
let spec_name = format!("{:?}", spec).to_lowercase();
let spec = match EvmTestClient::spec_from_json(spec) {
Some(spec) => {
informant.before_test(&format!("{}:{}:{}", name, spec_name, idx), "starting");
spec
}
None => {
informant.before_test(
&format!("{}:{}:{}", name, spec_name, idx),
"skipping because of missing spec",
);
return;
}
};
informant.set_gas(env_info.gas_limit);
let mut sink = informant.clone_sink();
let result = run(
&spec,
trie_spec,
transaction.tx().gas,
pre_state,
|mut client| {
let result = client.transact(env_info, transaction, trace::NoopTracer, informant);
match result {
Ok(TransactSuccess {
state_root,
gas_left,
output,
vm_trace,
end_state,
..
}) => {
if state_root != post_root {
(
Err(EvmTestError::PostCondition(format!(
"State root mismatch (got: {:#x}, expected: {:#x})",
state_root, post_root,
))),
state_root,
end_state,
Some(gas_left),
None,
)
} else {
(Ok(output), state_root, end_state, Some(gas_left), vm_trace)
}
}
Err(TransactErr {
state_root,
error,
end_state,
}) => (
Err(EvmTestError::PostCondition(format!(
"Unexpected execution error: {:?}",
error
))),
state_root,
end_state,
None,
None,
),
}
},
);
T::finish(result, &mut sink)
}
fn dump_state(state: &state::State<state_db::StateDB>) -> Option<pod_state::PodState> {
state.to_pod_full().ok()
}
/// Execute VM with given `ActionParams`
pub fn run<'a, F, X>(
spec: &'a spec::Spec,
trie_spec: TrieSpec,
initial_gas: U256,
pre_state: &'a pod_state::PodState,
run: F,
) -> RunResult<X>
where
F: FnOnce(
EvmTestClient,
) -> (
Result<Vec<u8>, EvmTestError>,
H256,
Option<pod_state::PodState>,
Option<U256>,
Option<X>,
),
{
let do_dump = trie_spec == TrieSpec::Fat;
let mut test_client =
EvmTestClient::from_pod_state_with_trie(spec, pre_state.clone(), trie_spec).map_err(
|error| Failure {
gas_used: 0.into(),
error,
time: Duration::from_secs(0),
traces: None,
state_root: H256::default(),
end_state: None,
},
)?;
if do_dump {
test_client.set_dump_state_fn(dump_state);
}
let start = Instant::now();
let result = run(test_client);
let time = start.elapsed();
match result {
(Ok(output), state_root, end_state, gas_left, traces) => Ok(Success {
state_root,
gas_used: gas_left
.map(|gas_left| initial_gas - gas_left)
.unwrap_or(initial_gas),
output,
time,
traces,
end_state,
}),
(Err(error), state_root, end_state, gas_left, traces) => Err(Failure {
gas_used: gas_left
.map(|gas_left| initial_gas - gas_left)
.unwrap_or(initial_gas),
error,
time,
traces,
state_root,
end_state,
}),
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use ethereum_types::Address;
use rustc_hex::FromHex;
use std::sync::Arc;
use tempdir::TempDir;
pub fn run_test<T, I, F>(informant: I, compare: F, code: &str, gas: T, expected: &str)
where
T: Into<U256>,
I: Informant,
F: FnOnce(Option<I::Output>, &str),
{
let mut params = ActionParams::default();
params.code = Some(Arc::new(code.from_hex().unwrap()));
params.gas = gas.into();
let tempdir = TempDir::new("").unwrap();
let spec = ::ethcore::ethereum::new_foundation(&tempdir.path());
let result = run_action(&spec, params, informant, TrieSpec::Secure);
match result {
Ok(Success { traces, .. }) => compare(traces, expected),
Err(Failure { traces, .. }) => compare(traces, expected),
}
}
#[test]
fn should_call_account_from_spec() {
use display::{config::Config, std_json::tests::informant};
let (inf, res) = informant(Config::default());
let mut params = ActionParams::default();
params.code_address = Address::from_low_u64_be(0x20);
params.gas = 0xffff.into();
let spec = ::ethcore::ethereum::load(None, include_bytes!("../res/testchain.json"));
let _result = run_action(&spec, params, inf, TrieSpec::Secure);
assert_eq!(
&String::from_utf8_lossy(&**res.lock().unwrap()),
r#"{"depth":1,"gas":"0xffff","op":98,"opName":"PUSH3","pc":0,"stack":[],"storage":{}}
{"depth":1,"gas":"0xfffc","op":96,"opName":"PUSH1","pc":4,"stack":["0xaaaaaa"],"storage":{}}
{"depth":1,"gas":"0xfff9","op":96,"opName":"PUSH1","pc":6,"stack":["0xaaaaaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xfff6","op":80,"opName":"POP","pc":8,"stack":["0xaaaaaa","0xaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xfff4","op":96,"opName":"PUSH1","pc":9,"stack":["0xaaaaaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xfff1","op":96,"opName":"PUSH1","pc":11,"stack":["0xaaaaaa","0xaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xffee","op":96,"opName":"PUSH1","pc":13,"stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xffeb","op":96,"opName":"PUSH1","pc":15,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xffe8","op":96,"opName":"PUSH1","pc":17,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}}
{"depth":1,"gas":"0xffe5","op":96,"opName":"PUSH1","pc":19,"stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{}}
"#
);
}
}

511
bin/evmbin/src/main.rs Normal file
View File

@ -0,0 +1,511 @@
// 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/>.
//! OpenEthereum EVM interpreter binary.
#![warn(missing_docs)]
extern crate common_types as types;
extern crate ethcore;
extern crate ethjson;
extern crate rustc_hex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
extern crate docopt;
extern crate env_logger;
extern crate ethereum_types;
extern crate evm;
extern crate panic_hook;
extern crate parity_bytes as bytes;
extern crate vm;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
#[cfg(test)]
extern crate tempdir;
use bytes::Bytes;
use docopt::Docopt;
use ethcore::{json_tests, spec, TrieSpec};
use ethereum_types::{Address, U256};
use ethjson::spec::ForkSpec;
use evm::EnvInfo;
use rustc_hex::FromHex;
use std::{fmt, fs, path::PathBuf, sync::Arc};
use vm::{ActionParams, CallType};
mod display;
mod info;
use info::Informant;
const USAGE: &'static str = r#"
EVM implementation for Parity.
Copyright 2015-2020 Parity Technologies (UK) Ltd.
Usage:
openethereum-evm state-test <file> [--json --std-json --std-dump-json --only NAME --chain CHAIN --std-out-only --std-err-only --omit-storage-output --omit-memory-output]
openethereum-evm stats [options]
openethereum-evm stats-jsontests-vm <file>
openethereum-evm [options]
openethereum-evm [-h | --help]
Commands:
state-test Run a state test from a json file.
stats Execute EVM runtime code and return the statistics.
stats-jsontests-vm Execute standard json-tests format VMTests and return
timing statistics in tsv format.
Transaction options:
--code CODE Contract code as hex (without 0x).
--to ADDRESS Recipient address (without 0x).
--from ADDRESS Sender address (without 0x).
--input DATA Input data as hex (without 0x).
--gas GAS Supplied gas as hex (without 0x).
--gas-price WEI Supplied gas price as hex (without 0x).
State test options:
--chain CHAIN Run only from specific chain name (i.e. one of EIP150, EIP158,
Frontier, Homestead, Byzantium, Constantinople,
ConstantinopleFix, Istanbul, EIP158ToByzantiumAt5, FrontierToHomesteadAt5,
HomesteadToDaoAt5, HomesteadToEIP150At5, Berlin, Yolo3).
--only NAME Runs only a single test matching the name.
General options:
--json Display verbose results in JSON.
--std-json Display results in standardized JSON format.
--std-err-only With --std-json redirect to err output only.
--std-out-only With --std-json redirect to out output only.
--omit-storage-output With --std-json omit storage output.
--omit-memory-output With --std-json omit memory output.
--std-dump-json Display results in standardized JSON format
with additional state dump.
Display result state dump in standardized JSON format.
--chain CHAIN Chain spec file path.
-h, --help Display this message and exit.
"#;
fn main() {
panic_hook::set_abort();
env_logger::init();
let args: Args = Docopt::new(USAGE)
.and_then(|d| d.deserialize())
.unwrap_or_else(|e| e.exit());
let config = args.config();
if args.cmd_state_test {
run_state_test(args)
} else if args.cmd_stats_jsontests_vm {
run_stats_jsontests_vm(args)
} else if args.flag_json {
run_call(args, display::json::Informant::new(config))
} else if args.flag_std_dump_json || args.flag_std_json {
if args.flag_std_err_only {
run_call(args, display::std_json::Informant::err_only(config))
} else if args.flag_std_out_only {
run_call(args, display::std_json::Informant::out_only(config))
} else {
run_call(args, display::std_json::Informant::new_default(config))
};
} else {
run_call(args, display::simple::Informant::new(config))
}
}
fn run_stats_jsontests_vm(args: Args) {
use json_tests::HookType;
use std::{
collections::HashMap,
time::{Duration, Instant},
};
let file = args.arg_file.expect("FILE (or PATH) is required");
let mut timings: HashMap<String, (Instant, Option<Duration>)> = HashMap::new();
{
let mut record_time = |name: &str, typ: HookType| match typ {
HookType::OnStart => {
timings.insert(name.to_string(), (Instant::now(), None));
}
HookType::OnStop => {
timings.entry(name.to_string()).and_modify(|v| {
v.1 = Some(v.0.elapsed());
});
}
};
for file_path in json_tests::find_json_files_recursive(&file) {
let json_data = std::fs::read(&file_path).unwrap();
json_tests::json_executive_test(&file_path, &json_data, &mut record_time);
}
}
for (name, v) in timings {
println!(
"{}\t{}",
name,
display::as_micros(&v.1.expect("All hooks are called with OnStop; qed"))
);
}
}
fn run_state_test(args: Args) {
use ethjson::state::test::Test;
let config = args.config();
let file = args.arg_file.expect("FILE is required");
let mut file = match fs::File::open(&file) {
Err(err) => die(format!("Unable to open: {:?}: {}", file, err)),
Ok(file) => file,
};
let state_test = match Test::load(&mut file) {
Err(err) => die(format!("Unable to load the test file: {}", err)),
Ok(test) => test,
};
let only_test = args.flag_only.map(|s| s.to_lowercase());
let only_chain = args.flag_chain.map(|s| s.to_lowercase());
for (name, test) in state_test {
if let Some(false) = only_test
.as_ref()
.map(|only_test| &name.to_lowercase() == only_test)
{
continue;
}
let multitransaction = test.transaction;
let env_info: EnvInfo = test.env.into();
let pre = test.pre_state.into();
for (spec, states) in test.post_states {
//hardcode base fee for part of the london tests, that miss base fee field in env
let mut test_env = env_info.clone();
if spec >= ForkSpec::London {
if test_env.base_fee.is_none() {
test_env.base_fee = Some(0x0a.into());
}
}
if let Some(false) = only_chain
.as_ref()
.map(|only_chain| &format!("{:?}", spec).to_lowercase() == only_chain)
{
continue;
}
for (idx, state) in states.into_iter().enumerate() {
let post_root = state.hash.into();
let transaction = multitransaction.select(&state.indexes);
let trie_spec = if args.flag_std_dump_json {
TrieSpec::Fat
} else {
TrieSpec::Secure
};
if args.flag_json {
info::run_transaction(
&name,
idx,
&spec,
&pre,
post_root,
&test_env,
transaction,
display::json::Informant::new(config),
trie_spec,
)
} else if args.flag_std_dump_json || args.flag_std_json {
if args.flag_std_err_only {
info::run_transaction(
&name,
idx,
&spec,
&pre,
post_root,
&test_env,
transaction,
display::std_json::Informant::err_only(config),
trie_spec,
)
} else if args.flag_std_out_only {
info::run_transaction(
&name,
idx,
&spec,
&pre,
post_root,
&test_env,
transaction,
display::std_json::Informant::out_only(config),
trie_spec,
)
} else {
info::run_transaction(
&name,
idx,
&spec,
&pre,
post_root,
&test_env,
transaction,
display::std_json::Informant::new_default(config),
trie_spec,
)
}
} else {
info::run_transaction(
&name,
idx,
&spec,
&pre,
post_root,
&test_env,
transaction,
display::simple::Informant::new(config),
trie_spec,
)
}
}
}
}
}
fn run_call<T: Informant>(args: Args, informant: T) {
let from = arg(args.from(), "--from");
let to = arg(args.to(), "--to");
let code = arg(args.code(), "--code");
let spec = arg(args.spec(), "--chain");
let gas = arg(args.gas(), "--gas");
let gas_price = arg(args.gas_price(), "--gas-price");
let data = arg(args.data(), "--input");
if code.is_none() && to == Address::default() {
die("Either --code or --to is required.");
}
let mut params = ActionParams::default();
if spec.engine.params().eip2929_transition == 0 {
params.access_list.enable();
params.access_list.insert_address(from);
params.access_list.insert_address(to);
for (builtin, _) in spec.engine.builtins() {
params.access_list.insert_address(*builtin);
}
}
params.call_type = if code.is_none() {
CallType::Call
} else {
CallType::None
};
params.code_address = to;
params.address = to;
params.sender = from;
params.origin = from;
params.gas = gas;
params.gas_price = gas_price;
params.code = code.map(Arc::new);
params.data = data;
let mut sink = informant.clone_sink();
let result = if args.flag_std_dump_json {
info::run_action(&spec, params, informant, TrieSpec::Fat)
} else {
info::run_action(&spec, params, informant, TrieSpec::Secure)
};
T::finish(result, &mut sink);
}
#[derive(Debug, Deserialize)]
struct Args {
cmd_stats: bool,
cmd_state_test: bool,
cmd_stats_jsontests_vm: bool,
arg_file: Option<PathBuf>,
flag_only: Option<String>,
flag_from: Option<String>,
flag_to: Option<String>,
flag_code: Option<String>,
flag_gas: Option<String>,
flag_gas_price: Option<String>,
flag_input: Option<String>,
flag_chain: Option<String>,
flag_json: bool,
flag_std_json: bool,
flag_std_dump_json: bool,
flag_std_err_only: bool,
flag_std_out_only: bool,
flag_omit_storage_output: bool,
flag_omit_memory_output: bool,
}
impl Args {
pub fn gas(&self) -> Result<U256, String> {
match self.flag_gas {
Some(ref gas) => gas.parse().map_err(to_string),
None => Ok(U256::from(u64::max_value())),
}
}
pub fn gas_price(&self) -> Result<U256, String> {
match self.flag_gas_price {
Some(ref gas_price) => gas_price.parse().map_err(to_string),
None => Ok(U256::zero()),
}
}
pub fn from(&self) -> Result<Address, String> {
match self.flag_from {
Some(ref from) => from.parse().map_err(to_string),
None => Ok(Address::default()),
}
}
pub fn to(&self) -> Result<Address, String> {
match self.flag_to {
Some(ref to) => to.parse().map_err(to_string),
None => Ok(Address::default()),
}
}
pub fn code(&self) -> Result<Option<Bytes>, String> {
match self.flag_code {
Some(ref code) => code.from_hex().map(Some).map_err(to_string),
None => Ok(None),
}
}
pub fn data(&self) -> Result<Option<Bytes>, String> {
match self.flag_input {
Some(ref input) => input.from_hex().map_err(to_string).map(Some),
None => Ok(None),
}
}
pub fn spec(&self) -> Result<spec::Spec, String> {
Ok(match self.flag_chain {
Some(ref spec_name) => {
let fork_spec: Result<ethjson::spec::ForkSpec, _> =
serde_json::from_str(&format!("{:?}", spec_name));
if let Ok(fork_spec) = fork_spec {
ethcore::client::EvmTestClient::spec_from_json(&fork_spec)
.expect("this forkspec is not defined")
} else {
let file = fs::File::open(spec_name).map_err(|e| format!("{}", e))?;
spec::Spec::load(&::std::env::temp_dir(), file)?
}
}
None => ethcore::ethereum::new_foundation(&::std::env::temp_dir()),
})
}
pub fn config(&self) -> display::config::Config {
display::config::Config::new(self.flag_omit_storage_output, self.flag_omit_memory_output)
}
}
fn arg<T>(v: Result<T, String>, param: &str) -> T {
v.unwrap_or_else(|e| die(format!("Invalid {}: {}", param, e)))
}
fn to_string<T: fmt::Display>(msg: T) -> String {
format!("{}", msg)
}
fn die<T: fmt::Display>(msg: T) -> ! {
println!("{}", msg);
::std::process::exit(-1)
}
#[cfg(test)]
mod tests {
use super::{Args, USAGE};
use docopt::Docopt;
use ethereum_types::Address;
fn run<T: AsRef<str>>(args: &[T]) -> Args {
Docopt::new(USAGE)
.and_then(|d| d.argv(args.into_iter()).deserialize())
.unwrap()
}
#[test]
fn should_parse_all_the_options() {
let args = run(&[
"openethereum-evm",
"--json",
"--std-json",
"--std-dump-json",
"--gas",
"1",
"--gas-price",
"2",
"--from",
"0000000000000000000000000000000000000003",
"--to",
"0000000000000000000000000000000000000004",
"--code",
"05",
"--input",
"06",
"--chain",
"./testfile",
"--std-err-only",
"--std-out-only",
]);
assert_eq!(args.flag_json, true);
assert_eq!(args.flag_std_json, true);
assert_eq!(args.flag_std_dump_json, true);
assert_eq!(args.flag_std_err_only, true);
assert_eq!(args.flag_std_out_only, true);
assert_eq!(args.gas(), Ok(1.into()));
assert_eq!(args.gas_price(), Ok(2.into()));
assert_eq!(args.from(), Ok(Address::from_low_u64_be(3)));
assert_eq!(args.to(), Ok(Address::from_low_u64_be(4)));
assert_eq!(args.code(), Ok(Some(vec![05])));
assert_eq!(args.data(), Ok(Some(vec![06])));
assert_eq!(args.flag_chain, Some("./testfile".to_owned()));
}
#[test]
fn should_parse_state_test_command() {
let args = run(&[
"openethereum-evm",
"state-test",
"./file.json",
"--chain",
"homestead",
"--only=add11",
"--json",
"--std-json",
"--std-dump-json",
]);
assert_eq!(args.cmd_state_test, true);
assert!(args.arg_file.is_some());
assert_eq!(args.flag_json, true);
assert_eq!(args.flag_std_json, true);
assert_eq!(args.flag_std_dump_json, true);
assert_eq!(args.flag_chain, Some("homestead".to_owned()));
assert_eq!(args.flag_only, Some("add11".to_owned()));
}
}

141
bin/oe/account.rs Normal file
View File

@ -0,0 +1,141 @@
// 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 crate::params::SpecType;
use std::num::NonZeroU32;
#[derive(Debug, PartialEq)]
pub enum AccountCmd {
New(NewAccount),
List(ListAccounts),
Import(ImportAccounts),
}
#[derive(Debug, PartialEq)]
pub struct ListAccounts {
pub path: String,
pub spec: SpecType,
}
#[derive(Debug, PartialEq)]
pub struct NewAccount {
pub iterations: NonZeroU32,
pub path: String,
pub spec: SpecType,
pub password_file: Option<String>,
}
#[derive(Debug, PartialEq)]
pub struct ImportAccounts {
pub from: Vec<String>,
pub to: String,
pub spec: SpecType,
}
#[cfg(not(feature = "accounts"))]
pub fn execute(_cmd: AccountCmd) -> Result<String, String> {
Err("Account management is deprecated. Please see #9997 for alternatives:\nhttps://github.com/openethereum/openethereum/issues/9997".into())
}
#[cfg(feature = "accounts")]
mod command {
use super::*;
use crate::{
accounts::{AccountProvider, AccountProviderSettings},
helpers::{password_from_file, password_prompt},
};
use ethstore::{accounts_dir::RootDiskDirectory, import_account, import_accounts, EthStore};
use std::path::PathBuf;
pub fn execute(cmd: AccountCmd) -> Result<String, String> {
match cmd {
AccountCmd::New(new_cmd) => new(new_cmd),
AccountCmd::List(list_cmd) => list(list_cmd),
AccountCmd::Import(import_cmd) => import(import_cmd),
}
}
fn keys_dir(path: String, spec: SpecType) -> Result<RootDiskDirectory, String> {
let spec = spec.spec(&::std::env::temp_dir())?;
let mut path = PathBuf::from(&path);
path.push(spec.data_dir);
RootDiskDirectory::create(path).map_err(|e| format!("Could not open keys directory: {}", e))
}
fn secret_store(
dir: Box<RootDiskDirectory>,
iterations: Option<NonZeroU32>,
) -> Result<EthStore, String> {
match iterations {
Some(i) => EthStore::open_with_iterations(dir, i),
_ => EthStore::open(dir),
}
.map_err(|e| format!("Could not open keys store: {}", e))
}
fn new(n: NewAccount) -> Result<String, String> {
let password = match n.password_file {
Some(file) => password_from_file(file)?,
None => password_prompt()?,
};
let dir = Box::new(keys_dir(n.path, n.spec)?);
let secret_store = Box::new(secret_store(dir, Some(n.iterations))?);
let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default());
let new_account = acc_provider
.new_account(&password)
.map_err(|e| format!("Could not create new account: {}", e))?;
Ok(format!("0x{:x}", new_account))
}
fn list(list_cmd: ListAccounts) -> Result<String, String> {
let dir = Box::new(keys_dir(list_cmd.path, list_cmd.spec)?);
let secret_store = Box::new(secret_store(dir, None)?);
let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default());
let accounts = acc_provider.accounts().map_err(|e| format!("{}", e))?;
let result = accounts
.into_iter()
.map(|a| format!("0x{:x}", a))
.collect::<Vec<String>>()
.join("\n");
Ok(result)
}
fn import(i: ImportAccounts) -> Result<String, String> {
let to = keys_dir(i.to, i.spec)?;
let mut imported = 0;
for path in &i.from {
let path = PathBuf::from(path);
if path.is_dir() {
let from = RootDiskDirectory::at(&path);
imported += import_accounts(&from, &to)
.map_err(|e| format!("Importing accounts from {:?} failed: {}", path, e))?
.len();
} else if path.is_file() {
import_account(&path, &to)
.map_err(|e| format!("Importing account from {:?} failed: {}", path, e))?;
imported += 1;
}
}
Ok(format!("{} account(s) imported", imported))
}
}
#[cfg(feature = "accounts")]
pub use self::command::execute;

263
bin/oe/account_utils.rs Normal file
View File

@ -0,0 +1,263 @@
// 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::sync::Arc;
use crypto::publickey;
use dir::Directories;
use ethereum_types::{Address, H160};
use ethkey::Password;
use crate::params::{AccountsConfig, SpecType};
#[cfg(not(feature = "accounts"))]
mod accounts {
use super::*;
/// Dummy AccountProvider
pub struct AccountProvider;
impl ::ethcore::miner::LocalAccounts for AccountProvider {
fn is_local(&self, _address: &Address) -> bool {
false
}
}
pub fn prepare_account_provider(
_spec: &SpecType,
_dirs: &Directories,
_data_dir: &str,
_cfg: AccountsConfig,
_passwords: &[Password],
) -> Result<AccountProvider, String> {
warn!("Note: Your instance of OpenEthereum is running without account support. Some CLI options are ignored.");
Ok(AccountProvider)
}
pub fn miner_local_accounts(_: Arc<AccountProvider>) -> AccountProvider {
AccountProvider
}
pub fn miner_author(
_spec: &SpecType,
_dirs: &Directories,
_account_provider: &Arc<AccountProvider>,
_engine_signer: Address,
_passwords: &[Password],
) -> Result<Option<::ethcore::miner::Author>, String> {
Ok(None)
}
pub fn accounts_list(
_account_provider: Arc<AccountProvider>,
) -> Arc<dyn Fn() -> Vec<Address> + Send + Sync> {
Arc::new(|| vec![])
}
}
#[cfg(feature = "accounts")]
mod accounts {
use super::*;
use crate::{ethereum_types::H256, upgrade::upgrade_key_location};
use std::str::FromStr;
pub use crate::accounts::AccountProvider;
/// Pops along with error messages when a password is missing or invalid.
const VERIFY_PASSWORD_HINT: &str = "Make sure valid password is present in files passed using `--password` or in the configuration file.";
/// Initialize account provider
pub fn prepare_account_provider(
spec: &SpecType,
dirs: &Directories,
data_dir: &str,
cfg: AccountsConfig,
passwords: &[Password],
) -> Result<AccountProvider, String> {
use crate::accounts::AccountProviderSettings;
use ethstore::{accounts_dir::RootDiskDirectory, EthStore};
let path = dirs.keys_path(data_dir);
upgrade_key_location(&dirs.legacy_keys_path(cfg.testnet), &path);
let dir = Box::new(
RootDiskDirectory::create(&path)
.map_err(|e| format!("Could not open keys directory: {}", e))?,
);
let account_settings = AccountProviderSettings {
unlock_keep_secret: cfg.enable_fast_unlock,
blacklisted_accounts: match *spec {
SpecType::Morden
| SpecType::Ropsten
| SpecType::Kovan
| SpecType::Goerli
| SpecType::Sokol
| SpecType::Dev => vec![],
_ => vec![H160::from_str("00a329c0648769a73afac7f9381e08fb43dbea72")
.expect("the string is valid hex; qed")],
},
};
let ethstore = EthStore::open_with_iterations(dir, cfg.iterations)
.map_err(|e| format!("Could not open keys directory: {}", e))?;
if cfg.refresh_time > 0 {
ethstore.set_refresh_time(::std::time::Duration::from_secs(cfg.refresh_time));
}
let account_provider = AccountProvider::new(Box::new(ethstore), account_settings);
// Add development account if running dev chain:
if let SpecType::Dev = *spec {
insert_dev_account(&account_provider);
}
for a in cfg.unlocked_accounts {
// Check if the account exists
if !account_provider.has_account(a) {
return Err(format!(
"Account {} not found for the current chain. {}",
a,
build_create_account_hint(spec, &dirs.keys)
));
}
// Check if any passwords have been read from the password file(s)
if passwords.is_empty() {
return Err(format!(
"No password found to unlock account {}. {}",
a, VERIFY_PASSWORD_HINT
));
}
if !passwords.iter().any(|p| {
account_provider
.unlock_account_permanently(a, (*p).clone())
.is_ok()
}) {
return Err(format!(
"No valid password to unlock account {}. {}",
a, VERIFY_PASSWORD_HINT
));
}
}
Ok(account_provider)
}
pub struct LocalAccounts(Arc<AccountProvider>);
impl ::ethcore::miner::LocalAccounts for LocalAccounts {
fn is_local(&self, address: &Address) -> bool {
self.0.has_account(*address)
}
}
pub fn miner_local_accounts(account_provider: Arc<AccountProvider>) -> LocalAccounts {
LocalAccounts(account_provider)
}
pub fn miner_author(
spec: &SpecType,
dirs: &Directories,
account_provider: &Arc<AccountProvider>,
engine_signer: Address,
passwords: &[Password],
) -> Result<Option<::ethcore::miner::Author>, String> {
use ethcore::engines::EngineSigner;
// Check if engine signer exists
if !account_provider.has_account(engine_signer) {
return Err(format!(
"Consensus signer account not found for the current chain. {}",
build_create_account_hint(spec, &dirs.keys)
));
}
// Check if any passwords have been read from the password file(s)
if passwords.is_empty() {
return Err(format!(
"No password found for the consensus signer {}. {}",
engine_signer, VERIFY_PASSWORD_HINT
));
}
let mut author = None;
for password in passwords {
let signer = parity_rpc::signer::EngineSigner::new(
account_provider.clone(),
engine_signer,
password.clone(),
);
// sign dummy msg to check if password and account can be used.
if signer.sign(H256::from_low_u64_be(1)).is_ok() {
author = Some(::ethcore::miner::Author::Sealer(Box::new(signer)));
}
}
if author.is_none() {
return Err(format!(
"No valid password for the consensus signer {}. {}",
engine_signer, VERIFY_PASSWORD_HINT
));
}
Ok(author)
}
pub fn accounts_list(
account_provider: Arc<AccountProvider>,
) -> Arc<dyn Fn() -> Vec<Address> + Send + Sync> {
Arc::new(move || account_provider.accounts().unwrap_or_default())
}
fn insert_dev_account(account_provider: &AccountProvider) {
let secret = publickey::Secret::from_str(
"4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7",
)
.expect("Valid account;qed");
let dev_account = publickey::KeyPair::from_secret(secret.clone())
.expect("Valid secret produces valid key;qed");
if !account_provider.has_account(dev_account.address()) {
match account_provider.insert_account(secret, &Password::from(String::new())) {
Err(e) => warn!("Unable to add development account: {}", e),
Ok(address) => {
let _ = account_provider
.set_account_name(address.clone(), "Development Account".into());
let _ = account_provider.set_account_meta(
address,
::serde_json::to_string(
&(vec![
(
"description",
"Never use this account outside of development chain!",
),
("passwordHint", "Password is empty string"),
]
.into_iter()
.collect::<::std::collections::HashMap<_, _>>()),
)
.expect("Serialization of hashmap does not fail."),
);
}
}
}
}
// Construct an error `String` with an adaptive hint on how to create an account.
fn build_create_account_hint(spec: &SpecType, keys: &str) -> String {
format!("You can create an account via RPC, UI or `openethereum account new --chain {} --keys-path {}`.", spec, keys)
}
}
pub use self::accounts::{
accounts_list, miner_author, miner_local_accounts, prepare_account_provider, AccountProvider,
};

551
bin/oe/blockchain.rs Normal file
View File

@ -0,0 +1,551 @@
// 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::{fs, io, sync::Arc, time::Instant};
use crate::{
bytes::ToPretty,
cache::CacheConfig,
db,
hash::{keccak, KECCAK_NULL_RLP},
helpers::{execute_upgrades, to_client_config},
informant::{FullNodeInformantData, Informant, MillisecondDuration},
params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch},
types::data_format::DataFormat,
user_defaults::UserDefaults,
};
use ansi_term::Colour;
use dir::Directories;
use ethcore::{
client::{
Balance, BlockChainClient, BlockChainReset, BlockId, DatabaseCompactionProfile,
ImportExportBlocks, Mode, Nonce, VMType,
},
miner::Miner,
verification::queue::VerifierSettings,
};
use ethcore_service::ClientService;
use ethereum_types::{Address, H256, U256};
#[derive(Debug, PartialEq)]
pub enum BlockchainCmd {
Kill(KillBlockchain),
Import(ImportBlockchain),
Export(ExportBlockchain),
ExportState(ExportState),
Reset(ResetBlockchain),
}
#[derive(Debug, PartialEq)]
pub struct ResetBlockchain {
pub dirs: Directories,
pub spec: SpecType,
pub pruning: Pruning,
pub pruning_history: u64,
pub pruning_memory: usize,
pub tracing: Switch,
pub fat_db: Switch,
pub compaction: DatabaseCompactionProfile,
pub cache_config: CacheConfig,
pub num: u32,
}
#[derive(Debug, PartialEq)]
pub struct KillBlockchain {
pub spec: SpecType,
pub dirs: Directories,
pub pruning: Pruning,
}
#[derive(Debug, PartialEq)]
pub struct ImportBlockchain {
pub spec: SpecType,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
pub format: Option<DataFormat>,
pub pruning: Pruning,
pub pruning_history: u64,
pub pruning_memory: usize,
pub compaction: DatabaseCompactionProfile,
pub tracing: Switch,
pub fat_db: Switch,
pub vm_type: VMType,
pub check_seal: bool,
pub with_color: bool,
pub verifier_settings: VerifierSettings,
pub max_round_blocks_to_import: usize,
}
#[derive(Debug, PartialEq)]
pub struct ExportBlockchain {
pub spec: SpecType,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
pub format: Option<DataFormat>,
pub pruning: Pruning,
pub pruning_history: u64,
pub pruning_memory: usize,
pub compaction: DatabaseCompactionProfile,
pub fat_db: Switch,
pub tracing: Switch,
pub from_block: BlockId,
pub to_block: BlockId,
pub check_seal: bool,
pub max_round_blocks_to_import: usize,
}
#[derive(Debug, PartialEq)]
pub struct ExportState {
pub spec: SpecType,
pub cache_config: CacheConfig,
pub dirs: Directories,
pub file_path: Option<String>,
pub format: Option<DataFormat>,
pub pruning: Pruning,
pub pruning_history: u64,
pub pruning_memory: usize,
pub compaction: DatabaseCompactionProfile,
pub fat_db: Switch,
pub tracing: Switch,
pub at: BlockId,
pub storage: bool,
pub code: bool,
pub min_balance: Option<U256>,
pub max_balance: Option<U256>,
pub max_round_blocks_to_import: usize,
}
pub fn execute(cmd: BlockchainCmd) -> Result<(), String> {
match cmd {
BlockchainCmd::Kill(kill_cmd) => kill_db(kill_cmd),
BlockchainCmd::Import(import_cmd) => execute_import(import_cmd),
BlockchainCmd::Export(export_cmd) => execute_export(export_cmd),
BlockchainCmd::ExportState(export_cmd) => execute_export_state(export_cmd),
BlockchainCmd::Reset(reset_cmd) => execute_reset(reset_cmd),
}
}
fn execute_import(cmd: ImportBlockchain) -> Result<(), String> {
let timer = Instant::now();
// load spec file
let spec = cmd.spec.spec(&cmd.dirs.cache)?;
// load genesis hash
let genesis_hash = spec.genesis_header().hash();
// database paths
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir.clone());
// user defaults path
let user_defaults_path = db_dirs.user_defaults_path();
// load user defaults
let mut user_defaults = UserDefaults::load(&user_defaults_path)?;
// select pruning algorithm
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
// check if tracing is on
let tracing = tracing_switch_to_bool(cmd.tracing, &user_defaults)?;
// check if fatdb is on
let fat_db = fatdb_switch_to_bool(cmd.fat_db, &user_defaults, algorithm)?;
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path();
// execute upgrades
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
// create dirs used by parity
cmd.dirs.create_dirs(false, false)?;
// prepare client config
let mut client_config = to_client_config(
&cmd.cache_config,
spec.name.to_lowercase(),
Mode::Active,
tracing,
fat_db,
cmd.compaction,
cmd.vm_type,
"".into(),
algorithm,
cmd.pruning_history,
cmd.pruning_memory,
cmd.check_seal,
12,
);
client_config.queue.verifier_settings = cmd.verifier_settings;
let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config);
let client_db = restoration_db_handler
.open(&client_path)
.map_err(|e| format!("Failed to open database {:?}", e))?;
// build client
let service = ClientService::start(
client_config,
&spec,
client_db,
&snapshot_path,
restoration_db_handler,
&cmd.dirs.ipc_path(),
// TODO [ToDr] don't use test miner here
// (actually don't require miner at all)
Arc::new(Miner::new_for_tests(&spec, None)),
)
.map_err(|e| format!("Client service error: {:?}", e))?;
// free up the spec in memory.
drop(spec);
let client = service.client();
let instream: Box<dyn io::Read> = match cmd.file_path {
Some(f) => {
Box::new(fs::File::open(&f).map_err(|_| format!("Cannot open given file: {}", f))?)
}
None => Box::new(io::stdin()),
};
let informant = Arc::new(Informant::new(
FullNodeInformantData {
client: client.clone(),
sync: None,
net: None,
},
None,
None,
cmd.with_color,
));
service
.register_io_handler(informant)
.map_err(|_| "Unable to register informant handler".to_owned())?;
client.import_blocks(instream, cmd.format)?;
// save user defaults
user_defaults.pruning = algorithm;
user_defaults.tracing = tracing;
user_defaults.fat_db = fat_db;
user_defaults.save(&user_defaults_path)?;
let report = client.report();
let ms = timer.elapsed().as_milliseconds();
info!("Import completed in {} seconds, {} blocks, {} blk/s, {} transactions, {} tx/s, {} Mgas, {} Mgas/s",
ms / 1000,
report.blocks_imported,
(report.blocks_imported * 1000) as u64 / ms,
report.transactions_applied,
(report.transactions_applied * 1000) as u64 / ms,
report.gas_processed / 1_000_000,
(report.gas_processed / (ms * 1000)).low_u64(),
);
Ok(())
}
fn start_client(
dirs: Directories,
spec: SpecType,
pruning: Pruning,
pruning_history: u64,
pruning_memory: usize,
tracing: Switch,
fat_db: Switch,
compaction: DatabaseCompactionProfile,
cache_config: CacheConfig,
require_fat_db: bool,
max_round_blocks_to_import: usize,
) -> Result<ClientService, String> {
// load spec file
let spec = spec.spec(&dirs.cache)?;
// load genesis hash
let genesis_hash = spec.genesis_header().hash();
// database paths
let db_dirs = dirs.database(genesis_hash, None, spec.data_dir.clone());
// user defaults path
let user_defaults_path = db_dirs.user_defaults_path();
// load user defaults
let user_defaults = UserDefaults::load(&user_defaults_path)?;
// select pruning algorithm
let algorithm = pruning.to_algorithm(&user_defaults);
// check if tracing is on
let tracing = tracing_switch_to_bool(tracing, &user_defaults)?;
// check if fatdb is on
let fat_db = fatdb_switch_to_bool(fat_db, &user_defaults, algorithm)?;
if !fat_db && require_fat_db {
return Err("This command requires OpenEthereum to be synced with --fat-db on.".to_owned());
}
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path();
// execute upgrades
execute_upgrades(&dirs.base, &db_dirs, algorithm, &compaction)?;
// create dirs used by OpenEthereum.
dirs.create_dirs(false, false)?;
// prepare client config
let client_config = to_client_config(
&cache_config,
spec.name.to_lowercase(),
Mode::Active,
tracing,
fat_db,
compaction,
VMType::default(),
"".into(),
algorithm,
pruning_history,
pruning_memory,
true,
max_round_blocks_to_import,
);
let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config);
let client_db = restoration_db_handler
.open(&client_path)
.map_err(|e| format!("Failed to open database {:?}", e))?;
let service = ClientService::start(
client_config,
&spec,
client_db,
&snapshot_path,
restoration_db_handler,
&dirs.ipc_path(),
// It's fine to use test version here,
// since we don't care about miner parameters at all
Arc::new(Miner::new_for_tests(&spec, None)),
)
.map_err(|e| format!("Client service error: {:?}", e))?;
drop(spec);
Ok(service)
}
fn execute_export(cmd: ExportBlockchain) -> Result<(), String> {
let service = start_client(
cmd.dirs,
cmd.spec,
cmd.pruning,
cmd.pruning_history,
cmd.pruning_memory,
cmd.tracing,
cmd.fat_db,
cmd.compaction,
cmd.cache_config,
false,
cmd.max_round_blocks_to_import,
)?;
let client = service.client();
let out: Box<dyn io::Write> = match cmd.file_path {
Some(f) => Box::new(
fs::File::create(&f).map_err(|_| format!("Cannot write to file given: {}", f))?,
),
None => Box::new(io::stdout()),
};
client.export_blocks(out, cmd.from_block, cmd.to_block, cmd.format)?;
info!("Export completed.");
Ok(())
}
fn execute_export_state(cmd: ExportState) -> Result<(), String> {
let service = start_client(
cmd.dirs,
cmd.spec,
cmd.pruning,
cmd.pruning_history,
cmd.pruning_memory,
cmd.tracing,
cmd.fat_db,
cmd.compaction,
cmd.cache_config,
true,
cmd.max_round_blocks_to_import,
)?;
let client = service.client();
let mut out: Box<dyn io::Write> = match cmd.file_path {
Some(f) => Box::new(
fs::File::create(&f).map_err(|_| format!("Cannot write to file given: {}", f))?,
),
None => Box::new(io::stdout()),
};
let mut last: Option<Address> = None;
let at = cmd.at;
let mut i = 0usize;
out.write_fmt(format_args!("{{ \"state\": {{",))
.expect("Couldn't write to stream.");
loop {
let accounts = client
.list_accounts(at, last.as_ref(), 1000)
.ok_or("Specified block not found")?;
if accounts.is_empty() {
break;
}
for account in accounts.into_iter() {
let balance = client
.balance(&account, at.into())
.unwrap_or_else(U256::zero);
if cmd.min_balance.map_or(false, |m| balance < m)
|| cmd.max_balance.map_or(false, |m| balance > m)
{
last = Some(account);
continue; //filtered out
}
if i != 0 {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!(
"\n\"0x{:x}\": {{\"balance\": \"{:x}\", \"nonce\": \"{:x}\"",
account,
balance,
client.nonce(&account, at).unwrap_or_else(U256::zero)
))
.expect("Write error");
let code = client
.code(&account, at.into())
.unwrap_or(None)
.unwrap_or_else(Vec::new);
if !code.is_empty() {
out.write_fmt(format_args!(", \"code_hash\": \"0x{:x}\"", keccak(&code)))
.expect("Write error");
if cmd.code {
out.write_fmt(format_args!(", \"code\": \"{}\"", code.to_hex()))
.expect("Write error");
}
}
let storage_root = client.storage_root(&account, at).unwrap_or(KECCAK_NULL_RLP);
if storage_root != KECCAK_NULL_RLP {
out.write_fmt(format_args!(", \"storage_root\": \"0x{:x}\"", storage_root))
.expect("Write error");
if cmd.storage {
out.write_fmt(format_args!(", \"storage\": {{"))
.expect("Write error");
let mut last_storage: Option<H256> = None;
loop {
let keys = client
.list_storage(at, &account, last_storage.as_ref(), 1000)
.ok_or("Specified block not found")?;
if keys.is_empty() {
break;
}
for key in keys.into_iter() {
if last_storage.is_some() {
out.write(b",").expect("Write error");
}
out.write_fmt(format_args!(
"\n\t\"0x{:x}\": \"0x{:x}\"",
key,
client
.storage_at(&account, &key, at.into())
.unwrap_or_else(Default::default)
))
.expect("Write error");
last_storage = Some(key);
}
}
out.write(b"\n}").expect("Write error");
}
}
out.write(b"}").expect("Write error");
i += 1;
if i % 10000 == 0 {
info!("Account #{}", i);
}
last = Some(account);
}
}
out.write_fmt(format_args!("\n}}}}")).expect("Write error");
info!("Export completed.");
Ok(())
}
fn execute_reset(cmd: ResetBlockchain) -> Result<(), String> {
let service = start_client(
cmd.dirs,
cmd.spec,
cmd.pruning,
cmd.pruning_history,
cmd.pruning_memory,
cmd.tracing,
cmd.fat_db,
cmd.compaction,
cmd.cache_config,
false,
0,
)?;
let client = service.client();
client.reset(cmd.num)?;
info!("{}", Colour::Green.bold().paint("Successfully reset db!"));
Ok(())
}
pub fn kill_db(cmd: KillBlockchain) -> Result<(), String> {
let spec = cmd.spec.spec(&cmd.dirs.cache)?;
let genesis_hash = spec.genesis_header().hash();
let db_dirs = cmd.dirs.database(genesis_hash, None, spec.data_dir);
let user_defaults_path = db_dirs.user_defaults_path();
let mut user_defaults = UserDefaults::load(&user_defaults_path)?;
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
let dir = db_dirs.db_path(algorithm);
fs::remove_dir_all(&dir).map_err(|e| format!("Error removing database: {:?}", e))?;
user_defaults.is_first_launch = true;
user_defaults.save(&user_defaults_path)?;
info!("Database deleted.");
Ok(())
}
#[cfg(test)]
mod test {
use super::DataFormat;
#[test]
fn test_data_format_parsing() {
assert_eq!(DataFormat::Binary, "binary".parse().unwrap());
assert_eq!(DataFormat::Binary, "bin".parse().unwrap());
assert_eq!(DataFormat::Hex, "hex".parse().unwrap());
}
}

142
bin/oe/cache.rs Normal file
View File

@ -0,0 +1,142 @@
// 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::cmp::max;
const MIN_BC_CACHE_MB: u32 = 4;
const MIN_DB_CACHE_MB: u32 = 8;
const MIN_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 16;
const DEFAULT_DB_CACHE_SIZE: u32 = 128;
const DEFAULT_BC_CACHE_SIZE: u32 = 8;
const DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB: u32 = 40;
const DEFAULT_TRACE_CACHE_SIZE: u32 = 20;
const DEFAULT_STATE_CACHE_SIZE: u32 = 25;
/// Configuration for application cache sizes.
/// All values are represented in MB.
#[derive(Debug, PartialEq)]
pub struct CacheConfig {
/// Size of rocksDB cache. Almost all goes to the state column.
db: u32,
/// Size of blockchain cache.
blockchain: u32,
/// Size of transaction queue cache.
queue: u32,
/// Size of traces cache.
traces: u32,
/// Size of the state cache.
state: u32,
}
impl Default for CacheConfig {
fn default() -> Self {
CacheConfig::new(
DEFAULT_DB_CACHE_SIZE,
DEFAULT_BC_CACHE_SIZE,
DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB,
DEFAULT_STATE_CACHE_SIZE,
)
}
}
impl CacheConfig {
/// Creates new cache config with cumulative size equal `total`.
pub fn new_with_total_cache_size(total: u32) -> Self {
CacheConfig {
db: total * 7 / 10,
blockchain: total / 10,
queue: DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB,
traces: DEFAULT_TRACE_CACHE_SIZE,
state: total * 2 / 10,
}
}
/// Creates new cache config with gitven details.
pub fn new(db: u32, blockchain: u32, queue: u32, state: u32) -> Self {
CacheConfig {
db: db,
blockchain: blockchain,
queue: queue,
traces: DEFAULT_TRACE_CACHE_SIZE,
state: state,
}
}
/// Size of db cache.
pub fn db_cache_size(&self) -> u32 {
max(MIN_DB_CACHE_MB, self.db)
}
/// Size of block queue size limit
pub fn queue(&self) -> u32 {
max(self.queue, MIN_BLOCK_QUEUE_SIZE_LIMIT_MB)
}
/// Size of the blockchain cache.
pub fn blockchain(&self) -> u32 {
max(self.blockchain, MIN_BC_CACHE_MB)
}
/// Size of the traces cache.
pub fn traces(&self) -> u32 {
self.traces
}
/// Size of the state cache.
pub fn state(&self) -> u32 {
self.state * 3 / 4
}
/// Size of the jump-tables cache.
pub fn jump_tables(&self) -> u32 {
self.state / 4
}
}
#[cfg(test)]
mod tests {
use super::CacheConfig;
#[test]
fn test_cache_config_constructor() {
let config = CacheConfig::new_with_total_cache_size(200);
assert_eq!(config.db, 140);
assert_eq!(config.blockchain(), 20);
assert_eq!(config.queue(), 40);
assert_eq!(config.state(), 30);
assert_eq!(config.jump_tables(), 10);
}
#[test]
fn test_cache_config_db_cache_sizes() {
let config = CacheConfig::new_with_total_cache_size(400);
assert_eq!(config.db, 280);
assert_eq!(config.db_cache_size(), 280);
}
#[test]
fn test_cache_config_default() {
assert_eq!(
CacheConfig::default(),
CacheConfig::new(
super::DEFAULT_DB_CACHE_SIZE,
super::DEFAULT_BC_CACHE_SIZE,
super::DEFAULT_BLOCK_QUEUE_SIZE_LIMIT_MB,
super::DEFAULT_STATE_CACHE_SIZE
)
);
}
}

1655
bin/oe/cli/mod.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
[parity]
no_consensus = true
chain = "dev"
[mining]
@ -10,7 +9,3 @@ min_gas_price = 0
interface = "all"
apis = ["all"]
hosts = ["all"]
[ipfs]
enable = false # this is the default
hosts = ["all"]

View File

@ -0,0 +1,4 @@
[rpc]
interface = "all"
apis = ["all"]
hosts = ["all"]

View File

@ -1,15 +1,11 @@
[network]
# Parity will try to maintain connection to at least 50 peers.
# OpenEthereum will try to maintain connection to at least 50 peers.
min_peers = 50
# Parity will maintain at most 100 peers.
# OpenEthereum will maintain at most 100 peers.
max_peers = 100
[ipc]
# You won't be able to use IPC to interact with Parity.
disable = true
[dapps]
# You won't be able to access any web Dapps.
# You won't be able to use IPC to interact with OpenEthereum.
disable = true
[mining]
@ -19,7 +15,7 @@ force_sealing = true
reseal_on_txs = "all"
# New pending block will be created only once per 4000 milliseconds.
reseal_min_period = 4000
# Parity will keep/relay at most 8192 transactions in queue.
# OpenEthereum will keep/relay at most 8192 transactions in queue.
tx_queue_size = 8192
tx_queue_per_sender = 128

View File

@ -1,5 +1,5 @@
[network]
# Parity will listen for connections on port 30305.
# OpenEthereum will listen for connections on port 30305.
port = 30305
[rpc]

View File

@ -1,18 +1,18 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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 Parity. If not, see <http://www.gnu.org/licenses/>.
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
use std::io::{Error, ErrorKind};

View File

@ -2,13 +2,6 @@
mode = "last"
mode_timeout = 300
mode_alarm = 3600
auto_update = "none"
auto_update_delay = 200
auto_update_check_frequency = 50
release_track = "current"
public_node = false
no_download = false
no_consensus = false
no_persistent_txqueue = false
chain = "homestead"
@ -16,28 +9,13 @@ base_path = "$HOME/.parity"
db_path = "$HOME/.parity/chains"
keys_path = "$HOME/.parity/keys"
identity = ""
light = false
no_hardcoded_sync = false
[account]
unlock = ["0xdeadbeefcafe0000000000000000000000000000"]
password = ["~/.safe/password.file"]
keys_iterations = 10240
[private_tx]
enabled = true
signer = "0xdeadbeefcafe0000000000000000000000000000"
validators = ["0xdeadbeefcafe0000000000000000000000000000"]
passwords = "~/.safe/password.file"
account = "0xdeadbeefcafe0000000000000000000000000000"
sstore_url = "http://localhost:8082"
sstore_threshold = 0
[ui]
force = false
disable = false
port = 8180
interface = "127.0.0.1"
path = "$HOME/.parity/signer"
[network]
@ -52,7 +30,6 @@ warp = true
allow_ips = "all"
snapshot_peers = 0
max_pending_peers = 64
no_serve_light = false
reserved_only = false
reserved_peers = "./path_to_file"
@ -64,6 +41,7 @@ interface = "local"
cors = ["null"]
apis = ["web3", "eth", "net", "parity", "traces", "rpc", "secretstore"]
hosts = ["none"]
allow_missing_blocks = false
[websockets]
disable = false
@ -78,16 +56,6 @@ disable = false
path = "$HOME/.parity/jsonrpc.ipc"
apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc", "secretstore"]
[dapps]
disable = false
port = 8080
interface = "local"
hosts = ["none"]
path = "$HOME/.parity/dapps"
# authorization:
user = "test_user"
pass = "test_pass"
[secretstore]
disable = false
disable_http = false
@ -105,13 +73,6 @@ interface = "local"
port = 8083
path = "$HOME/.parity/secretstore"
[ipfs]
enable = false
port = 5001
interface = "local"
cors = ["null"]
hosts = ["none"]
[mining]
author = "0xdeadbeefcafe0000000000000000000000000001"
engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
@ -128,6 +89,7 @@ price_update_period = "hourly"
gas_floor_target = "8000000"
gas_cap = "10000000"
tx_queue_size = 8192
tx_queue_locals = ["0xdeadbeefcafe0000000000000000000000000000"]
tx_queue_strategy = "gas_factor"
tx_queue_ban_count = 1
tx_queue_ban_time = 180 #s
@ -155,18 +117,10 @@ fat_db = "auto"
scale_verifiers = true
num_verifiers = 6
[light]
on_demand_retry_count = 15
on_demand_inactive_time_limit = 15000
[snapshots]
disable_periodic = false
enable = false
[misc]
logging = "own_tx=trace"
log_file = "/var/log/parity.log"
log_file = "/var/log/openethereum.log"
color = true
[whisper]
enabled = false
pool_size = 20

View File

@ -8,9 +8,6 @@ chain = "./chain.json"
unlock = ["0x1", "0x2", "0x3"]
password = ["passwdfile path"]
[ui]
disable = true
[network]
warp = false
discovery = true
@ -35,19 +32,16 @@ port = 8180
[ipc]
apis = ["rpc", "eth"]
[dapps]
port = 8080
user = "username"
pass = "password"
[metrics]
enable = true
interface = "local"
port = 4000
prefix = "oe"
[secretstore]
http_port = 8082
port = 8083
[ipfs]
enable = false
port = 5001
[mining]
author = "0xdeadbeefcafe0000000000000000000000000001"
engine_signer = "0xdeadbeefcafe0000000000000000000000000001"
@ -70,20 +64,12 @@ db_compaction = "ssd"
fat_db = "off"
scale_verifiers = false
[light]
on_demand_retry_count = 12
on_demand_inactive_time_limit = 20000
[snapshots]
disable_periodic = true
enable = false
[misc]
logging = "own_tx=trace"
log_file = "/var/log/parity.log"
log_file = "/var/log/openethereum.log"
color = true
ports_shift = 0
unsafe_expose = false
[whisper]
enabled = true
pool_size = 50

View File

@ -1,38 +1,38 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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 Parity. If not, see <http://www.gnu.org/licenses/>.
macro_rules! println_stderr(
($($arg:tt)*) => { {
let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
r.expect("failed printing to stderr");
} }
);
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
macro_rules! return_if_parse_error {
($e:expr) => (
match $e {
Err(clap_error @ ClapError { kind: ClapErrorKind::ValueValidation, .. }) => {
return Err(clap_error);
},
($e:expr) => {
match $e {
Err(
clap_error
@
ClapError {
kind: ClapErrorKind::ValueValidation,
..
},
) => {
return Err(clap_error);
}
// Otherwise, if $e is ClapErrorKind::ArgumentNotFound or Ok(),
// then convert to Option
_ => $e.ok()
}
)
// Otherwise, if $e is ClapErrorKind::ArgumentNotFound or Ok(),
// then convert to Option
_ => $e.ok(),
}
};
}
macro_rules! if_option {
@ -54,46 +54,46 @@ macro_rules! if_vec {
}
macro_rules! if_option_vec {
(Option<Vec<String>>, THEN {$then:expr} ELSE {$otherwise:expr}) => (
$then
);
(Option<$type:ty>, THEN {$then:expr} ELSE {$otherwise:expr}) => (
$otherwise
);
(Option<Vec<String>>, THEN {$then:expr} ELSE {$otherwise:expr}) => {
$then
};
(Option<$type:ty>, THEN {$then:expr} ELSE {$otherwise:expr}) => {
$otherwise
};
}
macro_rules! inner_option_type {
(Option<$type:ty>) => (
$type
)
(Option<$type:ty>) => {
$type
};
}
macro_rules! inner_vec_type {
(Vec<$type:ty>) => (
$type
)
(Vec<$type:ty>) => {
$type
};
}
macro_rules! inner_option_vec_type {
(Option<Vec<String>>) => (
String
)
(Option<Vec<String>>) => {
String
};
}
macro_rules! usage_with_ident {
($name:expr, $usage:expr, $help:expr) => (
if $usage.contains("<") {
format!("<{}> {} '{}'",$name, $usage, $help)
} else {
format!("[{}] {} '{}'",$name, $usage, $help)
}
);
($name:expr, $usage:expr, $help:expr) => {
if $usage.contains("<") {
format!("<{}> {} '{}'", $name, $usage, $help)
} else {
format!("[{}] {} '{}'", $name, $usage, $help)
}
};
}
macro_rules! underscore_to_hyphen {
($e:expr) => (
str::replace($e, "_", "-")
)
($e:expr) => {
str::replace($e, "_", "-")
};
}
macro_rules! usage {
@ -143,7 +143,7 @@ macro_rules! usage {
) => {
use toml;
use std::{fs, io, process, cmp};
use std::io::{Read, Write};
use std::io::Read;
use parity_version::version;
use clap::{Arg, App, SubCommand, AppSettings, ArgSettings, Error as ClapError, ErrorKind as ClapErrorKind};
use dir::helpers::replace_home;
@ -172,17 +172,17 @@ macro_rules! usage {
match self {
ArgsError::Clap(e) => e.exit(),
ArgsError::Decode(e) => {
println_stderr!("You might have supplied invalid parameters in config file.");
println_stderr!("{}", e);
eprintln!("You might have supplied invalid parameters in config file.");
eprintln!("{}", e);
process::exit(2)
},
ArgsError::Config(path, e) => {
println_stderr!("There was an error reading your config file at: {}", path);
println_stderr!("{}", e);
eprintln!("There was an error reading your config file at: {}", path);
eprintln!("{}", e);
process::exit(2)
},
ArgsError::PeerConfiguration => {
println_stderr!("You have supplied `min_peers` > `max_peers`");
eprintln!("You have supplied `min_peers` > `max_peers`");
process::exit(2)
}
}
@ -332,7 +332,7 @@ macro_rules! usage {
let args = match (fs::File::open(&config_file), raw_args.arg_config.clone()) {
// Load config file
(Ok(mut file), _) => {
println_stderr!("Loading config file from {}", &config_file);
eprintln!("Loading config file from {}", &config_file);
let mut config = String::new();
file.read_to_string(&mut config).map_err(|e| ArgsError::Config(config_file, e))?;
Ok(raw_args.into_args(Self::parse_config(&config)?))
@ -395,7 +395,7 @@ macro_rules! usage {
// Subcommands
let mut subcommands_wrapper = Wrapper::new(term_width).subsequent_indent(TAB);
help.push_str("parity [options]\n");
help.push_str("openethereum [options]\n");
$(
{
let mut subc_subc_exist = false;
@ -413,7 +413,7 @@ macro_rules! usage {
help.push_str(&subcommands_wrapper.fill(
format!(
"parity [options] {} {} {}\n",
"openethereum [options] {} {} {}\n",
underscore_to_hyphen!(&stringify!($subc)[4..]),
underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..]),
subc_subc_usages.join(" ")
@ -434,7 +434,7 @@ macro_rules! usage {
help.push_str(&subcommands_wrapper.fill(
format!(
"parity [options] {} {}\n",
"openethereum [options] {} {}\n",
underscore_to_hyphen!(&stringify!($subc)[4..]),
subc_usages.join(" ")
).as_ref())
@ -610,7 +610,7 @@ macro_rules! usage {
}
)*
let matches = App::new("Parity")
let matches = App::new("OpenEthereum")
.global_setting(AppSettings::VersionlessSubcommands)
.global_setting(AppSettings::DisableHelpSubcommand)
.max_term_width(MAX_TERM_WIDTH)
@ -633,7 +633,7 @@ macro_rules! usage {
.about($subc_help)
.args(&subc_usages.get(stringify!($subc)).unwrap().iter().map(|u| Arg::from_usage(u).use_delimiter(false).allow_hyphen_values(true)).collect::<Vec<Arg>>())
$(
.setting(AppSettings::SubcommandRequired) // prevent from running `parity account`
.setting(AppSettings::SubcommandRequired) // prevent from running `openethereum account`
.subcommand(
SubCommand::with_name(&underscore_to_hyphen!(&stringify!($subc_subc)[stringify!($subc).len()+1..]))
.about($subc_subc_help)

View File

@ -0,0 +1,6 @@
OpenEthereum Client.
By Wood/Paronyan/Kotewicz/Drwięga/Volf/Greeff
Habermeier/Czaban/Gotchac/Redman/Nikolsky
Schoedon/Tang/Adolfsson/Silva/Palm/Hirsz et al.
Copyright 2015-2020 Parity Technologies (UK) Ltd.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.

View File

@ -1,9 +1,10 @@
Parity Ethereum
OpenEthereum Client.
version {}
Copyright 2015-2018 Parity Technologies (UK) Ltd.
Copyright 2015-2020 Parity Technologies (UK) Ltd.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
By Wood/Paronyan/Kotewicz/Drwięga/Volf
Habermeier/Czaban/Greeff/Gotchac/Redmann
By Wood/Paronyan/Kotewicz/Drwięga/Volf/Greeff
Habermeier/Czaban/Gotchac/Redman/Nikolsky
Schoedon/Tang/Adolfsson/Silva/Palm/Hirsz et al.

2045
bin/oe/configuration.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,25 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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 Parity. If not, see <http://www.gnu.org/licenses/>.
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Database-related operations.
#[path="rocksdb/mod.rs"]
#[path = "rocksdb/mod.rs"]
mod impls;
pub use self::impls::{open_db, restoration_db_handler, migrate};
pub use self::impls::{migrate, restoration_db_handler};
#[cfg(feature = "secretstore")]
pub use self::impls::open_secretstore_db;

View File

@ -0,0 +1,83 @@
// 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/>.
//! Blooms migration from rocksdb to blooms-db
use super::{kvdb_rocksdb::DatabaseConfig, open_database};
use ethcore::error::Error;
use ethereum_types::Bloom;
use rlp;
use std::path::Path;
const LOG_BLOOMS_ELEMENTS_PER_INDEX: u64 = 16;
pub fn migrate_blooms<P: AsRef<Path>>(path: P, config: &DatabaseConfig) -> Result<(), Error> {
// init
let db = open_database(&path.as_ref().to_string_lossy(), config)?;
// possible optimization:
// pre-allocate space on disk for faster migration
// iterate over header blooms and insert them in blooms-db
// Some(3) -> COL_EXTRA
// 3u8 -> ExtrasIndex::BlocksBlooms
// 0u8 -> level 0
let blooms_iterator = db
.key_value()
.iter_from_prefix(Some(3), &[3u8, 0u8])
.filter(|(key, _)| key.len() == 6)
.take_while(|(key, _)| key[0] == 3u8 && key[1] == 0u8)
.map(|(key, group)| {
let index = (key[2] as u64) << 24
| (key[3] as u64) << 16
| (key[4] as u64) << 8
| (key[5] as u64);
let number = index * LOG_BLOOMS_ELEMENTS_PER_INDEX;
let blooms = rlp::decode_list::<Bloom>(&group);
(number, blooms)
});
for (number, blooms) in blooms_iterator {
db.blooms().insert_blooms(number, blooms.iter())?;
}
// iterate over trace blooms and insert them in blooms-db
// Some(4) -> COL_TRACE
// 1u8 -> TraceDBIndex::BloomGroups
// 0u8 -> level 0
let trace_blooms_iterator = db
.key_value()
.iter_from_prefix(Some(4), &[1u8, 0u8])
.filter(|(key, _)| key.len() == 6)
.take_while(|(key, _)| key[0] == 1u8 && key[1] == 0u8)
.map(|(key, group)| {
let index = (key[2] as u64)
| (key[3] as u64) << 8
| (key[4] as u64) << 16
| (key[5] as u64) << 24;
let number = index * LOG_BLOOMS_ELEMENTS_PER_INDEX;
let blooms = rlp::decode_list::<Bloom>(&group);
(number, blooms)
});
for (number, blooms) in trace_blooms_iterator {
db.trace_blooms().insert_blooms(number, blooms.iter())?;
}
Ok(())
}

View File

@ -0,0 +1,40 @@
// 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::kvdb_rocksdb::{CompactionProfile, DatabaseConfig};
use ethcore::client::{ClientConfig, DatabaseCompactionProfile};
use ethcore_db::NUM_COLUMNS;
use std::path::Path;
pub fn compaction_profile(
profile: &DatabaseCompactionProfile,
db_path: &Path,
) -> CompactionProfile {
match profile {
&DatabaseCompactionProfile::Auto => CompactionProfile::auto(db_path),
&DatabaseCompactionProfile::SSD => CompactionProfile::ssd(),
&DatabaseCompactionProfile::HDD => CompactionProfile::hdd(),
}
}
pub fn client_db_config(client_path: &Path, client_config: &ClientConfig) -> DatabaseConfig {
let mut client_db_config = DatabaseConfig::with_columns(NUM_COLUMNS);
client_db_config.memory_budget = client_config.db_cache_size;
client_db_config.compaction = compaction_profile(&client_config.db_compaction, &client_path);
client_db_config
}

View File

@ -0,0 +1,262 @@
// 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::{
kvdb_rocksdb::{CompactionProfile, DatabaseConfig},
migration_rocksdb::{ChangeColumns, Config as MigrationConfig, Manager as MigrationManager},
};
use ethcore::{self, client::DatabaseCompactionProfile};
use std::{
fmt::{Display, Error as FmtError, Formatter},
fs,
io::{Error as IoError, ErrorKind, Read, Write},
path::{Path, PathBuf},
};
use super::{blooms::migrate_blooms, helpers};
/// The migration from v10 to v11.
/// Adds a column for node info.
pub const TO_V11: ChangeColumns = ChangeColumns {
pre_columns: Some(6),
post_columns: Some(7),
version: 11,
};
/// The migration from v11 to v12.
/// Adds a column for light chain storage.
pub const TO_V12: ChangeColumns = ChangeColumns {
pre_columns: Some(7),
post_columns: Some(8),
version: 12,
};
/// Database is assumed to be at default version, when no version file is found.
const DEFAULT_VERSION: u32 = 5;
/// Current version of database models.
const CURRENT_VERSION: u32 = 16;
/// Until this version please use upgrade tool.
const USE_MIGRATION_TOOL: u32 = 15;
/// A version of database at which blooms-db was introduced
const BLOOMS_DB_VERSION: u32 = 13;
/// Defines how many items are migrated to the new version of database at once.
const BATCH_SIZE: usize = 1024;
/// Version file name.
const VERSION_FILE_NAME: &'static str = "db_version";
/// Migration related erorrs.
#[derive(Debug)]
pub enum Error {
/// Returned when current version cannot be read or guessed.
UnknownDatabaseVersion,
/// Existing DB is newer than the known one.
FutureDBVersion,
/// Migration is not possible.
MigrationImpossible,
/// For old versions use external migration tool
UseMigrationTool,
/// Blooms-db migration error.
BloomsDB(ethcore::error::Error),
/// Migration was completed succesfully,
/// but there was a problem with io.
Io(IoError),
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
let out = match *self {
Error::UnknownDatabaseVersion => "Current database version cannot be read".into(),
Error::FutureDBVersion => "Database was created with newer client version. Upgrade your client or delete DB and resync.".into(),
Error::MigrationImpossible => format!("Database migration to version {} is not possible.", CURRENT_VERSION),
Error::BloomsDB(ref err) => format!("blooms-db migration error: {}", err),
Error::UseMigrationTool => "For db versions 15 and lower (v2.5.13=>13, 2.7.2=>14, v3.0.1=>15) please use upgrade db tool to manually upgrade db: https://github.com/openethereum/3.1-db-upgrade-tool".into(),
Error::Io(ref err) => format!("Unexpected io error on DB migration: {}.", err),
};
write!(f, "{}", out)
}
}
impl From<IoError> for Error {
fn from(err: IoError) -> Self {
Error::Io(err)
}
}
/// Returns the version file path.
fn version_file_path(path: &Path) -> PathBuf {
let mut file_path = path.to_owned();
file_path.push(VERSION_FILE_NAME);
file_path
}
/// Reads current database version from the file at given path.
/// If the file does not exist returns `DEFAULT_VERSION`.
fn current_version(path: &Path) -> Result<u32, Error> {
match fs::File::open(version_file_path(path)) {
Err(ref err) if err.kind() == ErrorKind::NotFound => Ok(DEFAULT_VERSION),
Err(_) => Err(Error::UnknownDatabaseVersion),
Ok(mut file) => {
let mut s = String::new();
file.read_to_string(&mut s)
.map_err(|_| Error::UnknownDatabaseVersion)?;
u32::from_str_radix(&s, 10).map_err(|_| Error::UnknownDatabaseVersion)
}
}
}
/// Writes current database version to the file.
/// Creates a new file if the version file does not exist yet.
fn update_version(path: &Path) -> Result<(), Error> {
fs::create_dir_all(path)?;
let mut file = fs::File::create(version_file_path(path))?;
file.write_all(format!("{}", CURRENT_VERSION).as_bytes())?;
Ok(())
}
/// Consolidated database path
fn consolidated_database_path(path: &Path) -> PathBuf {
let mut state_path = path.to_owned();
state_path.push("db");
state_path
}
/// Database backup
fn backup_database_path(path: &Path) -> PathBuf {
let mut backup_path = path.to_owned();
backup_path.pop();
backup_path.push("temp_backup");
backup_path
}
/// Default migration settings.
pub fn default_migration_settings(compaction_profile: &CompactionProfile) -> MigrationConfig {
MigrationConfig {
batch_size: BATCH_SIZE,
compaction_profile: *compaction_profile,
}
}
/// Migrations on the consolidated database.
fn consolidated_database_migrations(
compaction_profile: &CompactionProfile,
) -> Result<MigrationManager, Error> {
let mut manager = MigrationManager::new(default_migration_settings(compaction_profile));
manager
.add_migration(TO_V11)
.map_err(|_| Error::MigrationImpossible)?;
manager
.add_migration(TO_V12)
.map_err(|_| Error::MigrationImpossible)?;
Ok(manager)
}
/// Migrates database at given position with given migration rules.
fn migrate_database(
version: u32,
db_path: &Path,
mut migrations: MigrationManager,
) -> Result<(), Error> {
// check if migration is needed
if !migrations.is_needed(version) {
return Ok(());
}
let backup_path = backup_database_path(&db_path);
// remove the backup dir if it exists
let _ = fs::remove_dir_all(&backup_path);
// migrate old database to the new one
let temp_path = migrations.execute(&db_path, version)?;
// completely in-place migration leads to the paths being equal.
// in that case, no need to shuffle directories.
if temp_path == db_path {
return Ok(());
}
// create backup
fs::rename(&db_path, &backup_path)?;
// replace the old database with the new one
if let Err(err) = fs::rename(&temp_path, &db_path) {
// if something went wrong, bring back backup
fs::rename(&backup_path, &db_path)?;
return Err(err.into());
}
// remove backup
fs::remove_dir_all(&backup_path).map_err(Into::into)
}
fn exists(path: &Path) -> bool {
fs::metadata(path).is_ok()
}
/// Migrates the database.
pub fn migrate(path: &Path, compaction_profile: &DatabaseCompactionProfile) -> Result<(), Error> {
let compaction_profile = helpers::compaction_profile(&compaction_profile, path);
// read version file.
let version = current_version(path)?;
// migrate the databases.
// main db directory may already exists, so let's check if we have blocks dir
if version > CURRENT_VERSION {
return Err(Error::FutureDBVersion);
}
// We are in the latest version, yay!
if version == CURRENT_VERSION {
return Ok(());
}
if version != DEFAULT_VERSION && version <= USE_MIGRATION_TOOL {
return Err(Error::UseMigrationTool);
}
let db_path = consolidated_database_path(path);
// Further migrations
if version < CURRENT_VERSION && exists(&db_path) {
println!(
"Migrating database from version {} to {}",
version, CURRENT_VERSION
);
migrate_database(
version,
&db_path,
consolidated_database_migrations(&compaction_profile)?,
)?;
if version < BLOOMS_DB_VERSION {
println!("Migrating blooms to blooms-db...");
let db_config = DatabaseConfig {
max_open_files: 64,
memory_budget: None,
compaction: compaction_profile,
columns: ethcore_db::NUM_COLUMNS,
};
migrate_blooms(&db_path, &db_config).map_err(Error::BloomsDB)?;
}
println!("Migration finished");
}
// update version file.
update_version(path)
}

119
bin/oe/db/rocksdb/mod.rs Normal file
View File

@ -0,0 +1,119 @@
// 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/>.
extern crate ethcore_blockchain;
extern crate kvdb_rocksdb;
extern crate migration_rocksdb;
use self::{
ethcore_blockchain::{BlockChainDB, BlockChainDBHandler},
kvdb_rocksdb::{Database, DatabaseConfig},
};
use blooms_db;
use ethcore::client::ClientConfig;
use ethcore_db::KeyValueDB;
use stats::PrometheusMetrics;
use std::{fs, io, path::Path, sync::Arc};
mod blooms;
mod helpers;
mod migration;
pub use self::migration::migrate;
struct AppDB {
key_value: Arc<dyn KeyValueDB>,
blooms: blooms_db::Database,
trace_blooms: blooms_db::Database,
}
impl BlockChainDB for AppDB {
fn key_value(&self) -> &Arc<dyn KeyValueDB> {
&self.key_value
}
fn blooms(&self) -> &blooms_db::Database {
&self.blooms
}
fn trace_blooms(&self) -> &blooms_db::Database {
&self.trace_blooms
}
}
impl PrometheusMetrics for AppDB {
fn prometheus_metrics(&self, _: &mut stats::PrometheusRegistry) {}
}
/// Open a secret store DB using the given secret store data path. The DB path is one level beneath the data path.
#[cfg(feature = "secretstore")]
pub fn open_secretstore_db(data_path: &str) -> Result<Arc<dyn KeyValueDB>, String> {
use std::path::PathBuf;
let mut db_path = PathBuf::from(data_path);
db_path.push("db");
let db_path = db_path
.to_str()
.ok_or_else(|| "Invalid secretstore path".to_string())?;
Ok(Arc::new(
Database::open_default(&db_path).map_err(|e| format!("Error opening database: {:?}", e))?,
))
}
/// Create a restoration db handler using the config generated by `client_path` and `client_config`.
pub fn restoration_db_handler(
client_path: &Path,
client_config: &ClientConfig,
) -> Box<dyn BlockChainDBHandler> {
let client_db_config = helpers::client_db_config(client_path, client_config);
struct RestorationDBHandler {
config: DatabaseConfig,
}
impl BlockChainDBHandler for RestorationDBHandler {
fn open(&self, db_path: &Path) -> io::Result<Arc<dyn BlockChainDB>> {
open_database(&db_path.to_string_lossy(), &self.config)
}
}
Box::new(RestorationDBHandler {
config: client_db_config,
})
}
pub fn open_database(
client_path: &str,
config: &DatabaseConfig,
) -> io::Result<Arc<dyn BlockChainDB>> {
let path = Path::new(client_path);
let blooms_path = path.join("blooms");
let trace_blooms_path = path.join("trace_blooms");
fs::create_dir_all(&blooms_path)?;
fs::create_dir_all(&trace_blooms_path)?;
let db = Database::open(&config, client_path)?;
let db_with_metrics = ethcore_db::DatabaseWithMetrics::new(db);
let db = AppDB {
key_value: Arc::new(db_with_metrics),
blooms: blooms_db::Database::open(blooms_path)?,
trace_blooms: blooms_db::Database::open(trace_blooms_path)?,
};
Ok(Arc::new(db))
}

600
bin/oe/helpers.rs Normal file
View File

@ -0,0 +1,600 @@
// 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 crate::{
cache::CacheConfig,
db::migrate,
miner::pool::PrioritizationStrategy,
sync::{self, validate_node_url},
upgrade::{upgrade, upgrade_data_paths},
};
use dir::{helpers::replace_home, DatabaseDirectories};
use ethcore::{
client::{BlockId, ClientConfig, DatabaseCompactionProfile, Mode, VMType, VerifierType},
miner::{Penalization, PendingSet},
};
use ethereum_types::{Address, U256};
use ethkey::Password;
use journaldb::Algorithm;
use std::{
collections::HashSet,
fs::File,
io,
io::{BufRead, BufReader, Write},
time::Duration,
};
pub fn to_duration(s: &str) -> Result<Duration, String> {
to_seconds(s).map(Duration::from_secs)
}
fn clean_0x(s: &str) -> &str {
if s.starts_with("0x") {
&s[2..]
} else {
s
}
}
fn to_seconds(s: &str) -> Result<u64, String> {
let bad = |_| {
format!(
"{}: Invalid duration given. See openethereum --help for more information.",
s
)
};
match s {
"twice-daily" => Ok(12 * 60 * 60),
"half-hourly" => Ok(30 * 60),
"1second" | "1 second" | "second" => Ok(1),
"1minute" | "1 minute" | "minute" => Ok(60),
"hourly" | "1hour" | "1 hour" | "hour" => Ok(60 * 60),
"daily" | "1day" | "1 day" | "day" => Ok(24 * 60 * 60),
x if x.ends_with("seconds") => x[0..x.len() - 7].trim().parse().map_err(bad),
x if x.ends_with("minutes") => x[0..x.len() - 7]
.trim()
.parse::<u64>()
.map_err(bad)
.map(|x| x * 60),
x if x.ends_with("hours") => x[0..x.len() - 5]
.trim()
.parse::<u64>()
.map_err(bad)
.map(|x| x * 60 * 60),
x if x.ends_with("days") => x[0..x.len() - 4]
.trim()
.parse::<u64>()
.map_err(bad)
.map(|x| x * 24 * 60 * 60),
x => x.trim().parse().map_err(bad),
}
}
pub fn to_mode(s: &str, timeout: u64, alarm: u64) -> Result<Mode, String> {
match s {
"active" => Ok(Mode::Active),
"passive" => Ok(Mode::Passive(
Duration::from_secs(timeout),
Duration::from_secs(alarm),
)),
"dark" => Ok(Mode::Dark(Duration::from_secs(timeout))),
"offline" => Ok(Mode::Off),
_ => Err(format!(
"{}: Invalid value for --mode. Must be one of active, passive, dark or offline.",
s
)),
}
}
pub fn to_block_id(s: &str) -> Result<BlockId, String> {
if s == "latest" {
Ok(BlockId::Latest)
} else if let Ok(num) = s.parse() {
Ok(BlockId::Number(num))
} else if let Ok(hash) = s.parse() {
Ok(BlockId::Hash(hash))
} else {
Err("Invalid block.".into())
}
}
pub fn to_u256(s: &str) -> Result<U256, String> {
if let Ok(decimal) = U256::from_dec_str(s) {
Ok(decimal)
} else {
clean_0x(s)
.parse()
.map_err(|_| format!("Invalid numeric value: {}", s))
}
}
pub fn to_pending_set(s: &str) -> Result<PendingSet, String> {
match s {
"cheap" => Ok(PendingSet::AlwaysQueue),
"strict" => Ok(PendingSet::AlwaysSealing),
"lenient" => Ok(PendingSet::SealingOrElseQueue),
other => Err(format!("Invalid pending set value: {:?}", other)),
}
}
pub fn to_queue_strategy(s: &str) -> Result<PrioritizationStrategy, String> {
match s {
"gas_price" => Ok(PrioritizationStrategy::GasPriceOnly),
other => Err(format!("Invalid queue strategy: {}", other)),
}
}
pub fn to_queue_penalization(time: Option<u64>) -> Result<Penalization, String> {
Ok(match time {
Some(threshold_ms) => Penalization::Enabled {
offend_threshold: Duration::from_millis(threshold_ms),
},
None => Penalization::Disabled,
})
}
pub fn to_address(s: Option<String>) -> Result<Address, String> {
match s {
Some(ref a) => clean_0x(a)
.parse()
.map_err(|_| format!("Invalid address: {:?}", a)),
None => Ok(Address::default()),
}
}
pub fn to_addresses(s: &Option<String>) -> Result<Vec<Address>, String> {
match *s {
Some(ref adds) if !adds.is_empty() => adds
.split(',')
.map(|a| {
clean_0x(a)
.parse()
.map_err(|_| format!("Invalid address: {:?}", a))
})
.collect(),
_ => Ok(Vec::new()),
}
}
/// Tries to parse string as a price.
pub fn to_price(s: &str) -> Result<f32, String> {
s.parse::<f32>().map_err(|_| {
format!(
"Invalid transaction price {:?} given. Must be a decimal number.",
s
)
})
}
pub fn join_set(set: Option<&HashSet<String>>) -> Option<String> {
set.map(|s| {
s.iter()
.map(|s| s.as_str())
.collect::<Vec<&str>>()
.join(",")
})
}
/// Flush output buffer.
pub fn flush_stdout() {
io::stdout().flush().expect("stdout is flushable; qed");
}
/// Formats and returns parity ipc path.
pub fn parity_ipc_path(base: &str, path: &str, shift: u16) -> String {
let mut path = path.to_owned();
if shift != 0 {
path = path.replace("jsonrpc.ipc", &format!("jsonrpc-{}.ipc", shift));
}
replace_home(base, &path)
}
/// Validates and formats bootnodes option.
pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
match *bootnodes {
Some(ref x) if !x.is_empty() => x
.split(',')
.map(|s| match validate_node_url(s).map(Into::into) {
None => Ok(s.to_owned()),
Some(sync::ErrorKind::AddressResolve(_)) => {
Err(format!("Failed to resolve hostname of a boot node: {}", s))
}
Some(_) => Err(format!(
"Invalid node address format given for a boot node: {}",
s
)),
})
.collect(),
Some(_) => Ok(vec![]),
None => Ok(vec![]),
}
}
#[cfg(test)]
pub fn default_network_config() -> crate::sync::NetworkConfiguration {
use super::network::IpFilter;
use crate::sync::NetworkConfiguration;
NetworkConfiguration {
config_path: Some(replace_home(&::dir::default_data_path(), "$BASE/network")),
net_config_path: None,
listen_address: Some("0.0.0.0:30303".into()),
public_address: None,
udp_port: None,
nat_enabled: true,
discovery_enabled: true,
boot_nodes: Vec::new(),
use_secret: None,
max_peers: 50,
min_peers: 25,
snapshot_peers: 0,
max_pending_peers: 64,
ip_filter: IpFilter::default(),
reserved_nodes: Vec::new(),
allow_non_reserved: true,
client_version: ::parity_version::version(),
}
}
pub fn to_client_config(
cache_config: &CacheConfig,
spec_name: String,
mode: Mode,
tracing: bool,
fat_db: bool,
compaction: DatabaseCompactionProfile,
vm_type: VMType,
name: String,
pruning: Algorithm,
pruning_history: u64,
pruning_memory: usize,
check_seal: bool,
max_round_blocks_to_import: usize,
) -> ClientConfig {
let mut client_config = ClientConfig::default();
let mb = 1024 * 1024;
// in bytes
client_config.blockchain.max_cache_size = cache_config.blockchain() as usize * mb;
// in bytes
client_config.blockchain.pref_cache_size = cache_config.blockchain() as usize * 3 / 4 * mb;
// db cache size, in megabytes
client_config.db_cache_size = Some(cache_config.db_cache_size() as usize);
// db queue cache size, in bytes
client_config.queue.max_mem_use = cache_config.queue() as usize * mb;
// in bytes
client_config.tracing.max_cache_size = cache_config.traces() as usize * mb;
// in bytes
client_config.tracing.pref_cache_size = cache_config.traces() as usize * 3 / 4 * mb;
// in bytes
client_config.state_cache_size = cache_config.state() as usize * mb;
// in bytes
client_config.jump_table_size = cache_config.jump_tables() as usize * mb;
// in bytes
client_config.history_mem = pruning_memory * mb;
client_config.mode = mode;
client_config.tracing.enabled = tracing;
client_config.fat_db = fat_db;
client_config.pruning = pruning;
client_config.history = pruning_history;
client_config.db_compaction = compaction;
client_config.vm_type = vm_type;
client_config.name = name;
client_config.verifier_type = if check_seal {
VerifierType::Canon
} else {
VerifierType::CanonNoSeal
};
client_config.spec_name = spec_name;
client_config.max_round_blocks_to_import = max_round_blocks_to_import;
client_config
}
pub fn execute_upgrades(
base_path: &str,
dirs: &DatabaseDirectories,
pruning: Algorithm,
compaction_profile: &DatabaseCompactionProfile,
) -> Result<(), String> {
upgrade_data_paths(base_path, dirs, pruning);
match upgrade(&dirs.path) {
Ok(upgrades_applied) if upgrades_applied > 0 => {
debug!("Executed {} upgrade scripts - ok", upgrades_applied);
}
Err(e) => {
return Err(format!("Error upgrading OpenEthereum data: {:?}", e));
}
_ => {}
}
let client_path = dirs.db_path(pruning);
migrate(&client_path, compaction_profile).map_err(|e| format!("{}", e))
}
/// Prompts user asking for password.
pub fn password_prompt() -> Result<Password, String> {
use rpassword::read_password;
const STDIN_ERROR: &'static str = "Unable to ask for password on non-interactive terminal.";
println!("Please note that password is NOT RECOVERABLE.");
print!("Type password: ");
flush_stdout();
let password = read_password().map_err(|_| STDIN_ERROR.to_owned())?.into();
print!("Repeat password: ");
flush_stdout();
let password_repeat = read_password().map_err(|_| STDIN_ERROR.to_owned())?.into();
if password != password_repeat {
return Err("Passwords do not match!".into());
}
Ok(password)
}
/// Read a password from password file.
pub fn password_from_file(path: String) -> Result<Password, String> {
let passwords = passwords_from_files(&[path])?;
// use only first password from the file
passwords
.get(0)
.map(Password::clone)
.ok_or_else(|| "Password file seems to be empty.".to_owned())
}
/// Reads passwords from files. Treats each line as a separate password.
pub fn passwords_from_files(files: &[String]) -> Result<Vec<Password>, String> {
let passwords = files.iter().map(|filename| {
let file = File::open(filename).map_err(|_| format!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename))?;
let reader = BufReader::new(&file);
let lines = reader.lines()
.filter_map(|l| l.ok())
.map(|pwd| pwd.trim().to_owned().into())
.collect::<Vec<Password>>();
Ok(lines)
}).collect::<Result<Vec<Vec<Password>>, String>>();
Ok(passwords?.into_iter().flat_map(|x| x).collect())
}
#[cfg(test)]
mod tests {
use super::{
join_set, password_from_file, to_address, to_addresses, to_block_id, to_bootnodes,
to_duration, to_mode, to_pending_set, to_price, to_u256,
};
use ethcore::{
client::{BlockId, Mode},
miner::PendingSet,
};
use ethereum_types::U256;
use ethkey::Password;
use std::{collections::HashSet, fs::File, io::Write, time::Duration};
use tempdir::TempDir;
#[test]
fn test_to_duration() {
assert_eq!(
to_duration("twice-daily").unwrap(),
Duration::from_secs(12 * 60 * 60)
);
assert_eq!(
to_duration("half-hourly").unwrap(),
Duration::from_secs(30 * 60)
);
assert_eq!(to_duration("1second").unwrap(), Duration::from_secs(1));
assert_eq!(to_duration("2seconds").unwrap(), Duration::from_secs(2));
assert_eq!(to_duration("15seconds").unwrap(), Duration::from_secs(15));
assert_eq!(to_duration("1minute").unwrap(), Duration::from_secs(1 * 60));
assert_eq!(
to_duration("2minutes").unwrap(),
Duration::from_secs(2 * 60)
);
assert_eq!(
to_duration("15minutes").unwrap(),
Duration::from_secs(15 * 60)
);
assert_eq!(to_duration("hourly").unwrap(), Duration::from_secs(60 * 60));
assert_eq!(
to_duration("daily").unwrap(),
Duration::from_secs(24 * 60 * 60)
);
assert_eq!(
to_duration("1hour").unwrap(),
Duration::from_secs(1 * 60 * 60)
);
assert_eq!(
to_duration("2hours").unwrap(),
Duration::from_secs(2 * 60 * 60)
);
assert_eq!(
to_duration("15hours").unwrap(),
Duration::from_secs(15 * 60 * 60)
);
assert_eq!(
to_duration("1day").unwrap(),
Duration::from_secs(1 * 24 * 60 * 60)
);
assert_eq!(
to_duration("2days").unwrap(),
Duration::from_secs(2 * 24 * 60 * 60)
);
assert_eq!(
to_duration("15days").unwrap(),
Duration::from_secs(15 * 24 * 60 * 60)
);
assert_eq!(
to_duration("15 days").unwrap(),
Duration::from_secs(15 * 24 * 60 * 60)
);
assert_eq!(to_duration("2 seconds").unwrap(), Duration::from_secs(2));
}
#[test]
fn test_to_mode() {
assert_eq!(to_mode("active", 0, 0).unwrap(), Mode::Active);
assert_eq!(
to_mode("passive", 10, 20).unwrap(),
Mode::Passive(Duration::from_secs(10), Duration::from_secs(20))
);
assert_eq!(
to_mode("dark", 20, 30).unwrap(),
Mode::Dark(Duration::from_secs(20))
);
assert!(to_mode("other", 20, 30).is_err());
}
#[test]
fn test_to_block_id() {
assert_eq!(to_block_id("latest").unwrap(), BlockId::Latest);
assert_eq!(to_block_id("0").unwrap(), BlockId::Number(0));
assert_eq!(to_block_id("2").unwrap(), BlockId::Number(2));
assert_eq!(to_block_id("15").unwrap(), BlockId::Number(15));
assert_eq!(
to_block_id("9fc84d84f6a785dc1bd5abacfcf9cbdd3b6afb80c0f799bfb2fd42c44a0c224e")
.unwrap(),
BlockId::Hash(
"9fc84d84f6a785dc1bd5abacfcf9cbdd3b6afb80c0f799bfb2fd42c44a0c224e"
.parse()
.unwrap()
)
);
}
#[test]
fn test_to_u256() {
assert_eq!(to_u256("0").unwrap(), U256::from(0));
assert_eq!(to_u256("11").unwrap(), U256::from(11));
assert_eq!(to_u256("0x11").unwrap(), U256::from(17));
assert!(to_u256("u").is_err())
}
#[test]
fn test_pending_set() {
assert_eq!(to_pending_set("cheap").unwrap(), PendingSet::AlwaysQueue);
assert_eq!(to_pending_set("strict").unwrap(), PendingSet::AlwaysSealing);
assert_eq!(
to_pending_set("lenient").unwrap(),
PendingSet::SealingOrElseQueue
);
assert!(to_pending_set("othe").is_err());
}
#[test]
fn test_to_address() {
assert_eq!(
to_address(Some("0xD9A111feda3f362f55Ef1744347CDC8Dd9964a41".into())).unwrap(),
"D9A111feda3f362f55Ef1744347CDC8Dd9964a41".parse().unwrap()
);
assert_eq!(
to_address(Some("D9A111feda3f362f55Ef1744347CDC8Dd9964a41".into())).unwrap(),
"D9A111feda3f362f55Ef1744347CDC8Dd9964a41".parse().unwrap()
);
assert_eq!(to_address(None).unwrap(), Default::default());
}
#[test]
fn test_to_addresses() {
let addresses = to_addresses(&Some(
"0xD9A111feda3f362f55Ef1744347CDC8Dd9964a41,D9A111feda3f362f55Ef1744347CDC8Dd9964a42"
.into(),
))
.unwrap();
assert_eq!(
addresses,
vec![
"D9A111feda3f362f55Ef1744347CDC8Dd9964a41".parse().unwrap(),
"D9A111feda3f362f55Ef1744347CDC8Dd9964a42".parse().unwrap(),
]
);
}
#[test]
fn test_password() {
let tempdir = TempDir::new("").unwrap();
let path = tempdir.path().join("file");
let mut file = File::create(&path).unwrap();
file.write_all(b"a bc ").unwrap();
assert_eq!(
password_from_file(path.to_str().unwrap().into())
.unwrap()
.as_bytes(),
b"a bc"
);
}
#[test]
fn test_password_multiline() {
let tempdir = TempDir::new("").unwrap();
let path = tempdir.path().join("file");
let mut file = File::create(path.as_path()).unwrap();
file.write_all(
br#" password with trailing whitespace
those passwords should be
ignored
but the first password is trimmed
"#,
)
.unwrap();
assert_eq!(
password_from_file(path.to_str().unwrap().into()).unwrap(),
Password::from("password with trailing whitespace")
);
}
#[test]
fn test_to_price() {
assert_eq!(to_price("1").unwrap(), 1.0);
assert_eq!(to_price("2.3").unwrap(), 2.3);
assert_eq!(to_price("2.33").unwrap(), 2.33);
}
#[test]
fn test_to_bootnodes() {
let one_bootnode = "enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303";
let two_bootnodes = "enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303,enode://e731347db0521f3476e6bbbb83375dcd7133a1601425ebd15fd10f3835fd4c304fba6282087ca5a0deeafadf0aa0d4fd56c3323331901c1f38bd181c283e3e35@128.199.55.137:30303";
assert_eq!(to_bootnodes(&Some("".into())), Ok(vec![]));
assert_eq!(to_bootnodes(&None), Ok(vec![]));
assert_eq!(
to_bootnodes(&Some(one_bootnode.into())),
Ok(vec![one_bootnode.into()])
);
assert_eq!(
to_bootnodes(&Some(two_bootnodes.into())),
Ok(vec![one_bootnode.into(), one_bootnode.into()])
);
}
#[test]
fn test_join_set() {
let mut test_set = HashSet::new();
test_set.insert("0x1111111111111111111111111111111111111111".to_string());
test_set.insert("0x0000000000000000000000000000000000000000".to_string());
let res = join_set(Some(&test_set)).unwrap();
assert!(
res == "0x1111111111111111111111111111111111111111,0x0000000000000000000000000000000000000000"
||
res == "0x0000000000000000000000000000000000000000,0x1111111111111111111111111111111111111111"
);
}
}

429
bin/oe/informant.rs Normal file
View File

@ -0,0 +1,429 @@
// 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/>.
extern crate ansi_term;
use self::ansi_term::{
Colour,
Colour::{Blue, Cyan, Green, White, Yellow},
Style,
};
use std::{
sync::{
atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering},
Arc,
},
time::{Duration, Instant},
};
use crate::{
io::{IoContext, IoHandler, TimerToken},
sync::{ManageNetwork, SyncProvider},
types::BlockNumber,
};
use atty;
use ethcore::{
client::{
BlockChainClient, BlockChainInfo, BlockId, BlockInfo, BlockQueueInfo, ChainInfo,
ChainNotify, Client, ClientIoMessage, ClientReport, NewBlocks,
},
snapshot::{service::Service as SnapshotService, RestorationStatus, SnapshotService as SS},
};
use number_prefix::{binary_prefix, Prefixed, Standalone};
use parity_rpc::{informant::RpcStats, is_major_importing_or_waiting};
use parking_lot::{Mutex, RwLock};
/// Format byte counts to standard denominations.
pub fn format_bytes(b: usize) -> String {
match binary_prefix(b as f64) {
Standalone(bytes) => format!("{} bytes", bytes),
Prefixed(prefix, n) => format!("{:.0} {}B", n, prefix),
}
}
/// Something that can be converted to milliseconds.
pub trait MillisecondDuration {
/// Get the value in milliseconds.
fn as_milliseconds(&self) -> u64;
}
impl MillisecondDuration for Duration {
fn as_milliseconds(&self) -> u64 {
self.as_secs() * 1000 + self.subsec_nanos() as u64 / 1_000_000
}
}
#[derive(Default)]
struct CacheSizes {
sizes: ::std::collections::BTreeMap<&'static str, usize>,
}
impl CacheSizes {
fn insert(&mut self, key: &'static str, bytes: usize) {
self.sizes.insert(key, bytes);
}
fn display<F>(&self, style: Style, paint: F) -> String
where
F: Fn(Style, String) -> String,
{
use std::fmt::Write;
let mut buf = String::new();
for (name, &size) in &self.sizes {
write!(buf, " {:>8} {}", paint(style, format_bytes(size)), name)
.expect("writing to string won't fail unless OOM; qed")
}
buf
}
}
pub struct SyncInfo {
last_imported_block_number: BlockNumber,
last_imported_ancient_number: Option<BlockNumber>,
num_peers: usize,
max_peers: u32,
snapshot_sync: bool,
}
pub struct Report {
importing: bool,
chain_info: BlockChainInfo,
client_report: ClientReport,
queue_info: BlockQueueInfo,
cache_sizes: CacheSizes,
sync_info: Option<SyncInfo>,
}
/// Something which can provide data to the informant.
pub trait InformantData: Send + Sync {
/// Whether it executes transactions
fn executes_transactions(&self) -> bool;
/// Whether it is currently importing (also included in `Report`)
fn is_major_importing(&self) -> bool;
/// Generate a report of blockchain status, memory usage, and sync info.
fn report(&self) -> Report;
}
/// Informant data for a full node.
pub struct FullNodeInformantData {
pub client: Arc<Client>,
pub sync: Option<Arc<dyn SyncProvider>>,
pub net: Option<Arc<dyn ManageNetwork>>,
}
impl InformantData for FullNodeInformantData {
fn executes_transactions(&self) -> bool {
true
}
fn is_major_importing(&self) -> bool {
let state = self.sync.as_ref().map(|sync| sync.status().state);
is_major_importing_or_waiting(state, self.client.queue_info(), false)
}
fn report(&self) -> Report {
let (client_report, queue_info, blockchain_cache_info) = (
self.client.report(),
self.client.queue_info(),
self.client.blockchain_cache_info(),
);
let chain_info = self.client.chain_info();
let mut cache_sizes = CacheSizes::default();
cache_sizes.insert("queue", queue_info.mem_used);
cache_sizes.insert("chain", blockchain_cache_info.total());
let importing = self.is_major_importing();
let sync_info = match (self.sync.as_ref(), self.net.as_ref()) {
(Some(sync), Some(net)) => {
let status = sync.status();
let num_peers_range = net.num_peers_range();
debug_assert!(num_peers_range.end() >= num_peers_range.start());
Some(SyncInfo {
last_imported_block_number: status
.last_imported_block_number
.unwrap_or(chain_info.best_block_number),
last_imported_ancient_number: status.last_imported_old_block_number,
num_peers: status.num_peers,
max_peers: status
.current_max_peers(*num_peers_range.start(), *num_peers_range.end()),
snapshot_sync: status.is_snapshot_syncing(),
})
}
_ => None,
};
Report {
importing,
chain_info,
client_report,
queue_info,
cache_sizes,
sync_info,
}
}
}
pub struct Informant<T> {
last_tick: RwLock<Instant>,
with_color: bool,
target: T,
snapshot: Option<Arc<SnapshotService>>,
rpc_stats: Option<Arc<RpcStats>>,
last_import: Mutex<Instant>,
skipped: AtomicUsize,
skipped_txs: AtomicUsize,
in_shutdown: AtomicBool,
last_report: Mutex<ClientReport>,
}
impl<T: InformantData> Informant<T> {
/// Make a new instance potentially `with_color` output.
pub fn new(
target: T,
snapshot: Option<Arc<SnapshotService>>,
rpc_stats: Option<Arc<RpcStats>>,
with_color: bool,
) -> Self {
Informant {
last_tick: RwLock::new(Instant::now()),
with_color: with_color,
target: target,
snapshot: snapshot,
rpc_stats: rpc_stats,
last_import: Mutex::new(Instant::now()),
skipped: AtomicUsize::new(0),
skipped_txs: AtomicUsize::new(0),
in_shutdown: AtomicBool::new(false),
last_report: Mutex::new(Default::default()),
}
}
/// Signal that we're shutting down; no more output necessary.
pub fn shutdown(&self) {
self.in_shutdown
.store(true, ::std::sync::atomic::Ordering::SeqCst);
}
pub fn tick(&self) {
let now = Instant::now();
let elapsed;
{
let last_tick = self.last_tick.read();
if now < *last_tick + Duration::from_millis(1500) {
return;
}
elapsed = now - *last_tick;
}
let (client_report, full_report) = {
let last_report = self.last_report.lock();
let full_report = self.target.report();
let diffed = full_report.client_report.clone() - &*last_report;
(diffed, full_report)
};
let Report {
importing,
chain_info,
queue_info,
cache_sizes,
sync_info,
..
} = full_report;
let rpc_stats = self.rpc_stats.as_ref();
let snapshot_sync = sync_info.as_ref().map_or(false, |s| s.snapshot_sync)
&& self
.snapshot
.as_ref()
.map_or(false, |s| match s.restoration_status() {
RestorationStatus::Ongoing { .. } | RestorationStatus::Initializing { .. } => {
true
}
_ => false,
});
if !importing && !snapshot_sync && elapsed < Duration::from_secs(30) {
return;
}
*self.last_tick.write() = now;
*self.last_report.lock() = full_report.client_report.clone();
let paint = |c: Style, t: String| match self.with_color && atty::is(atty::Stream::Stdout) {
true => format!("{}", c.paint(t)),
false => t,
};
info!(target: "import", "{}{} {} {} {}",
match importing {
true => match snapshot_sync {
false => format!("Syncing {} {} {} {}+{} Qed",
paint(White.bold(), format!("{:>8}", format!("#{}", chain_info.best_block_number))),
paint(White.bold(), format!("{}", chain_info.best_block_hash)),
if self.target.executes_transactions() {
format!("{} blk/s {} tx/s {} Mgas/s",
paint(Yellow.bold(), format!("{:7.2}", (client_report.blocks_imported * 1000) as f64 / elapsed.as_milliseconds() as f64)),
paint(Yellow.bold(), format!("{:6.1}", (client_report.transactions_applied * 1000) as f64 / elapsed.as_milliseconds() as f64)),
paint(Yellow.bold(), format!("{:6.1}", (client_report.gas_processed / 1000).low_u64() as f64 / elapsed.as_milliseconds() as f64))
)
} else {
format!("{} hdr/s",
paint(Yellow.bold(), format!("{:6.1}", (client_report.blocks_imported * 1000) as f64 / elapsed.as_milliseconds() as f64))
)
},
paint(Green.bold(), format!("{:5}", queue_info.unverified_queue_size)),
paint(Green.bold(), format!("{:5}", queue_info.verified_queue_size))
),
true => {
self.snapshot.as_ref().map_or(String::new(), |s|
match s.restoration_status() {
RestorationStatus::Ongoing { state_chunks, block_chunks, state_chunks_done, block_chunks_done, .. } => {
format!("Syncing snapshot {}/{}", state_chunks_done + block_chunks_done, state_chunks + block_chunks)
},
RestorationStatus::Initializing { chunks_done } => {
format!("Snapshot initializing ({} chunks restored)", chunks_done)
},
_ => String::new(),
}
)
},
},
false => String::new(),
},
match chain_info.ancient_block_number {
Some(ancient_number) => format!(" Ancient:#{}", ancient_number),
None => String::new(),
},
match sync_info.as_ref() {
Some(ref sync_info) => format!("{}{}/{} peers",
match importing {
true => format!("{}",
if self.target.executes_transactions() {
paint(Green.bold(), format!("{:>8} ", format!("LI:#{}", sync_info.last_imported_block_number)))
} else {
String::new()
}
),
false => match sync_info.last_imported_ancient_number {
Some(number) => format!("{} ", paint(Yellow.bold(), format!("{:>8}", format!("AB:#{}", number)))),
None => String::new(),
}
},
paint(Cyan.bold(), format!("{:2}", sync_info.num_peers)),
paint(Cyan.bold(), format!("{:2}", sync_info.max_peers)),
),
_ => String::new(),
},
cache_sizes.display(Blue.bold(), &paint),
match rpc_stats {
Some(ref rpc_stats) => format!(
"RPC: {} conn, {} req/s, {} µs",
paint(Blue.bold(), format!("{:2}", rpc_stats.sessions())),
paint(Blue.bold(), format!("{:4}", rpc_stats.requests_rate())),
paint(Blue.bold(), format!("{:4}", rpc_stats.approximated_roundtrip())),
),
_ => String::new(),
},
);
}
}
impl ChainNotify for Informant<FullNodeInformantData> {
// t_nb 11.2 Informant. Prints new block inclusiong to console/log.
fn new_blocks(&self, new_blocks: NewBlocks) {
if new_blocks.has_more_blocks_to_import {
return;
}
let mut last_import = self.last_import.lock();
let client = &self.target.client;
let importing = self.target.is_major_importing();
let ripe = Instant::now() > *last_import + Duration::from_secs(1) && !importing;
let txs_imported = new_blocks
.imported
.iter()
.take(
new_blocks
.imported
.len()
.saturating_sub(if ripe { 1 } else { 0 }),
)
.filter_map(|h| client.block(BlockId::Hash(*h)))
.map(|b| b.transactions_count())
.sum();
if ripe {
if let Some(block) = new_blocks
.imported
.last()
.and_then(|h| client.block(BlockId::Hash(*h)))
{
let header_view = block.header_view();
let size = block.rlp().as_raw().len();
let (skipped, skipped_txs) = (
self.skipped.load(AtomicOrdering::Relaxed) + new_blocks.imported.len() - 1,
self.skipped_txs.load(AtomicOrdering::Relaxed) + txs_imported,
);
info!(target: "import", "Imported {} {} ({} txs, {} Mgas, {} ms, {} KiB){}",
Colour::White.bold().paint(format!("#{}", header_view.number())),
Colour::White.bold().paint(format!("{}", header_view.hash())),
Colour::Yellow.bold().paint(format!("{}", block.transactions_count())),
Colour::Yellow.bold().paint(format!("{:.2}", header_view.gas_used().low_u64() as f32 / 1000000f32)),
Colour::Purple.bold().paint(format!("{}", new_blocks.duration.as_milliseconds())),
Colour::Blue.bold().paint(format!("{:.2}", size as f32 / 1024f32)),
if skipped > 0 {
format!(" + another {} block(s) containing {} tx(s)",
Colour::Red.bold().paint(format!("{}", skipped)),
Colour::Red.bold().paint(format!("{}", skipped_txs))
)
} else {
String::new()
}
);
self.skipped.store(0, AtomicOrdering::Relaxed);
self.skipped_txs.store(0, AtomicOrdering::Relaxed);
*last_import = Instant::now();
}
} else {
self.skipped
.fetch_add(new_blocks.imported.len(), AtomicOrdering::Relaxed);
self.skipped_txs
.fetch_add(txs_imported, AtomicOrdering::Relaxed);
}
}
}
const INFO_TIMER: TimerToken = 0;
impl<T: InformantData> IoHandler<ClientIoMessage> for Informant<T> {
fn initialize(&self, io: &IoContext<ClientIoMessage>) {
io.register_timer(INFO_TIMER, Duration::from_secs(5))
.expect("Error registering timer");
}
fn timeout(&self, _io: &IoContext<ClientIoMessage>, timer: TimerToken) {
if timer == INFO_TIMER && !self.in_shutdown.load(AtomicOrdering::SeqCst) {
self.tick();
}
}
}

240
bin/oe/lib.rs Normal file
View File

@ -0,0 +1,240 @@
// 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/>.
//! Ethcore client application.
#![warn(missing_docs)]
extern crate ansi_term;
extern crate docopt;
#[macro_use]
extern crate clap;
extern crate atty;
extern crate dir;
extern crate futures;
extern crate jsonrpc_core;
extern crate num_cpus;
extern crate number_prefix;
extern crate parking_lot;
extern crate regex;
extern crate rlp;
extern crate rpassword;
extern crate rustc_hex;
extern crate semver;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate blooms_db;
extern crate cli_signer;
extern crate common_types as types;
extern crate ethcore;
extern crate ethcore_call_contract as call_contract;
extern crate ethcore_db;
extern crate ethcore_io as io;
extern crate ethcore_logger;
extern crate ethcore_miner as miner;
extern crate ethcore_network as network;
extern crate ethcore_service;
extern crate ethcore_sync as sync;
extern crate ethereum_types;
extern crate ethkey;
extern crate ethstore;
extern crate fetch;
extern crate hyper;
extern crate journaldb;
extern crate keccak_hash as hash;
extern crate kvdb;
extern crate node_filter;
extern crate parity_bytes as bytes;
extern crate parity_crypto as crypto;
extern crate parity_local_store as local_store;
extern crate parity_path as path;
extern crate parity_rpc;
extern crate parity_runtime;
extern crate parity_version;
extern crate prometheus;
extern crate stats;
#[macro_use]
extern crate log as rlog;
#[cfg(feature = "ethcore-accounts")]
extern crate ethcore_accounts as accounts;
#[cfg(feature = "secretstore")]
extern crate ethcore_secretstore;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;
#[cfg(test)]
extern crate tempdir;
#[cfg(test)]
#[macro_use]
extern crate lazy_static;
mod account;
mod account_utils;
mod blockchain;
mod cache;
mod cli;
mod configuration;
mod db;
mod helpers;
mod informant;
mod metrics;
mod modules;
mod params;
mod presale;
mod rpc;
mod rpc_apis;
mod run;
mod secretstore;
mod signer;
mod snapshot;
mod upgrade;
mod user_defaults;
use std::{fs::File, io::BufReader, sync::Arc};
use crate::{
cli::Args,
configuration::{Cmd, Execute},
hash::keccak_buffer,
};
#[cfg(feature = "memory_profiling")]
use std::alloc::System;
pub use self::{configuration::Configuration, run::RunningClient};
pub use ethcore_logger::{setup_log, Config as LoggerConfig, RotatingLogger};
pub use parity_rpc::PubSubSession;
#[cfg(feature = "memory_profiling")]
#[global_allocator]
static A: System = System;
fn print_hash_of(maybe_file: Option<String>) -> Result<String, String> {
if let Some(file) = maybe_file {
let mut f =
BufReader::new(File::open(&file).map_err(|_| "Unable to open file".to_owned())?);
let hash = keccak_buffer(&mut f).map_err(|_| "Unable to read from file".to_owned())?;
Ok(format!("{:x}", hash))
} else {
Err("Streaming from standard input not yet supported. Specify a file.".to_owned())
}
}
#[cfg(feature = "deadlock_detection")]
fn run_deadlock_detection_thread() {
use ansi_term::Style;
use parking_lot::deadlock;
use std::{thread, time::Duration};
info!("Starting deadlock detection thread.");
// Create a background thread which checks for deadlocks every 10s
thread::spawn(move || loop {
thread::sleep(Duration::from_secs(10));
let deadlocks = deadlock::check_deadlock();
if deadlocks.is_empty() {
continue;
}
warn!(
"{} {} detected",
deadlocks.len(),
Style::new().bold().paint("deadlock(s)")
);
for (i, threads) in deadlocks.iter().enumerate() {
warn!("{} #{}", Style::new().bold().paint("Deadlock"), i);
for t in threads {
warn!("Thread Id {:#?}", t.thread_id());
warn!("{:#?}", t.backtrace());
}
}
});
}
/// Action that OpenEthereum performed when running `start`.
pub enum ExecutionAction {
/// The execution didn't require starting a node, and thus has finished.
/// Contains the string to print on stdout, if any.
Instant(Option<String>),
/// The client has started running and must be shut down manually by calling `shutdown`.
///
/// If you don't call `shutdown()`, execution will continue in the background.
Running(RunningClient),
}
fn execute(command: Execute, logger: Arc<RotatingLogger>) -> Result<ExecutionAction, String> {
#[cfg(feature = "deadlock_detection")]
run_deadlock_detection_thread();
match command.cmd {
Cmd::Run(run_cmd) => {
let outcome = run::execute(run_cmd, logger)?;
Ok(ExecutionAction::Running(outcome))
}
Cmd::Version => Ok(ExecutionAction::Instant(Some(Args::print_version()))),
Cmd::Hash(maybe_file) => {
print_hash_of(maybe_file).map(|s| ExecutionAction::Instant(Some(s)))
}
Cmd::Account(account_cmd) => {
account::execute(account_cmd).map(|s| ExecutionAction::Instant(Some(s)))
}
Cmd::ImportPresaleWallet(presale_cmd) => {
presale::execute(presale_cmd).map(|s| ExecutionAction::Instant(Some(s)))
}
Cmd::Blockchain(blockchain_cmd) => {
blockchain::execute(blockchain_cmd).map(|_| ExecutionAction::Instant(None))
}
Cmd::SignerToken(ws_conf, logger_config) => {
signer::execute(ws_conf, logger_config).map(|s| ExecutionAction::Instant(Some(s)))
}
Cmd::SignerSign {
id,
pwfile,
port,
authfile,
} => cli_signer::signer_sign(id, pwfile, port, authfile)
.map(|s| ExecutionAction::Instant(Some(s))),
Cmd::SignerList { port, authfile } => {
cli_signer::signer_list(port, authfile).map(|s| ExecutionAction::Instant(Some(s)))
}
Cmd::SignerReject { id, port, authfile } => {
cli_signer::signer_reject(id, port, authfile).map(|s| ExecutionAction::Instant(Some(s)))
}
Cmd::Snapshot(snapshot_cmd) => {
snapshot::execute(snapshot_cmd).map(|s| ExecutionAction::Instant(Some(s)))
}
}
}
/// Starts the OpenEthereum client.
///
/// The first parameter is the command line arguments that you would pass when running the openethereum
/// binary.
///
/// On error, returns what to print on stderr.
// FIXME: totally independent logging capability, see https://github.com/openethereum/openethereum/issues/10252
pub fn start(conf: Configuration, logger: Arc<RotatingLogger>) -> Result<ExecutionAction, String> {
execute(conf.into_command()?, logger)
}

View File

@ -1,5 +1,5 @@
[package]
description = "Log implementation for Parity"
description = "Parity Ethereum Logger Implementation"
name = "ethcore-logger"
version = "1.12.0"
license = "GPL-3.0"
@ -10,8 +10,8 @@ log = "0.4"
env_logger = "0.5"
atty = "0.2"
lazy_static = "1.0"
regex = "0.2"
regex = "1.0"
time = "0.1"
parking_lot = "0.6"
parking_lot = "0.11.1"
arrayvec = "0.4"
ansi_term = "0.10"

191
bin/oe/logger/src/lib.rs Normal file
View File

@ -0,0 +1,191 @@
// 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/>.
//! Logger for OpenEthereum executables
extern crate ansi_term;
extern crate arrayvec;
extern crate atty;
extern crate env_logger;
extern crate log as rlog;
extern crate parking_lot;
extern crate regex;
extern crate time;
#[macro_use]
extern crate lazy_static;
mod rotating;
use ansi_term::Colour;
use env_logger::{Builder as LogBuilder, Formatter};
use parking_lot::Mutex;
use regex::Regex;
use std::{
env, fs,
io::Write,
sync::{Arc, Weak},
thread,
};
pub use rotating::{init_log, RotatingLogger};
#[derive(Debug, PartialEq, Clone)]
pub struct Config {
pub mode: Option<String>,
pub color: bool,
pub file: Option<String>,
}
impl Default for Config {
fn default() -> Self {
Config {
mode: None,
color: !cfg!(windows),
file: None,
}
}
}
lazy_static! {
static ref ROTATING_LOGGER: Mutex<Weak<RotatingLogger>> = Mutex::new(Default::default());
}
/// Sets up the logger
pub fn setup_log(config: &Config) -> Result<Arc<RotatingLogger>, String> {
use rlog::*;
let mut levels = String::new();
let mut builder = LogBuilder::new();
// Disable info logging by default for some modules:
builder.filter(Some("ws"), LevelFilter::Warn);
builder.filter(Some("hyper"), LevelFilter::Warn);
builder.filter(Some("rustls"), LevelFilter::Error);
// Enable info for others.
builder.filter(None, LevelFilter::Info);
if let Ok(lvl) = env::var("RUST_LOG") {
levels.push_str(&lvl);
levels.push_str(",");
builder.parse(&lvl);
}
if let Some(ref s) = config.mode {
levels.push_str(s);
builder.parse(s);
}
let isatty = atty::is(atty::Stream::Stderr);
let enable_color = config.color && isatty;
let logs = Arc::new(RotatingLogger::new(levels));
let logger = logs.clone();
let mut open_options = fs::OpenOptions::new();
let maybe_file = match config.file.as_ref() {
Some(f) => Some(
open_options
.append(true)
.create(true)
.open(f)
.map_err(|e| format!("Cannot write to log file given: {}, {}", f, e))?,
),
None => None,
};
let format = move |buf: &mut Formatter, record: &Record| {
let timestamp = time::strftime("%Y-%m-%d %H:%M:%S %Z", &time::now()).unwrap();
let with_color = if max_level() <= LevelFilter::Info {
format!(
"{} {}",
Colour::Black.bold().paint(timestamp),
record.args()
)
} else {
let name = thread::current().name().map_or_else(Default::default, |x| {
format!("{}", Colour::Blue.bold().paint(x))
});
format!(
"{} {} {} {} {}",
Colour::Black.bold().paint(timestamp),
name,
record.level(),
record.target(),
record.args()
)
};
let removed_color = kill_color(with_color.as_ref());
let ret = match enable_color {
true => with_color,
false => removed_color.clone(),
};
if let Some(mut file) = maybe_file.as_ref() {
// ignore errors - there's nothing we can do
let _ = file.write_all(removed_color.as_bytes());
let _ = file.write_all(b"\n");
}
logger.append(removed_color);
if !isatty && record.level() <= Level::Info && atty::is(atty::Stream::Stdout) {
// duplicate INFO/WARN output to console
println!("{}", ret);
}
writeln!(buf, "{}", ret)
};
builder.format(format);
builder
.try_init()
.and_then(|_| {
*ROTATING_LOGGER.lock() = Arc::downgrade(&logs);
Ok(logs)
})
// couldn't create new logger - try to fall back on previous logger.
.or_else(|err| {
ROTATING_LOGGER
.lock()
.upgrade()
.ok_or_else(|| format!("{:?}", err))
})
}
fn kill_color(s: &str) -> String {
lazy_static! {
static ref RE: Regex = Regex::new("\x1b\\[[^m]+m").unwrap();
}
RE.replace_all(s, "").to_string()
}
#[test]
fn should_remove_colour() {
let before = "test";
let after = kill_color(&Colour::Red.bold().paint(before));
assert_eq!(after, "test");
}
#[test]
fn should_remove_multiple_colour() {
let t = format!(
"{} {}",
Colour::Red.bold().paint("test"),
Colour::White.normal().paint("again")
);
let after = kill_color(&t);
assert_eq!(after, "test again");
}

View File

@ -0,0 +1,121 @@
// 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/>.
//! Common log helper functions
use arrayvec::ArrayVec;
use env_logger::Builder as LogBuilder;
use rlog::LevelFilter;
use std::env;
use parking_lot::{RwLock, RwLockReadGuard};
lazy_static! {
static ref LOG_DUMMY: () = {
let mut builder = LogBuilder::new();
builder.filter(None, LevelFilter::Info);
if let Ok(log) = env::var("RUST_LOG") {
builder.parse(&log);
}
if !builder.try_init().is_ok() {
println!("logger initialization failed!");
}
};
}
/// Intialize log with default settings
pub fn init_log() {
*LOG_DUMMY
}
const LOG_SIZE: usize = 128;
/// Logger implementation that keeps up to `LOG_SIZE` log elements.
pub struct RotatingLogger {
/// Defined logger levels
levels: String,
/// Logs array. Latest log is always at index 0
logs: RwLock<ArrayVec<[String; LOG_SIZE]>>,
}
impl RotatingLogger {
/// Creates new `RotatingLogger` with given levels.
/// It does not enforce levels - it's just read only.
pub fn new(levels: String) -> Self {
RotatingLogger {
levels: levels,
logs: RwLock::new(ArrayVec::<[_; LOG_SIZE]>::new()),
}
}
/// Append new log entry
pub fn append(&self, log: String) {
let mut logs = self.logs.write();
if logs.is_full() {
logs.pop();
}
logs.insert(0, log);
}
/// Return levels
pub fn levels(&self) -> &str {
&self.levels
}
/// Return logs
pub fn logs(&self) -> RwLockReadGuard<ArrayVec<[String; LOG_SIZE]>> {
self.logs.read()
}
}
#[cfg(test)]
mod test {
use super::RotatingLogger;
fn logger() -> RotatingLogger {
RotatingLogger::new("test".to_owned())
}
#[test]
fn should_return_log_levels() {
// given
let logger = logger();
// when
let levels = logger.levels();
// then
assert_eq!(levels, "test");
}
#[test]
fn should_return_latest_logs() {
// given
let logger = logger();
// when
logger.append("a".to_owned());
logger.append("b".to_owned());
// then
let logs = logger.logs();
assert_eq!(logs[0], "b".to_owned());
assert_eq!(logs[1], "a".to_owned());
assert_eq!(logs.len(), 2);
}
}

180
bin/oe/main.rs Normal file
View File

@ -0,0 +1,180 @@
// 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/>.
//! Ethcore client application.
#![warn(missing_docs)]
extern crate ctrlc;
extern crate dir;
extern crate fdlimit;
#[macro_use]
extern crate log;
extern crate ansi_term;
extern crate openethereum;
extern crate panic_hook;
extern crate parity_daemonize;
extern crate parking_lot;
extern crate ethcore_logger;
#[cfg(windows)]
extern crate winapi;
use std::{
io::Write,
process,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
use ansi_term::Colour;
use ctrlc::CtrlC;
use ethcore_logger::setup_log;
use fdlimit::raise_fd_limit;
use openethereum::{start, ExecutionAction};
use parity_daemonize::AsHandle;
use parking_lot::{Condvar, Mutex};
#[derive(Debug)]
/// Status used to exit or restart the program.
struct ExitStatus {
/// Whether the program panicked.
panicking: bool,
/// Whether the program should exit.
should_exit: bool,
}
fn main() -> Result<(), i32> {
let conf = {
let args = std::env::args().collect::<Vec<_>>();
openethereum::Configuration::parse_cli(&args).unwrap_or_else(|e| e.exit())
};
let logger = setup_log(&conf.logger_config()).unwrap_or_else(|e| {
eprintln!("{}", e);
process::exit(2)
});
// FIXME: `pid_file` shouldn't need to cloned here
// see: `https://github.com/paritytech/parity-daemonize/pull/13` for more info
let handle = if let Some(pid) = conf.args.arg_daemon_pid_file.clone() {
info!(
"{}",
Colour::Blue.paint("starting in daemon mode").to_string()
);
let _ = std::io::stdout().flush();
match parity_daemonize::daemonize(pid) {
Ok(h) => Some(h),
Err(e) => {
error!("{}", Colour::Red.paint(format!("{}", e)));
return Err(1);
}
}
} else {
None
};
// increase max number of open files
raise_fd_limit();
let exit = Arc::new((
Mutex::new(ExitStatus {
panicking: false,
should_exit: false,
}),
Condvar::new(),
));
// Double panic can happen. So when we lock `ExitStatus` after the main thread is notified, it cannot be locked
// again.
let exiting = Arc::new(AtomicBool::new(false));
trace!(target: "mode", "Not hypervised: not setting exit handlers.");
let exec = start(conf, logger);
match exec {
Ok(result) => match result {
ExecutionAction::Instant(output) => {
if let Some(s) = output {
println!("{}", s);
}
}
ExecutionAction::Running(client) => {
panic_hook::set_with({
let e = exit.clone();
let exiting = exiting.clone();
move |panic_msg| {
warn!("Panic occured, see stderr for details");
eprintln!("{}", panic_msg);
if !exiting.swap(true, Ordering::SeqCst) {
*e.0.lock() = ExitStatus {
panicking: true,
should_exit: true,
};
e.1.notify_all();
}
}
});
CtrlC::set_handler({
let e = exit.clone();
let exiting = exiting.clone();
move || {
if !exiting.swap(true, Ordering::SeqCst) {
*e.0.lock() = ExitStatus {
panicking: false,
should_exit: true,
};
e.1.notify_all();
}
}
});
// so the client has started successfully
// if this is a daemon, detach from the parent process
if let Some(mut handle) = handle {
handle.detach()
}
// Wait for signal
let mut lock = exit.0.lock();
if !lock.should_exit {
let _ = exit.1.wait(&mut lock);
}
client.shutdown();
if lock.panicking {
return Err(1);
}
}
},
Err(err) => {
// error occured during start up
// if this is a daemon, detach from the parent process
if let Some(mut handle) = handle {
handle.detach_with_msg(format!("{}", Colour::Red.paint(&err)))
}
eprintln!("{}", err);
return Err(1);
}
};
Ok(())
}

117
bin/oe/metrics.rs Normal file
View File

@ -0,0 +1,117 @@
use std::{sync::Arc, time::Instant};
use crate::{futures::Future, rpc, rpc_apis};
use parking_lot::Mutex;
use hyper::{service::service_fn_ok, Body, Method, Request, Response, Server, StatusCode};
use stats::{
prometheus::{self, Encoder},
PrometheusMetrics, PrometheusRegistry,
};
#[derive(Debug, Clone, PartialEq)]
pub struct MetricsConfiguration {
/// Are metrics enabled (default is false)?
pub enabled: bool,
/// Prefix
pub prefix: String,
/// The IP of the network interface used (default is 127.0.0.1).
pub interface: String,
/// The network port (default is 3000).
pub port: u16,
}
impl Default for MetricsConfiguration {
fn default() -> Self {
MetricsConfiguration {
enabled: false,
prefix: "".into(),
interface: "127.0.0.1".into(),
port: 3000,
}
}
}
struct State {
rpc_apis: Arc<rpc_apis::FullDependencies>,
}
fn handle_request(
req: Request<Body>,
conf: Arc<MetricsConfiguration>,
state: Arc<Mutex<State>>,
) -> Response<Body> {
let (parts, _body) = req.into_parts();
match (parts.method, parts.uri.path()) {
(Method::GET, "/metrics") => {
let start = Instant::now();
let mut reg = PrometheusRegistry::new(conf.prefix.clone());
let state = state.lock();
state.rpc_apis.client.prometheus_metrics(&mut reg);
state.rpc_apis.sync.prometheus_metrics(&mut reg);
let elapsed = start.elapsed();
reg.register_gauge(
"metrics_time",
"Time to perform rpc metrics",
elapsed.as_millis() as i64,
);
let mut buffer = vec![];
let encoder = prometheus::TextEncoder::new();
let metric_families = reg.registry().gather();
encoder
.encode(&metric_families, &mut buffer)
.expect("all source of metrics are static; qed");
let text = String::from_utf8(buffer).expect("metrics encoding is ASCII; qed");
Response::new(Body::from(text))
}
(_, _) => {
let mut res = Response::new(Body::from("not found"));
*res.status_mut() = StatusCode::NOT_FOUND;
res
}
}
}
/// Start the prometheus metrics server accessible via GET <host>:<port>/metrics
pub fn start_prometheus_metrics(
conf: &MetricsConfiguration,
deps: &rpc::Dependencies<rpc_apis::FullDependencies>,
) -> Result<(), String> {
if !conf.enabled {
return Ok(());
}
let addr = format!("{}:{}", conf.interface, conf.port);
let addr = addr
.parse()
.map_err(|err| format!("Failed to parse address '{}': {}", addr, err))?;
let state = State {
rpc_apis: deps.apis.clone(),
};
let state = Arc::new(Mutex::new(state));
let conf = Arc::new(conf.to_owned());
let server = Server::bind(&addr)
.serve(move || {
// This is the `Service` that will handle the connection.
// `service_fn_ok` is a helper to convert a function that
// returns a Response into a `Service`.
let state = state.clone();
let conf = conf.clone();
service_fn_ok(move |req: Request<Body>| {
handle_request(req, conf.clone(), state.clone())
})
})
.map_err(|e| eprintln!("server error: {}", e));
info!("Started prometeus metrics at http://{}/metrics", addr);
deps.executor.spawn(server);
Ok(())
}

63
bin/oe/modules.rs Normal file
View File

@ -0,0 +1,63 @@
// 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::sync::{mpsc, Arc};
use crate::{
sync::{self, ConnectionFilter, NetworkConfiguration, Params, SyncConfig},
types::BlockNumber,
};
use ethcore::{client::BlockChainClient, snapshot::SnapshotService};
use std::collections::BTreeSet;
pub use crate::sync::{EthSync, ManageNetwork, SyncProvider};
pub use ethcore::client::ChainNotify;
use ethcore_logger::Config as LogConfig;
pub type SyncModules = (
Arc<dyn SyncProvider>,
Arc<dyn ManageNetwork>,
Arc<dyn ChainNotify>,
mpsc::Sender<sync::PriorityTask>,
);
pub fn sync(
config: SyncConfig,
network_config: NetworkConfiguration,
chain: Arc<dyn BlockChainClient>,
forks: BTreeSet<BlockNumber>,
snapshot_service: Arc<dyn SnapshotService>,
_log_settings: &LogConfig,
connection_filter: Option<Arc<dyn ConnectionFilter>>,
) -> Result<SyncModules, sync::Error> {
let eth_sync = EthSync::new(
Params {
config,
chain,
forks,
snapshot_service,
network_config,
},
connection_filter,
)?;
Ok((
eth_sync.clone() as Arc<dyn SyncProvider>,
eth_sync.clone() as Arc<dyn ManageNetwork>,
eth_sync.clone() as Arc<dyn ChainNotify>,
eth_sync.priority_tasks(),
))
}

542
bin/oe/params.rs Normal file
View File

@ -0,0 +1,542 @@
// 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::{collections::HashSet, fmt, fs, num::NonZeroU32, str, time::Duration};
use crate::{
miner::{
gas_price_calibrator::{GasPriceCalibrator, GasPriceCalibratorOptions},
gas_pricer::GasPricer,
},
user_defaults::UserDefaults,
};
use ethcore::{
client::Mode,
ethereum,
spec::{Spec, SpecParams},
};
use ethereum_types::{Address, U256};
use fetch::Client as FetchClient;
use journaldb::Algorithm;
use parity_runtime::Executor;
use parity_version::version_data;
use crate::configuration;
#[derive(Debug, PartialEq)]
pub enum SpecType {
Foundation,
Poanet,
Xdai,
Volta,
Ewc,
Musicoin,
Ellaism,
Mix,
Callisto,
Morden,
Ropsten,
Kovan,
Rinkeby,
Goerli,
Sokol,
Yolo3,
Dev,
Custom(String),
}
impl Default for SpecType {
fn default() -> Self {
SpecType::Foundation
}
}
impl str::FromStr for SpecType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let spec = match s {
"eth" | "ethereum" | "foundation" | "mainnet" => SpecType::Foundation,
"poanet" | "poacore" => SpecType::Poanet,
"xdai" => SpecType::Xdai,
"volta" => SpecType::Volta,
"ewc" | "energyweb" => SpecType::Ewc,
"musicoin" => SpecType::Musicoin,
"ellaism" => SpecType::Ellaism,
"mix" => SpecType::Mix,
"callisto" => SpecType::Callisto,
"morden" => SpecType::Morden,
"ropsten" => SpecType::Ropsten,
"kovan" => SpecType::Kovan,
"rinkeby" => SpecType::Rinkeby,
"goerli" | "görli" | "testnet" => SpecType::Goerli,
"sokol" | "poasokol" => SpecType::Sokol,
"yolo3" => SpecType::Yolo3,
"dev" => SpecType::Dev,
other => SpecType::Custom(other.into()),
};
Ok(spec)
}
}
impl fmt::Display for SpecType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
SpecType::Foundation => "foundation",
SpecType::Poanet => "poanet",
SpecType::Xdai => "xdai",
SpecType::Volta => "volta",
SpecType::Ewc => "energyweb",
SpecType::Musicoin => "musicoin",
SpecType::Ellaism => "ellaism",
SpecType::Mix => "mix",
SpecType::Callisto => "callisto",
SpecType::Morden => "morden",
SpecType::Ropsten => "ropsten",
SpecType::Kovan => "kovan",
SpecType::Rinkeby => "rinkeby",
SpecType::Goerli => "goerli",
SpecType::Sokol => "sokol",
SpecType::Yolo3 => "yolo3",
SpecType::Dev => "dev",
SpecType::Custom(ref custom) => custom,
})
}
}
impl SpecType {
pub fn spec<'a, T: Into<SpecParams<'a>>>(&self, params: T) -> Result<Spec, String> {
let params = params.into();
match *self {
SpecType::Foundation => Ok(ethereum::new_foundation(params)),
SpecType::Poanet => Ok(ethereum::new_poanet(params)),
SpecType::Xdai => Ok(ethereum::new_xdai(params)),
SpecType::Volta => Ok(ethereum::new_volta(params)),
SpecType::Ewc => Ok(ethereum::new_ewc(params)),
SpecType::Musicoin => Ok(ethereum::new_musicoin(params)),
SpecType::Ellaism => Ok(ethereum::new_ellaism(params)),
SpecType::Mix => Ok(ethereum::new_mix(params)),
SpecType::Callisto => Ok(ethereum::new_callisto(params)),
SpecType::Morden => Ok(ethereum::new_morden(params)),
SpecType::Ropsten => Ok(ethereum::new_ropsten(params)),
SpecType::Kovan => Ok(ethereum::new_kovan(params)),
SpecType::Rinkeby => Ok(ethereum::new_rinkeby(params)),
SpecType::Goerli => Ok(ethereum::new_goerli(params)),
SpecType::Sokol => Ok(ethereum::new_sokol(params)),
SpecType::Yolo3 => Ok(ethereum::new_yolo3(params)),
SpecType::Dev => Ok(Spec::new_instant()),
SpecType::Custom(ref filename) => {
let file = fs::File::open(filename).map_err(|e| {
format!("Could not load specification file at {}: {}", filename, e)
})?;
Spec::load(params, file)
}
}
}
pub fn legacy_fork_name(&self) -> Option<String> {
match *self {
SpecType::Musicoin => Some("musicoin".to_owned()),
_ => None,
}
}
}
#[derive(Debug, PartialEq)]
pub enum Pruning {
Specific(Algorithm),
Auto,
}
impl Default for Pruning {
fn default() -> Self {
Pruning::Auto
}
}
impl str::FromStr for Pruning {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"auto" => Ok(Pruning::Auto),
other => other.parse().map(Pruning::Specific),
}
}
}
impl Pruning {
pub fn to_algorithm(&self, user_defaults: &UserDefaults) -> Algorithm {
match *self {
Pruning::Specific(algo) => algo,
Pruning::Auto => user_defaults.pruning,
}
}
}
#[derive(Debug, PartialEq)]
pub struct ResealPolicy {
pub own: bool,
pub external: bool,
}
impl Default for ResealPolicy {
fn default() -> Self {
ResealPolicy {
own: true,
external: true,
}
}
}
impl str::FromStr for ResealPolicy {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (own, external) = match s {
"none" => (false, false),
"own" => (true, false),
"ext" => (false, true),
"all" => (true, true),
x => return Err(format!("Invalid reseal value: {}", x)),
};
let reseal = ResealPolicy {
own: own,
external: external,
};
Ok(reseal)
}
}
#[derive(Debug, PartialEq)]
pub struct AccountsConfig {
pub iterations: NonZeroU32,
pub refresh_time: u64,
pub testnet: bool,
pub password_files: Vec<String>,
pub unlocked_accounts: Vec<Address>,
pub enable_fast_unlock: bool,
}
impl Default for AccountsConfig {
fn default() -> Self {
AccountsConfig {
iterations: NonZeroU32::new(10240).expect("10240 > 0; qed"),
refresh_time: 5,
testnet: false,
password_files: Vec::new(),
unlocked_accounts: Vec::new(),
enable_fast_unlock: false,
}
}
}
#[derive(Debug, PartialEq)]
pub enum GasPricerConfig {
Fixed(U256),
Calibrated {
usd_per_tx: f32,
recalibration_period: Duration,
api_endpoint: String,
},
}
impl Default for GasPricerConfig {
fn default() -> Self {
GasPricerConfig::Calibrated {
usd_per_tx: 0.0001f32,
recalibration_period: Duration::from_secs(3600),
api_endpoint: configuration::ETHERSCAN_ETH_PRICE_ENDPOINT.to_string(),
}
}
}
impl GasPricerConfig {
pub fn to_gas_pricer(&self, fetch: FetchClient, p: Executor) -> GasPricer {
match *self {
GasPricerConfig::Fixed(u) => GasPricer::Fixed(u),
GasPricerConfig::Calibrated {
usd_per_tx,
recalibration_period,
ref api_endpoint,
} => GasPricer::new_calibrated(GasPriceCalibrator::new(
GasPriceCalibratorOptions {
usd_per_tx: usd_per_tx,
recalibration_period: recalibration_period,
},
fetch,
p,
api_endpoint.clone(),
)),
}
}
}
#[derive(Debug, PartialEq)]
pub struct MinerExtras {
pub author: Address,
pub engine_signer: Address,
pub extra_data: Vec<u8>,
pub gas_range_target: (U256, U256),
pub work_notify: Vec<String>,
pub local_accounts: HashSet<Address>,
}
impl Default for MinerExtras {
fn default() -> Self {
MinerExtras {
author: Default::default(),
engine_signer: Default::default(),
extra_data: version_data(),
gas_range_target: (8_000_000.into(), 10_000_000.into()),
work_notify: Default::default(),
local_accounts: Default::default(),
}
}
}
/// 3-value enum.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Switch {
/// True.
On,
/// False.
Off,
/// Auto.
Auto,
}
impl Default for Switch {
fn default() -> Self {
Switch::Auto
}
}
impl str::FromStr for Switch {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"on" => Ok(Switch::On),
"off" => Ok(Switch::Off),
"auto" => Ok(Switch::Auto),
other => Err(format!("Invalid switch value: {}", other)),
}
}
}
pub fn tracing_switch_to_bool(
switch: Switch,
user_defaults: &UserDefaults,
) -> Result<bool, String> {
match (user_defaults.is_first_launch, switch, user_defaults.tracing) {
(false, Switch::On, false) => Err("TraceDB resync required".into()),
(_, Switch::On, _) => Ok(true),
(_, Switch::Off, _) => Ok(false),
(_, Switch::Auto, def) => Ok(def),
}
}
pub fn fatdb_switch_to_bool(
switch: Switch,
user_defaults: &UserDefaults,
_algorithm: Algorithm,
) -> Result<bool, String> {
let result = match (user_defaults.is_first_launch, switch, user_defaults.fat_db) {
(false, Switch::On, false) => Err("FatDB resync required".into()),
(_, Switch::On, _) => Ok(true),
(_, Switch::Off, _) => Ok(false),
(_, Switch::Auto, def) => Ok(def),
};
result
}
pub fn mode_switch_to_bool(
switch: Option<Mode>,
user_defaults: &UserDefaults,
) -> Result<Mode, String> {
Ok(switch.unwrap_or(user_defaults.mode().clone()))
}
#[cfg(test)]
mod tests {
use super::{tracing_switch_to_bool, Pruning, ResealPolicy, SpecType, Switch};
use crate::user_defaults::UserDefaults;
use journaldb::Algorithm;
#[test]
fn test_spec_type_parsing() {
assert_eq!(SpecType::Foundation, "eth".parse().unwrap());
assert_eq!(SpecType::Foundation, "ethereum".parse().unwrap());
assert_eq!(SpecType::Foundation, "foundation".parse().unwrap());
assert_eq!(SpecType::Foundation, "mainnet".parse().unwrap());
assert_eq!(SpecType::Poanet, "poanet".parse().unwrap());
assert_eq!(SpecType::Poanet, "poacore".parse().unwrap());
assert_eq!(SpecType::Xdai, "xdai".parse().unwrap());
assert_eq!(SpecType::Volta, "volta".parse().unwrap());
assert_eq!(SpecType::Ewc, "ewc".parse().unwrap());
assert_eq!(SpecType::Ewc, "energyweb".parse().unwrap());
assert_eq!(SpecType::Musicoin, "musicoin".parse().unwrap());
assert_eq!(SpecType::Ellaism, "ellaism".parse().unwrap());
assert_eq!(SpecType::Mix, "mix".parse().unwrap());
assert_eq!(SpecType::Callisto, "callisto".parse().unwrap());
assert_eq!(SpecType::Morden, "morden".parse().unwrap());
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
assert_eq!(SpecType::Kovan, "kovan".parse().unwrap());
assert_eq!(SpecType::Rinkeby, "rinkeby".parse().unwrap());
assert_eq!(SpecType::Goerli, "goerli".parse().unwrap());
assert_eq!(SpecType::Goerli, "görli".parse().unwrap());
assert_eq!(SpecType::Goerli, "testnet".parse().unwrap());
assert_eq!(SpecType::Sokol, "sokol".parse().unwrap());
assert_eq!(SpecType::Sokol, "poasokol".parse().unwrap());
}
#[test]
fn test_spec_type_default() {
assert_eq!(SpecType::Foundation, SpecType::default());
}
#[test]
fn test_spec_type_display() {
assert_eq!(format!("{}", SpecType::Foundation), "foundation");
assert_eq!(format!("{}", SpecType::Poanet), "poanet");
assert_eq!(format!("{}", SpecType::Xdai), "xdai");
assert_eq!(format!("{}", SpecType::Volta), "volta");
assert_eq!(format!("{}", SpecType::Ewc), "energyweb");
assert_eq!(format!("{}", SpecType::Musicoin), "musicoin");
assert_eq!(format!("{}", SpecType::Ellaism), "ellaism");
assert_eq!(format!("{}", SpecType::Mix), "mix");
assert_eq!(format!("{}", SpecType::Callisto), "callisto");
assert_eq!(format!("{}", SpecType::Morden), "morden");
assert_eq!(format!("{}", SpecType::Ropsten), "ropsten");
assert_eq!(format!("{}", SpecType::Kovan), "kovan");
assert_eq!(format!("{}", SpecType::Rinkeby), "rinkeby");
assert_eq!(format!("{}", SpecType::Goerli), "goerli");
assert_eq!(format!("{}", SpecType::Sokol), "sokol");
assert_eq!(format!("{}", SpecType::Dev), "dev");
assert_eq!(format!("{}", SpecType::Custom("foo/bar".into())), "foo/bar");
}
#[test]
fn test_pruning_parsing() {
assert_eq!(Pruning::Auto, "auto".parse().unwrap());
assert_eq!(
Pruning::Specific(Algorithm::Archive),
"archive".parse().unwrap()
);
assert_eq!(
Pruning::Specific(Algorithm::EarlyMerge),
"light".parse().unwrap()
);
assert_eq!(
Pruning::Specific(Algorithm::OverlayRecent),
"fast".parse().unwrap()
);
assert_eq!(
Pruning::Specific(Algorithm::RefCounted),
"basic".parse().unwrap()
);
}
#[test]
fn test_pruning_default() {
assert_eq!(Pruning::Auto, Pruning::default());
}
#[test]
fn test_reseal_policy_parsing() {
let none = ResealPolicy {
own: false,
external: false,
};
let own = ResealPolicy {
own: true,
external: false,
};
let ext = ResealPolicy {
own: false,
external: true,
};
let all = ResealPolicy {
own: true,
external: true,
};
assert_eq!(none, "none".parse().unwrap());
assert_eq!(own, "own".parse().unwrap());
assert_eq!(ext, "ext".parse().unwrap());
assert_eq!(all, "all".parse().unwrap());
}
#[test]
fn test_reseal_policy_default() {
let all = ResealPolicy {
own: true,
external: true,
};
assert_eq!(all, ResealPolicy::default());
}
#[test]
fn test_switch_parsing() {
assert_eq!(Switch::On, "on".parse().unwrap());
assert_eq!(Switch::Off, "off".parse().unwrap());
assert_eq!(Switch::Auto, "auto".parse().unwrap());
}
#[test]
fn test_switch_default() {
assert_eq!(Switch::default(), Switch::Auto);
}
fn user_defaults_with_tracing(first_launch: bool, tracing: bool) -> UserDefaults {
let mut ud = UserDefaults::default();
ud.is_first_launch = first_launch;
ud.tracing = tracing;
ud
}
#[test]
fn test_switch_to_bool() {
assert!(
!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(true, true)).unwrap()
);
assert!(
!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(true, false)).unwrap()
);
assert!(
!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(false, true)).unwrap()
);
assert!(
!tracing_switch_to_bool(Switch::Off, &user_defaults_with_tracing(false, false))
.unwrap()
);
assert!(
tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(true, true)).unwrap()
);
assert!(
tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(true, false)).unwrap()
);
assert!(
tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(false, true)).unwrap()
);
assert!(
tracing_switch_to_bool(Switch::On, &user_defaults_with_tracing(false, false)).is_err()
);
}
}

65
bin/oe/presale.rs Normal file
View File

@ -0,0 +1,65 @@
// 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 crate::{
helpers::{password_from_file, password_prompt},
params::SpecType,
};
use crypto::publickey;
use ethkey::Password;
use ethstore::PresaleWallet;
use std::num::NonZeroU32;
#[derive(Debug, PartialEq)]
pub struct ImportWallet {
pub iterations: NonZeroU32,
pub path: String,
pub spec: SpecType,
pub wallet_path: String,
pub password_file: Option<String>,
}
pub fn execute(cmd: ImportWallet) -> Result<String, String> {
let password = match cmd.password_file.clone() {
Some(file) => password_from_file(file)?,
None => password_prompt()?,
};
let wallet = PresaleWallet::open(cmd.wallet_path.clone())
.map_err(|_| "Unable to open presale wallet.")?;
let kp = wallet.decrypt(&password).map_err(|_| "Invalid password.")?;
let address = kp.address();
import_account(&cmd, kp, password);
Ok(format!("{:?}", address))
}
#[cfg(feature = "accounts")]
pub fn import_account(cmd: &ImportWallet, kp: publickey::KeyPair, password: Password) {
use accounts::{AccountProvider, AccountProviderSettings};
use ethstore::{accounts_dir::RootDiskDirectory, EthStore};
let dir = Box::new(RootDiskDirectory::create(cmd.path.clone()).unwrap());
let secret_store = Box::new(EthStore::open_with_iterations(dir, cmd.iterations).unwrap());
let acc_provider = AccountProvider::new(secret_store, AccountProviderSettings::default());
acc_provider
.insert_account(kp.secret().clone(), &password)
.unwrap();
}
#[cfg(not(feature = "accounts"))]
pub fn import_account(_cmd: &ImportWallet, _kp: publickey::KeyPair, _password: Password) {}

364
bin/oe/rpc.rs Normal file
View File

@ -0,0 +1,364 @@
// 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::{collections::HashSet, io, path::PathBuf, sync::Arc};
use crate::{
helpers::parity_ipc_path,
rpc_apis::{self, ApiSet},
};
use dir::{default_data_path, helpers::replace_home};
use jsonrpc_core::MetaIoHandler;
use parity_rpc::{
self as rpc,
informant::{Middleware, RpcStats},
DomainsValidation, Metadata,
};
use parity_runtime::Executor;
pub use parity_rpc::{HttpServer, IpcServer, RequestMiddleware};
//pub use parity_rpc::ws::Server as WsServer;
pub use parity_rpc::ws::{ws, Server as WsServer};
pub const DAPPS_DOMAIN: &'static str = "web3.site";
#[derive(Debug, Clone, PartialEq)]
pub struct HttpConfiguration {
pub enabled: bool,
pub interface: String,
pub port: u16,
pub apis: ApiSet,
pub cors: Option<Vec<String>>,
pub hosts: Option<Vec<String>>,
pub server_threads: usize,
pub processing_threads: usize,
pub max_payload: usize,
pub keep_alive: bool,
}
impl Default for HttpConfiguration {
fn default() -> Self {
HttpConfiguration {
enabled: true,
interface: "127.0.0.1".into(),
port: 8545,
apis: ApiSet::UnsafeContext,
cors: Some(vec![]),
hosts: Some(vec![]),
server_threads: 1,
processing_threads: 4,
max_payload: 5,
keep_alive: true,
}
}
}
#[derive(Debug, PartialEq)]
pub struct IpcConfiguration {
pub enabled: bool,
pub socket_addr: String,
pub apis: ApiSet,
}
impl Default for IpcConfiguration {
fn default() -> Self {
IpcConfiguration {
enabled: true,
socket_addr: if cfg!(windows) {
r"\\.\pipe\jsonrpc.ipc".into()
} else {
let data_dir = ::dir::default_data_path();
parity_ipc_path(&data_dir, "$BASE/jsonrpc.ipc", 0)
},
apis: ApiSet::IpcContext,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct WsConfiguration {
pub enabled: bool,
pub interface: String,
pub port: u16,
pub apis: ApiSet,
pub max_connections: usize,
pub origins: Option<Vec<String>>,
pub hosts: Option<Vec<String>>,
pub signer_path: PathBuf,
pub support_token_api: bool,
pub max_payload: usize,
}
impl Default for WsConfiguration {
fn default() -> Self {
let data_dir = default_data_path();
WsConfiguration {
enabled: true,
interface: "127.0.0.1".into(),
port: 8546,
apis: ApiSet::UnsafeContext,
max_connections: 100,
origins: Some(vec![
"parity://*".into(),
"chrome-extension://*".into(),
"moz-extension://*".into(),
]),
hosts: Some(Vec::new()),
signer_path: replace_home(&data_dir, "$BASE/signer").into(),
support_token_api: true,
max_payload: 5,
}
}
}
impl WsConfiguration {
pub fn address(&self) -> Option<rpc::Host> {
address(self.enabled, &self.interface, self.port, &self.hosts)
}
}
fn address(
enabled: bool,
bind_iface: &str,
bind_port: u16,
hosts: &Option<Vec<String>>,
) -> Option<rpc::Host> {
if !enabled {
return None;
}
match *hosts {
Some(ref hosts) if !hosts.is_empty() => Some(hosts[0].clone().into()),
_ => Some(format!("{}:{}", bind_iface, bind_port).into()),
}
}
pub struct Dependencies<D: rpc_apis::Dependencies> {
pub apis: Arc<D>,
pub executor: Executor,
pub stats: Arc<RpcStats>,
}
pub fn new_ws<D: rpc_apis::Dependencies>(
conf: WsConfiguration,
deps: &Dependencies<D>,
) -> Result<Option<WsServer>, String> {
if !conf.enabled {
return Ok(None);
}
let domain = DAPPS_DOMAIN;
let url = format!("{}:{}", conf.interface, conf.port);
let addr = url
.parse()
.map_err(|_| format!("Invalid WebSockets listen host/port given: {}", url))?;
let full_handler = setup_apis(rpc_apis::ApiSet::All, deps);
let handler = {
let mut handler = MetaIoHandler::with_middleware((
rpc::WsDispatcher::new(full_handler),
Middleware::new(deps.stats.clone(), deps.apis.activity_notifier()),
));
let apis = conf.apis.list_apis();
deps.apis.extend_with_set(&mut handler, &apis);
handler
};
let allowed_origins = into_domains(with_domain(conf.origins, domain, &None));
let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into())));
let signer_path;
let path = match conf.support_token_api {
true => {
signer_path = crate::signer::codes_path(&conf.signer_path);
Some(signer_path.as_path())
}
false => None,
};
let start_result = rpc::start_ws(
&addr,
handler,
allowed_origins,
allowed_hosts,
conf.max_connections,
rpc::WsExtractor::new(path.clone()),
rpc::WsExtractor::new(path.clone()),
rpc::WsStats::new(deps.stats.clone()),
conf.max_payload,
);
// match start_result {
// Ok(server) => Ok(Some(server)),
// Err(rpc::ws::Error::Io(rpc::ws::ErrorKind::Io(ref err), _)) if err.kind() == io::ErrorKind::AddrInUse => Err(
// format!("WebSockets address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --ws-port and --ws-interface options.", url)
// ),
// Err(e) => Err(format!("WebSockets error: {:?}", e)),
// }
match start_result {
Ok(server) => Ok(Some(server)),
Err(rpc::ws::Error::WsError(ws::Error {
kind: ws::ErrorKind::Io(ref err), ..
})) if err.kind() == io::ErrorKind::AddrInUse => Err(
format!("WebSockets address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --ws-port and --ws-interface options.", url)
),
Err(e) => Err(format!("WebSockets error: {:?}", e)),
}
}
pub fn new_http<D: rpc_apis::Dependencies>(
id: &str,
options: &str,
conf: HttpConfiguration,
deps: &Dependencies<D>,
) -> Result<Option<HttpServer>, String> {
if !conf.enabled {
return Ok(None);
}
let domain = DAPPS_DOMAIN;
let url = format!("{}:{}", conf.interface, conf.port);
let addr = url
.parse()
.map_err(|_| format!("Invalid {} listen host/port given: {}", id, url))?;
let handler = setup_apis(conf.apis, deps);
let cors_domains = into_domains(conf.cors);
let allowed_hosts = into_domains(with_domain(conf.hosts, domain, &Some(url.clone().into())));
let start_result = rpc::start_http(
&addr,
cors_domains,
allowed_hosts,
handler,
rpc::RpcExtractor,
conf.server_threads,
conf.max_payload,
conf.keep_alive,
);
match start_result {
Ok(server) => Ok(Some(server)),
Err(ref err) if err.kind() == io::ErrorKind::AddrInUse => Err(
format!("{} address {} is already in use, make sure that another instance of an Ethereum client is not running or change the address using the --{}-port and --{}-interface options.", id, url, options, options)
),
Err(e) => Err(format!("{} error: {:?}", id, e)),
}
}
pub fn new_ipc<D: rpc_apis::Dependencies>(
conf: IpcConfiguration,
dependencies: &Dependencies<D>,
) -> Result<Option<IpcServer>, String> {
if !conf.enabled {
return Ok(None);
}
let handler = setup_apis(conf.apis, dependencies);
let path = PathBuf::from(&conf.socket_addr);
// Make sure socket file can be created on unix-like OS.
// Windows pipe paths are not on the FS.
if !cfg!(windows) {
if let Some(dir) = path.parent() {
::std::fs::create_dir_all(&dir).map_err(|err| {
format!(
"Unable to create IPC directory at {}: {}",
dir.display(),
err
)
})?;
}
}
match rpc::start_ipc(&conf.socket_addr, handler, rpc::RpcExtractor) {
Ok(server) => Ok(Some(server)),
Err(io_error) => Err(format!("IPC error: {}", io_error)),
}
}
fn into_domains<T: From<String>>(items: Option<Vec<String>>) -> DomainsValidation<T> {
items
.map(|vals| vals.into_iter().map(T::from).collect())
.into()
}
fn with_domain(
items: Option<Vec<String>>,
domain: &str,
dapps_address: &Option<rpc::Host>,
) -> Option<Vec<String>> {
fn extract_port(s: &str) -> Option<u16> {
s.split(':').nth(1).and_then(|s| s.parse().ok())
}
items.map(move |items| {
let mut items = items.into_iter().collect::<HashSet<_>>();
{
let mut add_hosts = |address: &Option<rpc::Host>| {
if let Some(host) = address.clone() {
items.insert(host.to_string());
items.insert(host.replace("127.0.0.1", "localhost"));
items.insert(format!("http://*.{}", domain)); //proxypac
if let Some(port) = extract_port(&*host) {
items.insert(format!("http://*.{}:{}", domain, port));
}
}
};
add_hosts(dapps_address);
}
items.into_iter().collect()
})
}
pub fn setup_apis<D>(
apis: ApiSet,
deps: &Dependencies<D>,
) -> MetaIoHandler<Metadata, Middleware<D::Notifier>>
where
D: rpc_apis::Dependencies,
{
let mut handler = MetaIoHandler::with_middleware(Middleware::new(
deps.stats.clone(),
deps.apis.activity_notifier(),
));
let apis = apis.list_apis();
deps.apis.extend_with_set(&mut handler, &apis);
handler
}
#[cfg(test)]
mod tests {
use super::address;
#[test]
fn should_return_proper_address() {
assert_eq!(address(false, "localhost", 8180, &None), None);
assert_eq!(
address(true, "localhost", 8180, &None),
Some("localhost:8180".into())
);
assert_eq!(
address(true, "localhost", 8180, &Some(vec!["host:443".into()])),
Some("host:443".into())
);
assert_eq!(
address(true, "localhost", 8180, &Some(vec!["host".into()])),
Some("host".into())
);
}
}

646
bin/oe/rpc_apis.rs Normal file
View File

@ -0,0 +1,646 @@
// 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::{
cmp::PartialEq,
collections::{BTreeMap, HashSet},
str::FromStr,
sync::Arc,
};
pub use parity_rpc::signer::SignerService;
use crate::{
account_utils::{self, AccountProvider},
miner::external::ExternalMiner,
sync::{ManageNetwork, SyncProvider},
};
use ethcore::{client::Client, miner::Miner, snapshot::SnapshotService};
use ethcore_logger::RotatingLogger;
use fetch::Client as FetchClient;
use jsonrpc_core::{self as core, MetaIoHandler};
use parity_rpc::{
dispatch::FullDispatcher,
informant::{ActivityNotifier, ClientNotifier},
Host, Metadata, NetworkSettings,
};
use parity_runtime::Executor;
use parking_lot::Mutex;
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
pub enum Api {
/// Web3 (Safe)
Web3,
/// Net (Safe)
Net,
/// Eth (Safe)
Eth,
/// Eth Pub-Sub (Safe)
EthPubSub,
/// Geth-compatible "personal" API (DEPRECATED; only used in `--geth` mode.)
Personal,
/// Signer - Confirm transactions in Signer (UNSAFE: Passwords, List of transactions)
Signer,
/// Parity - Custom extensions (Safe)
Parity,
/// Traces (Safe)
Traces,
/// Rpc (Safe)
Rpc,
/// Parity PubSub - Generic Publish-Subscriber (Safety depends on other APIs exposed).
ParityPubSub,
/// Parity Accounts extensions (UNSAFE: Passwords, Side Effects (new account))
ParityAccounts,
/// Parity - Set methods (UNSAFE: Side Effects affecting node operation)
ParitySet,
/// SecretStore (UNSAFE: arbitrary hash signing)
SecretStore,
/// Geth-compatible (best-effort) debug API (Potentially UNSAFE)
/// NOTE We don't aim to support all methods, only the ones that are useful.
Debug,
}
impl FromStr for Api {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use self::Api::*;
match s {
"debug" => Ok(Debug),
"eth" => Ok(Eth),
"net" => Ok(Net),
"parity" => Ok(Parity),
"parity_accounts" => Ok(ParityAccounts),
"parity_pubsub" => Ok(ParityPubSub),
"parity_set" => Ok(ParitySet),
"personal" => Ok(Personal),
"pubsub" => Ok(EthPubSub),
"rpc" => Ok(Rpc),
"secretstore" => Ok(SecretStore),
"signer" => Ok(Signer),
"traces" => Ok(Traces),
"web3" => Ok(Web3),
api => Err(format!("Unknown api: {}", api)),
}
}
}
#[derive(Debug, Clone)]
pub enum ApiSet {
// Unsafe context (like jsonrpc over http)
UnsafeContext,
// All possible APIs (safe context like token-protected WS interface)
All,
// Local "unsafe" context and accounts access
IpcContext,
// APIs for Parity Generic Pub-Sub
PubSub,
// Fixed list of APis
List(HashSet<Api>),
}
impl Default for ApiSet {
fn default() -> Self {
ApiSet::UnsafeContext
}
}
impl PartialEq for ApiSet {
fn eq(&self, other: &Self) -> bool {
self.list_apis() == other.list_apis()
}
}
impl FromStr for ApiSet {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut apis = HashSet::new();
for api in s.split(',') {
match api {
"all" => {
apis.extend(ApiSet::All.list_apis());
}
"safe" => {
// Safe APIs are those that are safe even in UnsafeContext.
apis.extend(ApiSet::UnsafeContext.list_apis());
}
// Remove the API
api if api.starts_with("-") => {
let api = api[1..].parse()?;
apis.remove(&api);
}
api => {
let api = api.parse()?;
apis.insert(api);
}
}
}
Ok(ApiSet::List(apis))
}
}
fn to_modules(apis: &HashSet<Api>) -> BTreeMap<String, String> {
let mut modules = BTreeMap::new();
for api in apis {
let (name, version) = match *api {
Api::Debug => ("debug", "1.0"),
Api::Eth => ("eth", "1.0"),
Api::EthPubSub => ("pubsub", "1.0"),
Api::Net => ("net", "1.0"),
Api::Parity => ("parity", "1.0"),
Api::ParityAccounts => ("parity_accounts", "1.0"),
Api::ParityPubSub => ("parity_pubsub", "1.0"),
Api::ParitySet => ("parity_set", "1.0"),
Api::Personal => ("personal", "1.0"),
Api::Rpc => ("rpc", "1.0"),
Api::SecretStore => ("secretstore", "1.0"),
Api::Signer => ("signer", "1.0"),
Api::Traces => ("traces", "1.0"),
Api::Web3 => ("web3", "1.0"),
};
modules.insert(name.into(), version.into());
}
modules
}
macro_rules! add_signing_methods {
($namespace:ident, $handler:expr, $deps:expr, $dispatch:expr) => {{
let deps = &$deps;
let (dispatcher, accounts) = $dispatch;
if deps.signer_service.is_enabled() {
$handler.extend_with($namespace::to_delegate(SigningQueueClient::new(
&deps.signer_service,
dispatcher.clone(),
deps.executor.clone(),
accounts,
)))
} else {
$handler.extend_with($namespace::to_delegate(SigningUnsafeClient::new(
accounts,
dispatcher.clone(),
)))
}
}};
}
/// RPC dependencies can be used to initialize RPC endpoints from APIs.
pub trait Dependencies {
type Notifier: ActivityNotifier;
/// Create the activity notifier.
fn activity_notifier(&self) -> Self::Notifier;
/// Extend the given I/O handler with endpoints for each API.
fn extend_with_set<S>(&self, handler: &mut MetaIoHandler<Metadata, S>, apis: &HashSet<Api>)
where
S: core::Middleware<Metadata>;
}
/// RPC dependencies for a full node.
pub struct FullDependencies {
pub signer_service: Arc<SignerService>,
pub client: Arc<Client>,
pub snapshot: Arc<dyn SnapshotService>,
pub sync: Arc<dyn SyncProvider>,
pub net: Arc<dyn ManageNetwork>,
pub accounts: Arc<AccountProvider>,
pub miner: Arc<Miner>,
pub external_miner: Arc<ExternalMiner>,
pub logger: Arc<RotatingLogger>,
pub settings: Arc<NetworkSettings>,
pub net_service: Arc<dyn ManageNetwork>,
pub experimental_rpcs: bool,
pub ws_address: Option<Host>,
pub fetch: FetchClient,
pub executor: Executor,
pub gas_price_percentile: usize,
pub poll_lifetime: u32,
pub allow_missing_blocks: bool,
pub no_ancient_blocks: bool,
}
impl FullDependencies {
fn extend_api<S>(
&self,
handler: &mut MetaIoHandler<Metadata, S>,
apis: &HashSet<Api>,
for_generic_pubsub: bool,
) where
S: core::Middleware<Metadata>,
{
use parity_rpc::v1::*;
let nonces = Arc::new(Mutex::new(dispatch::Reservations::new(
self.executor.clone(),
)));
let dispatcher = FullDispatcher::new(
self.client.clone(),
self.miner.clone(),
nonces.clone(),
self.gas_price_percentile,
);
let account_signer = Arc::new(dispatch::Signer::new(self.accounts.clone())) as _;
let accounts = account_utils::accounts_list(self.accounts.clone());
for api in apis {
match *api {
Api::Debug => {
handler.extend_with(DebugClient::new(self.client.clone()).to_delegate());
}
Api::Web3 => {
handler.extend_with(Web3Client::default().to_delegate());
}
Api::Net => {
handler.extend_with(NetClient::new(&self.sync).to_delegate());
}
Api::Eth => {
let client = EthClient::new(
&self.client,
&self.snapshot,
&self.sync,
&accounts,
&self.miner,
&self.external_miner,
EthClientOptions {
gas_price_percentile: self.gas_price_percentile,
allow_missing_blocks: self.allow_missing_blocks,
allow_experimental_rpcs: self.experimental_rpcs,
no_ancient_blocks: self.no_ancient_blocks,
},
);
handler.extend_with(client.to_delegate());
if !for_generic_pubsub {
let filter_client = EthFilterClient::new(
self.client.clone(),
self.miner.clone(),
self.poll_lifetime,
);
handler.extend_with(filter_client.to_delegate());
add_signing_methods!(
EthSigning,
handler,
self,
(&dispatcher, &account_signer)
);
}
}
Api::EthPubSub => {
if !for_generic_pubsub {
let client =
EthPubSubClient::new(self.client.clone(), self.executor.clone());
let h = client.handler();
self.miner
.add_transactions_listener(Box::new(move |hashes| {
if let Some(h) = h.upgrade() {
h.notify_new_transactions(hashes);
}
}));
if let Some(h) = client.handler().upgrade() {
self.client.add_notify(h);
}
handler.extend_with(client.to_delegate());
}
}
Api::Personal => {
#[cfg(feature = "accounts")]
handler.extend_with(
PersonalClient::new(
&self.accounts,
dispatcher.clone(),
self.experimental_rpcs,
)
.to_delegate(),
);
}
Api::Signer => {
handler.extend_with(
SignerClient::new(
account_signer.clone(),
dispatcher.clone(),
&self.signer_service,
self.executor.clone(),
)
.to_delegate(),
);
}
Api::Parity => {
let signer = match self.signer_service.is_enabled() {
true => Some(self.signer_service.clone()),
false => None,
};
handler.extend_with(
ParityClient::new(
self.client.clone(),
self.miner.clone(),
self.sync.clone(),
self.net_service.clone(),
self.logger.clone(),
self.settings.clone(),
signer,
self.ws_address.clone(),
self.snapshot.clone().into(),
)
.to_delegate(),
);
#[cfg(feature = "accounts")]
handler.extend_with(ParityAccountsInfo::to_delegate(
ParityAccountsClient::new(&self.accounts),
));
if !for_generic_pubsub {
add_signing_methods!(
ParitySigning,
handler,
self,
(&dispatcher, &account_signer)
);
}
}
Api::ParityPubSub => {
if !for_generic_pubsub {
let mut rpc = MetaIoHandler::default();
let apis = ApiSet::List(apis.clone())
.retain(ApiSet::PubSub)
.list_apis();
self.extend_api(&mut rpc, &apis, true);
handler.extend_with(
PubSubClient::new(rpc, self.executor.clone()).to_delegate(),
);
}
}
Api::ParityAccounts => {
#[cfg(feature = "accounts")]
handler.extend_with(ParityAccounts::to_delegate(ParityAccountsClient::new(
&self.accounts,
)));
}
Api::ParitySet => {
handler.extend_with(
ParitySetClient::new(
&self.client,
&self.miner,
&self.net_service,
self.fetch.clone(),
)
.to_delegate(),
);
#[cfg(feature = "accounts")]
handler.extend_with(
ParitySetAccountsClient::new(&self.accounts, &self.miner).to_delegate(),
);
}
Api::Traces => handler.extend_with(TracesClient::new(&self.client).to_delegate()),
Api::Rpc => {
let modules = to_modules(&apis);
handler.extend_with(RpcClient::new(modules).to_delegate());
}
Api::SecretStore => {
#[cfg(feature = "accounts")]
handler.extend_with(SecretStoreClient::new(&self.accounts).to_delegate());
}
}
}
}
}
impl Dependencies for FullDependencies {
type Notifier = ClientNotifier;
fn activity_notifier(&self) -> ClientNotifier {
ClientNotifier {
client: self.client.clone(),
}
}
fn extend_with_set<S>(&self, handler: &mut MetaIoHandler<Metadata, S>, apis: &HashSet<Api>)
where
S: core::Middleware<Metadata>,
{
self.extend_api(handler, apis, false)
}
}
impl ApiSet {
/// Retains only APIs in given set.
pub fn retain(self, set: Self) -> Self {
ApiSet::List(&self.list_apis() & &set.list_apis())
}
pub fn list_apis(&self) -> HashSet<Api> {
let mut public_list: HashSet<Api> = [
Api::Web3,
Api::Net,
Api::Eth,
Api::EthPubSub,
Api::Parity,
Api::Rpc,
]
.iter()
.cloned()
.collect();
match *self {
ApiSet::List(ref apis) => apis.clone(),
ApiSet::UnsafeContext => {
public_list.insert(Api::Traces);
public_list.insert(Api::ParityPubSub);
public_list
}
ApiSet::IpcContext => {
public_list.insert(Api::Traces);
public_list.insert(Api::ParityPubSub);
public_list.insert(Api::ParityAccounts);
public_list
}
ApiSet::All => {
public_list.insert(Api::Debug);
public_list.insert(Api::Traces);
public_list.insert(Api::ParityPubSub);
public_list.insert(Api::ParityAccounts);
public_list.insert(Api::ParitySet);
public_list.insert(Api::Signer);
public_list.insert(Api::Personal);
public_list.insert(Api::SecretStore);
public_list
}
ApiSet::PubSub => [
Api::Eth,
Api::Parity,
Api::ParityAccounts,
Api::ParitySet,
Api::Traces,
]
.iter()
.cloned()
.collect(),
}
}
}
#[cfg(test)]
mod test {
use super::{Api, ApiSet};
#[test]
fn test_api_parsing() {
assert_eq!(Api::Debug, "debug".parse().unwrap());
assert_eq!(Api::Web3, "web3".parse().unwrap());
assert_eq!(Api::Net, "net".parse().unwrap());
assert_eq!(Api::Eth, "eth".parse().unwrap());
assert_eq!(Api::EthPubSub, "pubsub".parse().unwrap());
assert_eq!(Api::Personal, "personal".parse().unwrap());
assert_eq!(Api::Signer, "signer".parse().unwrap());
assert_eq!(Api::Parity, "parity".parse().unwrap());
assert_eq!(Api::ParityAccounts, "parity_accounts".parse().unwrap());
assert_eq!(Api::ParitySet, "parity_set".parse().unwrap());
assert_eq!(Api::Traces, "traces".parse().unwrap());
assert_eq!(Api::Rpc, "rpc".parse().unwrap());
assert_eq!(Api::SecretStore, "secretstore".parse().unwrap());
assert!("rp".parse::<Api>().is_err());
}
#[test]
fn test_api_set_default() {
assert_eq!(ApiSet::UnsafeContext, ApiSet::default());
}
#[test]
fn test_api_set_parsing() {
assert_eq!(
ApiSet::List(vec![Api::Web3, Api::Eth].into_iter().collect()),
"web3,eth".parse().unwrap()
);
}
#[test]
fn test_api_set_unsafe_context() {
let expected = vec![
// make sure this list contains only SAFE methods
Api::Web3,
Api::Net,
Api::Eth,
Api::EthPubSub,
Api::Parity,
Api::ParityPubSub,
Api::Traces,
Api::Rpc,
]
.into_iter()
.collect();
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
}
#[test]
fn test_api_set_ipc_context() {
let expected = vec![
// safe
Api::Web3,
Api::Net,
Api::Eth,
Api::EthPubSub,
Api::Parity,
Api::ParityPubSub,
Api::Traces,
Api::Rpc,
// semi-safe
Api::ParityAccounts,
]
.into_iter()
.collect();
assert_eq!(ApiSet::IpcContext.list_apis(), expected);
}
#[test]
fn test_all_apis() {
assert_eq!(
"all".parse::<ApiSet>().unwrap(),
ApiSet::List(
vec![
Api::Web3,
Api::Net,
Api::Eth,
Api::EthPubSub,
Api::Parity,
Api::ParityPubSub,
Api::Traces,
Api::Rpc,
Api::SecretStore,
Api::ParityAccounts,
Api::ParitySet,
Api::Signer,
Api::Personal,
Api::Debug,
]
.into_iter()
.collect()
)
);
}
#[test]
fn test_all_without_personal_apis() {
assert_eq!(
"personal,all,-personal".parse::<ApiSet>().unwrap(),
ApiSet::List(
vec![
Api::Web3,
Api::Net,
Api::Eth,
Api::EthPubSub,
Api::Parity,
Api::ParityPubSub,
Api::Traces,
Api::Rpc,
Api::SecretStore,
Api::ParityAccounts,
Api::ParitySet,
Api::Signer,
Api::Debug,
]
.into_iter()
.collect()
)
);
}
#[test]
fn test_safe_parsing() {
assert_eq!(
"safe".parse::<ApiSet>().unwrap(),
ApiSet::List(
vec![
Api::Web3,
Api::Net,
Api::Eth,
Api::EthPubSub,
Api::Parity,
Api::ParityPubSub,
Api::Traces,
Api::Rpc,
]
.into_iter()
.collect()
)
);
}
}

751
bin/oe/run.rs Normal file
View File

@ -0,0 +1,751 @@
// 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::{
any::Any,
str::FromStr,
sync::{atomic, Arc, Weak},
thread,
time::{Duration, Instant},
};
use crate::{
account_utils,
cache::CacheConfig,
db,
helpers::{execute_upgrades, passwords_from_files, to_client_config},
informant::{FullNodeInformantData, Informant},
metrics::{start_prometheus_metrics, MetricsConfiguration},
miner::{external::ExternalMiner, work_notify::WorkPoster},
modules,
params::{
fatdb_switch_to_bool, mode_switch_to_bool, tracing_switch_to_bool, AccountsConfig,
GasPricerConfig, MinerExtras, Pruning, SpecType, Switch,
},
rpc, rpc_apis, secretstore, signer,
sync::{self, SyncConfig},
user_defaults::UserDefaults,
};
use ansi_term::Colour;
use dir::{DatabaseDirectories, Directories};
use ethcore::{
client::{BlockChainClient, BlockInfo, Client, DatabaseCompactionProfile, Mode, VMType},
miner::{self, stratum, Miner, MinerOptions, MinerService},
snapshot::{self, SnapshotConfiguration},
verification::queue::VerifierSettings,
};
use ethcore_logger::{Config as LogConfig, RotatingLogger};
use ethcore_service::ClientService;
use ethereum_types::{H256, U64};
use journaldb::Algorithm;
use jsonrpc_core;
use node_filter::NodeFilter;
use parity_rpc::{
informant, is_major_importing, FutureOutput, FutureResponse, FutureResult, Metadata,
NetworkSettings, Origin, PubSubSession,
};
use parity_runtime::Runtime;
use parity_version::version;
// How often we attempt to take a snapshot: only snapshot on blocknumbers that are multiples of this.
const SNAPSHOT_PERIOD: u64 = 20000;
// Start snapshoting from `tip`-`history, with this we want to bypass reorgs. Should be smaller than prunning history.
const SNAPSHOT_HISTORY: u64 = 50;
// Full client number of DNS threads
const FETCH_FULL_NUM_DNS_THREADS: usize = 4;
#[derive(Debug, PartialEq)]
pub struct RunCmd {
pub cache_config: CacheConfig,
pub dirs: Directories,
pub spec: SpecType,
pub pruning: Pruning,
pub pruning_history: u64,
pub pruning_memory: usize,
/// Some if execution should be daemonized. Contains pid_file path.
pub daemon: Option<String>,
pub logger_config: LogConfig,
pub miner_options: MinerOptions,
pub gas_price_percentile: usize,
pub poll_lifetime: u32,
pub ws_conf: rpc::WsConfiguration,
pub http_conf: rpc::HttpConfiguration,
pub ipc_conf: rpc::IpcConfiguration,
pub net_conf: sync::NetworkConfiguration,
pub network_id: Option<u64>,
pub warp_sync: bool,
pub warp_barrier: Option<u64>,
pub acc_conf: AccountsConfig,
pub gas_pricer_conf: GasPricerConfig,
pub miner_extras: MinerExtras,
pub mode: Option<Mode>,
pub tracing: Switch,
pub fat_db: Switch,
pub compaction: DatabaseCompactionProfile,
pub vm_type: VMType,
pub experimental_rpcs: bool,
pub net_settings: NetworkSettings,
pub secretstore_conf: secretstore::Configuration,
pub name: String,
pub custom_bootnodes: bool,
pub stratum: Option<stratum::Options>,
pub snapshot_conf: SnapshotConfiguration,
pub check_seal: bool,
pub allow_missing_blocks: bool,
pub download_old_blocks: bool,
pub verifier_settings: VerifierSettings,
pub no_persistent_txqueue: bool,
pub max_round_blocks_to_import: usize,
pub metrics_conf: MetricsConfiguration,
}
// node info fetcher for the local store.
struct FullNodeInfo {
miner: Option<Arc<Miner>>, // TODO: only TXQ needed, just use that after decoupling.
}
impl crate::local_store::NodeInfo for FullNodeInfo {
fn pending_transactions(&self) -> Vec<crate::types::transaction::PendingTransaction> {
let miner = match self.miner.as_ref() {
Some(m) => m,
None => return Vec::new(),
};
miner
.local_transactions()
.values()
.filter_map(|status| match *status {
crate::miner::pool::local_transactions::Status::Pending(ref tx) => {
Some(tx.pending().clone())
}
_ => None,
})
.collect()
}
}
/// Executes the given run command.
///
/// On error, returns what to print on stderr.
pub fn execute(cmd: RunCmd, logger: Arc<RotatingLogger>) -> Result<RunningClient, String> {
// load spec
let spec = cmd.spec.spec(&cmd.dirs.cache)?;
// load genesis hash
let genesis_hash = spec.genesis_header().hash();
// database paths
let db_dirs = cmd.dirs.database(
genesis_hash,
cmd.spec.legacy_fork_name(),
spec.data_dir.clone(),
);
// user defaults path
let user_defaults_path = db_dirs.user_defaults_path();
// load user defaults
let mut user_defaults = UserDefaults::load(&user_defaults_path)?;
// select pruning algorithm
let algorithm = cmd.pruning.to_algorithm(&user_defaults);
// check if tracing is on
let tracing = tracing_switch_to_bool(cmd.tracing, &user_defaults)?;
// check if fatdb is on
let fat_db = fatdb_switch_to_bool(cmd.fat_db, &user_defaults, algorithm)?;
// get the mode
let mode = mode_switch_to_bool(cmd.mode, &user_defaults)?;
trace!(target: "mode", "mode is {:?}", mode);
let network_enabled = match mode {
Mode::Dark(_) | Mode::Off => false,
_ => true,
};
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path();
// execute upgrades
execute_upgrades(&cmd.dirs.base, &db_dirs, algorithm, &cmd.compaction)?;
// create dirs used by parity
cmd.dirs.create_dirs(
cmd.acc_conf.unlocked_accounts.len() == 0,
cmd.secretstore_conf.enabled,
)?;
//print out running parity environment
print_running_environment(&spec.data_dir, &cmd.dirs, &db_dirs);
// display info about used pruning algorithm
info!(
"State DB configuration: {}{}{}",
Colour::White.bold().paint(algorithm.as_str()),
match fat_db {
true => Colour::White.bold().paint(" +Fat").to_string(),
false => "".to_owned(),
},
match tracing {
true => Colour::White.bold().paint(" +Trace").to_string(),
false => "".to_owned(),
}
);
info!(
"Operating mode: {}",
Colour::White.bold().paint(format!("{}", mode))
);
// display warning about using experimental journaldb algorithm
if !algorithm.is_stable() {
warn!(
"Your chosen strategy is {}! You can re-run with --pruning to change.",
Colour::Red.bold().paint("unstable")
);
}
// create sync config
let mut sync_config = SyncConfig::default();
sync_config.network_id = match cmd.network_id {
Some(id) => id,
None => spec.network_id(),
};
if spec.subprotocol_name().len() > 8 {
warn!("Your chain specification's subprotocol length is more then 8. Ignoring.");
} else {
sync_config.subprotocol_name = U64::from(spec.subprotocol_name().as_bytes())
}
sync_config.fork_block = spec.fork_block();
let mut warp_sync = spec.engine.supports_warp() && cmd.warp_sync;
if warp_sync {
// Logging is not initialized yet, so we print directly to stderr
if fat_db {
warn!("Warning: Warp Sync is disabled because Fat DB is turned on.");
warp_sync = false;
} else if tracing {
warn!("Warning: Warp Sync is disabled because tracing is turned on.");
warp_sync = false;
} else if algorithm != Algorithm::OverlayRecent {
warn!("Warning: Warp Sync is disabled because of non-default pruning mode.");
warp_sync = false;
}
}
sync_config.warp_sync = match (warp_sync, cmd.warp_barrier) {
(true, Some(block)) => sync::WarpSync::OnlyAndAfter(block),
(true, _) => sync::WarpSync::Enabled,
_ => sync::WarpSync::Disabled,
};
sync_config.download_old_blocks = cmd.download_old_blocks;
sync_config.eip1559_transition = spec.params().eip1559_transition;
let passwords = passwords_from_files(&cmd.acc_conf.password_files)?;
// prepare account provider
let account_provider = Arc::new(account_utils::prepare_account_provider(
&cmd.spec,
&cmd.dirs,
&spec.data_dir,
cmd.acc_conf,
&passwords,
)?);
// spin up event loop
let runtime = Runtime::with_default_thread_count();
// fetch service
let fetch = fetch::Client::new(FETCH_FULL_NUM_DNS_THREADS)
.map_err(|e| format!("Error starting fetch client: {:?}", e))?;
let txpool_size = cmd.miner_options.pool_limits.max_count;
// create miner
let miner = Arc::new(Miner::new(
cmd.miner_options,
cmd.gas_pricer_conf
.to_gas_pricer(fetch.clone(), runtime.executor()),
&spec,
(
cmd.miner_extras.local_accounts,
account_utils::miner_local_accounts(account_provider.clone()),
),
));
miner.set_author(miner::Author::External(cmd.miner_extras.author));
miner.set_gas_range_target(cmd.miner_extras.gas_range_target);
miner.set_extra_data(cmd.miner_extras.extra_data);
if !cmd.miner_extras.work_notify.is_empty() {
miner.add_work_listener(Box::new(WorkPoster::new(
&cmd.miner_extras.work_notify,
fetch.clone(),
runtime.executor(),
)));
}
let engine_signer = cmd.miner_extras.engine_signer;
if engine_signer != Default::default() {
if let Some(author) = account_utils::miner_author(
&cmd.spec,
&cmd.dirs,
&account_provider,
engine_signer,
&passwords,
)? {
miner.set_author(author);
}
}
// create client config
let mut client_config = to_client_config(
&cmd.cache_config,
spec.name.to_lowercase(),
mode.clone(),
tracing,
fat_db,
cmd.compaction,
cmd.vm_type,
cmd.name,
algorithm,
cmd.pruning_history,
cmd.pruning_memory,
cmd.check_seal,
cmd.max_round_blocks_to_import,
);
client_config.queue.verifier_settings = cmd.verifier_settings;
client_config.queue.verifier_settings.bad_hashes = verification_bad_blocks(&cmd.spec);
client_config.transaction_verification_queue_size = ::std::cmp::max(2048, txpool_size / 4);
client_config.snapshot = cmd.snapshot_conf.clone();
// set up bootnodes
let mut net_conf = cmd.net_conf;
if !cmd.custom_bootnodes {
net_conf.boot_nodes = spec.nodes.clone();
}
// set network path.
net_conf.net_config_path = Some(db_dirs.network_path().to_string_lossy().into_owned());
let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config);
let client_db = restoration_db_handler
.open(&client_path)
.map_err(|e| format!("Failed to open database {:?}", e))?;
// create client service.
let service = ClientService::start(
client_config,
&spec,
client_db,
&snapshot_path,
restoration_db_handler,
&cmd.dirs.ipc_path(),
miner.clone(),
)
.map_err(|e| format!("Client service error: {:?}", e))?;
let connection_filter_address = spec.params().node_permission_contract;
// drop the spec to free up genesis state.
let forks = spec.hard_forks.clone();
drop(spec);
// take handle to client
let client = service.client();
// Update miners block gas limit and base_fee
let base_fee = client
.engine()
.calculate_base_fee(&client.best_block_header());
let allow_non_eoa_sender = client
.engine()
.allow_non_eoa_sender(client.best_block_header().number() + 1);
miner.update_transaction_queue_limits(
*client.best_block_header().gas_limit(),
base_fee,
allow_non_eoa_sender,
);
let connection_filter = connection_filter_address.map(|a| {
Arc::new(NodeFilter::new(
Arc::downgrade(&client) as Weak<dyn BlockChainClient>,
a,
))
});
let snapshot_service = service.snapshot_service();
// initialize the local node information store.
let store = {
let db = service.db();
let node_info = FullNodeInfo {
miner: match cmd.no_persistent_txqueue {
true => None,
false => Some(miner.clone()),
},
};
let store = crate::local_store::create(
db.key_value().clone(),
::ethcore_db::COL_NODE_INFO,
node_info,
);
if cmd.no_persistent_txqueue {
info!("Running without a persistent transaction queue.");
if let Err(e) = store.clear() {
warn!("Error clearing persistent transaction queue: {}", e);
}
}
// re-queue pending transactions.
match store.pending_transactions() {
Ok(pending) => {
for pending_tx in pending {
if let Err(e) = miner.import_own_transaction(&*client, pending_tx) {
warn!("Error importing saved transaction: {}", e)
}
}
}
Err(e) => warn!("Error loading cached pending transactions from disk: {}", e),
}
Arc::new(store)
};
// register it as an IO service to update periodically.
service
.register_io_handler(store)
.map_err(|_| "Unable to register local store handler".to_owned())?;
// create external miner
let external_miner = Arc::new(ExternalMiner::default());
// start stratum
if let Some(ref stratum_config) = cmd.stratum {
stratum::Stratum::register(stratum_config, miner.clone(), Arc::downgrade(&client))
.map_err(|e| format!("Stratum start error: {:?}", e))?;
}
// create sync object
let (sync_provider, manage_network, chain_notify, priority_tasks) = modules::sync(
sync_config,
net_conf.clone().into(),
client.clone(),
forks,
snapshot_service.clone(),
&cmd.logger_config,
connection_filter
.clone()
.map(|f| f as Arc<dyn crate::sync::ConnectionFilter + 'static>),
)
.map_err(|e| format!("Sync error: {}", e))?;
service.add_notify(chain_notify.clone());
// Propagate transactions as soon as they are imported.
let tx = ::parking_lot::Mutex::new(priority_tasks);
let is_ready = Arc::new(atomic::AtomicBool::new(true));
miner.add_transactions_listener(Box::new(move |_hashes| {
// we want to have only one PendingTransactions task in the queue.
if is_ready
.compare_exchange(
true,
false,
atomic::Ordering::SeqCst,
atomic::Ordering::SeqCst,
)
.is_ok()
{
let task =
crate::sync::PriorityTask::PropagateTransactions(Instant::now(), is_ready.clone());
// we ignore error cause it means that we are closing
let _ = tx.lock().send(task);
}
}));
// start network
if network_enabled {
chain_notify.start();
}
// set up dependencies for rpc servers
let rpc_stats = Arc::new(informant::RpcStats::default());
let secret_store = account_provider.clone();
let signer_service = Arc::new(signer::new_service(&cmd.ws_conf, &cmd.logger_config));
let deps_for_rpc_apis = Arc::new(rpc_apis::FullDependencies {
signer_service: signer_service,
snapshot: snapshot_service.clone(),
client: client.clone(),
sync: sync_provider.clone(),
net: manage_network.clone(),
accounts: secret_store,
miner: miner.clone(),
external_miner: external_miner.clone(),
logger: logger.clone(),
settings: Arc::new(cmd.net_settings.clone()),
net_service: manage_network.clone(),
experimental_rpcs: cmd.experimental_rpcs,
ws_address: cmd.ws_conf.address(),
fetch: fetch.clone(),
executor: runtime.executor(),
gas_price_percentile: cmd.gas_price_percentile,
poll_lifetime: cmd.poll_lifetime,
allow_missing_blocks: cmd.allow_missing_blocks,
no_ancient_blocks: !cmd.download_old_blocks,
});
let dependencies = rpc::Dependencies {
apis: deps_for_rpc_apis.clone(),
executor: runtime.executor(),
stats: rpc_stats.clone(),
};
// start rpc servers
let rpc_direct = rpc::setup_apis(rpc_apis::ApiSet::All, &dependencies);
let ws_server = rpc::new_ws(cmd.ws_conf.clone(), &dependencies)?;
let ipc_server = rpc::new_ipc(cmd.ipc_conf, &dependencies)?;
// start the prometheus metrics server
start_prometheus_metrics(&cmd.metrics_conf, &dependencies)?;
let http_server = rpc::new_http(
"HTTP JSON-RPC",
"jsonrpc",
cmd.http_conf.clone(),
&dependencies,
)?;
// secret store key server
let secretstore_deps = secretstore::Dependencies {
client: client.clone(),
sync: sync_provider.clone(),
miner: miner.clone(),
account_provider,
accounts_passwords: &passwords,
};
let secretstore_key_server = secretstore::start(
cmd.secretstore_conf.clone(),
secretstore_deps,
runtime.executor(),
)?;
// the informant
let informant = Arc::new(Informant::new(
FullNodeInformantData {
client: service.client(),
sync: Some(sync_provider.clone()),
net: Some(manage_network.clone()),
},
Some(snapshot_service.clone()),
Some(rpc_stats.clone()),
cmd.logger_config.color,
));
service.add_notify(informant.clone());
service
.register_io_handler(informant.clone())
.map_err(|_| "Unable to register informant handler".to_owned())?;
// save user defaults
user_defaults.is_first_launch = false;
user_defaults.pruning = algorithm;
user_defaults.tracing = tracing;
user_defaults.fat_db = fat_db;
user_defaults.set_mode(mode);
user_defaults.save(&user_defaults_path)?;
// tell client how to save the default mode if it gets changed.
client.on_user_defaults_change(move |mode: Option<Mode>| {
if let Some(mode) = mode {
user_defaults.set_mode(mode);
}
let _ = user_defaults.save(&user_defaults_path); // discard failures - there's nothing we can do
});
// the watcher must be kept alive.
let watcher = match cmd.snapshot_conf.enable {
false => None,
true => {
let sync = sync_provider.clone();
let client = client.clone();
let watcher = Arc::new(snapshot::Watcher::new(
service.client(),
move || is_major_importing(Some(sync.status().state), client.queue_info()),
service.io().channel(),
SNAPSHOT_PERIOD,
SNAPSHOT_HISTORY,
));
service.add_notify(watcher.clone());
Some(watcher)
}
};
Ok(RunningClient {
inner: RunningClientInner::Full {
rpc: rpc_direct,
informant,
client,
client_service: Arc::new(service),
keep_alive: Box::new((
watcher,
ws_server,
http_server,
ipc_server,
secretstore_key_server,
runtime,
)),
},
})
}
/// Set bad blocks in VerificationQeueu. By omiting header we can omit particular fork of chain.
fn verification_bad_blocks(spec: &SpecType) -> Vec<H256> {
match *spec {
SpecType::Ropsten => {
vec![
H256::from_str("1eac3d16c642411f13c287e29144c6f58fda859407c8f24c38deb168e1040714")
.expect("Valid hex string"),
]
}
_ => vec![],
}
}
/// Parity client currently executing in background threads.
///
/// Should be destroyed by calling `shutdown()`, otherwise execution will continue in the
/// background.
pub struct RunningClient {
inner: RunningClientInner,
}
enum RunningClientInner {
Full {
rpc:
jsonrpc_core::MetaIoHandler<Metadata, informant::Middleware<informant::ClientNotifier>>,
informant: Arc<Informant<FullNodeInformantData>>,
client: Arc<Client>,
client_service: Arc<ClientService>,
keep_alive: Box<dyn Any>,
},
}
impl RunningClient {
/// Performs an asynchronous RPC query.
// FIXME: [tomaka] This API should be better, with for example a Future
pub fn rpc_query(
&self,
request: &str,
session: Option<Arc<PubSubSession>>,
) -> FutureResult<FutureResponse, FutureOutput> {
let metadata = Metadata {
origin: Origin::CApi,
session,
};
match self.inner {
RunningClientInner::Full { ref rpc, .. } => rpc.handle_request(request, metadata),
}
}
/// Shuts down the client.
pub fn shutdown(self) {
match self.inner {
RunningClientInner::Full {
rpc,
informant,
client,
client_service,
keep_alive,
} => {
info!("Finishing work, please wait...");
// Create a weak reference to the client so that we can wait on shutdown
// until it is dropped
let weak_client = Arc::downgrade(&client);
// Shutdown and drop the ClientService
client_service.shutdown();
trace!(target: "shutdown", "ClientService shut down");
drop(client_service);
trace!(target: "shutdown", "ClientService dropped");
// drop this stuff as soon as exit detected.
drop(rpc);
trace!(target: "shutdown", "RPC dropped");
drop(keep_alive);
trace!(target: "shutdown", "KeepAlive dropped");
// to make sure timer does not spawn requests while shutdown is in progress
informant.shutdown();
trace!(target: "shutdown", "Informant shut down");
// just Arc is dropping here, to allow other reference release in its default time
drop(informant);
trace!(target: "shutdown", "Informant dropped");
drop(client);
trace!(target: "shutdown", "Client dropped");
// This may help when debugging ref cycles. Requires nightly-only `#![feature(weak_counts)]`
// trace!(target: "shutdown", "Waiting for refs to Client to shutdown, strong_count={:?}, weak_count={:?}", weak_client.strong_count(), weak_client.weak_count());
trace!(target: "shutdown", "Waiting for refs to Client to shutdown");
wait_for_drop(weak_client);
}
}
}
}
fn print_running_environment(data_dir: &str, dirs: &Directories, db_dirs: &DatabaseDirectories) {
info!("Starting {}", Colour::White.bold().paint(version()));
info!(
"Keys path {}",
Colour::White
.bold()
.paint(dirs.keys_path(data_dir).to_string_lossy().into_owned())
);
info!(
"DB path {}",
Colour::White
.bold()
.paint(db_dirs.db_root_path().to_string_lossy().into_owned())
);
}
fn wait_for_drop<T>(w: Weak<T>) {
const SLEEP_DURATION: Duration = Duration::from_secs(1);
const WARN_TIMEOUT: Duration = Duration::from_secs(60);
const MAX_TIMEOUT: Duration = Duration::from_secs(300);
let instant = Instant::now();
let mut warned = false;
while instant.elapsed() < MAX_TIMEOUT {
if w.upgrade().is_none() {
return;
}
if !warned && instant.elapsed() > WARN_TIMEOUT {
warned = true;
warn!("Shutdown is taking longer than expected.");
}
thread::sleep(SLEEP_DURATION);
// When debugging shutdown issues on a nightly build it can help to enable this with the
// `#![feature(weak_counts)]` added to lib.rs (TODO: enable when
// https://github.com/rust-lang/rust/issues/57977 is stable)
// trace!(target: "shutdown", "Waiting for client to drop, strong_count={:?}, weak_count={:?}", w.strong_count(), w.weak_count());
trace!(target: "shutdown", "Waiting for client to drop");
}
warn!("Shutdown timeout reached, exiting uncleanly.");
}

333
bin/oe/secretstore.rs Normal file
View File

@ -0,0 +1,333 @@
// 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 crate::{account_utils::AccountProvider, sync::SyncProvider};
use crypto::publickey::{Public, Secret};
use dir::{default_data_path, helpers::replace_home};
use ethcore::{client::Client, miner::Miner};
use ethereum_types::Address;
use ethkey::Password;
use parity_runtime::Executor;
use std::{collections::BTreeMap, sync::Arc};
/// This node secret key.
#[derive(Debug, PartialEq, Clone)]
pub enum NodeSecretKey {
/// Stored as plain text in configuration file.
Plain(Secret),
/// Stored as account in key store.
#[cfg(feature = "accounts")]
KeyStore(Address),
}
/// Secret store service contract address.
#[derive(Debug, PartialEq, Clone)]
pub enum ContractAddress {
/// Contract address is read from registry.
Registry,
/// Contract address is specified.
Address(Address),
}
#[derive(Debug, PartialEq, Clone)]
/// Secret store configuration
pub struct Configuration {
/// Is secret store functionality enabled?
pub enabled: bool,
/// Is HTTP API enabled?
pub http_enabled: bool,
/// Is auto migrate enabled.
pub auto_migrate_enabled: bool,
/// ACL check contract address.
pub acl_check_contract_address: Option<ContractAddress>,
/// Service contract address.
pub service_contract_address: Option<ContractAddress>,
/// Server key generation service contract address.
pub service_contract_srv_gen_address: Option<ContractAddress>,
/// Server key retrieval service contract address.
pub service_contract_srv_retr_address: Option<ContractAddress>,
/// Document key store service contract address.
pub service_contract_doc_store_address: Option<ContractAddress>,
/// Document key shadow retrieval service contract address.
pub service_contract_doc_sretr_address: Option<ContractAddress>,
/// This node secret.
pub self_secret: Option<NodeSecretKey>,
/// Other nodes IDs + addresses.
pub nodes: BTreeMap<Public, (String, u16)>,
/// Key Server Set contract address. If None, 'nodes' map is used.
pub key_server_set_contract_address: Option<ContractAddress>,
/// Interface to listen to
pub interface: String,
/// Port to listen to
pub port: u16,
/// Interface to listen to
pub http_interface: String,
/// Port to listen to
pub http_port: u16,
/// Data directory path for secret store
pub data_path: String,
/// Administrator public key.
pub admin_public: Option<Public>,
}
/// Secret store dependencies
pub struct Dependencies<'a> {
/// Blockchain client.
pub client: Arc<Client>,
/// Sync provider.
pub sync: Arc<dyn SyncProvider>,
/// Miner service.
pub miner: Arc<Miner>,
/// Account provider.
pub account_provider: Arc<AccountProvider>,
/// Passed accounts passwords.
pub accounts_passwords: &'a [Password],
}
#[cfg(not(feature = "secretstore"))]
mod server {
use super::{Configuration, Dependencies, Executor};
/// Noop key server implementation
pub struct KeyServer;
impl KeyServer {
/// Create new noop key server
pub fn new(
_conf: Configuration,
_deps: Dependencies,
_executor: Executor,
) -> Result<Self, String> {
Ok(KeyServer)
}
}
}
#[cfg(feature = "secretstore")]
mod server {
use super::{Configuration, ContractAddress, Dependencies, Executor, NodeSecretKey};
use ansi_term::Colour::{Red, White};
use db;
use ethcore_secretstore;
use ethkey::KeyPair;
use std::sync::Arc;
fn into_service_contract_address(
address: ContractAddress,
) -> ethcore_secretstore::ContractAddress {
match address {
ContractAddress::Registry => ethcore_secretstore::ContractAddress::Registry,
ContractAddress::Address(address) => {
ethcore_secretstore::ContractAddress::Address(address)
}
}
}
/// Key server
pub struct KeyServer {
_key_server: Box<dyn ethcore_secretstore::KeyServer>,
}
impl KeyServer {
/// Create new key server
pub fn new(
mut conf: Configuration,
deps: Dependencies,
executor: Executor,
) -> Result<Self, String> {
let self_secret: Arc<dyn ethcore_secretstore::NodeKeyPair> =
match conf.self_secret.take() {
Some(NodeSecretKey::Plain(secret)) => {
Arc::new(ethcore_secretstore::PlainNodeKeyPair::new(
KeyPair::from_secret(secret)
.map_err(|e| format!("invalid secret: {}", e))?,
))
}
#[cfg(feature = "accounts")]
Some(NodeSecretKey::KeyStore(account)) => {
// Check if account exists
if !deps.account_provider.has_account(account.clone()) {
return Err(format!(
"Account {} passed as secret store node key is not found",
account
));
}
// Check if any passwords have been read from the password file(s)
if deps.accounts_passwords.is_empty() {
return Err(format!(
"No password found for the secret store node account {}",
account
));
}
// Attempt to sign in the engine signer.
let password = deps
.accounts_passwords
.iter()
.find(|p| {
deps.account_provider
.sign(account.clone(), Some((*p).clone()), Default::default())
.is_ok()
})
.ok_or_else(|| {
format!(
"No valid password for the secret store node account {}",
account
)
})?;
Arc::new(
ethcore_secretstore::KeyStoreNodeKeyPair::new(
deps.account_provider,
account,
password.clone(),
)
.map_err(|e| format!("{}", e))?,
)
}
None => return Err("self secret is required when using secretstore".into()),
};
info!(
"Starting SecretStore node: {}",
White.bold().paint(format!("{:?}", self_secret.public()))
);
if conf.acl_check_contract_address.is_none() {
warn!(
"Running SecretStore with disabled ACL check: {}",
Red.bold().paint("everyone has access to stored keys")
);
}
let key_server_name = format!("{}:{}", conf.interface, conf.port);
let mut cconf = ethcore_secretstore::ServiceConfiguration {
listener_address: if conf.http_enabled {
Some(ethcore_secretstore::NodeAddress {
address: conf.http_interface.clone(),
port: conf.http_port,
})
} else {
None
},
service_contract_address: conf
.service_contract_address
.map(into_service_contract_address),
service_contract_srv_gen_address: conf
.service_contract_srv_gen_address
.map(into_service_contract_address),
service_contract_srv_retr_address: conf
.service_contract_srv_retr_address
.map(into_service_contract_address),
service_contract_doc_store_address: conf
.service_contract_doc_store_address
.map(into_service_contract_address),
service_contract_doc_sretr_address: conf
.service_contract_doc_sretr_address
.map(into_service_contract_address),
acl_check_contract_address: conf
.acl_check_contract_address
.map(into_service_contract_address),
cluster_config: ethcore_secretstore::ClusterConfiguration {
listener_address: ethcore_secretstore::NodeAddress {
address: conf.interface.clone(),
port: conf.port,
},
nodes: conf
.nodes
.into_iter()
.map(|(p, (ip, port))| {
(
p,
ethcore_secretstore::NodeAddress {
address: ip,
port: port,
},
)
})
.collect(),
key_server_set_contract_address: conf
.key_server_set_contract_address
.map(into_service_contract_address),
allow_connecting_to_higher_nodes: true,
admin_public: conf.admin_public,
auto_migrate_enabled: conf.auto_migrate_enabled,
},
};
cconf.cluster_config.nodes.insert(
self_secret.public().clone(),
cconf.cluster_config.listener_address.clone(),
);
let db = db::open_secretstore_db(&conf.data_path)?;
let key_server = ethcore_secretstore::start(
deps.client,
deps.sync,
deps.miner,
self_secret,
cconf,
db,
executor,
)
.map_err(|e| format!("Error starting KeyServer {}: {}", key_server_name, e))?;
Ok(KeyServer {
_key_server: key_server,
})
}
}
}
pub use self::server::KeyServer;
impl Default for Configuration {
fn default() -> Self {
let data_dir = default_data_path();
Configuration {
enabled: true,
http_enabled: true,
auto_migrate_enabled: true,
acl_check_contract_address: Some(ContractAddress::Registry),
service_contract_address: None,
service_contract_srv_gen_address: None,
service_contract_srv_retr_address: None,
service_contract_doc_store_address: None,
service_contract_doc_sretr_address: None,
self_secret: None,
admin_public: None,
nodes: BTreeMap::new(),
key_server_set_contract_address: Some(ContractAddress::Registry),
interface: "127.0.0.1".to_owned(),
port: 8083,
http_interface: "127.0.0.1".to_owned(),
http_port: 8082,
data_path: replace_home(&data_dir, "$BASE/secretstore"),
}
}
}
/// Start secret store-related functionality
pub fn start(
conf: Configuration,
deps: Dependencies,
executor: Executor,
) -> Result<Option<KeyServer>, String> {
if !conf.enabled {
return Ok(None);
}
KeyServer::new(conf, deps, executor).map(|s| Some(s))
}

98
bin/oe/signer.rs Normal file
View File

@ -0,0 +1,98 @@
// 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::{
io,
path::{Path, PathBuf},
};
use crate::{path::restrict_permissions_owner, rpc, rpc_apis};
use ansi_term::Colour::White;
use ethcore_logger::Config as LogConfig;
use parity_rpc;
pub const CODES_FILENAME: &'static str = "authcodes";
pub struct NewToken {
pub token: String,
pub message: String,
}
pub fn new_service(
ws_conf: &rpc::WsConfiguration,
logger_config: &LogConfig,
) -> rpc_apis::SignerService {
let logger_config_color = logger_config.color;
let signer_path = ws_conf.signer_path.clone();
let signer_enabled = ws_conf.support_token_api;
rpc_apis::SignerService::new(
move || {
generate_new_token(&signer_path, logger_config_color).map_err(|e| format!("{:?}", e))
},
signer_enabled,
)
}
pub fn codes_path(path: &Path) -> PathBuf {
let mut p = path.to_owned();
p.push(CODES_FILENAME);
let _ = restrict_permissions_owner(&p, true, false);
p
}
pub fn execute(ws_conf: rpc::WsConfiguration, logger_config: LogConfig) -> Result<String, String> {
Ok(generate_token_and_url(&ws_conf, &logger_config)?.message)
}
pub fn generate_token_and_url(
ws_conf: &rpc::WsConfiguration,
logger_config: &LogConfig,
) -> Result<NewToken, String> {
let code = generate_new_token(&ws_conf.signer_path, logger_config.color)
.map_err(|err| format!("Error generating token: {:?}", err))?;
let colored = |s: String| match logger_config.color {
true => format!("{}", White.bold().paint(s)),
false => s,
};
Ok(NewToken {
token: code.clone(),
message: format!(
r#"
Generated token:
{}
"#,
colored(code)
),
})
}
fn generate_new_token(path: &Path, logger_config_color: bool) -> io::Result<String> {
let path = codes_path(path);
let mut codes = parity_rpc::AuthCodes::from_file(&path)?;
codes.clear_garbage();
let code = codes.generate_new()?;
codes.to_file(&path)?;
trace!(
"New key code created: {}",
match logger_config_color {
true => format!("{}", White.bold().paint(&code[..])),
false => format!("{}", &code[..]),
}
);
Ok(code)
}

347
bin/oe/snapshot.rs Normal file
View File

@ -0,0 +1,347 @@
// 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/>.
//! Snapshot and restoration commands.
use std::{
path::{Path, PathBuf},
sync::Arc,
time::Duration,
};
use crate::{hash::keccak, types::ids::BlockId};
use ethcore::{
client::{DatabaseCompactionProfile, Mode, VMType},
miner::Miner,
snapshot::{
io::{PackedReader, PackedWriter, SnapshotReader},
service::Service as SnapshotService,
Progress, RestorationStatus, SnapshotConfiguration, SnapshotService as SS,
},
};
use ethcore_service::ClientService;
use crate::{
cache::CacheConfig,
db,
helpers::{execute_upgrades, to_client_config},
params::{fatdb_switch_to_bool, tracing_switch_to_bool, Pruning, SpecType, Switch},
user_defaults::UserDefaults,
};
use dir::Directories;
/// Kinds of snapshot commands.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Kind {
/// Take a snapshot.
Take,
/// Restore a snapshot.
Restore,
}
/// Command for snapshot creation or restoration.
#[derive(Debug, PartialEq)]
pub struct SnapshotCommand {
pub cache_config: CacheConfig,
pub dirs: Directories,
pub spec: SpecType,
pub pruning: Pruning,
pub pruning_history: u64,
pub pruning_memory: usize,
pub tracing: Switch,
pub fat_db: Switch,
pub compaction: DatabaseCompactionProfile,
pub file_path: Option<String>,
pub kind: Kind,
pub block_at: BlockId,
pub max_round_blocks_to_import: usize,
pub snapshot_conf: SnapshotConfiguration,
}
// helper for reading chunks from arbitrary reader and feeding them into the
// service.
fn restore_using<R: SnapshotReader>(
snapshot: Arc<SnapshotService>,
reader: &R,
recover: bool,
) -> Result<(), String> {
let manifest = reader.manifest();
info!(
"Restoring to block #{} (0x{:?})",
manifest.block_number, manifest.block_hash
);
snapshot
.init_restore(manifest.clone(), recover)
.map_err(|e| format!("Failed to begin restoration: {}", e))?;
let (num_state, num_blocks) = (manifest.state_hashes.len(), manifest.block_hashes.len());
let informant_handle = snapshot.clone();
::std::thread::spawn(move || {
while let RestorationStatus::Ongoing {
state_chunks_done,
block_chunks_done,
..
} = informant_handle.restoration_status()
{
info!(
"Processed {}/{} state chunks and {}/{} block chunks.",
state_chunks_done, num_state, block_chunks_done, num_blocks
);
::std::thread::sleep(Duration::from_secs(5));
}
});
info!("Restoring state");
for &state_hash in &manifest.state_hashes {
if snapshot.restoration_status() == RestorationStatus::Failed {
return Err("Restoration failed".into());
}
let chunk = reader.chunk(state_hash).map_err(|e| {
format!(
"Encountered error while reading chunk {:?}: {}",
state_hash, e
)
})?;
let hash = keccak(&chunk);
if hash != state_hash {
return Err(format!(
"Mismatched chunk hash. Expected {:?}, got {:?}",
state_hash, hash
));
}
snapshot.feed_state_chunk(state_hash, &chunk);
}
info!("Restoring blocks");
for &block_hash in &manifest.block_hashes {
if snapshot.restoration_status() == RestorationStatus::Failed {
return Err("Restoration failed".into());
}
let chunk = reader.chunk(block_hash).map_err(|e| {
format!(
"Encountered error while reading chunk {:?}: {}",
block_hash, e
)
})?;
let hash = keccak(&chunk);
if hash != block_hash {
return Err(format!(
"Mismatched chunk hash. Expected {:?}, got {:?}",
block_hash, hash
));
}
snapshot.feed_block_chunk(block_hash, &chunk);
}
match snapshot.restoration_status() {
RestorationStatus::Ongoing { .. } => {
Err("Snapshot file is incomplete and missing chunks.".into())
}
RestorationStatus::Initializing { .. } => {
Err("Snapshot restoration is still initializing.".into())
}
RestorationStatus::Failed => Err("Snapshot restoration failed.".into()),
RestorationStatus::Inactive => {
info!("Restoration complete.");
Ok(())
}
}
}
impl SnapshotCommand {
// shared portion of snapshot commands: start the client service
fn start_service(self) -> Result<ClientService, String> {
// load spec file
let spec = self.spec.spec(&self.dirs.cache)?;
// load genesis hash
let genesis_hash = spec.genesis_header().hash();
// database paths
let db_dirs = self
.dirs
.database(genesis_hash, None, spec.data_dir.clone());
// user defaults path
let user_defaults_path = db_dirs.user_defaults_path();
// load user defaults
let user_defaults = UserDefaults::load(&user_defaults_path)?;
// select pruning algorithm
let algorithm = self.pruning.to_algorithm(&user_defaults);
// check if tracing is on
let tracing = tracing_switch_to_bool(self.tracing, &user_defaults)?;
// check if fatdb is on
let fat_db = fatdb_switch_to_bool(self.fat_db, &user_defaults, algorithm)?;
// prepare client and snapshot paths.
let client_path = db_dirs.client_path(algorithm);
let snapshot_path = db_dirs.snapshot_path();
// execute upgrades
execute_upgrades(&self.dirs.base, &db_dirs, algorithm, &self.compaction)?;
// prepare client config
let mut client_config = to_client_config(
&self.cache_config,
spec.name.to_lowercase(),
Mode::Active,
tracing,
fat_db,
self.compaction,
VMType::default(),
"".into(),
algorithm,
self.pruning_history,
self.pruning_memory,
true,
self.max_round_blocks_to_import,
);
client_config.snapshot = self.snapshot_conf;
let restoration_db_handler = db::restoration_db_handler(&client_path, &client_config);
let client_db = restoration_db_handler
.open(&client_path)
.map_err(|e| format!("Failed to open database {:?}", e))?;
let service = ClientService::start(
client_config,
&spec,
client_db,
&snapshot_path,
restoration_db_handler,
&self.dirs.ipc_path(),
// TODO [ToDr] don't use test miner here
// (actually don't require miner at all)
Arc::new(Miner::new_for_tests(&spec, None)),
)
.map_err(|e| format!("Client service error: {:?}", e))?;
Ok(service)
}
/// restore from a snapshot
pub fn restore(self) -> Result<(), String> {
let file = self.file_path.clone();
let service = self.start_service()?;
warn!("Snapshot restoration is experimental and the format may be subject to change.");
warn!(
"On encountering an unexpected error, please ensure that you have a recent snapshot."
);
let snapshot = service.snapshot_service();
if let Some(file) = file {
info!("Attempting to restore from snapshot at '{}'", file);
let reader = PackedReader::new(Path::new(&file))
.map_err(|e| format!("Couldn't open snapshot file: {}", e))
.and_then(|x| x.ok_or("Snapshot file has invalid format.".into()));
let reader = reader?;
restore_using(snapshot, &reader, true)?;
} else {
info!("Attempting to restore from local snapshot.");
// attempting restoration with recovery will lead to deadlock
// as we currently hold a read lock on the service's reader.
match *snapshot.reader() {
Some(ref reader) => restore_using(snapshot.clone(), reader, false)?,
None => return Err("No local snapshot found.".into()),
}
}
Ok(())
}
/// Take a snapshot from the head of the chain.
pub fn take_snapshot(self) -> Result<(), String> {
let file_path = self
.file_path
.clone()
.ok_or("No file path provided.".to_owned())?;
let file_path: PathBuf = file_path.into();
let block_at = self.block_at;
let service = self.start_service()?;
warn!("Snapshots are currently experimental. File formats may be subject to change.");
let writer = PackedWriter::new(&file_path)
.map_err(|e| format!("Failed to open snapshot writer: {}", e))?;
let progress = Arc::new(Progress::default());
let p = progress.clone();
let informant_handle = ::std::thread::spawn(move || {
::std::thread::sleep(Duration::from_secs(5));
let mut last_size = 0;
while !p.done() {
let cur_size = p.size();
if cur_size != last_size {
last_size = cur_size;
let bytes = crate::informant::format_bytes(cur_size as usize);
info!(
"Snapshot: {} accounts {} blocks {}",
p.accounts(),
p.blocks(),
bytes
);
}
::std::thread::sleep(Duration::from_secs(5));
}
});
if let Err(e) = service.client().take_snapshot(writer, block_at, &*progress) {
let _ = ::std::fs::remove_file(&file_path);
return Err(format!(
"Encountered fatal error while creating snapshot: {}",
e
));
}
info!("snapshot creation complete");
assert!(progress.done());
informant_handle
.join()
.map_err(|_| "failed to join logger thread")?;
Ok(())
}
}
/// Execute this snapshot command.
pub fn execute(cmd: SnapshotCommand) -> Result<String, String> {
match cmd.kind {
Kind::Take => cmd.take_snapshot()?,
Kind::Restore => cmd.restore()?,
}
Ok(String::new())
}

View File

@ -1,20 +1,20 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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 Parity. If not, see <http://www.gnu.org/licenses/>.
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Parity sync service
//! OpenEthereum sync service
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
@ -39,7 +39,7 @@ struct StratumControlService {
impl ControlService for StratumControlService {
fn shutdown(&self) -> bool {
trace!(target: "hypervisor", "Received shutdown from control service");
self.stop.store(true, ::std::sync::atomic::Ordering::Relaxed);
self.stop.store(true, ::std::sync::atomic::Ordering::SeqCst);
true
}
}

246
bin/oe/upgrade.rs Normal file
View File

@ -0,0 +1,246 @@
// 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/>.
//! Parity upgrade logic
use dir::{default_data_path, helpers::replace_home, home_dir, DatabaseDirectories};
use journaldb::Algorithm;
use semver::{SemVerError, Version};
use std::{
collections::*,
fs::{self, create_dir_all, File},
io,
io::{Read, Write},
path::{Path, PathBuf},
};
#[derive(Debug)]
pub enum Error {
CannotCreateConfigPath(io::Error),
CannotWriteVersionFile(io::Error),
CannotUpdateVersionFile(io::Error),
SemVer(SemVerError),
}
impl From<SemVerError> for Error {
fn from(err: SemVerError) -> Self {
Error::SemVer(err)
}
}
const CURRENT_VERSION: &'static str = env!("CARGO_PKG_VERSION");
#[derive(Hash, PartialEq, Eq)]
struct UpgradeKey {
pub old_version: Version,
pub new_version: Version,
}
type UpgradeList = HashMap<UpgradeKey, fn() -> Result<(), Error>>;
impl UpgradeKey {
// given the following config exist
// ver.lock 1.1 (`previous_version`)
//
// current_version 1.4 (`current_version`)
//
//
//upgrades (set of `UpgradeKey`)
// 1.0 -> 1.1 (u1)
// 1.1 -> 1.2 (u2)
// 1.2 -> 1.3 (u3)
// 1.3 -> 1.4 (u4)
// 1.4 -> 1.5 (u5)
//
// then the following upgrades should be applied:
// u2, u3, u4
fn is_applicable(&self, previous_version: &Version, current_version: &Version) -> bool {
self.old_version >= *previous_version && self.new_version <= *current_version
}
}
// dummy upgrade (remove when the first one is in)
fn dummy_upgrade() -> Result<(), Error> {
Ok(())
}
fn push_upgrades(upgrades: &mut UpgradeList) {
// dummy upgrade (remove when the first one is in)
upgrades.insert(
UpgradeKey {
old_version: Version::new(0, 9, 0),
new_version: Version::new(1, 0, 0),
},
dummy_upgrade,
);
}
fn upgrade_from_version(previous_version: &Version) -> Result<usize, Error> {
let mut upgrades = HashMap::new();
push_upgrades(&mut upgrades);
let current_version = Version::parse(CURRENT_VERSION)?;
let mut count = 0;
for upgrade_key in upgrades.keys() {
if upgrade_key.is_applicable(previous_version, &current_version) {
let upgrade_script = upgrades[upgrade_key];
upgrade_script()?;
count += 1;
}
}
Ok(count)
}
fn with_locked_version<F>(db_path: &str, script: F) -> Result<usize, Error>
where
F: Fn(&Version) -> Result<usize, Error>,
{
let mut path = PathBuf::from(db_path);
create_dir_all(&path).map_err(Error::CannotCreateConfigPath)?;
path.push("ver.lock");
let version = File::open(&path)
.ok()
.and_then(|ref mut file| {
let mut version_string = String::new();
file.read_to_string(&mut version_string)
.ok()
.and_then(|_| Version::parse(&version_string).ok())
})
.unwrap_or(Version::new(0, 9, 0));
let mut lock = File::create(&path).map_err(Error::CannotWriteVersionFile)?;
let result = script(&version);
let written_version = Version::parse(CURRENT_VERSION)?;
lock.write_all(written_version.to_string().as_bytes())
.map_err(Error::CannotUpdateVersionFile)?;
result
}
pub fn upgrade(db_path: &str) -> Result<usize, Error> {
with_locked_version(db_path, |ver| upgrade_from_version(ver))
}
fn file_exists(path: &Path) -> bool {
match fs::metadata(&path) {
Err(ref e) if e.kind() == io::ErrorKind::NotFound => false,
_ => true,
}
}
#[cfg(any(test, feature = "accounts"))]
pub fn upgrade_key_location(from: &PathBuf, to: &PathBuf) {
match fs::create_dir_all(&to).and_then(|()| fs::read_dir(from)) {
Ok(entries) => {
let files: Vec<_> = entries
.filter_map(|f| {
f.ok().and_then(|f| {
if f.file_type().ok().map_or(false, |f| f.is_file()) {
f.file_name().to_str().map(|s| s.to_owned())
} else {
None
}
})
})
.collect();
let mut num: usize = 0;
for name in files {
let mut from = from.clone();
from.push(&name);
let mut to = to.clone();
to.push(&name);
if !file_exists(&to) {
if let Err(e) = fs::rename(&from, &to) {
debug!("Error upgrading key {:?}: {:?}", from, e);
} else {
num += 1;
}
} else {
debug!("Skipped upgrading key {:?}", from);
}
}
if num > 0 {
info!(
"Moved {} keys from {} to {}",
num,
from.to_string_lossy(),
to.to_string_lossy()
);
}
}
Err(e) => {
debug!("Error moving keys from {:?} to {:?}: {:?}", from, to, e);
}
}
}
fn upgrade_dir_location(source: &PathBuf, dest: &PathBuf) {
if file_exists(&source) {
if !file_exists(&dest) {
let mut parent = dest.clone();
parent.pop();
if let Err(e) = fs::create_dir_all(&parent).and_then(|()| fs::rename(&source, &dest)) {
debug!("Skipped path {:?} -> {:?} :{:?}", source, dest, e);
} else {
info!(
"Moved {} to {}",
source.to_string_lossy(),
dest.to_string_lossy()
);
}
} else {
debug!(
"Skipped upgrading directory {:?}, Destination already exists at {:?}",
source, dest
);
}
}
}
fn upgrade_user_defaults(dirs: &DatabaseDirectories) {
let source = dirs.legacy_user_defaults_path();
let dest = dirs.user_defaults_path();
if file_exists(&source) {
if !file_exists(&dest) {
if let Err(e) = fs::rename(&source, &dest) {
debug!("Skipped upgrading user defaults {:?}:{:?}", dest, e);
}
} else {
debug!(
"Skipped upgrading user defaults {:?}, File exists at {:?}",
source, dest
);
}
}
}
pub fn upgrade_data_paths(base_path: &str, dirs: &DatabaseDirectories, pruning: Algorithm) {
if home_dir().is_none() {
return;
}
let legacy_root_path = replace_home("", "$HOME/.parity");
let default_path = default_data_path();
if legacy_root_path != base_path && base_path == default_path {
upgrade_dir_location(&PathBuf::from(legacy_root_path), &PathBuf::from(&base_path));
}
upgrade_dir_location(&dirs.legacy_version_path(pruning), &dirs.db_path(pruning));
upgrade_dir_location(&dirs.legacy_snapshot_path(), &dirs.snapshot_path());
upgrade_dir_location(&dirs.legacy_network_path(), &dirs.network_path());
upgrade_user_defaults(&dirs);
}

188
bin/oe/user_defaults.rs Normal file
View File

@ -0,0 +1,188 @@
// 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 ethcore::client::Mode as ClientMode;
use journaldb::Algorithm;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json::{de::from_reader, ser::to_string};
use std::{fs::File, io::Write, path::Path, time::Duration};
#[derive(Clone)]
pub struct Seconds(Duration);
impl Seconds {
pub fn value(&self) -> u64 {
self.0.as_secs()
}
}
impl From<u64> for Seconds {
fn from(s: u64) -> Seconds {
Seconds(Duration::from_secs(s))
}
}
impl From<Duration> for Seconds {
fn from(d: Duration) -> Seconds {
Seconds(d)
}
}
impl Into<Duration> for Seconds {
fn into(self) -> Duration {
self.0
}
}
impl Serialize for Seconds {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_u64(self.value())
}
}
impl<'de> Deserialize<'de> for Seconds {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let secs = u64::deserialize(deserializer)?;
Ok(Seconds::from(secs))
}
}
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase", tag = "mode")]
pub enum Mode {
Active,
Passive {
#[serde(rename = "mode.timeout")]
timeout: Seconds,
#[serde(rename = "mode.alarm")]
alarm: Seconds,
},
Dark {
#[serde(rename = "mode.timeout")]
timeout: Seconds,
},
Offline,
}
impl Into<ClientMode> for Mode {
fn into(self) -> ClientMode {
match self {
Mode::Active => ClientMode::Active,
Mode::Passive { timeout, alarm } => ClientMode::Passive(timeout.into(), alarm.into()),
Mode::Dark { timeout } => ClientMode::Dark(timeout.into()),
Mode::Offline => ClientMode::Off,
}
}
}
impl From<ClientMode> for Mode {
fn from(mode: ClientMode) -> Mode {
match mode {
ClientMode::Active => Mode::Active,
ClientMode::Passive(timeout, alarm) => Mode::Passive {
timeout: timeout.into(),
alarm: alarm.into(),
},
ClientMode::Dark(timeout) => Mode::Dark {
timeout: timeout.into(),
},
ClientMode::Off => Mode::Offline,
}
}
}
#[derive(Serialize, Deserialize)]
pub struct UserDefaults {
pub is_first_launch: bool,
#[serde(with = "algorithm_serde")]
pub pruning: Algorithm,
pub tracing: bool,
pub fat_db: bool,
#[serde(flatten)]
mode: Mode,
}
impl UserDefaults {
pub fn mode(&self) -> ClientMode {
self.mode.clone().into()
}
pub fn set_mode(&mut self, mode: ClientMode) {
self.mode = mode.into();
}
}
mod algorithm_serde {
use journaldb::Algorithm;
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
pub fn serialize<S>(algorithm: &Algorithm, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
algorithm.as_str().serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Algorithm, D::Error>
where
D: Deserializer<'de>,
{
let pruning = String::deserialize(deserializer)?;
pruning
.parse()
.map_err(|_| Error::custom("invalid pruning method"))
}
}
impl Default for UserDefaults {
fn default() -> Self {
UserDefaults {
is_first_launch: true,
pruning: Algorithm::OverlayRecent,
tracing: false,
fat_db: false,
mode: Mode::Active,
}
}
}
impl UserDefaults {
pub fn load<P>(path: P) -> Result<Self, String>
where
P: AsRef<Path>,
{
match File::open(path) {
Ok(file) => match from_reader(file) {
Ok(defaults) => Ok(defaults),
Err(e) => {
warn!("Error loading user defaults file: {:?}", e);
Ok(UserDefaults::default())
}
},
_ => Ok(UserDefaults::default()),
}
}
pub fn save<P>(&self, path: P) -> Result<(), String>
where
P: AsRef<Path>,
{
let mut file: File =
File::create(path).map_err(|_| "Cannot create user defaults file".to_owned())?;
file.write_all(to_string(&self).unwrap().as_bytes())
.map_err(|_| "Failed to save user defaults".to_owned())
}
}

View File

@ -1,64 +0,0 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
extern crate serde_json;
extern crate serde_ignored;
extern crate ethjson;
use std::collections::BTreeSet;
use std::{fs, env, process};
use ethjson::spec::Spec;
fn quit(s: &str) -> ! {
println!("{}", s);
process::exit(1);
}
fn main() {
let mut args = env::args();
if args.len() != 2 {
quit("You need to specify chainspec.json\n\
\n\
./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 mut unused = BTreeSet::new();
let mut deserializer = serde_json::Deserializer::from_reader(file);
let spec: Result<Spec, _> = serde_ignored::deserialize(&mut deserializer, |field| {
unused.insert(field.to_string());
});
if let Err(err) = spec {
quit(&format!("{} {}", path, err.to_string()));
}
if !unused.is_empty() {
let err = unused.into_iter()
.map(|field| format!("{} unexpected field `{}`", path, field))
.collect::<Vec<_>>()
.join("\n");
quit(&err);
}
println!("{} is valid", path);
}

View File

@ -0,0 +1,23 @@
[package]
description = "OpenEthereum Account Management"
homepage = "https://github.com/openethereum/openethereum"
license = "GPL-3.0"
name = "ethcore-accounts"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
[dependencies]
common-types = { path = "../ethcore/types" }
ethkey = { path = "ethkey" }
ethstore = { path = "ethstore" }
log = "0.4"
parity-crypto = { version = "0.6.2", features = [ "publickey" ] }
parking_lot = "0.11.1"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
[dev-dependencies]
ethereum-types = "0.9.2"
tempdir = "0.3"

View File

@ -1,20 +1,20 @@
[package]
description = "Parity Ethereum Keys Generator"
name = "ethkey"
version = "0.3.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.0"
edit-distance = "2.0"
parity-crypto = "0.2"
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethereum-types = "0.4"
parity-crypto = { version = "0.6.2", features = ["publickey"] }
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1", rev = "9791e79f21a5309dcb6e0bd254b1ef88fca2f1f4" }
ethereum-types = "0.9.2"
lazy_static = "1.0"
log = "0.4"
mem = { path = "../util/mem" }
parity-wordlist = "1.2"
memzero = { path = "../../../crates/util/memzero" }
parity-wordlist = "1.3"
quick-error = "1.2.2"
rand = "0.4"
rand = "0.7.3"
rustc-hex = "1.0"
serde = "1.0"
serde_derive = "1.0"

View File

@ -5,8 +5,8 @@ Parity Ethereum keys generator.
### Usage
```
Parity Ethereum keys generator.
Copyright 2015-2018 Parity Technologies (UK) Ltd.
Parity Ethereum Keys Generator.
Copyright 2015-2019 Parity Technologies (UK) Ltd.
Usage:
ethkey info <secret-or-phrase> [options]
@ -216,6 +216,5 @@ _This project is a part of the Parity Ethereum toolchain._
- [evmbin](https://github.com/paritytech/parity-ethereum/blob/master/evmbin/) - EVM implementation for Parity Ethereum.
- [ethabi](https://github.com/paritytech/ethabi) - Parity Ethereum function calls encoding.
- [ethstore](https://github.com/paritytech/parity-ethereum/blob/master/ethstore/) - Parity Ethereum key management.
- [ethkey](https://github.com/paritytech/parity-ethereum/blob/master/ethkey/) - Parity Ethereum keys generator.
- [whisper](https://github.com/paritytech/parity-ethereum/blob/master/whisper/) - Implementation of Whisper-v2 PoC.
- [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.

View File

@ -0,0 +1,69 @@
// 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 parity_crypto::{
publickey::{KeyPair, Secret},
Keccak256,
};
use parity_wordlist;
/// Simple brainwallet.
pub struct Brain(String);
impl Brain {
pub fn new(s: String) -> Self {
Brain(s)
}
pub fn validate_phrase(phrase: &str, expected_words: usize) -> Result<(), ::WordlistError> {
parity_wordlist::validate_phrase(phrase, expected_words)
}
pub fn generate(&mut self) -> KeyPair {
let seed = self.0.clone();
let mut secret = seed.into_bytes().keccak256();
let mut i = 0;
loop {
secret = secret.keccak256();
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 pair;
}
}
}
}
}
}
}
#[cfg(test)]
mod tests {
use Brain;
#[test]
fn test_brain() {
let words = "this is sparta!".to_owned();
let first_keypair = Brain::new(words.clone()).generate();
let second_keypair = Brain::new(words.clone()).generate();
assert_eq!(first_keypair.secret(), second_keypair.secret());
}
}

View File

@ -0,0 +1,69 @@
// 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::Brain;
use parity_crypto::publickey::{Error, KeyPair};
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,
}
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 phrase(&self) -> &str {
&self.last_phrase
}
pub 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();
if keypair.address().as_ref().starts_with(&self.prefix) {
self.last_phrase = phrase;
return Ok(keypair);
}
}
Err(Error::Custom("Could not find keypair".into()))
}
}
#[cfg(test)]
mod tests {
use BrainPrefix;
#[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

@ -0,0 +1,177 @@
// 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::collections::HashSet;
use edit_distance::edit_distance;
use parity_crypto::publickey::Address;
use parity_wordlist;
use super::Brain;
/// Tries to find a phrase for address, given the number
/// of expected words and a partial phrase.
///
/// Returns `None` if phrase couldn't be found.
pub fn brain_recover(
address: &Address,
known_phrase: &str,
expected_words: usize,
) -> Option<String> {
let it = PhrasesIterator::from_known_phrase(known_phrase, expected_words);
for phrase in it {
let keypair = Brain::new(phrase.clone()).generate();
trace!("Testing: {}, got: {:?}", phrase, keypair.address());
if &keypair.address() == address {
return Some(phrase);
}
}
None
}
fn generate_substitutions(word: &str) -> Vec<&'static str> {
let mut words = parity_wordlist::WORDS
.iter()
.cloned()
.map(|w| (edit_distance(w, word), w))
.collect::<Vec<_>>();
words.sort_by(|a, b| a.0.cmp(&b.0));
words.into_iter().map(|pair| pair.1).collect()
}
/// Iterator over possible
pub struct PhrasesIterator {
words: Vec<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<_>>();
// add missing words
if words.len() < expected_words {
let to_add = expected_words - words.len();
info!("Number of words is insuficcient adding {} more.", to_add);
for _ in 0..to_add {
words.push(parity_wordlist::WORDS.iter().cloned().collect());
}
}
// start searching
PhrasesIterator::new(words)
}
pub fn new(words: Vec<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,
}
}
pub fn combinations(&self) -> u64 {
self.combinations
}
fn current(&self) -> String {
let mut s = self.words[0][self.indexes[0]].to_owned();
for i in 1..self.indexes.len() {
s.push(' ');
s.push_str(self.words[i][self.indexes[i]]);
}
s
}
fn next_index(&mut self) -> bool {
let mut pos = self.indexes.len();
while pos > 0 {
pos -= 1;
self.indexes[pos] += 1;
if self.indexes[pos] >= self.words[pos].len() {
self.indexes[pos] = 0;
} else {
return true;
}
}
false
}
}
impl Iterator for PhrasesIterator {
type Item = String;
fn next(&mut self) -> Option<String> {
if !self.has_next {
return None;
}
let phrase = self.current();
self.has_next = self.next_index();
Some(phrase)
}
}
#[cfg(test)]
mod tests {
use super::PhrasesIterator;
#[test]
fn should_generate_possible_combinations() {
let mut it =
PhrasesIterator::new(vec![vec!["1", "2", "3"], vec!["test"], vec!["a", "b", "c"]]);
assert_eq!(it.combinations(), 9);
assert_eq!(it.next(), Some("1 test a".to_owned()));
assert_eq!(it.next(), Some("1 test b".to_owned()));
assert_eq!(it.next(), Some("1 test c".to_owned()));
assert_eq!(it.next(), Some("2 test a".to_owned()));
assert_eq!(it.next(), Some("2 test b".to_owned()));
assert_eq!(it.next(), Some("2 test c".to_owned()));
assert_eq!(it.next(), Some("3 test a".to_owned()));
assert_eq!(it.next(), Some("3 test b".to_owned()));
assert_eq!(it.next(), Some("3 test c".to_owned()));
assert_eq!(it.next(), None);
}
}

View File

@ -0,0 +1,88 @@
// 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 crypto::Error as CryptoError;
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 {
format!("{:?}", &self)
}
}
impl Into<String> for Error {
fn into(self) -> String {
format!("{}", self)
}
}
impl From<CryptoError> for Error {
fn from(e: CryptoError) -> Error {
Error::Custom(e.to_string())
}
}
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

@ -0,0 +1,39 @@
// 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/>.
// #![warn(missing_docs)]
extern crate edit_distance;
extern crate parity_crypto;
extern crate parity_wordlist;
extern crate serde;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
mod brain;
mod brain_prefix;
mod password;
mod prefix;
pub mod brain_recover;
pub use self::{
brain::Brain, brain_prefix::BrainPrefix, parity_wordlist::Error as WordlistError,
password::Password, prefix::Prefix,
};

View File

@ -0,0 +1,59 @@
// 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::{fmt, ptr};
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Password(String);
impl fmt::Debug for Password {
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_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)
}
}
}
}
impl From<String> for Password {
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))
}
}

View File

@ -0,0 +1,54 @@
// 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 parity_crypto::publickey::{Error, Generator, KeyPair, Random};
/// Tries to find keypair with address starting with given prefix.
pub struct Prefix {
prefix: Vec<u8>,
iterations: usize,
}
impl Prefix {
pub fn new(prefix: Vec<u8>, iterations: usize) -> Self {
Prefix { prefix, iterations }
}
pub 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()))
}
}
#[cfg(test)]
mod tests {
use 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));
}
}

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