beta backports for 2.0.3 (#9229)

* parity-version: bump beta to 2.0.2

* remove ssl from dockerfiles, closes #8880 (#9195)

* snap: remove ssl dependencies from snapcraft definition (#9222)

* parity-version: bump beta to 2.0.3

* Remove all dapp permissions related settings (#9120)

* Completely remove all dapps struct from rpc

* Remove unused pub use

* Remove dapp policy/permission func in ethcore

* Remove all dapps settings from rpc

* Fix rpc tests

* Use both origin and user_agent

* Address grumbles

* Address grumbles

* Fix tests

* Check if synced when using eth_getWork (#9193) (#9210)

* Check if synced when using eth_getWork (#9193)

* Don't use fn syncing

* Fix identation

* Fix typo

* Don't check for warping

* rpc: avoid calling queue_info twice on eth_getWork

* Fix potential as_usize overflow when casting from U256 in miner (#9221)

* Allow old blocks from peers with lower difficulty (#9226)

Previously we only allow downloading of old blocks if the peer
difficulty was greater than our syncing difficulty. This change allows
downloading of blocks from peers where the difficulty is greater then
the last downloaded old block.

* Update Dockerfile (#9242)

* Update Dockerfile

fix Docker build

* fix dockerfile paths: parity -> parity-ethereum (#9248)

* Propagate transactions for next 4 blocks. (#9265)

Closes #9255 

This PR also removes the limit of max 64 transactions per packet, currently we only attempt to prevent the packet size to go over 8MB. This will only be the case for super-large transactions or high-block-gas-limit chains.

Patching this is important only for chains that have blocks that can fit more than 4k transactions (over 86M block gas limit)

For mainnet, we should actually see a tiny bit faster propagation since instead of computing 4k pending set, we only need `4 * 8M / 21k = 1523` transactions.

Running some tests on `dekompile` node right now, to check how it performs in the wild.

* Update tobalaba.json (#9313)

* Fix load share (#9321)

* fix(light_sync): calculate `load_share` properly

* refactor(api.rs): extract `light_params` fn, add test

* style(api.rs): add trailing commas

* ethcore: fix pow difficulty validation (#9328)

* ethcore: fix pow difficulty validation

* ethcore: validate difficulty is not zero

* ethcore: add issue link to regression test

* ethcore: fix tests

* ethcore: move difficulty_to_boundary to ethash crate

* ethcore: reuse difficulty_to_boundary and boundary_to_difficulty

* ethcore: fix grumbles in difficulty_to_boundary_aux

* Light client `Provide default nonce in transactions when it´s missing` (#9370)

* Provide `default_nonce` in tx`s when it´s missing

When `nonce` is missing in a `EthTransaction` will cause it to fall in
these cases provide `default_nonce` value instead!

* Changed http:// to https:// on Yasm link (#9369)

Changed http:// to https:// on Yasm link in README.md

* Provide `default_nonce` in tx`s when it´s missing

When `nonce` is missing in a `EthTransaction` will cause it to fall in
these cases provide `default_nonce` value instead!

* Address grumbles

* ethcore: kovan: delay activation of strict score validation (#9406)

* Better support for eth_getLogs in light mode (#9186)

* Light client on-demand request for headers range.

* Cache headers in HeaderWithAncestors response.

Also fulfills request locally if all headers are in cache.

* LightFetch::logs fetches missing headers on demand.

* LightFetch::logs limit the number of headers requested at a time.

* LightFetch::logs refactor header fetching logic.

* Enforce limit on header range length in light client logs request.

* Fix light request tests after struct change.

* Respond to review comments.

* Add update docs script to CI (#9219)

* Add update docs script to CI

Added a script to CI that will use the jsonrpc tool to update rpc
documentation then commit and push those to the wiki repo.

* fix gitlab ci lint

* Only apply jsonrpc docs update on tags

* Update gitlab-rpc-docs.sh

* Copy correct parity repo to jsonrpc folder

Copy correct parity repo to jsonrpc folder before attempting to build docs since the CI runner clones the repo as parity and not parity-ethereum.

* Fix JSONRPC docs CI job

Update remote config in wiki repo before pushing changes using a github
token for authentication. Add message to wiki tag when pushing changes.
Use project directory to correctly copy parity code base into the
jsonrpc repo for doc generation.

* Fix set_remote_wiki function call in CI

* Prevent blockchain & miner racing when accessing pending block. (#9310)

* Prevent blockchain & miner racing when accessing pending block.

* Fix unavailability of pending block during reseal.

* Prevent sync restart if import queue full (#9381)

* Add POA Networks: Core and Sokol (#9413)

* ethcore: add poa network and sokol chainspecs

* rpc: simplify chain spec docs

* cli: rearrange networks by main/test and size/range

* parity: don't blacklist 0x00a328 on sokol testnet

* parity: add sokol and poanet to params and clean up a bit, add tests

* ethcore: add the poa networks and clean up a bit

* ethcore: fix path to poacore chain spec

* parity: rename poa networks to poacore and poasokol

* parity: fix configuration tests

* parity: fix parameter tests

* ethcore: rename POA Core and POA Sokol

* Update tobalaba.json (#9419)

* Update hardcoded sync (#9421)

- Update foundation hardcoded header to block 6219777 
- Update ropsten hardcoded header to block 3917825 
- Update kovan hardcoded header to block 8511489
This commit is contained in:
Afri Schoedon 2018-08-31 15:44:12 +02:00 committed by GitHub
parent e7dc0bed16
commit a0a2beddfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
83 changed files with 1962 additions and 1583 deletions

View File

@ -2,6 +2,7 @@ stages:
- test
- push-release
- build
- docs
variables:
RUST_BACKTRACE: "1"
RUSTFLAGS: ""
@ -220,6 +221,15 @@ test-rust-nightly:
- rust
- rust-nightly
allow_failure: true
json-rpc-docs:
stage: docs
only:
- tags
image: parity/rust:gitlab-ci
script:
- scripts/gitlab-rpc-docs.sh
tags:
- docs
push-release:
stage: push-release
only:

134
Cargo.lock generated
View File

@ -76,7 +76,7 @@ name = "base64"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -85,7 +85,7 @@ name = "base64"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -94,7 +94,7 @@ name = "bincode"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -131,7 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "blooms-db"
version = "0.1.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -141,15 +141,16 @@ dependencies = [
[[package]]
name = "bn"
version = "0.4.4"
source = "git+https://github.com/paritytech/bn#964b48fad5dffbaa124c2f10699e76faf5846c4e"
source = "git+https://github.com/paritytech/bn#2a71dbde5ca93451c8da2135767896a64483759e"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byteorder"
version = "1.2.1"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@ -157,7 +158,7 @@ name = "bytes"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -217,6 +218,14 @@ dependencies = [
"vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cmake"
version = "0.1.31"
@ -310,6 +319,11 @@ name = "crunchy"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "crunchy"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ct-logs"
version = "0.2.0"
@ -456,8 +470,9 @@ version = "1.12.0"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -483,7 +498,7 @@ dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"blooms-db 0.1.0",
"bn 0.4.4 (git+https://github.com/paritytech/bn)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -518,7 +533,7 @@ dependencies = [
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0",
"memory-cache 0.1.0",
"memorydb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
"num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -593,7 +608,7 @@ dependencies = [
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memory-cache 0.1.0",
"memorydb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
@ -747,7 +762,7 @@ dependencies = [
name = "ethcore-secretstore"
version = "1.0.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -821,6 +836,7 @@ dependencies = [
name = "ethcore-sync"
version = "1.12.0"
dependencies = [
"common-types 0.1.0",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0",
"ethcore-io 1.12.0",
@ -904,7 +920,7 @@ dependencies = [
name = "ethkey"
version = "0.3.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1158,7 +1174,7 @@ dependencies = [
[[package]]
name = "hashdb"
version = "0.2.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1316,7 +1332,7 @@ dependencies = [
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"memorydb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -1422,7 +1438,7 @@ dependencies = [
[[package]]
name = "keccak-hash"
version = "0.1.2"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1450,7 +1466,7 @@ dependencies = [
[[package]]
name = "kvdb"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -1459,7 +1475,7 @@ dependencies = [
[[package]]
name = "kvdb-memorydb"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1468,7 +1484,7 @@ dependencies = [
[[package]]
name = "kvdb-rocksdb"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1638,8 +1654,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memorydb"
version = "0.2.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
version = "0.2.1"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
@ -1908,19 +1924,19 @@ dependencies = [
[[package]]
name = "parity-bytes"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
[[package]]
name = "parity-clib"
version = "1.12.0"
dependencies = [
"parity-ethereum 2.0.1",
"parity-ethereum 2.0.3",
]
[[package]]
name = "parity-crypto"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1931,7 +1947,7 @@ dependencies = [
[[package]]
name = "parity-ethereum"
version = "2.0.1"
version = "2.0.3"
dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1980,7 +1996,7 @@ dependencies = [
"parity-rpc 1.12.0",
"parity-rpc-client 1.4.0",
"parity-updater 1.12.0",
"parity-version 2.0.1",
"parity-version 2.0.3",
"parity-whisper 0.1.0",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"path 0.1.1 (git+https://github.com/paritytech/parity-common)",
@ -2119,9 +2135,10 @@ dependencies = [
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-reactor 0.1.0",
"parity-updater 1.12.0",
"parity-version 2.0.1",
"parity-version 2.0.3",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
@ -2189,7 +2206,7 @@ dependencies = [
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-hash-fetch 1.12.0",
"parity-version 2.0.1",
"parity-version 2.0.3",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"path 0.1.1 (git+https://github.com/paritytech/parity-common)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2200,7 +2217,7 @@ dependencies = [
[[package]]
name = "parity-version"
version = "2.0.1"
version = "2.0.3"
dependencies = [
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
@ -2215,7 +2232,7 @@ name = "parity-wasm"
version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2223,7 +2240,7 @@ name = "parity-whisper"
version = "0.1.0"
dependencies = [
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-network 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0",
@ -2283,12 +2300,12 @@ dependencies = [
[[package]]
name = "path"
version = "0.1.1"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
[[package]]
name = "patricia-trie"
version = "0.2.1"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
@ -2363,7 +2380,7 @@ dependencies = [
[[package]]
name = "plain_hasher"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2476,7 +2493,7 @@ name = "pwasm-utils"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2513,6 +2530,23 @@ dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rayon"
version = "1.0.1"
@ -2599,9 +2633,9 @@ dependencies = [
[[package]]
name = "rlp"
version = "0.2.1"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3276,7 +3310,7 @@ dependencies = [
[[package]]
name = "trie-standardmap"
version = "0.1.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
@ -3287,7 +3321,7 @@ dependencies = [
[[package]]
name = "triehash"
version = "0.2.0"
source = "git+https://github.com/paritytech/parity-common#5f05acd90cf173f2e1ce477665be2a40502fef42"
source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c962a0b27e2caf3b9474"
dependencies = [
"elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3309,7 +3343,7 @@ name = "uint"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3426,7 +3460,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "vm"
version = "0.1.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethjson 0.1.0",
@ -3447,7 +3481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "wasm"
version = "0.1.0"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-logger 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3463,7 +3497,7 @@ name = "wasmi"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3539,7 +3573,7 @@ name = "ws"
version = "0.7.5"
source = "git+https://github.com/tomusdrw/ws-rs#f12d19c4c19422fc79af28a3181f598bc07ecd1e"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3599,13 +3633,14 @@ dependencies = [
"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum bn 0.4.4 (git+https://github.com/paritytech/bn)" = "<none>"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "74c0b906e9446b0a2e4f760cdb3fa4b2c48cdc6db8766a845c54b6ff063fd2e9"
"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9"
"checksum cc 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "49ec142f5768efb5b7622aebc3fdbdbb8950a4b9ba996393cb76ef7466e8747d"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6"
"checksum cid 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d85ee025368e69063c420cbb2ed9f852cb03a5e69b73be021e65726ce03585b6"
"checksum clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8f4a2b3bb7ef3c672d7c13d15613211d5a6976b6892c598b0fcb5d40765f19c2"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "95470235c31c726d72bf2e1f421adc1e65b9d561bf5529612cbe1a72da1467b3"
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
"checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3"
@ -3615,6 +3650,7 @@ dependencies = [
"checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
"checksum crossbeam-utils 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d636a8b3bcc1b409d7ffd3facef8f21dcb4009626adbd0c5e6c4305c07253c7b"
"checksum crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a2f4a431c5c9f662e1200b7c7f02c34e91361150e382089a8f2dec3ba680cbda"
"checksum crunchy 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c240f247c278fa08a6d4820a6a222bfc6e0d999e51ba67be94f44c905b2161f2"
"checksum ct-logs 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "61cd11fb222fecf889f4531855c614548e92e8bd2eb178e35296885df5ee9a7c"
"checksum ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)" = "<none>"
"checksum daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)" = "<none>"
@ -3696,7 +3732,7 @@ dependencies = [
"checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
"checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
"checksum memorydb 0.2.0 (git+https://github.com/paritytech/parity-common)" = "<none>"
"checksum memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)" = "<none>"
"checksum mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e3d709ffbb330e1566dc2f2a3c9b58a5ad4a381f740b810cd305dc3f089bc160"
"checksum mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27a5e6679a0614e25adc14c6434ba84e41632b765a6d9cb2031a0cca682699ae"
"checksum mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)" = "6d771e3ef92d58a8da8df7d6976bfca9371ed1de6619d9d5a5ce5b1f29b85bfe"
@ -3752,6 +3788,8 @@ dependencies = [
"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a"
"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1"
"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5"
"checksum rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "12397506224b2f93e6664ffc4f664b29be8208e5157d3d90b44f09b5fae470ea"
"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2"
"checksum rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80e811e76f1dbf68abf87a759083d34600017fc4e10b6bd5ad84a700f9dba4b1"
"checksum rayon-core 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d24ad214285a7729b174ed6d3bcfcb80177807f959d95fafd5bfc5c4f201ac8"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"

View File

@ -2,7 +2,7 @@
description = "Parity Ethereum client"
name = "parity-ethereum"
# NOTE Make sure to update util/version/Cargo.toml as well
version = "2.0.1"
version = "2.0.3"
license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"]

View File

@ -23,24 +23,6 @@ RUN /usr/local/android-ndk-r16b/build/tools/make-standalone-toolchain.sh \
--arch=arm --install-dir=/opt/ndk-standalone --stl=libc++ --platform=android-26
ENV PATH $PATH:/opt/ndk-standalone/bin
# Compiling OpenSSL for Android
RUN cd /root && \
git clone git://git.openssl.org/openssl.git && \
cd openssl && \
git checkout OpenSSL_1_1_0-stable
ENV CROSS_SYSROOT /opt/ndk-standalone/sysroot
RUN cd /root/openssl && \
./Configure android-armeabi --cross-compile-prefix=arm-linux-androideabi- \
-static no-stdio no-ui \
-I/usr/local/android-ndk-r16b/sysroot/usr/include \
-I/usr/local/android-ndk-r16b/sysroot/usr/include/arm-linux-androideabi \
-L/usr/local/android-ndk-r16b/sysroot/usr/lib \
--prefix=/opt/ndk-standalone/sysroot/usr
RUN cd /root/openssl && \
make build_libs && \
make install_dev
RUN rm -rf /root/openssl
# Compiling libudev for Android
# This is the most hacky part of the process, as we need to apply a patch and pass specific
# options that the compiler environment doesn't define.

View File

@ -23,8 +23,6 @@ RUN apt-get update && \
libc6-dev \
binutils \
file \
openssl \
libssl-dev \
libudev-dev \
pkg-config \
dpkg-dev \
@ -36,13 +34,13 @@ RUN apt-get update && \
# show backtraces
RUST_BACKTRACE=1 && \
# build parity
cd /build&&git clone https://github.com/paritytech/parity && \
cd parity && \
cd /build&&git clone https://github.com/paritytech/parity-ethereum && \
cd parity-ethereum && \
git pull&& \
git checkout $BUILD_TAG && \
cargo build --verbose --release --features final && \
strip /build/parity/target/release/parity && \
file /build/parity/target/release/parity&&mkdir -p /parity&& cp /build/parity/target/release/parity /parity&&\
strip /build/parity-ethereum/target/release/parity && \
file /build/parity-ethereum/target/release/parity&&mkdir -p /parity&& cp /build/parity-ethereum/target/release/parity /parity&&\
#cleanup Docker image
rm -rf /root/.cargo&&rm -rf /root/.multirust&&rm -rf /root/.rustup&&rm -rf /build&&\
apt-get purge -y \

View File

@ -11,7 +11,6 @@ RUN apt-get update && \
git \
file \
binutils \
libssl-dev \
pkg-config \
libudev-dev

View File

@ -6,13 +6,14 @@ authors = ["Parity Technologies <admin@parity.io>"]
[lib]
[dependencies]
log = "0.3"
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
primal = "0.2.3"
parking_lot = "0.6"
crunchy = "0.1.0"
memmap = "0.6"
either = "1.0.0"
ethereum-types = "0.3"
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
log = "0.4"
memmap = "0.6"
parking_lot = "0.6"
primal = "0.2.3"
[dev-dependencies]
tempdir = "0.3"

View File

@ -16,10 +16,11 @@
#![cfg_attr(feature = "benches", feature(test))]
extern crate primal;
extern crate parking_lot;
extern crate either;
extern crate ethereum_types;
extern crate memmap;
extern crate parking_lot;
extern crate primal;
#[macro_use]
extern crate crunchy;
@ -38,6 +39,7 @@ mod shared;
pub use cache::{NodeCacheBuilder, OptimizeFor};
pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number};
use compute::Light;
use ethereum_types::{U256, U512};
use keccak::H256;
use parking_lot::Mutex;
pub use seed_compute::SeedHashCompute;
@ -136,6 +138,29 @@ impl EthashManager {
}
}
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
pub fn boundary_to_difficulty(boundary: &ethereum_types::H256) -> U256 {
difficulty_to_boundary_aux(&**boundary)
}
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 {
difficulty_to_boundary_aux(difficulty).into()
}
fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U256 {
let difficulty = difficulty.into();
assert!(!difficulty.is_zero());
if difficulty == U512::one() {
U256::max_value()
} else {
// difficulty > 1, so result should never overflow 256 bits
U256::from((U512::one() << 256) / difficulty)
}
}
#[test]
fn test_lru() {
use tempdir::TempDir;
@ -155,6 +180,43 @@ fn test_lru() {
assert_eq!(ethash.cache.lock().prev_epoch.unwrap(), 0);
}
#[test]
fn test_difficulty_to_boundary() {
use ethereum_types::H256;
use std::str::FromStr;
assert_eq!(difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
assert_eq!(difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
assert_eq!(difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
assert_eq!(difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
}
#[test]
fn test_difficulty_to_boundary_regression() {
use ethereum_types::H256;
// the last bit was originally being truncated when performing the conversion
// https://github.com/paritytech/parity-ethereum/issues/8397
for difficulty in 1..9 {
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into())));
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into())));
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into()));
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into()));
}
}
#[test]
#[should_panic]
fn test_difficulty_to_boundary_panics_on_zero() {
difficulty_to_boundary(&U256::from(0));
}
#[test]
#[should_panic]
fn test_boundary_to_difficulty_panics_on_zero() {
boundary_to_difficulty(&ethereum_types::H256::from(0));
}
#[cfg(feature = "benches")]
mod benchmarks {
extern crate test;

View File

@ -43,7 +43,7 @@ pub mod provider;
mod types;
pub use self::cache::Cache;
pub use self::provider::Provider;
pub use self::provider::{Provider, MAX_HEADERS_PER_REQUEST};
pub use self::transaction_queue::TransactionQueue;
pub use types::request as request;

View File

@ -70,9 +70,6 @@ const PROPAGATE_TIMEOUT_INTERVAL: Duration = Duration::from_secs(5);
const RECALCULATE_COSTS_TIMEOUT: TimerToken = 3;
const RECALCULATE_COSTS_INTERVAL: Duration = Duration::from_secs(60 * 60);
/// Max number of transactions in a single packet.
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
// minimum interval between updates.
const UPDATE_INTERVAL: Duration = Duration::from_millis(5000);
@ -648,7 +645,7 @@ impl LightProtocol {
fn propagate_transactions(&self, io: &IoContext) {
if self.capabilities.read().tx_relay { return }
let ready_transactions = self.provider.ready_transactions(MAX_TRANSACTIONS_TO_PROPAGATE);
let ready_transactions = self.provider.transactions_to_propagate();
if ready_transactions.is_empty() { return }
trace!(target: "pip", "propagate transactions: {} ready", ready_transactions.len());

View File

@ -171,8 +171,8 @@ impl Provider for TestProvider {
})
}
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
self.0.client.ready_transactions(max_len)
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
self.0.client.transactions_to_propagate()
}
}

View File

@ -204,6 +204,8 @@ fn guess_capabilities(requests: &[CheckedRequest]) -> Capabilities {
caps.serve_headers = true,
CheckedRequest::HeaderByHash(_, _) =>
caps.serve_headers = true,
CheckedRequest::HeaderWithAncestors(_, _) =>
caps.serve_headers = true,
CheckedRequest::TransactionIndex(_, _) => {} // hashes yield no info.
CheckedRequest::Signal(_, _) =>
caps.serve_headers = true,

View File

@ -16,6 +16,7 @@
//! Request types, verification, and verification errors.
use std::cmp;
use std::sync::Arc;
use bytes::Bytes;
@ -47,6 +48,8 @@ pub enum Request {
HeaderProof(HeaderProof),
/// A request for a header by hash.
HeaderByHash(HeaderByHash),
/// A request for a header by hash with a range of its ancestors.
HeaderWithAncestors(HeaderWithAncestors),
/// A request for the index of a transaction.
TransactionIndex(TransactionIndex),
/// A request for block receipts.
@ -136,6 +139,7 @@ macro_rules! impl_single {
// implement traits for each kind of request.
impl_single!(HeaderProof, HeaderProof, (H256, U256));
impl_single!(HeaderByHash, HeaderByHash, encoded::Header);
impl_single!(HeaderWithAncestors, HeaderWithAncestors, Vec<encoded::Header>);
impl_single!(TransactionIndex, TransactionIndex, net_request::TransactionIndexResponse);
impl_single!(Receipts, BlockReceipts, Vec<Receipt>);
impl_single!(Body, Body, encoded::Block);
@ -246,6 +250,7 @@ impl From<encoded::Header> for HeaderRef {
pub enum CheckedRequest {
HeaderProof(HeaderProof, net_request::IncompleteHeaderProofRequest),
HeaderByHash(HeaderByHash, net_request::IncompleteHeadersRequest),
HeaderWithAncestors(HeaderWithAncestors, net_request::IncompleteHeadersRequest),
TransactionIndex(TransactionIndex, net_request::IncompleteTransactionIndexRequest),
Receipts(BlockReceipts, net_request::IncompleteReceiptsRequest),
Body(Body, net_request::IncompleteBodyRequest),
@ -267,6 +272,16 @@ impl From<Request> for CheckedRequest {
};
CheckedRequest::HeaderByHash(req, net_req)
}
Request::HeaderWithAncestors(req) => {
let net_req = net_request::IncompleteHeadersRequest {
start: req.block_hash.map(Into::into),
skip: 0,
max: req.ancestor_count + 1,
reverse: true,
};
trace!(target: "on_demand", "HeaderWithAncestors Request, {:?}", net_req);
CheckedRequest::HeaderWithAncestors(req, net_req)
}
Request::HeaderProof(req) => {
let net_req = net_request::IncompleteHeaderProofRequest {
num: req.num().into(),
@ -335,6 +350,7 @@ impl CheckedRequest {
match self {
CheckedRequest::HeaderProof(_, req) => NetRequest::HeaderProof(req),
CheckedRequest::HeaderByHash(_, req) => NetRequest::Headers(req),
CheckedRequest::HeaderWithAncestors(_, req) => NetRequest::Headers(req),
CheckedRequest::TransactionIndex(_, req) => NetRequest::TransactionIndex(req),
CheckedRequest::Receipts(_, req) => NetRequest::Receipts(req),
CheckedRequest::Body(_, req) => NetRequest::Body(req),
@ -390,6 +406,27 @@ impl CheckedRequest {
None
}
CheckedRequest::HeaderWithAncestors(_, ref req) => {
if req.skip != 1 || !req.reverse {
return None;
}
if let Some(&net_request::HashOrNumber::Hash(start)) = req.start.as_ref() {
let mut result = Vec::with_capacity(req.max as usize);
let mut hash = start;
let mut cache = cache.lock();
for _ in 0..req.max {
match cache.block_header(&hash) {
Some(header) => {
hash = header.parent_hash();
result.push(header);
}
None => return None,
}
}
Some(Response::HeaderWithAncestors(result))
} else { None }
}
CheckedRequest::Receipts(ref check, ref req) => {
// empty transactions -> no receipts
if check.0.as_ref().ok().map_or(false, |hdr| hdr.receipts_root() == KECCAK_NULL_RLP) {
@ -458,6 +495,7 @@ macro_rules! match_me {
match $me {
CheckedRequest::HeaderProof($check, $req) => $e,
CheckedRequest::HeaderByHash($check, $req) => $e,
CheckedRequest::HeaderWithAncestors($check, $req) => $e,
CheckedRequest::TransactionIndex($check, $req) => $e,
CheckedRequest::Receipts($check, $req) => $e,
CheckedRequest::Body($check, $req) => $e,
@ -487,6 +525,15 @@ impl IncompleteRequest for CheckedRequest {
_ => Ok(()),
}
}
CheckedRequest::HeaderWithAncestors(ref check, ref req) => {
req.check_outputs(&mut f)?;
// make sure the output given is definitively a hash.
match check.block_hash {
Field::BackReference(r, idx) => f(r, idx, OutputKind::Hash),
_ => Ok(()),
}
}
CheckedRequest::TransactionIndex(_, ref req) => req.check_outputs(f),
CheckedRequest::Receipts(_, ref req) => req.check_outputs(f),
CheckedRequest::Body(_, ref req) => req.check_outputs(f),
@ -507,15 +554,46 @@ impl IncompleteRequest for CheckedRequest {
fn complete(self) -> Result<Self::Complete, net_request::NoSuchOutput> {
match self {
CheckedRequest::HeaderProof(_, req) => req.complete().map(CompleteRequest::HeaderProof),
CheckedRequest::HeaderByHash(_, req) => req.complete().map(CompleteRequest::Headers),
CheckedRequest::TransactionIndex(_, req) => req.complete().map(CompleteRequest::TransactionIndex),
CheckedRequest::Receipts(_, req) => req.complete().map(CompleteRequest::Receipts),
CheckedRequest::Body(_, req) => req.complete().map(CompleteRequest::Body),
CheckedRequest::Account(_, req) => req.complete().map(CompleteRequest::Account),
CheckedRequest::Code(_, req) => req.complete().map(CompleteRequest::Code),
CheckedRequest::Execution(_, req) => req.complete().map(CompleteRequest::Execution),
CheckedRequest::Signal(_, req) => req.complete().map(CompleteRequest::Signal),
CheckedRequest::HeaderProof(_, req) => {
trace!(target: "on_demand", "HeaderProof request completed {:?}", req);
req.complete().map(CompleteRequest::HeaderProof)
}
CheckedRequest::HeaderByHash(_, req) => {
trace!(target: "on_demand", "HeaderByHash request completed {:?}", req);
req.complete().map(CompleteRequest::Headers)
}
CheckedRequest::HeaderWithAncestors(_, req) => {
trace!(target: "on_demand", "HeaderWithAncestors request completed {:?}", req);
req.complete().map(CompleteRequest::Headers)
}
CheckedRequest::TransactionIndex(_, req) => {
trace!(target: "on_demand", "TransactionIndex request completed {:?}", req);
req.complete().map(CompleteRequest::TransactionIndex)
}
CheckedRequest::Receipts(_, req) => {
trace!(target: "on_demand", "Receipt request completed {:?}", req);
req.complete().map(CompleteRequest::Receipts)
}
CheckedRequest::Body(_, req) => {
trace!(target: "on_demand", "Block request completed {:?}", req);
req.complete().map(CompleteRequest::Body)
}
CheckedRequest::Account(_, req) => {
trace!(target: "on_demand", "Account request completed {:?}", req);
req.complete().map(CompleteRequest::Account)
}
CheckedRequest::Code(_, req) => {
trace!(target: "on_demand", "Code request completed {:?}", req);
req.complete().map(CompleteRequest::Code)
}
CheckedRequest::Execution(_, req) => {
trace!(target: "on_demand", "Execution request completed {:?}", req);
req.complete().map(CompleteRequest::Execution)
}
CheckedRequest::Signal(_, req) => {
trace!(target: "on_demand", "Signal request completed {:?}", req);
req.complete().map(CompleteRequest::Signal)
}
}
}
@ -551,6 +629,9 @@ impl net_request::CheckedRequest for CheckedRequest {
CheckedRequest::HeaderByHash(ref prover, _) =>
expect!((&NetResponse::Headers(ref res), &CompleteRequest::Headers(ref req)) =>
prover.check_response(cache, &req.start, &res.headers).map(Response::HeaderByHash)),
CheckedRequest::HeaderWithAncestors(ref prover, _) =>
expect!((&NetResponse::Headers(ref res), &CompleteRequest::Headers(ref req)) =>
prover.check_response(cache, &req.start, &res.headers).map(Response::HeaderWithAncestors)),
CheckedRequest::TransactionIndex(ref prover, _) =>
expect!((&NetResponse::TransactionIndex(ref res), _) =>
prover.check_response(cache, res).map(Response::TransactionIndex)),
@ -584,6 +665,8 @@ pub enum Response {
HeaderProof((H256, U256)),
/// Response to a header-by-hash request.
HeaderByHash(encoded::Header),
/// Response to a header-by-hash with ancestors request.
HeaderWithAncestors(Vec<encoded::Header>),
/// Response to a transaction-index request.
TransactionIndex(net_request::TransactionIndexResponse),
/// Response to a receipts request.
@ -625,6 +708,10 @@ pub enum Error {
Decoder(::rlp::DecoderError),
/// Empty response.
Empty,
/// Response data length exceeds request max.
TooManyResults(u64, u64),
/// Response data is incomplete.
TooFewResults(u64, u64),
/// Trie lookup error (result of bad proof)
Trie(TrieError),
/// Bad inclusion proof
@ -641,6 +728,8 @@ pub enum Error {
WrongTrieRoot(H256, H256),
/// Wrong response kind.
WrongKind,
/// Wrong sequence of headers.
WrongHeaderSequence,
}
impl From<::rlp::DecoderError> for Error {
@ -701,6 +790,65 @@ impl HeaderProof {
}
}
/// Request for a header by hash with a range of ancestors.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HeaderWithAncestors {
/// Hash of the last block in the range to fetch.
pub block_hash: Field<H256>,
/// Number of headers before the last block to fetch in addition.
pub ancestor_count: u64,
}
impl HeaderWithAncestors {
/// Check a response for the headers.
pub fn check_response(
&self,
cache: &Mutex<::cache::Cache>,
start: &net_request::HashOrNumber,
headers: &[encoded::Header]
) -> Result<Vec<encoded::Header>, Error> {
let expected_hash = match (self.block_hash, start) {
(Field::Scalar(ref h), &net_request::HashOrNumber::Hash(ref h2)) => {
if h != h2 { return Err(Error::WrongHash(*h, *h2)) }
*h
}
(_, &net_request::HashOrNumber::Hash(h2)) => h2,
_ => return Err(Error::HeaderByNumber),
};
let start_header = headers.first().ok_or(Error::Empty)?;
let start_hash = start_header.hash();
if start_hash != expected_hash {
return Err(Error::WrongHash(expected_hash, start_hash));
}
let expected_len = 1 + cmp::min(self.ancestor_count, start_header.number());
let actual_len = headers.len() as u64;
match actual_len.cmp(&expected_len) {
cmp::Ordering::Less =>
return Err(Error::TooFewResults(expected_len, actual_len)),
cmp::Ordering::Greater =>
return Err(Error::TooManyResults(expected_len, actual_len)),
cmp::Ordering::Equal => (),
};
for (header, prev_header) in headers.iter().zip(headers[1..].iter()) {
if header.number() != prev_header.number() + 1 ||
header.parent_hash() != prev_header.hash()
{
return Err(Error::WrongHeaderSequence)
}
}
let mut cache = cache.lock();
for header in headers {
cache.insert_block_header(header.hash(), header.clone());
}
Ok(headers.to_vec())
}
}
/// Request for a header by hash.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct HeaderByHash(pub Field<H256>);
@ -993,6 +1141,83 @@ mod tests {
assert!(HeaderByHash(hash.into()).check_response(&cache, &hash.into(), &[raw_header]).is_ok())
}
#[test]
fn check_header_with_ancestors() {
let mut last_header_hash = H256::default();
let mut headers = (0..11).map(|num| {
let mut header = Header::new();
header.set_number(num);
header.set_parent_hash(last_header_hash);
last_header_hash = header.hash();
header
}).collect::<Vec<_>>();
headers.reverse(); // because responses are in reverse order
let raw_headers = headers.iter()
.map(|hdr| encoded::Header::new(::rlp::encode(hdr).into_vec()))
.collect::<Vec<_>>();
let mut invalid_successor = Header::new();
invalid_successor.set_number(11);
invalid_successor.set_parent_hash(headers[1].hash());
let raw_invalid_successor = encoded::Header::new(::rlp::encode(&invalid_successor).into_vec());
let cache = Mutex::new(make_cache());
let header_with_ancestors = |hash, count| {
HeaderWithAncestors {
block_hash: hash,
ancestor_count: count
}
};
// Correct responses
assert!(header_with_ancestors(headers[0].hash().into(), 0)
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..1]).is_ok());
assert!(header_with_ancestors(headers[0].hash().into(), 2)
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..3]).is_ok());
assert!(header_with_ancestors(headers[0].hash().into(), 10)
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..11]).is_ok());
assert!(header_with_ancestors(headers[2].hash().into(), 2)
.check_response(&cache, &headers[2].hash().into(), &raw_headers[2..5]).is_ok());
assert!(header_with_ancestors(headers[2].hash().into(), 10)
.check_response(&cache, &headers[2].hash().into(), &raw_headers[2..11]).is_ok());
assert!(header_with_ancestors(invalid_successor.hash().into(), 0)
.check_response(&cache, &invalid_successor.hash().into(), &[raw_invalid_successor.clone()]).is_ok());
// Incorrect responses
assert_eq!(header_with_ancestors(invalid_successor.hash().into(), 0)
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..1]),
Err(Error::WrongHash(invalid_successor.hash(), headers[0].hash())));
assert_eq!(header_with_ancestors(headers[0].hash().into(), 0)
.check_response(&cache, &headers[0].hash().into(), &[]),
Err(Error::Empty));
assert_eq!(header_with_ancestors(headers[0].hash().into(), 10)
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..10]),
Err(Error::TooFewResults(11, 10)));
assert_eq!(header_with_ancestors(headers[0].hash().into(), 9)
.check_response(&cache, &headers[0].hash().into(), &raw_headers[0..11]),
Err(Error::TooManyResults(10, 11)));
let response = &[raw_headers[0].clone(), raw_headers[2].clone()];
assert_eq!(header_with_ancestors(headers[0].hash().into(), 1)
.check_response(&cache, &headers[0].hash().into(), response),
Err(Error::WrongHeaderSequence));
let response = &[raw_invalid_successor.clone(), raw_headers[0].clone()];
assert_eq!(header_with_ancestors(invalid_successor.hash().into(), 1)
.check_response(&cache, &invalid_successor.hash().into(), response),
Err(Error::WrongHeaderSequence));
let response = &[raw_invalid_successor.clone(), raw_headers[1].clone()];
assert_eq!(header_with_ancestors(invalid_successor.hash().into(), 1)
.check_response(&cache, &invalid_successor.hash().into(), response),
Err(Error::WrongHeaderSequence));
}
#[test]
fn check_body() {
use rlp::RlpStream;

View File

@ -33,6 +33,9 @@ use transaction_queue::TransactionQueue;
use request;
/// Maximum allowed size of a headers request.
pub const MAX_HEADERS_PER_REQUEST: u64 = 512;
/// Defines the operations that a provider for the light subprotocol must fulfill.
pub trait Provider: Send + Sync {
/// Provide current blockchain info.
@ -54,7 +57,6 @@ pub trait Provider: Send + Sync {
/// results within must adhere to the `skip` and `reverse` parameters.
fn block_headers(&self, req: request::CompleteHeadersRequest) -> Option<request::HeadersResponse> {
use request::HashOrNumber;
const MAX_HEADERS_TO_SEND: u64 = 512;
if req.max == 0 { return None }
@ -83,7 +85,7 @@ pub trait Provider: Send + Sync {
}
};
let max = ::std::cmp::min(MAX_HEADERS_TO_SEND, req.max);
let max = ::std::cmp::min(MAX_HEADERS_PER_REQUEST, req.max);
let headers: Vec<_> = (0u64..max)
.map(|x: u64| x.saturating_mul(req.skip.saturating_add(1)))
@ -128,7 +130,7 @@ pub trait Provider: Send + Sync {
fn header_proof(&self, req: request::CompleteHeaderProofRequest) -> Option<request::HeaderProofResponse>;
/// Provide pending transactions.
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction>;
fn transactions_to_propagate(&self) -> Vec<PendingTransaction>;
/// Provide a proof-of-execution for the given transaction proof request.
/// Returns a vector of all state items necessary to execute the transaction.
@ -283,8 +285,8 @@ impl<T: ProvingBlockChainClient + ?Sized> Provider for T {
.map(|(_, proof)| ::request::ExecutionResponse { items: proof })
}
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
BlockChainClient::ready_transactions(self, max_len)
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
BlockChainClient::transactions_to_propagate(self)
.into_iter()
.map(|tx| tx.pending().clone())
.collect()
@ -370,12 +372,10 @@ impl<L: AsLightClient + Send + Sync> Provider for LightProvider<L> {
None
}
fn ready_transactions(&self, max_len: usize) -> Vec<PendingTransaction> {
fn transactions_to_propagate(&self) -> Vec<PendingTransaction> {
let chain_info = self.chain_info();
let mut transactions = self.txqueue.read()
.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp);
transactions.truncate(max_len);
transactions
self.txqueue.read()
.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
}
}

View File

@ -174,8 +174,8 @@
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
},
"hardcodedSync": {
"header": "f9020ba0bb120488b73cb04a3c423dfa6760eb631165fa3d6d8e0b1be360d3e2a00add78a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452e44f279f4203dcf680395379e5f9990a69f13ca02d2cbb3c43370257122898259f1e06da38fd23031f74b40d6bd022b037ecd3daa0107b3a01662ca77aa1c72cde45bd66c062d781310d7a364e5b6442bd791431cea011e451bfe7b89addb96020182e0e7eb448d0a66303924a2835a149247bea4188b90100000000200004820000130000020000322004002000140000801000081208000880800200100000000a080000000800400000000000080240800000020028a100000400410000001088008008400080000100000000200000000220804028000000302000000180200c004644000000000101800000040040020200100020100220200a00000000280002011040000000000080a00000002002048000100001000206000000c000002010000004800030000000000300884008121000208020080000020280000000010104002000004000002084000c08402820000004000001841109008410040410080080004121044080800800000000004858040000c000870c64944ccfd130835aa801837a212d8320dc6b845b452c758a7777772e62772e636f6da02078861f3b30aaea6fad290d86919dd7542433a56edc1af557426cbd2eacd60d88a68a26940894b23f",
"totalDifficulty": "5282739680501645457616",
"header": "f9020ba0c7139a7f4b14c2e12dbe34aeb92711b37747bf8698ecdd6f2c3b1f5f3840e288a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452e44f279f4203dcf680395379e5f9990a69f13ca06e817f8a9b206f93a393da76a3ece2a74b98eaecc4dae0cfa8f409455e88ccb4a0d739197170d2bc6bbb24fac0ce695982090702082fe1541bb7634f018dfe87b3a038503b7299fb1c113a78b4a3a5dfd997ef32e7fbf722fc178dfcb21e1af1f7f5b9010000020000000000000008000000000010000000000000000000000000000200000002000000000008000000000000000000000000000000000000000000000000000000000000000001004008000000000000000000000000000080000000000008000000080000000000008000000000000000000000000000040210004000000010000000400000000001040000000200000000000000440008000000040000000000000000000000000010000000000000000000000000000000800000000000100002000000000000000000002000000000000000000000000000000000000080000000100000000000000000040400000000000000004000000000000000870c90e059b181c6835ee8018379fb9583065150845b833d198a7777772e62772e636f6da0171fc2d066507ea10c8c2d7bedd5ccc3f0dfb4d590a3998a614013326c0b213a88b4fd884826187393",
"totalDifficulty": "6255555800944520547241",
"CHTs": [
"0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc",
"0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11",
@ -3077,7 +3077,143 @@
"0x8a5cb6854c19a865f51e3ee9eaf8e843a97b272f6467634ba40e547a435ef624",
"0x9afe42a0dffca8ec063c83908fd6237d6130c9dfeab57078bdd02b6ac6d0ea07",
"0xa05cc6108b475d3e68e280e98f514cfb6df4f004e1b7708fcfd4528d346bea6b",
"0x71f10879b875caefab46669e8525b9c0487bbe3247e43a6cdb1dedbfb4d4ba33"
"0x71f10879b875caefab46669e8525b9c0487bbe3247e43a6cdb1dedbfb4d4ba33",
"0x7debdafd2b1410469fd76e2a39dcd1b8f400292f5359ecd39186a5be0f9e44b8",
"0x076f8741b668f3f715a7142f5c1592ffb58ca13e8612edc340619a1ca6ce3f2a",
"0xe312bb85cd945eb45f72868e6651633964f22ce3ffcbd0f3701bf57ac0c13edd",
"0xe6eae7aad7fed9c690a14eb7aa107c83a5e54736940ac6d82e251181e1103eae",
"0x794c8ade9063600442f83d4be14d7bbb191c692314253a2c62dcb33f3e7d28bd",
"0x6fd9db41dc1074a4349a6d3881757ad931bdf9ec261fc4e0a5ba9cfa5fafbf41",
"0x37557ead7100564651992a919949af3f39f3eacc03aa0ea158dd59abc4e2a93d",
"0x7a3b01cf210dfc42e4e41c95af1af357d15409fecae888abf4fa35149f44ed2e",
"0x89e952ed9afda8aa0ff80ceb90e5857dc7fc3cb6259ac6089da5fed49223cf42",
"0xf1ae8d3769142a1f3c8bc0ecf8454f05b09354a2ad5c921d0a6845417bc2f244",
"0xa04e022b2afd83a1e14d0d67595070b29f196dcfc05d92b2ce7c582d67af4a00",
"0xa3a0c85dfc3d8055a29de34492b3e231691bb6e9ca06684a205837ab9870c72e",
"0xee2529ad0af60748cc0bd8d97189d878643a52710dd200f79f27d8a4a4c8c093",
"0xac88fe07805a058f1341ed89795f0e5e9ace050de0742f863c1c9c63b17aed12",
"0x8fddc716ab43397541f6b22644949c6d7214b01ca8223310a34840df37c47746",
"0x3cbb4d1a2ea6fce170de64b1f4bbb8d9239fe191018b737e62eda77aeb7d0306",
"0x3807421ad84d6f2f9d5d830364a0455d6846e114b87cd08a3cb9a33e40c7c084",
"0x283199cbf0e1c997025bd36522619417d9e6184073b830fb22c3de106a68b598",
"0xcbc85a7ee2122abad27b1f5a07bd15d864af382a62fd552092b7feec4d2e4856",
"0x84586eae7108f2e1217d53be81f26bff7cc35409c64c1af827bb5263d813302f",
"0x5d2d93535aa7db5e2204e419ecf4d7c0647ce40522806bd24ecf348eb49a1f17",
"0x3a6118c84312f120c0d3e4ae4ec0b8103448da31953fa27a8400ed7e4875897e",
"0x4a0d1639274d31dc5d9eb49338b204e9cc9610913c0320e7da74a02ed2486fb6",
"0xa7770b7cf4f83c387344cff6ddd3441dd131333df0f210a57a271fc1a61f08f8",
"0x35066ce607eafc9bdd3386097a98c844bda683ce29faf25708b1a2f3e25c9aca",
"0x7068b1f5c017ff5b995f2c65db7daed3cd9fd0e658322ee2debbba7de3ebdd72",
"0xfbcf8cec0ed675d12ab4fab45754fd00a329d19ad77afe4413a0581bb6dab8dd",
"0x78035e412813b0a3f7e3f46bafe436b57b83278499fe8b8a1bdb3066f538d0b1",
"0x28bfbcd7eb38793a1ea711b6dd73c55da0faee3a9707c743737f0692dc6b56a1",
"0x9fb1607599329b61570a0daeb7b1a93210ac286e02a64ae309e1950cdd76c5e5",
"0x8903d98196291218a50fe03a5cd51592e1b458315491d735187cb39d0e21f397",
"0x97aa20d84821d36a44ce18eff501df95549c8266220ad612d0ba9d293d65271a",
"0x3245e35a2c6d46002dbf5bfedee31fd28a88409edbc55ee1ef7972a249b1cce2",
"0xd6149428168dbf78ab2f706f041a61e3074e3d18ed47bd343d54c3e4f2e051fe",
"0x9f4a04d0e3a2b8773a258bfcdee5242e44761aa1a1d2f9a7162f04a2b85de6c8",
"0x0162a3449c2be2a0a45a771027e5fb67169c5a56c4ef6f386093fa79f9942fce",
"0x5c1196a72f2c6fb5771e0390ef25499acd52c6aeeac3615ff17dcf2c405069ca",
"0x319097551b7df30bc67f5ee6f068cf3b34e71371b91635e9009af7acfe97e12d",
"0x8b89e2e091824d0c3276128543991cf7c35a82bed4b92b4e67aeb4652033a823",
"0x75d6dd431d5568625946b3578e68d47523518cb2e141369aee5273fb7cdc4013",
"0xc473b7b23c164759487af8c96865f0f3af3f3e40e9607665f94f937c3334f604",
"0x1f61783925fc03f3f5465f37aad2276c466ddb91a47db036f042c0b2edbbf643",
"0x3f6370976528cc31e4d099711329d5c670a2538623621b164d470fd7ee2cfb17",
"0x3705bd7548fcdeb0dbb3162394edb2adcd5128524eb837b71a04ff0c9c21c22b",
"0xe15e99e427efae16230af47e59ff89b76df25db44fa2dfe95d2419b6de35ee7a",
"0xbb4a17b5e4879b52e6a4838df9525ae01b168197db2910caea805011588559a7",
"0x60e6cc67da461bafef5c3b7e4f9e964a24c3146c4fc22c2e046301e457d1cdfc",
"0x72ef37234da6fe157e0e87b11528c3e41d115f10f1dcfce60e54d83c1406989a",
"0x63c3a73812427f73be785d4690a6ff81912d3ac17c8d76970ded284383ec97a2",
"0xf88c0457e00ec47c27ddc6d99fe6c0b82bf9249018a96b1c7e6b90e906adfaad",
"0x9258fa102e450844e091b58dfff2fd05b8fa099d53667626e340fda7ff7f9bd1",
"0x68adeaa1063528386db31407596442f815769731da8b560272ba3e1b8817a11a",
"0x222a41b6e681d2acf8a9fbd9310d34145a3c49160c29681b95c85176abadddf2",
"0x00745c4bb8cf5fb63700444f9258eb94e4b527ba8739fed4bbd7b13083854929",
"0xf27199044245d103b296bb81188982baa87175843b06424e0b5fe9dc6e005705",
"0xe00c3bfee8d71930faae9ca720f25f342ad166f438c07b0664c0c2d6b9f82c58",
"0x05e2bd6caee8a926c0f61bd0e5553b304656cf4749f54bb45b72d2a84fcf2378",
"0xcff8627a22e37d1087c3b858079a4f90a1fac65cd397dce26be8c3efe2515e1e",
"0x4885a5f8fb2e367a9edb32b02ad4390a4ef8f317a0e7d3bcfd5eccb9d8d05b1d",
"0x194638cb01699bfdb67b09ce5e2e8d5dbcfd403ae325a7a0311923ba5207c5b6",
"0x20e7c0ec1db7ca6adeeeb0c7950b7911e1627bb173425c4eaa105cfcc9c43db6",
"0x1010eb2f28d04da879c67f4c9e51fd480753081eac6123c5161502f3180764f0",
"0x09a0d0aac41a4e2fadb48c1751011fb46774f10ee263567d823e275aa0a33ec3",
"0xde190e4dde46d967a4e32ecfda15323c7f4081f40d5f245916055af44b008e81",
"0x21870402899f8c05003a175f2c0d37fdfb52c9bda3eea3ac8616c832fd8ac173",
"0xbec735492b66890aeb0ccb5611a84a908477269c2336e076c42cbb620cee8861",
"0xb9daeedd739766f82a95505a9e71daa503a5f0c3ee1a6a97f842b2ffb6ddc6ad",
"0x9f30d706fc86c7322a10a3c572df2ef4f2f49bcb49c5afc2c6299cf051e2e38f",
"0x9dc1d641fab155885db408328e60c06d97a0e3327b64a18d46e7ced7cacff446",
"0x252594a4da3cc4e794d954e88c15a2c847dd84d895eca06b9365a85a71fc46eb",
"0x979ea7682319cb0674066b10eb7919a87ad1ec0618ddb24723f13c55899cbb6c",
"0x570b4dce3b4613a8266688291f06bafa9d3b7828e3e6a9bfd27e7d2f3ba59125",
"0x39e97e3c20af2dcfa347ec193cae2c00100effd4f3987bfe21973db8c5e11fc5",
"0xf66b0859b41bf7dc53dd23762ecc593f4572a8a9f82b4c51257af1eda6344bcf",
"0xfc32a5b84537ed5947874eca72d189f74676855be5ded4d32eac2ebc0c3a3306",
"0xa89c577f12bedcc225cdfbf86ebe8112aef97b9c34a504dda52cea4f40f72be1",
"0x67e4b71c08fd93f1c37cc60826c5d8c18e14b89a7f271e0828b114de39aff694",
"0x342279789cd6a721f5f4866e3a16d19f88b24ac277563ec7b0716ecdf8dace3d",
"0x220a5babb290dc16440f4b01bc117c41af5073110b1375cae0317f9fd364d44c",
"0xbc1019eec10ff493e095915f66d46f0855b55aa681352774dc300d54147efb00",
"0xa9cc80ffc08c2b4c38fa178e3ac56ef982d0487b7139ed241fdda3894f4b67e2",
"0xb35267a4b6020a2e53e112f4ba7807ec50ba78a3b2d64fc3e3bfe918bb25bd9e",
"0xd5021c0c199dbb1b61e5e0d4bcd59fd064ddb6d6611421e57161f9c37fba91f0",
"0xea0af5bbcc015b06951c9ff3df3c233f4bdd6ef8eab97f0b3a9e10b01efd7a5a",
"0xc060f20f45851e6de2fe1dcb6d8996add5335c34892f84a1db711d0c47c5da4a",
"0xbd30199b078305b459565598fea6740a4d187e4813d3887f72d7958ebcc8da48",
"0xeafa07e96737a0e53ee7a09bc1b394ae4c1ec6c937901a8066b0cb6b6908aff5",
"0x68abed404e0a66ded23d152fc5544b14b0a4fe918a51b667f2dc827575c12136",
"0x27da4b5111565097dba6e6dade4f0275ea8234b50f391aa270bb3cfb361e6331",
"0x85126b95e3532b5045710f60d0aa3f6b0e801130722bc7d85a67479e0b1fba25",
"0x658afe5a3d3b0916372785f952d92069045b747fc67be6c8bce3d695a434d058",
"0x9017ad7725867d37402da5ef1727289abcdf9982a0c7dbd7fa6f175ef8ff5f90",
"0x892a34192371a1de6d4c2ceabeff5aa9e26c3f41e74260d305872f366bdb73d1",
"0x786a848c13f84c87ca554654f0ab35f7fea5014669d919595e087e6463c47253",
"0xf1235641dd0ac33ed19e39ee58e282f2e0dd8edc0949e0510f2c65469d85e1ef",
"0xa55273939373f7a4052d8bc36501fe17d9b571fd170041ada7b4385d49ecb5e6",
"0x79ba81c39c2e7dad9768cdbf754242dc2b5b74fde750c32ee153ab121a633406",
"0x74ef128355bdc842c1b109d4b1d3dc6f85a21a110b32fe1b4ce71cd282a20ba5",
"0xf0a05137693ab9dae7624cbf4abce1554d4921014cda61584d649c66e9eb09f0",
"0x5566a8d7495aae3cb42e66bcc683bb194f53894e3281812484bf36da583b7d9a",
"0xbe65f10ed3eb5e862850eb4e30c73172f5417634b087b1dece7df97dda2857c9",
"0x5ad40161397a2d0f53d71284d878e711b6d73930d2a79a789e4bf08223e9eeb9",
"0x1a88c4e12ba89abf67c8f8de223964e4f3d0ee8951b9a1851c9172b278b956e8",
"0xc1bae22721de65936975b20b01380c7707cb603622106a166c1472bdcaaaf94b",
"0x68106522840c17b0e93b0cacfdbb1d2c5b219cb90aa61a5d0b04a0291caa4b82",
"0x0e8a214b18b92fc025bd374a8d9859244b3855a7d3a364d1a0e092546a17b2b0",
"0x584294fe2fc330adfcbbaf251480f2c727da2d38ce54ffcc1b363adb9c0fdb0a",
"0xb86b9042acd8d6dd4eaa967b3dce6e4e49cbad95f4a7cfea95299da0cb3aecab",
"0x99d4f215dabbe6bcd894d4ce7ee6d16a4543c38d9ab19a4f3b933f37eaa7fa5f",
"0xd078bfda23ecf966b656aabf0bb69d27902d33773b2471145268426846a5a1b8",
"0x87234af13d71e681c987c38fcc3661889b406e298e3a1ffbd5115fe6fe6e65c8",
"0xb9f78fdabc8cd4fbb08fd1e1d00ed552c4bc7cba0672ce91c52deb2834a7b223",
"0x76704df0766b51c9327acf08ffd35fb9c3f041b73808094b0d4ae1f7e7d7d0b8",
"0xb5e4ec16c993e2ade6e951099512deb2f8fd07956e4d97dfc639a7eeef96d336",
"0xc9c919862f5a82a5381e7def2883049fbbb99f24be9902152323811e32db40bc",
"0x8df21edd784b8b776ffd603a6da87a6602e6424cb3905d977b909a7b10160abe",
"0xd5c524bf24c3c8f2e9cccd5aff20b96fbb8f2045f37ef1014eeea1b82787361f",
"0xb64756c799db5e1eca16416cb833605916a9bbbcb3c82a54def34f16e6fcfdaa",
"0xfac273bab2facbfc28e2c53c03a44e69ddadfbf57b08499bb43855abae456f1c",
"0x43f8990cdc4735bc47fd89cd23c9a99d5453885b1903d4b3185b6b0413735ff6",
"0x7420a69d819df5f4106fc9e315e8c125c8876a3a1cae8ef7198a921c121792ec",
"0x696861af19fa56f07d5e2eacffa3508cc3638b7acfe4789c002929dfdc47fc3a",
"0x86c80d2150fca01803a41a900e66b764ce82af2e0ec19fde53971afbb6390ead",
"0x9cf14af73b44b555ceec13119567723ae8e8af927a6f24846635ff5000acfec6",
"0x95b50e682e4b6b2a08606a62bce427682ce484c2056d891dc206fae9e062d3f0",
"0x789755e975f432a059cb5cbeb067c8f9dfd97b54d8d1a45a1e47592d9eb770d6",
"0x87b682b780890ad3d542c76548d7d5287fb244291d62619ed079340293a245d6",
"0x8c0155b066048d9e95f5eb1b6ecfcc179feb71ee0426301b03f778573eeee7a7",
"0x0fe45f09ef25d05e5c42751a35714af86a5d7a4fa235956edaa36dd0e5ea7533",
"0x3b5ee72615fcc04f48cec067ba2d1d9bc0e64c4cdf9d5bcf97c1a999ae940245",
"0xcf773973676c9b0e31a549d78a6bbc79826c471b6fed42078d9b35a08d1d28a0",
"0xd5ecadc4dba308c0d790adea1e118d6984716600091d341276311631acfbb267",
"0xf344c0cf6516f0fa6617e48076726aefbdaaf5a31f67ad8199bc3f6e426bf904",
"0x3f3d2d33f36ba9009e9a72f3f5bbcb5df5392a19fc7afc8d37823aaf52b03477",
"0x346a89411f090d559ff90e670bf0a385b1b09f117fc9ffa18b09d3b6d5d8e45c",
"0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357"
]
},
"nodes": [

View File

@ -19,7 +19,7 @@
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"validateScoreTransition": 1000000,
"validateScoreTransition": 4301764,
"validateStepTransition": 1500000,
"maximumUncleCountTransition": 5067000,
"maximumUncleCount": 0
@ -56,8 +56,8 @@
"gasLimit": "0x5B8D80"
},
"hardcodedSync": {
"header": "f9023ea070413bfe3ceb9160c7dee87bf060a0cc5e324f7c539cfce4e78802ff805063b6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e4a10650e5a6d6001c38ff8e64f97016a1645ca0f8ac12c30b4fd0d27a1a50c090659014574b554ba6e9cdb76f57efbcfbd390a9a0b474ac6cc4673c17c5f511a8b43cc44dbb01bb028735830163667d7a3a2582b9a0bcd44b7c04fa24760df7d733ca8ecd99e8da89de0716e6017fffa434bfd7519ab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd83755801837a11f88301d8de845b27471c96d583010b038650617269747986312e32362e31826c698416c9d1c7b8418bc805f23fb01fdd498b37df5519f49691d65160fe6a6794b8106e2ecc4782407f0dae3a512546b7d93e89bbb2a761c750553deeea1f9401231f56ae0ccb059201",
"totalDifficulty": "2654916374389120143910668097894183918476475680",
"header": "f9023ea00861b3771ffb84fce48b8ba3c54a09f81e91ccb38c401261f06d370098889a43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a071cc81d58cdd21d1e17f7389e55c530cd9f94cc15bb32af6477320682327dcffa06090021a7c09ae5e75e443410ebdb76de04f1eafb0ab910daae96ee6eec560eaa032510bf257dd03b11f3b4761b94b495a5b5a18cd6eb17c77785e0f46e2ffc882b901000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8381e001837a12008306697a845b83bd6096d583010b068650617269747986312e32372e30826c698416e0ef58b841117e2088e2835bf2afcd5d48f42b3bf2a1f33435f21f089ead2a6bae7d01c1486e645b460bb3c726a827ff1eb50e0579f3410563bae090fc256cf1d8d594b82100",
"totalDifficulty": "2845866505151538604560067685603735513869853136",
"CHTs": [
"0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac",
"0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02",
@ -3940,7 +3940,281 @@
"0x36e94b03402f18c689f5234973ce1e626a82aac085dbdd682b51cce21f8c1872",
"0x00abd1d34c7e55f58681866558cb844c11faa55e8cac70ede75811f55341cfde",
"0x9983fc20e63e77ec0680522035b03167403681674ec62293cd6b7fe360c69157",
"0xe98b658fb8b6b7fba7463562f86348bf1e3534bc9148e8559423b3ee5ab68472"
"0xe98b658fb8b6b7fba7463562f86348bf1e3534bc9148e8559423b3ee5ab68472",
"0x77ea189d3a408a8c5b1792881d93ba7a471f90a976ed334cfbdf865ff94cf20f",
"0xfbe2fb93b3ecb384679870205f2be2f47140f8d832f841ba8653e00d68056c82",
"0x330f5f04314ae57097db5258d861b993cbdc2ca0522421917463b94636a99d1b",
"0xa59cbefffd0e1cff04bd4004d21fbb64c4ca542b98220487ccc79a39a6a0fba8",
"0xe08f21b0f5ab216c1009c904939515d0ef8d8ca80f8c3cd5465944bb6550e728",
"0x37f1db42a7e99ea8b6d7f9ec5bfb39f9613cf79d98345816533b85726c64dab8",
"0x8c226434c5115b7ac0f894d8c4389a1e38a3118fa0993b59a42291286b85bd7e",
"0xa9977dc362eba9d32d13188dffa6cd0178e0b8c29cc24a3c04cd6cb0781fc133",
"0x502a68fcd1c187d662ff6852179d7602b04b5ec3141ffb39841b571bbc6cce25",
"0x09a716a32626ad3443d7f5f6e5fce5145e8b962a531464e36aae6356ae93b15f",
"0x2c165daaf0e8a4433d8bf97091bb573f1a7cbc7e82f2af353af9c580fbffa8c6",
"0xd8b47ed7ed3bb85bf44ac2b5e5916bbb282353f71dea6e172434f05cb1276c4b",
"0x2bff102b5209c88370b2deaf941653c364a90b39a6c3402336b8b3c9b47731a9",
"0xf6011e416be00e243d9b6b57df1bec2458d271b2a8a964292521f6f8bc7355de",
"0x8f4a6d08359aa81c14391d8483bb8e621c24bac1e32b2c5c505d5617487bd06d",
"0xd2f89aa90547e1956491879dd5924a50142d76460532f00423cfe70f36546873",
"0x929b13fbde5275f999f145a273219d6f7f4c25ac29b4eab3f89d68305e7f4341",
"0x1e7e79d55594c3555eb7d90e4b5bcc8b59ecd98848884b81ac5c2d53bebd5cbb",
"0x11c2705c4a89fa9187f63dfc7a8bd4e2c087d6e937e777393f1e2856f6f00104",
"0x294b40af144ac5046bd2a5451d1cc9900858e0e351f3f78b50b2dbc203111600",
"0x26432c2ba81f919c085a4d2326c22bac341c17f456d8a93a1971c0fd741ea79a",
"0xc488baa35e04ed6bf20753fcf856f31a98c00be65d51b73c6a5490d18fb89d71",
"0x915e1768627ebbee21159a0562d8a5df69b05f057fdc8b4bb69bcadaeadf2ae6",
"0x2303b2be6801e3fe8c02c0d0355069240da4f617b47a4ce6bbfaaae56a1e0915",
"0x0e4af9d5e2cab6a62d9203979db08996bd1f111a315049859e2093e83e465262",
"0xe54756890992736382616fceb3999d22ae462b9b5f8b1da072277da2df6b5f4b",
"0xb5aa407d54e2ea651563333d3d330af0cf45a992bf89db0c229962454c4da4cf",
"0x88832a6db2c8c3d899dc59154ca323c08c5eaa8c05d142978490246e7b4ba7ad",
"0xdca9619220c991618eca5cb18b1c14c6fe4167614a8360c9e1737c93a129e714",
"0x3fad9a66462792be9f771b39b6f64e537683a74441b85b53f9c5e6a2fb687100",
"0x6dc5466ae00317d52511d9e153ffa37cb6060639a010c8db25b33aed702b486e",
"0x2a2ca3148598d3106bae23b6f66a24e3e93afeb576d283ba6822220780008e95",
"0x480f699ec76a16530e382c2e8d91c7edd3ec0d393ccdeb28c7d692eb52b0af96",
"0x082d3f5dcff2a41e2fad715d64eef361271648bd976d895b40765089c544b65e",
"0xed14dc5ed74dfdda8b45dfcfe99e8581767cac57505805a4945b79e2110bf92c",
"0x6890d1a6c90f5c1020ea4439957ea54df3cc22f14e22047f63c9a93696210b95",
"0x55ae4e30fc02206a0f389e03c0ef5b1409f8fe34d6a5dbd5487af608e3b82369",
"0xa709e308a7899591337d59ea459098364c1d6638202047583851acc5e6df5017",
"0xaed8371c95bccbe53effffee29f40a3e9656bc95cceefa364f7191415dbe15bd",
"0xa7450bb8e1ff3c7b53bada0cb8ae783e561a3ef74cd3be0d19cb9ac5ae807aea",
"0x9fdebd0ae46437e3421d7f0a95a76f47b34f0e0eda37d69c078ef5b44411c027",
"0xa18a165a98307fb994401171c41e375a4637fcf2beeaec8c18fd24304b068570",
"0x930f3cd1edb90c020c19a6f6a8b86c86981c3ebb8fc19073f09c345fa4b0ea6e",
"0xe4c0549658dbbf4f541c60606c8b85dba190f58e5af0bcfbed101e0ff4a8f455",
"0xcfd5428494534819ee14e002c69987fc54207917e83a2b6e97a1e1b801a5d939",
"0x0cc3a6a2a5de66f64f5491908b5585eb3464fda42c7a58a9100a8cd0ce763b04",
"0xcf635d0b4522c64a9b00902770ae33b618580983bb32b94134a69ca8f6c6258f",
"0x2cf5c41cf911dff328ef15253a7419733a104cf9cd1846af43d5fdcd914b321c",
"0x6d4ea125dbf83b8a9dcba40c4a81673a365ce81dd8eb1fc10510ee7e80a40b1f",
"0x9c68f243fdf1738f9218c30664318278afa8f461c13bf5e1bf30133d3fa6347e",
"0x62aa880648363c1f3b5bbba3e73dc58566870ddbde0911c5e11aca003a13b525",
"0x286a2b6f2e35c2a6900a02d37d82263dc55a3c40d6c40488258af61f8cb8b589",
"0x296136ec9fba18ad43a5435acbc3006e52a182aea1e3eb005f25ceaafde2d0de",
"0x9ebd2127fa6f5f43a03fcad8dea37bde3893f627b48e63b9e2c6e33af811a95a",
"0xe8e58e2b6fe45ba1881eef4ec1e1d954e12793ee68060d50b9c9502009725317",
"0xf831613def863279307f637be60e9608179e9a148557585034d20816ed7d5553",
"0x9ac311437bfcaa1c66e1c32fa18f8964ca9d9ffe3cb3be306b64519b35051e48",
"0x931a4862f94054ec0f96037a225f1c3421ef99d8e4a8f774407cf913273bf4ec",
"0x07dead0442ebccefbadb2859e0f462fe8d3e6677c7fd04b0f35165ceb017c171",
"0xc4afb80e1dcb56ab83d5b20475d2212b6c55ab63fee058a914661657d2b1187e",
"0xe198b8ed96c1b7dcefab5197036f1e5789ea6622dcca2d817e63537b00710b6f",
"0x728b8b91918a059e3f46ec7658bc5948016f76ec200d91ec3a163bad8ad6bfd6",
"0xacdebce23301e49e068c83a73ad8484d8af7a0c28d066e62787542e154b42559",
"0x7f66807da0c2b155126b1d3a69488b10de7f0ca38f6cfe6fa670dce511a1f667",
"0xabf510ce1a016b5b3d4610b3cc5c9dec43a6a66f3555a70e1c16cd451e8894c6",
"0x56ee11eb3233fefdc056827fccbea1ff2be8a3f460038eef68a1c730bc1104cf",
"0xbc4df43d4acd0fc2cea064abc5b5d1754b29073533652448d44c09adc1d32998",
"0xf61b97d2d1e537a6d20438f4729bb59ffc8db6b7375c6e710b4be9e136f1e19d",
"0xf89f04d5cde25522103d1e175d68dfb4955b4519a5c2cda1a041298579174be1",
"0x702c60e25d6a10ac9657553e376f2385cc94737ee292a3ae671ec02af982ad84",
"0x5194589410d5f02de764bba1c25da027861793270c956c56e67e017d89323799",
"0xc448a3b8bb1b6efed04d84f82d63aa0c7ca19d3cbf817efe4db82b897ad6a019",
"0xdee875d8c517db5cf20b745be7ea1d389612e47880657d003c6bfcfdbc8a6303",
"0x0528ce8bc52f4878268be5e00b5028c9af85cf61a6279e75240e2adf7b498ac2",
"0x6cc80f5c62a1510d9cc97ca8b4c6245938ddbefce782635dde0ca2516932fa21",
"0x184f9e305ce4fa0bdb47ad00bc7d10691bfbd7cb13b9c9d4d82c37678e8df080",
"0x69456f4aae64f57b3709d6c6701a1894802a4db96374da6b979b87aeaa5e301e",
"0x60d1bd0acd9013472acc0b8ce0b90a088f35d5c19645146ed8b3c6330ec92052",
"0x09f87c83c6be698b2eff45ffbeef79254e5ff8d3534831c79346e5b837110c1d",
"0xc5fc2dab2c43c27132f31a915423a6d6a30a560e4aa266483ef2ef1ac48d0fba",
"0x87a147b03150b429b0c86569db27ecde32c1bb9a48b1ea4426d8dfb895339673",
"0x1a68fd5e6efa8e5183843fad88d6445fe8b07c01b884f30563ce527e6b10749d",
"0x4123e02f2c2869bfd99f3138aac82bcf1923260ac28f33bc4ff2dfcd54c48e4b",
"0x452345c2de5fb18422b4327a79053cfff33f277f0e3fc69bf2073d0bda4dfb74",
"0x830eb26c402a88c6281b0a48a93ab16a64a8e4244f87d589b471a3ceb4577f6a",
"0x84445f1f8805d911009a3e55ebda5e12ff347e5a34d0028ca44a2a26846ba903",
"0xf91a600ecc8aa47f838a8d877487c15babc10ff97a5be8bbe4c3eb705fb04dc5",
"0x01e749439d413c66340934dce9d4c55179375208069fefbf89aef7c3c7f02bb8",
"0xacfb6917a7365046ccbad1ca8fdaccf8164c216ba8d96cf64af5340ee3aec2c7",
"0xa1c20a4bb21a0a99f3a38818c05a3ba66e8321f24dcc7ab26487810be8211dbc",
"0x7c88ea06f3c8cab9ac0b29376f53fff4b56672a1704520fbe8de0e3ca0bf8acc",
"0xc19e59ef2361963b94bb211b8f6c172670ed83fce3d54b3e00d1a82f292d1d2f",
"0x386ebf9ab1a551ddaf599d9384e70a34a961ec55d5f609c088c6fdbf38add80f",
"0x8a635842c7d38cb2bae11ebe3f6ec09e2d41ef6b7093e4ea8cbf079df97f06e8",
"0x2d12afbf38c0378d287693cc7fd49f3e068d454ac5ea7bc76f6b3e505bb09f27",
"0x33b7eb72362caff0e54cd853549bc4a802345d774856558a8b128e494ec63948",
"0x31eef3a0c2c9f586ad2305d8ed9831619ad6ce2aee9a16800cf4aa048b1d593d",
"0xfbeb707dd62204a0f3a06ef9046fba5b3b88fff3a38b5b08cc3213f5965c69c8",
"0xc8913325245c39d0609c6af407354e9d309c5d582c8957a90c86c944d2f5c6aa",
"0xbedd0ccdb57b01e688c14d6230aa84f5912cf13a72839f654eede63ca05ff52e",
"0x0b0b7435e02cbc3654eabd042c32409f4e178cb60f5e306ba041c985378cc286",
"0x749b3fade2cbe924b3d76f2b9e216c1675e8687bf7ede81b090ea36a4468871a",
"0x9a59125cd56262bf0b6d2393be4ba8f769b9d5a53b644a0700c9905dc4d91c14",
"0xdd2001f6cbcaf2d29a7d022e6f723e4691390f56ed6a599cb58bee74c64c67a7",
"0x05870eb07cf5d1c1013fedd8cbab73b7341e930a0c02e2dfe898d5299981e34d",
"0xef78e2f60d74c818cbf8996913c08a7c5abedb3f0f7ca412737c071cd6a38ccc",
"0x636a6d39d02bc22c139d9e203b1ae8b2dc485cb596641ba6e05929296e87ffc4",
"0x8cd6e1340deed5cf75bb30c3183807b653c7ccca712f379d5f885ef1a4100945",
"0x549d904ec260af5776c241a80c2075e31869b8da7026a078fe158c0b0d646b11",
"0xc73927c3be804cdab32e543e78f38f8e0899d7f0418e0b37af336c2bb37269cd",
"0x62a4d4dc610995d0f08756056ac199c3f0959674eee8d4503067b822e37bd1a5",
"0x4b4a3cb0ac65532d63592978b1afe838cceb7cac04d30a58cd4d73af4b99d2de",
"0x2c5aa96bb3b58a76b4acefd0275f9f7f82418501ac2c2052e0a5f43eaa4eed64",
"0xd6b8f1a8e502a93e14a8177bd750fb7e7974b7527f50bee37690b523dbeb077e",
"0xaf38bbf2941d5ac311f8ab4cec22642049473bb3a8493ecc27cce73dad188797",
"0x778b83f79934655d67e52a38c09410e5b5cc28b26f4f70b84d2bdff5519bcc74",
"0xcc016a4cf3d1f7119704551809e89c1b4f95d1dfc4cb7f95db2c5d2a6ff1036a",
"0x6b904799fc1df35a787bd7b1ce4337697bad98b25b2bbf264a7bc68d452df41c",
"0x915536046dad19310976f8d158795e4237bec7fd5c2d2fc8ab1fd6a3b5b75e43",
"0xc84167f477d317ed1e6b1452cd746d43ed679f4ff2eae84b1676ae99d3bb0fca",
"0x71758a9fb0e66a7a04a076569cd3bb41d5b91cd1cc26b21a773e67524af84e63",
"0x54f60d40ea84652f938d2856533d82a7c0b91091a0ad009f48e599a917b52bb1",
"0x618cec420aeabdbdedb8afba71b0d0408da5095ea3231455b6c817f9a585d437",
"0x57cf387db60cc35262bfa939b0272af7c490720e496b5f8cbbed6b4b26397824",
"0x7c8973551ad57c278a0d8702cfed004dac293e2b9464debdc48fa88be033ba5c",
"0xc80eed1b2bf137a5574d40252d4d02d0e3f87618c79b764407d8009a2b4932e2",
"0x09ab540be725d669810c498557b61a53b343104c5303cccaeb31e518782d64d0",
"0xc996eeca57ce9a7ed79f6db45ecefe1710abc4b3e21dec8f707eb5f7632c9c43",
"0x160af8ed3f5f55bfe0a9129da94ed002277580b297e29cbe23a962c41eed1cf4",
"0xb8935e0d55dad821ba5605607cd6a025d6ff76ac3d9d855fbdb3d000ef864dec",
"0x10f6dcd55318225d362a40859030fed3199ae015791ccf4c4bb343e7cb97822f",
"0x6f3a76c93761f73bd148c57f2bd00670c20bbd19338b7fddbbca65e598b70ab5",
"0x6e99e5531942dde6d881eac1f03c6fd2ba6f9d79b6f88408eca815d84ff48157",
"0xb05ebff5d64b736d36b372da80fe28d6e76b64c74e1ca94f1a859936c7ecfe7b",
"0x815a140ac8538595dd724ab2c31e13d30c03ed3b64d2cbc72871fe402c7c88b8",
"0xf4376c81472e0b3995618f7845887159eec1e929b8a485c2693219f4d5ade069",
"0x30ff47cd807666e5ac48659bbfdcf8883fc1c9ea4e9be8b397dbc969a82f8d95",
"0x74e35254636ae2f72005ec69e62273e9cb7387fbd4234aa58184e11725e2f569",
"0xb4f3de4e9a22e787077a53017e72bcc8ec26a1499c98305dabb61ce6582cbb09",
"0x3a05acc943f2b7d0c93cb4c5fcbbfa3ab9e536a2cda7f1c325fe3748401b4f71",
"0xd75d428c14fcc7ceb929328989235a5fc46f8ed3e0136d81dfc15866756455a1",
"0x20833cf410b3a0626a6c7e07d5fe09bee17b218416725ec3fac716597e1f6576",
"0xed31b1b593289be968e483888fc80e5c360beb66626702f388a0848bf104687a",
"0xf55fdb35314f9b873a70bb207536eb2e22958ff9264f1e088b0dd82bb9358b2a",
"0x701d2b5d8794e244d85366d13fa0382827ccbcf557ae2735bc3f88bcb5c778d9",
"0x0492794944f7d179da85f68eec5ce4575a90b7a6f161ae199373ac4685c6c665",
"0xb1fb246d93a6ca7a0ce6518a4d0cbaab074bf2ada05fad7a6d199cb830bebf8f",
"0x77172f0acbcf0eb3ffc2e314b548210fc74c10826162b2d63195cb984d606623",
"0xc9f684762b2378428ebf3dc8e207fe8d2b33c5a0ae1510ef44e2dda7e5979faa",
"0xeb864bdea464cbc95b1e3a4be62231f91d1230179b7bf61f755abf5f05cbc9a3",
"0x10fb3751407e792cd70fced2271f125d438d9cf3843d9ac6f89681616d0cb1ad",
"0x79f96b934d4b22eb9315230c113fcfe0ee2828133e10b14cf2e9b3a8007dd7ec",
"0xf8c0546c0c5eb3d9ee16295c5e0fb510a0ff3f55cb654313db2d8ec6195ee996",
"0xcdc41342d4045064634291c9bbce68efd7227bc2832b372502fd4907f1957ca3",
"0x7c09a67309e6a0993fe1cabb7528e5cab4ba6a79042b22b3a6cbb10778cdecc3",
"0x7d5c881d1a199b82608d7e27456788164041cb1e5ece5e3b813db550cb402203",
"0x4f7238409440404425f9f60c034696e4713bab4f4e507b76bdb2697d1117ad70",
"0x8e8642cc65aae464b068178c4c2276dc8860b63cdd8f3447ba07a0e7a9b20c71",
"0x59fd79b1b77ddb040cb6bd45f10ec5ebbc7ba421e14dd79755e568774010041f",
"0xc8bfd004b479e0ac8e2e798045343198909a6f5657625028bd28af69de58d9d0",
"0xb550f5483d01e8d32258708d82d463f28658d5155a15da214bb2c748e27365e6",
"0xeb7de7083d7c73f3f443e6d009e97783ecefd77157b830cab2ae7d41a91b0b0c",
"0x6f3145fafbfa23c5667b646b3b5fe12b0fb08e45f09e62e9254efed6ed812880",
"0x66cbab429d401739e655ee55de9dc3ee6223230e38daadb1fee88da03c46197e",
"0x410eb1081b98fc38f2447bcd358a0996bb9660f949b4d9d6a6596aa41de59557",
"0x2fb84f43e9750be8f37cd293742776ec76d95170689710254d7847369626d6c8",
"0xf1d6c7c8a81aeb7611531452bc46b69db1b56a31c1c835ec5b497b6f4aad2b8e",
"0x1449b942575209a4bfcac57d594cba694bf494e98e154142d5423deb193ad2dc",
"0xa14bbe0f97892409b86989212bf815a5024769707bb8fea7479417402a346f05",
"0x1ebaf8a3c224720c6cb4079b8e355411f0181318dff7766faa204d4292e6593f",
"0x70169dab4258b561057c427b3d31de403d87302180db843d3ac6fcece4a8bff6",
"0xeafa1e0854e1d0dedffc92fe173f2333d3a0581199fd3c63ea69356206329d65",
"0x54de1a943017c40959dbfc25e318b0055b0e041cb170b0f34e1fe76f41bf2f15",
"0xb4ce2d897abe390b9b53be9809fbc1dce8d23c2d726dfa1d0e1419d8caf2c6a5",
"0xca872995f8268bb0855fc685e69d590defd10fc6befb61a57ae75255ef92cc23",
"0x3e3606562cdf9f8460c18efeca2d7f3649ac96fcd81d2bbd501e73a01c729f27",
"0xec09b7014e049e25e0749f0a0899a2893605003f128bca3bfbe92a00c9dbbda8",
"0x9421e443b91c741c80138137362f7b30dd9a0db6a815a3b4a799ec12ba6de4c4",
"0x78c95ab7995ca6058f64f7fc4af9575923bfa70a092ad2268f0b2a3a20dcc247",
"0x386b36edeea33668de333683b1ec3d9c665f150aa96cf78be27fdfd8f185479e",
"0xc732d05a6122e07f7566a2a751adf5da1cd1ee23dc0b34c0cfe7cc12f0970c5f",
"0x283d97620ed18ac85ab1d2c613d64df485b6efa26aa6efa71f840240a95cc240",
"0xce779d27aacf6e512f5b52f96507325568f754b31db766cb4aede53c9e1845af",
"0x50bbb90f2a3cf4c479be3e118936246db591f98e37caef06fbee553502b4c364",
"0xcdf95c14c577f913331709c5d044fa536a4afbc06cd8d60ea7b5d9ac463e86e1",
"0x3a7d03a8ed71d0ef15ed70677ece7a2ea32ad1e96ea5c3266a1d9f580efa862e",
"0xda132c0fa137c542b06170fe085b483afdbc97c63b4546079262ed0fe1125c1b",
"0xe4cc4056951325ee41cbb70fb823eccad0f266e032e839a2e3a8e851f0a6c73a",
"0xc301415694835a5bf36e226ffa42d2fa8069dba6be6becbc2a7a6653c295e8a4",
"0x1856c6fbe4494ba46fb87deed5c10e361a83ee73bfbc8f1b604c6fc0301f62db",
"0x1b822bd73acd2fed2f8daf6936ddc8175507f373e701217b645cd6cb2ef2019f",
"0xdaec59b4c520d6b5be4d82b1b1338a5dd55c9df443d697fbab750c337f6986d3",
"0xce6ff73593693f7cda1159724457a2aebf0ca608105a5926fc98afe5010349b1",
"0x53c50cc4da6192ddfa851aa104f92c865ce212a87500098d18100394140ad6ce",
"0xf015a6887a543a0849a128cec761f10f7d94f7be083f739c767c727aa9ed95d1",
"0xa54bdb8a7ce7327aee991715a7d673d403f2248574bbc0ae5aeb9a32b3d9528d",
"0x47d46b4777a303430fa4e45305b31a113acb4aeebf205ca215447f9d27ea401b",
"0x7a9504b64ca570814194b95acb8400357667122b5b1fa4cef386b35e28de2c61",
"0xa63e5964474672c45b8b021b7cc408e30364c163c800fc302f342f119689e022",
"0x988eaa51716d4cb523fdd5fed04dcc195c5fe00a8e4b6135fe70b6f09520bdb0",
"0xfb8a8f98809114b3d433875844e5fe90cf0321b772aaf86863f96e8013b8de7c",
"0xc893ef50496aa272414f6a06af7d53281fbc7265a3e389a42c7c49d32d24fc46",
"0x4956f7747cb6489eeeb92b1c759f54d534397074c9cd017b2f5181187248449f",
"0x4b48dfaa0b7984d4eea56cc40c5130936f98752e1c2d02762b5caab600c39691",
"0x23df05dd92b7e6c024c02fef9cc6aef2ceea2d0a4827de1f87bc7eb4f8c8907c",
"0x47ba2e8a2e5d4fd0bb04be0d76a2d553d4bbfc574d1b5c715393fea03672f4dd",
"0xa8553d8cc2aa6cfa89c96564022be9e89aa5a6b0b98d88fb7976583cb2b4d2ef",
"0xaa3e7684a3a9daeb343a10566c21ed1fccb46f4ac4b80efaa8725127468b7072",
"0x55acb0e629a6b654ba723f330770a4238cee9aa9b98fc4536a7c8bcf6050b9e0",
"0xcf2cc1a66e1d9e2fcd8709c6e695bef0ea95e4d14523d34a544adacaef0bf786",
"0x6d955c9a59acd3c90593b8eb22dcd614a89ec947d554a0fc8323e817cea7b332",
"0xe29b3ce7a0e8325135a33a1127d1db2f17637090712a0b440bcc3a3bd6301186",
"0x47187e16fd16d67eb94e48e2f35eb520191ce412b95c1d18443487887700c516",
"0xe2ea962ec229af7a26687783a7ba8f65490d9aed8f34bdf7aeb978c901f67c1f",
"0xcbbc65451fd646ce67f78593806e3b66379d1a3aed301e6e67df9e3ecfd3cdea",
"0xedc8308273c7ec9b50c8c328c62cda10e4e8505e3f67d134d0961d0fda239747",
"0x57d5dda883a2dc7ef9b36453edcf481d97c06113d7a060131dd39133ded06e6a",
"0x9392ffa1001ca3a85455471b660ee9d89c8d6d421fb4b00d7ef1eaef22747009",
"0x0751d3a58d8bfce5febe6980c821c92f9bf5beb8685358375640f751fc5c8369",
"0x6ad5fcb53f602b55dc728c7850f628ed5c500b65c6b0d22c077fc4df980d9306",
"0xb9f2d92291fede8a3def3f527a8449f6e330d587df1ec3daedc1f42cdcbd6af2",
"0x85eef96182742e4090221c1ac4433c106467e48f8c46ead864e6150d7d50946d",
"0x6e800d685f7f68839978c124f300aedb6c34dd7ccd7b2dcd3144223d0e3db527",
"0x9395edff6ff47843cda1e5cee061f449dcb7b5a0ca07daf9788079aa7c5b2ca3",
"0xa2995f2cd9a79024f92ecfaac2cbb17a9325b3f54480bf2ae5f3d171132780f6",
"0xef907147aaa023015d9b8f3e7414dd4b84e551af0d9f19fb918ad5f632096657",
"0xa44d76467ee5fd7acc90c13bb12740b3fa8a0096ad0be0e3619841e67323c5ba",
"0xaa574a790a0a50cdac6be3819be64c67427f5a891a0029333da60a01680d83f3",
"0x531d9c8a5d68299fd55cfe498922d54af8b119500f7e6bc0c1b66b45234dab1d",
"0x45cc89de803b6eea973d45c26b4b4287d322dae61163ecebdd3db92f8a40be52",
"0xb305c50ca54418553d0a08c2a01908f3d413ee3eafb55eeb4cfe32aaad32597c",
"0x5767e979f2322c81537baf5d300d24e736373eb399c0e7ae989fc0f177c40bcd",
"0xe3646fedcf2aa89d6ab6a6a225cbfcf539317e4c59be2655b46f0d89142d9b18",
"0x9edc1e15d3b2e5eb5f0b60f15e3b39b0be95ddf0bb6e4d18f4c52322b66c7867",
"0x5bf071715890e9f227fc66c705e782add56e39eadd30dc982066fc067ac64fcd",
"0xddb572bdf8c2ff6ce8a0d9b6b2c95cbb33dfa9b96bde4b74812ac016a93770e2",
"0xf0687ab1fb94e49d1e113b1fb0127548d60ca1dcf341a1952d16dec090aa2736",
"0x94308074a4ed0dda1ebaf569b6cd5b4b6f7e77bbc41c737c78462a1ab330e3c1",
"0xa7141bddbfa78144aae11810acf034e48bffc3368c862d4f750112899150936d",
"0x1560476607eb8c091ffbc0ec21cb3091c3385f9c83f8d27c4a301ac200a92820",
"0x8c0b77737383dde0abf21d1350f0d2c285344720c314c564717ffa034acb1739",
"0x2782b37efd53e9a34ed2742be32de2480de342a384d81bdf3359d3686a3b504f",
"0x6e9848f3a434e019bc209a02ec769dc63e084b9c0f00472c218589dd3c256017",
"0x721d8f1bc957b825d3abe06a6ad9d8bba2e03b915aa779ac42fd9e5bc247411a",
"0xb937b6dbba5291fd35427afb0126ffd47962a07c3bbd6c77e4b80f6bf751c684",
"0xa5461d8dd8d05bf13875c6b2b62c82d371163d2f8ca80c2c0ee4d94061355a7b",
"0x58901227df5457e57c74db16ed72b9b6f9303de046e7adf6fc269db7ee9e0a28",
"0x33cb303cd28fa770e6c9f067831cb1829a8ccce845ac6bdce7d3da5d4ba8f3d1",
"0x3ea819ffcb3839d7a16ce09958849118a801152ecedc92de0ae5154f6c8a5d1f",
"0x001ed88b63827a6c71d7214b42551990e3f313720d982ea5f1049ede4f9d228a",
"0x2e346b0acbeeeb88e08ca6af0f2bcc3669e093475d8c224f23a45d4e2fca462c",
"0xb4ed38878080e2128b706ca1ac4c92c0def02a8ec094d07312068c10f6b144ca",
"0xd0d3c577cf73421791431a6f00452f33fd06f771de9ae2caa32ef2c93bd03951",
"0xb3dc9827308478b197b3995e39aa930d40df8cb98fcb2958c6ff8ece2bbd4c16",
"0x44547163a565de79110c1e42b81151a6e304df14953e648742558efa6f63672f",
"0x487a072363419adfe51ce0b8be352c0f497e5720617e9a237500293459cb7bc0",
"0xe7e9d6bbc5de3d62822c92cec484926d935038fff8be29ff3743008499000d9f",
"0xe151cd789208eeaa791f146f7e7efd46c17e2f8aaf061ba5bdbd7357a32cea39",
"0xf5e2de235cd7ecbc34828c244da80de6c9c452c253e6c876d9843bf5bc665daf",
"0xd0bdde209238ddc6ccd1e06e6e69c2c16b38ebac8b9f3202d46bd6bebacdd893",
"0x5c3cab37f5d83ad8fe9349ba88ead08f36e71f149f10642c819ae53b26ccb0a6",
"0x1d069657a6a467ecb3a781a3d72a8b701faf497e1098fbb9c04ae29820fa4e75",
"0x8fa114b013195af63e697432f3be7017ce8fd6e7ec26f23f832b003e82f17ce0",
"0x2664fa9d45f83ddb5c8a758c6fa3201abe7ea14571c886815585c543f245b301",
"0xd6c3528e946a4461efa56df07020008870ed64fde08cd72e7f8be581207f0d1a",
"0xdc4c0f579f3e44278905dbc69610f7d1025e068f75e5475400d96c97297fe5a3",
"0x06124cac7f9a1c10d48216905db968c9580b3744ff89b37b9b49e7308b04da8a",
"0x5c0c6c98bce9c64b7b62d62ecf02f435ce54b76c58883da177611774c79d5fba",
"0x424553682070092aa2ab3e454c66dac9d6bf6baae6379d91405a47fa48a3f200",
"0x3d09aa437ff840909ec6024c1e407ee7b5622561e4991b76968c146ae1c4976b",
"0x3ef50c81169af169c100f58f3afcb8e2f926d957b2adbaca8787be5d4e8d7233",
"0x8783eaeb56ca2d7fec84e0e272b77271fdfd6c14452a2e1dd83de770c5d99a1a",
"0x861024460895378ba100c5d0c05e62bb6cac8b21ae529ab5cab39eb6c6cabd90",
"0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b"
]
},
"accounts": {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -53,8 +53,8 @@
"gasLimit": "0x1000000"
},
"hardcodedSync":{
"header": "f90213a0f6a1b2e8155af1d1d77879826e2535cb6023ba35705934380ab05f65bcbfb107a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f3af96f89b3d7cdcbe0c083690a28185feb0b3cea015ca95dffe4c5de6d9c02d9282df0db94855b0d602738f4b6fcb2268694cd92aa07ecb0900077c45bd4d3ca910218099f726fea18461f90be18897710767a51559a0251f2cb798e965c5d9b11c882f37c69fd2c42b314fabe64d2b4998c76eb93ae8b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008439b475f9833720018389769d82f618845b45928b96d583010b038650617269747986312e32362e31826c69a0fbd0db05012df54423a6b25395ec4f6e66d9f11af8b9c492c4fb7197fcd6a5ba8877d4a227c2bdf4de",
"totalDifficulty": "8809217991079619",
"header": "f9020fa0a415a8dcd55fe9c93372da415ff6897036e48cd3c1a5ff8ffe119eea1096ecd6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479443d58f2096e015db88e44346e73d8c59cb1753bda0100f05d66d36782b7c061c724d8d07619cc61053eda41badc8d2cb9292898ebaa00a60317b490365f40f0528e1f559b0f49facb6638c82a9490d368e963647c704a0118b536c3bdabf90273d527dfc26914c7878176fff16cee8fbb150e00ffcdd29b9010000000000000000040000002040000000000000000000000000000000000000000040020000000000010800000000000010000000000200000800000000600400000000080100c000004002080000000045000000008000080000000020000200404010010200010004000000000008020000008000000000000000108010440000800080000400010000080010820008000410800000100000000000000000000240244000000010000000000010010000000000002000000000000000000004000000020000001000002000000000000000013000000100000800008000200000104000000000000080000080200402010000000000000000001020000008008501602a8414833bc8018347b7a983476d40845b838083904d696e656420627920416e74506f6f6ca0f540bc9cfa258b97576bfb9a79518b2c07ed73a98bc6baa61cf7af4b40ad5b6988965658a406315a8a",
"totalDifficulty": "9811143388018700",
"CHTs": [
"0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a",
"0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc",
@ -1819,7 +1819,156 @@
"0x4b40cd83205f8b946ca9f11fc3306872650e658e631511fd4080bc8ca749d913",
"0x652acc59b71ca20bb65ca195d1a4b3e177f6a3985bdcd6120e1a45b7d4a0c7ca",
"0x49a5e2580ceb329665244e489592aea27d54da8189a665d9435e037ea70c46a5",
"0x379801356beb3a8e5fa7311792c69c7ac1f675a9c08c837f9f0e9f53c243d6a7"
"0x379801356beb3a8e5fa7311792c69c7ac1f675a9c08c837f9f0e9f53c243d6a7",
"0xfeff4543c70356b7d9767c26b228cac8452c95bc4875e92a60d7e6fc50468667",
"0x82eb18827313399cb3b0d3c975eb9a9480c3aa5587ce72d321bedccaaab56115",
"0xa644c582a751a6d8cbf30e59d6e770a6f441c017b486cdb23e6b9c48c614967d",
"0x75e6f4d4185515a3c58dea60b55d5e50af053bb261db2d3de00f812a4072ee2c",
"0x9018506876afe91cd2cded037f41c5ee8503fede2a59c47dfe7ea1b36c460f73",
"0x0b8bc06bf211f715291846c6c34b805b6aee91ef4e8c63cf3d15ec79b44ddae8",
"0x150e43fee00d798b8611d4e03838072d8b9c8ee3771e840ee2c161a541d6b643",
"0xe98c938110bd4227c660a9bdccba3b5ce5b8414d909514502e8f354f96abce69",
"0x0fdc3bd666d74a99e623f6d4957bcbfb17395bbdacb52b18ecf7aa5d2e4ad2ce",
"0x2c72d738e803c0522b5f424731ad6327548ef08ded4caf4ae0466b2cf171ac4b",
"0xa7709a082f8a2ed01e2e88c4a2d18930f510fe5b831d2a1bbb1a85a858f19e54",
"0x8ccb960803f6b6e87515ec20a36734128da0dd6e65845013d89996070d3cbc69",
"0x4ab2e49286c8505f32ca54314d1b5c3b2952578d191c69d1cc7ba78a000a01d4",
"0x6bb792b52949c952f20b9d11274c8a05edb44c4070d949bdfddcb0eef2464454",
"0xf61eccaeddac91487b2f5d7b3ec57d1ccbdd0e1307d2f624319fff525149941f",
"0x2dcf01b0d9ce31c13c20959618f2e5e0c7f8c48521f00c12c99d28bfcf202f57",
"0xb1e83745e6013706904b7322350c8b453aaaba0a61ba89f35eef8f19759ceeb4",
"0x8a2cd4944bee70696aa216b453774f4d915dee4bb78c8f7ff55410cddec318fe",
"0x49a78ff97bd4938cd030df23e5ff4d84ace59ef3fdc0099941d8ad7f82235894",
"0x61e2096919419c8856a5473f135f4f9febb102f80eecc90ad60baaed77a99d29",
"0xb95709562a26564e57cafa00d0969305ffdd0aea7e523ba90957a6cbad6ceb70",
"0xb7a6438f176aed77a9c6470e28ab8cf19dad8f77dd3313cfbbbc9276761f454b",
"0xc85a1c37b5a4e1e8ae67df31b369f0b44cdcf66418b42206e5b4a738a0a0bae7",
"0xf034b0d125eb1bd1bbde1fe413aef80fdc136339eed062b97cb9da2f4bc94ba5",
"0xcddbaba3e9e1680a2d1586a1e9e2268afb51b4894f2b41fb2eac5f667b6cb655",
"0x971b2fbd25a97bc710c30b6b98efc90428a7e423c09fe772622e7ea37d18e49c",
"0x8571bcf05c836a59a5d3216634ed1f691edb7bcddc7b5412bc513ae9e1fc0423",
"0x0543d8abe5e1bd541a5bc994b0c7ea5a556575d2e9302d1dc36348ebb7ab9e82",
"0xebd8f9095619980043f234bf4f7682534ae6a15b4584e9d1ae524138471467c3",
"0xd0699a768c873ca5bd615ab5b0fd9c7c6c649c4245b58cb622210ac2bfcf3111",
"0x35bd5a50b11033878751d985459657bd4c0206584cd1def98a355d7ffb0539f4",
"0xd476d2b8b62b720520ba0990137629f83db9c6896f1e788fa5bf08614af1f2bb",
"0x2a8034765c582c07580c0da45c4216bb513171d073a99cbca2fa2adc0c05dbf8",
"0x084b45a575706daccfbbbcc321a9546b0c911861f2639d81f210b77680f60fb7",
"0x499bfc54ba17718aa8f74ceb412dd9b6b6c7d1cbde4d8ad2385a5d5d77e98915",
"0x8638684b06607afb53385f477f0f295453f14e36161da6dc7728336475303a9d",
"0xa686ad8ccc3507627712d203f7ff3be65c289da67269388d0ad8949ad3a5a589",
"0x6d262ff8babed3a603f400501cd77344585fff92e5bab5f5848873042ab87cb0",
"0xb5755234055b3534fceeafcc84d0d77dac220d3466e1dbbbe7d7d44c345e1eec",
"0x92a54b989a1aafd36f979ff0f1fc73f9b1508628f054430234f4460cd9f3959d",
"0x1a48d9bb57e9a70b03c066c97ff9520c177b8361f2b3c343ac71fd8cbdbadba5",
"0xc9e103919e8b6827a1fd57a3e99155a24810f524fb69a7e3fbf486707b2da690",
"0x22a5ba2899ce696fe691a2c545b98ddecb7c0a844cff2375e50e0a0f0f9cf9b3",
"0x154890ebebe7f014aa88f8da52c9713e2b0cc8b9b6c7d29b354afa000c2eb429",
"0xf9a72e3ce36943a442d0dbc7a869a6344003d6a7ee4d344c1899ab8b96746a6b",
"0x270fe45a526aa3bcc8e4a5be075610ae9b15d6fe48b04c6ff0c82a1c7f56e0d8",
"0x9eacbdd695faa85bdbff10bcefcd5edfcc489c3380cb1c73ab5ca6cba2492995",
"0xca15124d292e0465c7e50276cfd374c82391bb668d68a3b19c67fbb9e68b0bba",
"0x9a8cfd3f1b8ad178c982feed1fc306dc996da3d928e99a6f8ad240e55f52cc3e",
"0xc173b14778977c5d6dcb1079023c493406911c6d6791ad08104f847323aff7cf",
"0x82b3e9b9a407ff0596aa7eabdeba10dded85fbf3258d12949ed4f46484e0f649",
"0xb8a009c28a2328b7c95531bc64e072388d797130652ea0a84159c801af562a5f",
"0x80e45ff8b60d28dbb45530b7b56e049e605d28087df7133766de0e151dfbd01c",
"0x7667e9cd22c5427e6f37f215b1d9cd90b2659d5db0bb499daa382e09fcfd58e3",
"0x825014f354bee6aa4cf5283f86e8293c0ea6faf07862abe2cfa12740a0d846d3",
"0xbe9116073311dc303fa29f7a226ff79fd39ec2ffbd2d2270652b972a701aef54",
"0xb3fd19eb6b0163156a350156b15e660853f68a903ea6ed758bf80b2fbc5a655b",
"0x3c5a408909bf485e8c3d8e683d8ae4e7b7149d1f01874807428a3f88e1293d4f",
"0xc759f51aceddb90e6e4273fb9439908592dea649f5202f530d15d455c5c8c7c8",
"0x1fc97f79d1b1d72da309bf2027ae193f0594ecb77c07a472421baadda577a24c",
"0x09c4fd284e5c0672ad031629e58fb2776d1e772c6041c91433f287304dfdcd1a",
"0x8c6b40f8700a0638ca5b7bb003c2de6b54e731881a072988cb78ba89557db1d6",
"0xcbc701507f4f970d8dbf15306d6ac5bdd46b6f58bfd2dd07db4ee01c65aab5f7",
"0x6b911e52f43696cab429c0e511fc40011846af92a2631f4d3f2cd040567f021f",
"0x4fa5373f6eeacba61818052da8a9787c4ed86be0bffe0672c0aea792cc3d2d49",
"0x518ceeb36cf1a406b89040ab0c60e380068f5f6571d042d3bd9a9d7af1b12204",
"0x82039214db7d3beae631682e9249b06f98e16153f864c2026a6edcb0727a6532",
"0x9a9e534af83084007e54dadbce2a0224008a8c42356c2ea650606e8e72d2ad8d",
"0xc4dc0b662ac8d4d987b8c2c65cd27fb8992f65d598bbc25f017c45b7032451f9",
"0xa921f124b5275f07b2c064d477d5779963096632f03c54ac9c87917bc4aa6e52",
"0xb4fe786c84a19c8db63117c421ce53244436d0c04384c62d508a88589f4e5c83",
"0xd57ea382802130e3ee8e7671be2b40a1392ebc6528e2e10d9d51f2899ac7ea54",
"0x224523fcd11abd078840803bbde2c3d1d359a0c2cfdd6f9110a93ac4d3c49845",
"0x5da21f79c0f1030e2a5dbfa283becced75e7ff223ef14a6cb5527434503ac71a",
"0x3e315746e89fd3e662f4dfe28245457c3b8a4ea6d9450b93639424a6d8ef7d41",
"0xe142bd09a6967021c4c5a5c7491b0df3b1bcf13564ac934a2668e1b2252e4723",
"0x2e9ab88b366cba155d1f6093e4edbbafd80032b07a192a35942aeea1bf0f1074",
"0xbcbd1b446853135abae9f330d63a06119a93fb53b63c621941f5a74324c384a1",
"0x7816de8933a433aa2719c99db24e692e6ac6551416b08f803302c7751fcfa3ee",
"0x52c53032dd84842dff6580013ab1edca7c251598ba5fc8b903c40e3d9e537095",
"0x771222b46cdcbeba729436ef39f81732aaf4893da720c1e7b59ebb3fd38ab9d6",
"0xfc440de1896e1b2848f2cc5c7d62c0a6b0019008de8aab41df5395586d340d4c",
"0x0df9b803307465e54cc77ee60dd6988e3d713d496ac0209509c5312ad0f19888",
"0x88179429086844e69122c70b6af8b689abea11e13ba0809743532663e3047c3e",
"0x503898d86c4038eb76124e18459e0d57ec25b177fc79bb87eeccce3fa75f0037",
"0xf46efd490382e4e4a3ac0e10926b46ec56e833769acfe3879acffb13030cfe9d",
"0x6efde5293a9d22e688165f2a51bb83e3b53584f9ef5bacc0bd1d99f5c7df18d4",
"0xc03dc313d9be55674000d061851c139f4c57c6fb46106b98c3442832a51c5f3a",
"0x8ec2accb7c89019d0fe2a31ddada0b8251ebe88a439de9d68be73c0994a6523a",
"0x36ec73d7e8c0181f6335c668ad7713f8eed607e0c302b43413f904b26160bdc1",
"0xa53e90d88a751a78397adc6d2fb4f93ad2b38f0ebd00b32932c4b2a39a276d9f",
"0xea2a25111ca37a53c8fade1ef65097f0cb85e00881b1ff201d36c9151a8e1a0f",
"0x8c1a24ac75821a4b0570c22b682c6030c678244b059ffd4b21e4d3cd05afb585",
"0xd230d46b14f9586f7b1947add191a69ed381cb6fdaa9b28c28869da8c6724dc6",
"0x4e8c717de6c94b4be274f052d9df627c945afe18df35c58a90a035759dce6b48",
"0xdefefe94ca6d93b78ef9f92911eec4c2ae0c10148691755f1624f86445a3b2b2",
"0xfa6c031ec69c7dac9f9b6524054806e2fa524c3200fdeac030d3bf7029ab776b",
"0x9204683278cad559a3f9ed2ec1f6539f34efb17957830d0aaa92b73cd0994732",
"0x2bb26a0cc5eb7424033e8bf552c7964573a0954e5b6aae32a51d95d951fc044b",
"0xf6e3827687af53fc532ba163d7ebd5ce18ffa6384157982b6dfdb1f4be82faf5",
"0x627bda246bf499f4498e8c512c8f601e36a1dcd778f21a598736f83b5b33fbd8",
"0x5816773273e4ef45fbacbe920dc3420602d8134fffe302459891cd6e65627f6f",
"0x7cd637fa8a5bb32dfd7c076c34e0e536d7c6710f1888f5ec18d64191a9930744",
"0xfe016a6e9ffd59237b349a817ba8c36f7775fef6513c4d430fbfc20ce72fcb1d",
"0x7c466b30cf23cb7115a3855d9d9c537c29f380ecfd7aaa0a6e59d9680bc43971",
"0xc49551e5eb138d28f5557ea8e8a8bbc7c058084ba0edf8f6bf64471928ecde43",
"0x7366cd68072f52c5644dc9fbe2e72339705dddd2b03690dd748265723944e754",
"0xbfb7c3bed071283cc18cca4192e2bdc1f97aee9b7185d493a29f20ed4d52ae3d",
"0x40c9fbfde126c8c92cf6d15a18be4b5a4da39ff60ce45cf5e9a2c1782244947a",
"0x1358333dd1b82e7c805dced5dcc2edd5d5784fe8104b64eabc598096c26d05ed",
"0x0a9777f7711b6d9f6cc6ad4a78b716199b57f026d1f30f04ded5d2cd8286322c",
"0x7a848ef083a03e4112c75bef258633779cc495df4ac5529e12c8eadc484baad7",
"0x17025c4c255f509163d11df3cac35c1de823e5ec71cfd66693393882d81fddb8",
"0xed0a2fe0dfe85c7d606d0d1b355518a48220e91202ec1c1178c8b37c86e1c9cb",
"0x4674e5e97dc0c615b03c34c702ceb07aec48cd7e8edc953a188d194a8cab35c1",
"0xa004c31b7a6f6511d7eeda4c400c5ede847ce2ea4339641b6c419f688cc4e574",
"0x1bb6c124e94df05e091f6aea45e7658351fd21318e91105274a15be4f7a7a632",
"0xc365b8bab2d6b902508d075195a1e23b04c97e40217c4ffa49fe16bb13e5b575",
"0x93c1383e2ab52ded5fc86e1b6f6e292c0d0977e8756e1fcbf87b099682060e25",
"0x2921b874e3855d9afca966d5088e9b1cfe59f37db54bf0c1e8bc5c5a97e7ef6c",
"0xfee916dad70495cb45c6ac632241a73869f0f553bf7172cc4e63fa382a5e1077",
"0xc63d63b401941d11edf755d7b6564b4fcba1f84ed99cd08f1580faf2c224478c",
"0x8069f00ca36baba06b310e28f6873e78b3ded25b456d95dad7eef4c517e7d096",
"0x48dc0968af32e91a8a3f252bc0082d7c22f8dd9797e4fa774d5b5365386a4602",
"0x861ffb24def147c4577aaa332aa2b5d3165542c4fd1e1882a9050e5de10f1f57",
"0x9fdfb7305249e7a38068f8099b74c5584a2f2df3f0514371f20042a6c0d2c85e",
"0x90212f15c5d6b686810e1895a139bbc26141181c3c472ee28ef9904553a2faed",
"0xdf967dfde0b63153142628dae7522307afb35b24146d9fc1d35874914244eec8",
"0xfb17a9d9e9a5ab6d742f55c0e8d80c5e5d722e9411e84bc47b1d2fe5fc33dd71",
"0x56b2c30b802088f9ebf0918c7ce44b50a96a0eac98f89e1711f53452006259c2",
"0x4c38b33bd4089a48a65369955540219b44af520000b8f8c346bdc96d47dc2479",
"0x7d3487d3823204a94e557b7a942d7c657c1b49d9f40f2d739a9099d4438695b3",
"0x2f82f94eb74aa2c0fb91bdb38ba0b416ce7e033c7e2a74aea113d201b225e24d",
"0xce8ac4b2f0f74601280bc3df0f5955d033e5c511372d812b36dffbca4b2e4736",
"0xb6ea6c89e91ecca1fbd723188a77370e9d23c3df8aac282cbcbe000b13d31b57",
"0xb8b8b7cb900482562227a0a1256ddbe822cdcf134a196e29b1aa6fd92423a4ed",
"0x0f47ab9f4985c3175e0a30a237d4f7c42db4a58f95344a86a818e459296610fe",
"0xc26a55a23eb390fc83fbdc9f07ee3ce09e8a2b28bc09386323ffc0844e13be24",
"0x1d5e97a7fdf5f34192e9b6dd255c41b63e24e1b4ef4ea43ae510fd1f50abb022",
"0x58b6120c4f0a1004e51703e77decb1c85bdd40bc83654d3f8ce5f7e3b4b6ca25",
"0xa2f4b27f5641d9294ee0411bcabc574f94b294ed8c50c9ae0c3d58caea7d6ba9",
"0xc4d6d3a8b4debec7ec7f3e2a6e1c64de46ec1187ed6e87fa2d87412c9874a3a6",
"0xfb59d9b66471893988d0fed17898fe2b7873d85aed217c20b6f438ed70fc340b",
"0x850df664737f288ae16d701878ad04f399b367fccaa2ddbf975d77868bea7cf5",
"0x4dfe47362c005896f82ac2d02a12ee9418693cd2f5d1bcfdc321980897171993",
"0xb652952de1bf9e1174e5f6a37b069b437792672a37a9e0159c4f36b6e64306b4",
"0xb72dd6cb5df1b00dbbd84e097e2da79af2ce60559697ab4c93b0a8b85b2ee406",
"0xb96fd4a94ac30c10f757691f7f06f25a4900fe424f4eb7ccf322e2f95249b914",
"0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8"
]
},
"nodes": [

View File

@ -16,7 +16,16 @@
"gasLimitBoundDivisor": "0x400",
"minGasLimit": "0x1388",
"networkID": "0x62121",
"wasmActivationTransition": 4000000
"wasmActivationTransition": 7250000,
"eip140Transition": 7250000,
"eip211Transition": 7250000,
"eip214Transition": 7250000,
"eip658Transition": 7250000,
"maxCodeSize": 24576,
"maxCodeSizeTransition": 7250000,
"registrar": "0xb8624dc8cb3ca3147c178ac4c21734eb49e04071"
},
"genesis": {
"seal": {
@ -43,12 +52,22 @@
},
"0x4ba15b56452521c0826a35a6f2022e1210fc519b": {
"balance": "0x7E37BE2022B2B09472D89C0000"
}
},
"0x0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "activate_at": 7250000, "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "activate_at": 7250000, "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "activate_at": 7250000, "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "activate_at": 7250000, "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 7250000, "pricing": { "modexp": { "divisor": 20 } } } },
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 7250000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 7250000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 7250000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
},
"nodes": [
"enode://147573f46fe9f5cc38fbe070089a31390baec5dd2827c8f2ef168833e4d0254fbee3969a02c5b9910ea5d5b23d86a6ed5eabcda17cc12007b7d9178b6c697aa5@37.120.168.56:30303",
"enode://a370d5fd55959f20af6d1565b151a760c1372f5a2aaf674d4892cd4fd2de0d1f672781cd40e0d4e4b51c5823527ddec73b31cc14ac685449d9f0866996a16b9f@13.76.165.180:30303",
"enode://da019fa5fb1fda105100d68a986938ec15ac5c6ff69d6e4ad3e350e377057f3e67e33aea5feb22d5cdcfc22041d141c8453c77baa64a216fff98f191ca76b3ec@18.220.108.238:30303",
"enode://49498fb8cdcd79c813ccdaa9496a3a4be0a187a3183e99adbc04d9c90b9a62ad59f0b6832f6e43b48e63fbebf74ec5438eb0d6d9098330edf36413d276fedf81@13.80.148.117:30303"
"enode://eda34244538d72f42605a6fc8b8a34b15714c683989e8b29dc9e7a2b2088da490a5b32f2c149bec5a5c482bf03ec2c4f38b833ae31e36fcb26fb05fd094b2a88@18.197.33.9:30303",
"enode://12e903e900137b02b22e01f7918bd6e7310773c313e4e577281f35597e394a3e0b54c7314a8970a9776c5a3e5dc4daee289215dea3897bcb6d5cf0bb1dd2d356@18.197.31.231:30303",
"enode://423fdb91b37ec0714af0c19f625ec4af3ada2844367a36e45a05703577a84f7f0e9483585d4950a35c9e3738dba8c6abd7e1ce278d9a1f3f28065bc009f409cd@52.221.203.209:30303",
"enode://a9327d37d07799817d4a3e13d49fb4f5cc1486d4adf3ec8a6b98be62c4d7a5453914a5139dbe124809a388514cb0be37f9fa799539abe2250672f6d3d778b821@18.191.209.251:30303"
]
}

View File

@ -18,9 +18,9 @@
mod stores;
use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy};
use self::stores::AddressBook;
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::fmt;
use std::time::{Instant, Duration};
@ -96,20 +96,6 @@ impl From<SSError> for SignError {
/// `AccountProvider` errors.
pub type Error = SSError;
/// Dapp identifier
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct DappId(String);
impl From<DappId> for String {
fn from(id: DappId) -> String { id.0 }
}
impl From<String> for DappId {
fn from(id: String) -> DappId { DappId(id) }
}
impl<'a> From<&'a str> for DappId {
fn from(id: &'a str) -> DappId { DappId(id.to_owned()) }
}
fn transient_sstore() -> EthMultiStore {
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
}
@ -125,8 +111,6 @@ pub struct AccountProvider {
unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>,
/// Address book.
address_book: RwLock<AddressBook>,
/// Dapps settings.
dapps_settings: RwLock<DappsSettingsStore>,
/// Accounts on disk
sstore: Box<SecretStore>,
/// Accounts unlocked with rolling tokens
@ -167,7 +151,7 @@ impl AccountProvider {
/// Creates new account provider.
pub fn new(sstore: Box<SecretStore>, settings: AccountProviderSettings) -> Self {
let mut hardware_store = None;
if settings.enable_hardware_wallets {
match HardwareWalletManager::new() {
Ok(manager) => {
@ -195,7 +179,6 @@ impl AccountProvider {
unlocked_secrets: RwLock::new(HashMap::new()),
unlocked: RwLock::new(HashMap::new()),
address_book: RwLock::new(address_book),
dapps_settings: RwLock::new(DappsSettingsStore::new(&sstore.local_path())),
sstore: sstore,
transient_sstore: transient_sstore(),
hardware_store: hardware_store,
@ -210,7 +193,6 @@ impl AccountProvider {
unlocked_secrets: RwLock::new(HashMap::new()),
unlocked: RwLock::new(HashMap::new()),
address_book: RwLock::new(AddressBook::transient()),
dapps_settings: RwLock::new(DappsSettingsStore::transient()),
sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
transient_sstore: transient_sstore(),
hardware_store: None,
@ -290,9 +272,14 @@ impl AccountProvider {
)
}
/// Returns the address of default account.
pub fn default_account(&self) -> Result<Address, Error> {
Ok(self.accounts()?.first().cloned().unwrap_or_default())
}
/// Returns addresses of hardware accounts.
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
if !accounts.is_empty() {
return Ok(accounts.into_iter().map(|a| a.address).collect());
}
@ -308,7 +295,7 @@ impl AccountProvider {
Some(Ok(s)) => Ok(s),
}
}
/// Provide a pin to a locked hardware wallet on USB path to unlock it
pub fn hardware_pin_matrix_ack(&self, path: &str, pin: &str) -> Result<bool, SignError> {
match self.hardware_store.as_ref().map(|h| h.pin_matrix_ack(path, pin)) {
@ -318,175 +305,6 @@ impl AccountProvider {
}
}
/// Sets addresses of accounts exposed for unknown dapps.
/// `None` means that all accounts will be visible.
/// If not `None` or empty it will also override default account.
pub fn set_new_dapps_addresses(&self, accounts: Option<Vec<Address>>) -> Result<(), Error> {
let current_default = self.new_dapps_default_address()?;
self.dapps_settings.write().set_policy(match accounts {
None => NewDappsPolicy::AllAccounts {
default: current_default,
},
Some(accounts) => NewDappsPolicy::Whitelist(accounts),
});
Ok(())
}
/// Gets addresses of accounts exposed for unknown dapps.
/// `None` means that all accounts will be visible.
pub fn new_dapps_addresses(&self) -> Result<Option<Vec<Address>>, Error> {
Ok(match self.dapps_settings.read().policy() {
NewDappsPolicy::AllAccounts { .. } => None,
NewDappsPolicy::Whitelist(accounts) => Some(accounts),
})
}
/// Sets a default account for unknown dapps.
/// This account will always be returned as the first one.
pub fn set_new_dapps_default_address(&self, address: Address) -> Result<(), Error> {
if !self.valid_addresses()?.contains(&address) {
return Err(SSError::InvalidAccount.into());
}
let mut settings = self.dapps_settings.write();
let new_policy = match settings.policy() {
NewDappsPolicy::AllAccounts { .. } => NewDappsPolicy::AllAccounts { default: address },
NewDappsPolicy::Whitelist(list) => NewDappsPolicy::Whitelist(Self::insert_default(list, address)),
};
settings.set_policy(new_policy);
Ok(())
}
/// Inserts given address as first in the vector, preventing duplicates.
fn insert_default(mut addresses: Vec<Address>, default: Address) -> Vec<Address> {
if let Some(position) = addresses.iter().position(|address| address == &default) {
addresses.swap(0, position);
} else {
addresses.insert(0, default);
}
addresses
}
/// Returns a list of accounts that new dapp should see.
/// First account is always the default account.
fn new_dapps_addresses_list(&self) -> Result<Vec<Address>, Error> {
match self.dapps_settings.read().policy() {
NewDappsPolicy::AllAccounts { default } => if default.is_zero() {
self.accounts()
} else {
Ok(Self::insert_default(self.accounts()?, default))
},
NewDappsPolicy::Whitelist(accounts) => {
let addresses = self.filter_addresses(accounts)?;
if addresses.is_empty() {
Ok(vec![self.accounts()?.get(0).cloned().unwrap_or(0.into())])
} else {
Ok(addresses)
}
},
}
}
/// Gets a default account for new dapps
/// Will return zero address in case the default is not set and there are no accounts configured.
pub fn new_dapps_default_address(&self) -> Result<Address, Error> {
Ok(self.new_dapps_addresses_list()?
.get(0)
.cloned()
.unwrap_or(0.into())
)
}
/// Gets a list of dapps recently requesting accounts.
pub fn recent_dapps(&self) -> Result<HashMap<DappId, u64>, Error> {
Ok(self.dapps_settings.read().recent_dapps())
}
/// Marks dapp as recently used.
pub fn note_dapp_used(&self, dapp: DappId) -> Result<(), Error> {
let mut dapps = self.dapps_settings.write();
dapps.mark_dapp_used(dapp.clone());
Ok(())
}
/// Gets addresses visible for given dapp.
pub fn dapp_addresses(&self, dapp: DappId) -> Result<Vec<Address>, Error> {
let accounts = self.dapps_settings.read().settings().get(&dapp).map(|settings| {
(settings.accounts.clone(), settings.default.clone())
});
match accounts {
Some((Some(accounts), Some(default))) => self.filter_addresses(Self::insert_default(accounts, default)),
Some((Some(accounts), None)) => self.filter_addresses(accounts),
Some((None, Some(default))) => self.filter_addresses(Self::insert_default(self.new_dapps_addresses_list()?, default)),
_ => self.new_dapps_addresses_list(),
}
}
/// Returns default account for particular dapp falling back to other allowed accounts if necessary.
pub fn dapp_default_address(&self, dapp: DappId) -> Result<Address, Error> {
let dapp_default = self.dapp_addresses(dapp)?
.get(0)
.cloned();
match dapp_default {
Some(default) => Ok(default),
None => self.new_dapps_default_address(),
}
}
/// Sets default address for given dapp.
/// Does not alter dapp addresses, but this account will always be returned as the first one.
pub fn set_dapp_default_address(&self, dapp: DappId, address: Address) -> Result<(), Error> {
if !self.valid_addresses()?.contains(&address) {
return Err(SSError::InvalidAccount.into());
}
self.dapps_settings.write().set_default(dapp, address);
Ok(())
}
/// Sets addresses visible for given dapp.
/// If `None` - falls back to dapps addresses
/// If not `None` and not empty it will also override default account.
pub fn set_dapp_addresses(&self, dapp: DappId, addresses: Option<Vec<Address>>) -> Result<(), Error> {
let (addresses, default) = match addresses {
Some(addresses) => {
let addresses = self.filter_addresses(addresses)?;
let default = addresses.get(0).cloned();
(Some(addresses), default)
},
None => (None, None),
};
let mut settings = self.dapps_settings.write();
if let Some(default) = default {
settings.set_default(dapp.clone(), default);
}
settings.set_accounts(dapp, addresses);
Ok(())
}
fn valid_addresses(&self) -> Result<HashSet<Address>, Error> {
Ok(self.addresses_info().into_iter()
.map(|(address, _)| address)
.chain(self.accounts()?)
.collect())
}
/// Removes addresses that are neither accounts nor in address book.
fn filter_addresses(&self, addresses: Vec<Address>) -> Result<Vec<Address>, Error> {
let valid = self.valid_addresses()?;
Ok(addresses.into_iter()
.filter(|a| valid.contains(&a))
.collect()
)
}
/// Returns each address along with metadata.
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
self.address_book.read().get()
@ -849,7 +667,7 @@ impl AccountProvider {
#[cfg(test)]
mod tests {
use super::{AccountProvider, Unlock, DappId};
use super::{AccountProvider, Unlock};
use std::time::{Duration, Instant};
use ethstore::ethkey::{Generator, Random, Address};
use ethstore::{StoreAccountRef, Derivation};
@ -977,96 +795,6 @@ mod tests {
assert!(ap.sign_with_token(kp.address(), token, Default::default()).is_err(), "Second usage of the same token should fail.");
}
#[test]
fn should_reset_dapp_addresses_to_default() {
// given
let ap = AccountProvider::transient_provider();
let app = DappId("app1".into());
// add accounts to address book
ap.set_address_name(1.into(), "1".into());
ap.set_address_name(2.into(), "2".into());
// set `AllAccounts` policy
ap.set_new_dapps_addresses(Some(vec![1.into(), 2.into()])).unwrap();
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
// Alter and check
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 3.into()])).unwrap();
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
// Reset back to default
ap.set_dapp_addresses(app.clone(), None).unwrap();
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
}
#[test]
fn should_set_dapps_default_address() {
// given
let ap = AccountProvider::transient_provider();
let app = DappId("app1".into());
// set `AllAccounts` policy
ap.set_new_dapps_addresses(None).unwrap();
// add accounts to address book
ap.set_address_name(1.into(), "1".into());
ap.set_address_name(2.into(), "2".into());
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 2.into(), 3.into()])).unwrap();
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
// when setting empty list
ap.set_dapp_addresses(app.clone(), Some(vec![])).unwrap();
// then default account is intact
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
// alter default account
ap.set_dapp_default_address("app1".into(), 2.into()).unwrap();
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![2.into()]);
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 2.into());
}
#[test]
fn should_set_dapps_policy_and_default_account() {
// given
let ap = AccountProvider::transient_provider();
// default_account should be always available
assert_eq!(ap.new_dapps_default_address().unwrap(), 0.into());
let address = ap.new_account(&"test".into()).unwrap();
ap.set_address_name(1.into(), "1".into());
// Default account set to first account by default
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
// Even when returning nothing
ap.set_new_dapps_addresses(Some(vec![])).unwrap();
// Default account is still returned
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
// change to all
ap.set_new_dapps_addresses(None).unwrap();
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
// change to non-existent account
ap.set_new_dapps_addresses(Some(vec![2.into()])).unwrap();
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
// change to a addresses
ap.set_new_dapps_addresses(Some(vec![1.into()])).unwrap();
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![1.into()]);
// it overrides default account
assert_eq!(ap.new_dapps_default_address().unwrap(), 1.into());
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
ap.set_new_dapps_default_address(address).unwrap();
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
}
#[test]
fn should_not_return_blacklisted_account() {
// given

View File

@ -14,21 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Address Book and Dapps Settings Store
//! Address Book Store
use std::{fs, fmt, hash, ops};
use std::sync::atomic::{self, AtomicUsize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use ethstore::ethkey::Address;
use ethjson::misc::{
AccountMeta,
DappsSettings as JsonSettings,
DappsHistory as JsonDappsHistory,
NewDappsPolicy as JsonNewDappsPolicy,
};
use account_provider::DappId;
use ethjson::misc::AccountMeta;
/// Disk-backed map from Address to String. Uses JSON.
pub struct AddressBook {
@ -88,214 +81,6 @@ impl AddressBook {
}
}
/// Dapps user settings
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct DappsSettings {
/// A list of visible accounts
pub accounts: Option<Vec<Address>>,
/// Default account
pub default: Option<Address>,
}
impl From<JsonSettings> for DappsSettings {
fn from(s: JsonSettings) -> Self {
DappsSettings {
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
default: s.default.map(Into::into),
}
}
}
impl From<DappsSettings> for JsonSettings {
fn from(s: DappsSettings) -> Self {
JsonSettings {
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
default: s.default.map(Into::into),
}
}
}
/// Dapps user settings
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum NewDappsPolicy {
AllAccounts {
default: Address,
},
Whitelist(Vec<Address>),
}
impl From<JsonNewDappsPolicy> for NewDappsPolicy {
fn from(s: JsonNewDappsPolicy) -> Self {
match s {
JsonNewDappsPolicy::AllAccounts { default } => NewDappsPolicy::AllAccounts {
default: default.into(),
},
JsonNewDappsPolicy::Whitelist(accounts) => NewDappsPolicy::Whitelist(
accounts.into_iter().map(Into::into).collect()
),
}
}
}
impl From<NewDappsPolicy> for JsonNewDappsPolicy {
fn from(s: NewDappsPolicy) -> Self {
match s {
NewDappsPolicy::AllAccounts { default } => JsonNewDappsPolicy::AllAccounts {
default: default.into(),
},
NewDappsPolicy::Whitelist(accounts) => JsonNewDappsPolicy::Whitelist(
accounts.into_iter().map(Into::into).collect()
),
}
}
}
/// Transient dapps data
#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct TransientDappsData {
/// Timestamp of last access
pub last_accessed: u64,
}
impl From<JsonDappsHistory> for TransientDappsData {
fn from(s: JsonDappsHistory) -> Self {
TransientDappsData {
last_accessed: s.last_accessed,
}
}
}
impl From<TransientDappsData> for JsonDappsHistory {
fn from(s: TransientDappsData) -> Self {
JsonDappsHistory {
last_accessed: s.last_accessed,
}
}
}
enum TimeProvider {
Clock,
Incremenetal(AtomicUsize)
}
impl TimeProvider {
fn get(&self) -> u64 {
match *self {
TimeProvider::Clock => {
::std::time::UNIX_EPOCH.elapsed()
.expect("Correct time is required to be set")
.as_secs()
},
TimeProvider::Incremenetal(ref time) => {
time.fetch_add(1, atomic::Ordering::SeqCst) as u64
},
}
}
}
const MAX_RECENT_DAPPS: usize = 50;
/// Disk-backed map from DappId to Settings. Uses JSON.
pub struct DappsSettingsStore {
/// Dapps Settings
settings: DiskMap<DappId, DappsSettings>,
/// New Dapps Policy
policy: DiskMap<String, NewDappsPolicy>,
/// Transient Data of recently Accessed Dapps
history: DiskMap<DappId, TransientDappsData>,
/// Time
time: TimeProvider,
}
impl DappsSettingsStore {
/// Creates new store at given directory path.
pub fn new(path: &Path) -> Self {
let mut r = DappsSettingsStore {
settings: DiskMap::new(path, "dapps_accounts.json".into()),
policy: DiskMap::new(path, "dapps_policy.json".into()),
history: DiskMap::new(path, "dapps_history.json".into()),
time: TimeProvider::Clock,
};
r.settings.revert(JsonSettings::read);
r.policy.revert(JsonNewDappsPolicy::read);
r.history.revert(JsonDappsHistory::read);
r
}
/// Creates transient store (no changes are saved to disk).
pub fn transient() -> Self {
DappsSettingsStore {
settings: DiskMap::transient(),
policy: DiskMap::transient(),
history: DiskMap::transient(),
time: TimeProvider::Incremenetal(AtomicUsize::new(1)),
}
}
/// Get copy of the dapps settings
pub fn settings(&self) -> HashMap<DappId, DappsSettings> {
self.settings.clone()
}
/// Returns current new dapps policy
pub fn policy(&self) -> NewDappsPolicy {
self.policy.get("default").cloned().unwrap_or(NewDappsPolicy::AllAccounts {
default: 0.into(),
})
}
/// Returns recent dapps with last accessed timestamp
pub fn recent_dapps(&self) -> HashMap<DappId, u64> {
self.history.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect()
}
/// Marks recent dapp as used
pub fn mark_dapp_used(&mut self, dapp: DappId) {
{
let entry = self.history.entry(dapp).or_insert_with(|| Default::default());
entry.last_accessed = self.time.get();
}
// Clear extraneous entries
while self.history.len() > MAX_RECENT_DAPPS {
let min = self.history.iter()
.min_by_key(|&(_, ref v)| v.last_accessed)
.map(|(ref k, _)| k.clone())
.cloned();
match min {
Some(k) => self.history.remove(&k),
None => break,
};
}
self.history.save(JsonDappsHistory::write);
}
/// Sets current new dapps policy
pub fn set_policy(&mut self, policy: NewDappsPolicy) {
self.policy.insert("default".into(), policy);
self.policy.save(JsonNewDappsPolicy::write);
}
/// Sets accounts for specific dapp.
pub fn set_accounts(&mut self, id: DappId, accounts: Option<Vec<Address>>) {
{
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
settings.accounts = accounts;
}
self.settings.save(JsonSettings::write);
}
/// Sets a default account for specific dapp.
pub fn set_default(&mut self, id: DappId, default: Address) {
{
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
settings.default = Some(default);
}
self.settings.save(JsonSettings::write);
}
}
/// Disk-serializable HashMap
#[derive(Debug)]
struct DiskMap<K: hash::Hash + Eq, V> {
@ -366,8 +151,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
#[cfg(test)]
mod tests {
use super::{AddressBook, DappsSettingsStore, DappsSettings, NewDappsPolicy};
use account_provider::DappId;
use super::AddressBook;
use std::collections::HashMap;
use ethjson::misc::AccountMeta;
use tempdir::TempDir;
@ -398,63 +182,4 @@ mod tests {
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}
]);
}
#[test]
fn should_save_and_reload_dapps_settings() {
// given
let tempdir = TempDir::new("").unwrap();
let mut b = DappsSettingsStore::new(tempdir.path());
// when
b.set_accounts("dappOne".into(), Some(vec![1.into(), 2.into()]));
// then
let b = DappsSettingsStore::new(tempdir.path());
assert_eq!(b.settings(), hash_map![
"dappOne".into() => DappsSettings {
accounts: Some(vec![1.into(), 2.into()]),
default: None,
}
]);
}
#[test]
fn should_maintain_a_map_of_recent_dapps() {
let mut store = DappsSettingsStore::transient();
assert!(store.recent_dapps().is_empty(), "Initially recent dapps should be empty.");
let dapp1: DappId = "dapp1".into();
let dapp2: DappId = "dapp2".into();
store.mark_dapp_used(dapp1.clone());
let recent = store.recent_dapps();
assert_eq!(recent.len(), 1);
assert_eq!(recent.get(&dapp1), Some(&1));
store.mark_dapp_used(dapp2.clone());
let recent = store.recent_dapps();
assert_eq!(recent.len(), 2);
assert_eq!(recent.get(&dapp1), Some(&1));
assert_eq!(recent.get(&dapp2), Some(&2));
}
#[test]
fn should_store_dapps_policy() {
// given
let tempdir = TempDir::new("").unwrap();
let mut store = DappsSettingsStore::new(tempdir.path());
// Test default policy
assert_eq!(store.policy(), NewDappsPolicy::AllAccounts {
default: 0.into(),
});
// when
store.set_policy(NewDappsPolicy::Whitelist(vec![1.into(), 2.into()]));
// then
let store = DappsSettingsStore::new(tempdir.path());
assert_eq!(store.policy.clone(), hash_map![
"default".into() => NewDappsPolicy::Whitelist(vec![1.into(), 2.into()])
]);
}
}

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::{HashSet, BTreeMap, VecDeque};
use std::fmt;
use std::cmp;
use std::str::FromStr;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::sync::{Arc, Weak};
@ -50,13 +50,16 @@ use client::{
};
use encoded;
use engines::{EthEngine, EpochTransition, ForkChoice};
use error::{ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
use error::{
ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult,
QueueError, QueueErrorKind, Error as EthcoreError
};
use vm::{EnvInfo, LastHashes};
use evm::Schedule;
use executive::{Executive, Executed, TransactOptions, contract_address};
use factory::{Factories, VmFactory};
use header::{BlockNumber, Header, ExtendedHeader};
use io::{IoChannel, IoError};
use io::IoChannel;
use log_entry::LocalizedLogEntry;
use miner::{Miner, MinerService};
use ethcore_miner::pool::VerifiedTransaction;
@ -1952,7 +1955,25 @@ impl BlockChainClient for Client {
(*self.build_last_hashes(&self.chain.read().best_block_hash())).clone()
}
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>> {
fn transactions_to_propagate(&self) -> Vec<Arc<VerifiedTransaction>> {
const PROPAGATE_FOR_BLOCKS: u32 = 4;
const MIN_TX_TO_PROPAGATE: usize = 256;
let block_gas_limit = *self.best_block_header().gas_limit();
let min_tx_gas: U256 = self.latest_schedule().tx_gas.into();
let max_len = if min_tx_gas.is_zero() {
usize::max_value()
} else {
cmp::max(
MIN_TX_TO_PROPAGATE,
cmp::min(
(block_gas_limit / min_tx_gas) * PROPAGATE_FOR_BLOCKS,
// never more than usize
usize::max_value().into()
).as_u64() as usize
)
};
self.importer.miner.ready_transactions(self, max_len, ::miner::PendingOrdering::Priority)
}
@ -2060,7 +2081,7 @@ impl IoClient for Client {
let queued = self.queued_ancient_blocks.clone();
let lock = self.ancient_blocks_import_lock.clone();
match self.queue_ancient_blocks.queue(&self.io_channel.read(), 1, move |client| {
self.queue_ancient_blocks.queue(&self.io_channel.read(), 1, move |client| {
trace_time!("import_ancient_block");
// Make sure to hold the lock here to prevent importing out of order.
// We use separate lock, cause we don't want to block queueing.
@ -2085,10 +2106,9 @@ impl IoClient for Client {
break;
}
}
}) {
Ok(_) => Ok(hash),
Err(e) => bail!(BlockImportErrorKind::Other(format!("{}", e))),
}
})?;
Ok(hash)
}
fn queue_consensus_message(&self, message: Bytes) {
@ -2504,21 +2524,6 @@ mod tests {
}
}
#[derive(Debug)]
enum QueueError {
Channel(IoError),
Full(usize),
}
impl fmt::Display for QueueError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self {
QueueError::Channel(ref c) => fmt::Display::fmt(c, fmt),
QueueError::Full(limit) => write!(fmt, "The queue is full ({})", limit),
}
}
}
/// Queue some items to be processed by IO client.
struct IoChannelQueue {
currently_queued: Arc<AtomicUsize>,
@ -2537,7 +2542,7 @@ impl IoChannelQueue {
F: Fn(&Client) + Send + Sync + 'static,
{
let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed);
ensure!(queue_size < self.limit, QueueError::Full(self.limit));
ensure!(queue_size < self.limit, QueueErrorKind::Full(self.limit));
let currently_queued = self.currently_queued.clone();
let result = channel.send(ClientIoMessage::execute(move |client| {
@ -2550,7 +2555,7 @@ impl IoChannelQueue {
self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst);
Ok(())
},
Err(e) => Err(QueueError::Channel(e)),
Err(e) => bail!(QueueErrorKind::Channel(e)),
}
}
}

View File

@ -805,8 +805,8 @@ impl BlockChainClient for TestBlockChainClient {
self.traces.read().clone()
}
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>> {
self.miner.ready_transactions(self, max_len, miner::PendingOrdering::Priority)
fn transactions_to_propagate(&self) -> Vec<Arc<VerifiedTransaction>> {
self.miner.ready_transactions(self, 4096, miner::PendingOrdering::Priority)
}
fn signing_chain_id(&self) -> Option<u64> { None }

View File

@ -320,8 +320,8 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get last hashes starting from best block.
fn last_hashes(&self) -> LastHashes;
/// List all transactions that are allowed into the next block.
fn ready_transactions(&self, max_len: usize) -> Vec<Arc<VerifiedTransaction>>;
/// List all ready transactions that should be propagated to other peers.
fn transactions_to_propagate(&self) -> Vec<Arc<VerifiedTransaction>>;
/// Sorted list of transaction gas prices from at least last sample_size blocks.
fn gas_price_corpus(&self, sample_size: usize) -> ::stats::Corpus<U256> {

View File

@ -151,6 +151,24 @@ impl error::Error for BlockError {
}
}
error_chain! {
types {
QueueError, QueueErrorKind, QueueErrorResultExt, QueueErrorResult;
}
errors {
#[doc = "Queue is full"]
Full(limit: usize) {
description("Queue is full")
display("The queue is full ({})", limit)
}
}
foreign_links {
Channel(IoError) #[doc = "Io channel error"];
}
}
error_chain! {
types {
ImportError, ImportErrorKind, ImportErrorResultExt, ImportErrorResult;
@ -184,6 +202,7 @@ error_chain! {
links {
Import(ImportError, ImportErrorKind) #[doc = "Import error"];
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
}
foreign_links {

View File

@ -20,7 +20,7 @@ use std::collections::BTreeMap;
use std::sync::Arc;
use hash::{KECCAK_EMPTY_LIST_RLP};
use engines::block_reward::{self, RewardKind};
use ethash::{quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
use ethash::{self, quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
use ethereum_types::{H256, H64, U256, Address};
use unexpected::{OutOfBounds, Mismatch};
use block::*;
@ -302,7 +302,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.difficulty().clone() })))
}
let difficulty = Ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
let difficulty = ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
&header.bare_hash().0,
seal.nonce.low_u64(),
&seal.mix_hash.0
@ -324,7 +324,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
let result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, seal.nonce.low_u64());
let mix = H256(result.mix_hash);
let difficulty = Ethash::boundary_to_difficulty(&H256(result.value));
let difficulty = ethash::boundary_to_difficulty(&H256(result.value));
trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}",
num = header.number() as u64,
seed = H256(slow_hash_block_number(header.number() as u64)),
@ -447,25 +447,6 @@ impl Ethash {
}
target
}
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
pub fn boundary_to_difficulty(boundary: &H256) -> U256 {
let d = U256::from(*boundary);
if d <= U256::one() {
U256::max_value()
} else {
((U256::one() << 255) / d) << 1
}
}
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
pub fn difficulty_to_boundary(difficulty: &U256) -> H256 {
if *difficulty <= U256::one() {
U256::max_value().into()
} else {
(((U256::one() << 255) / *difficulty) << 1).into()
}
}
}
fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256) {
@ -766,16 +747,6 @@ mod tests {
}
}
#[test]
fn test_difficulty_to_boundary() {
// result of f(0) is undefined, so do not assert the result
let _ = Ethash::difficulty_to_boundary(&U256::from(0));
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
}
#[test]
fn difficulty_frontier() {
let machine = new_homestead_test_machine();

View File

@ -41,31 +41,31 @@ fn load_machine(b: &[u8]) -> EthereumMachine {
Spec::load_machine(b).expect("chain spec is invalid")
}
/// Create a new Foundation Olympic chain spec.
pub fn new_olympic<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/olympic.json"))
}
/// Create a new Foundation Mainnet chain spec.
/// Create a new Foundation mainnet chain spec.
pub fn new_foundation<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/foundation.json"))
}
/// Create a new Classic Mainnet chain spec without the DAO hardfork.
/// Create a new Classic mainnet chain spec without the DAO hardfork.
pub fn new_classic<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/classic.json"))
}
/// Create a new POA Network mainnet chain spec.
pub fn new_poanet<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/poacore.json"))
}
/// Create a new Tobalaba mainnet chain spec.
pub fn new_tobalaba<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/tobalaba.json"))
}
/// Create a new Expanse mainnet chain spec.
pub fn new_expanse<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/expanse.json"))
}
/// Create a new Tobalaba chain spec.
pub fn new_tobalaba<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/tobalaba.json"))
}
/// Create a new Musicoin mainnet chain spec.
pub fn new_musicoin<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/musicoin.json"))
@ -86,19 +86,29 @@ pub fn new_social<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/social.json"))
}
/// Create a new Olympic testnet chain spec.
pub fn new_olympic<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/olympic.json"))
}
/// Create a new Morden testnet chain spec.
pub fn new_morden<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/morden.json"))
}
/// Create a new Ropsten testnet chain spec.
pub fn new_ropsten<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/ropsten.json"))
}
/// Create a new Kovan testnet chain spec.
pub fn new_kovan<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/kovan.json"))
}
/// Create a new Foundation Ropsten chain spec.
pub fn new_ropsten<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/ropsten.json"))
}
/// Create a new Morden chain spec.
pub fn new_morden<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/morden.json"))
/// Create a new POA Sokol testnet chain spec.
pub fn new_sokol<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
load(params.into(), include_bytes!("../../res/ethereum/poasokol.json"))
}
// For tests

View File

@ -306,14 +306,15 @@ impl Miner {
/// Retrieves an existing pending block iff it's not older than given block number.
///
/// NOTE: This will not prepare a new pending block if it's not existing.
/// See `map_pending_block` for alternative behaviour.
fn map_existing_pending_block<F, T>(&self, f: F, latest_block_number: BlockNumber) -> Option<T> where
F: FnOnce(&ClosedBlock) -> T,
{
self.sealing.lock().queue
.peek_last_ref()
.and_then(|b| {
if b.block().header().number() > latest_block_number {
// to prevent a data race between block import and updating pending block
// we allow the number to be equal.
if b.block().header().number() >= latest_block_number {
Some(f(b))
} else {
None
@ -352,7 +353,7 @@ impl Miner {
// if at least one was pushed successfully, close and enqueue new ClosedBlock;
// otherwise, leave everything alone.
// otherwise, author a fresh block.
let mut open_block = match sealing.queue.pop_if(|b| b.block().header().parent_hash() == &best_hash) {
let mut open_block = match sealing.queue.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) {
Some(old_block) => {
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
// add transactions to old_block
@ -397,7 +398,7 @@ impl Miner {
let max_transactions = if min_tx_gas.is_zero() {
usize::max_value()
} else {
MAX_SKIPPED_TRANSACTIONS.saturating_add((*open_block.block().header().gas_limit() / min_tx_gas).as_u64() as usize)
MAX_SKIPPED_TRANSACTIONS.saturating_add(cmp::min(*open_block.block().header().gas_limit() / min_tx_gas, u64::max_value().into()).as_u64() as usize)
};
let pending: Vec<Arc<_>> = self.transaction_queue.pending(
@ -602,7 +603,7 @@ impl Miner {
{
let mut sealing = self.sealing.lock();
sealing.next_mandatory_reseal = Instant::now() + self.options.reseal_max_period;
sealing.queue.push(block.clone());
sealing.queue.set_pending(block.clone());
sealing.queue.use_last_ref();
}
@ -664,7 +665,7 @@ impl Miner {
);
let is_new = original_work_hash.map_or(true, |h| h != block_hash);
sealing.queue.push(block);
sealing.queue.set_pending(block);
#[cfg(feature = "work-notify")]
{
@ -1073,7 +1074,7 @@ impl miner::MinerService for Miner {
Some(false) => {
trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now");
// anyway, save the block for later use
self.sealing.lock().queue.push(block);
self.sealing.lock().queue.set_pending(block);
},
None => {
trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work");

View File

@ -22,8 +22,7 @@ use std::fmt;
use client::{Client, ImportSealedBlock};
use ethereum_types::{H64, H256, clean_0x, U256};
use ethereum::ethash::Ethash;
use ethash::SeedHashCompute;
use ethash::{self, SeedHashCompute};
#[cfg(feature = "work-notify")]
use ethcore_miner::work_notify::NotifyWork;
#[cfg(feature = "work-notify")]
@ -167,7 +166,7 @@ impl StratumJobDispatcher {
/// Serializes payload for stratum service
fn payload(&self, pow_hash: H256, difficulty: U256, number: u64) -> String {
// TODO: move this to engine
let target = Ethash::difficulty_to_boundary(&difficulty);
let target = ethash::difficulty_to_boundary(&difficulty);
let seed_hash = &self.seed_compute.lock().hash_block_number(number);
let seed_hash = H256::from_slice(&seed_hash[..]);
format!(

View File

@ -334,11 +334,11 @@ fn does_not_propagate_delayed_transactions() {
client.miner().import_own_transaction(&*client, tx0).unwrap();
client.miner().import_own_transaction(&*client, tx1).unwrap();
assert_eq!(0, client.ready_transactions(10).len());
assert_eq!(0, client.transactions_to_propagate().len());
assert_eq!(0, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len());
push_blocks_to_client(&client, 53, 2, 2);
client.flush_queue();
assert_eq!(2, client.ready_transactions(10).len());
assert_eq!(2, client.transactions_to_propagate().len());
assert_eq!(2, client.miner().ready_transactions(&*client, 10, PendingOrdering::Priority).len());
}

View File

@ -8,6 +8,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[lib]
[dependencies]
common-types = { path = "../types" }
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
ethcore-network = { path = "../../util/network" }
ethcore-network-devp2p = { path = "../../util/network-devp2p" }

View File

@ -24,6 +24,8 @@ use devp2p::NetworkService;
use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId,
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind,
ConnectionFilter};
use types::pruning_info::PruningInfo;
use ethereum_types::{H256, H512, U256};
use io::{TimerToken};
use ethcore::ethstore::ethkey::Secret;
@ -39,7 +41,10 @@ use chain::{ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_62,
PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3};
use light::client::AsLightClient;
use light::Provider;
use light::net::{self as light_net, LightProtocol, Params as LightParams, Capabilities, Handler as LightHandler, EventContext};
use light::net::{
self as light_net, LightProtocol, Params as LightParams,
Capabilities, Handler as LightHandler, EventContext, SampleStore,
};
use network::IpFilter;
use private_tx::PrivateTxHandler;
use transaction::UnverifiedTransaction;
@ -256,11 +261,35 @@ pub struct EthSync {
light_subprotocol_name: [u8; 3],
}
fn light_params(
network_id: u64,
max_peers: u32,
pruning_info: PruningInfo,
sample_store: Option<Box<SampleStore>>,
) -> LightParams {
const MAX_LIGHTSERV_LOAD: f64 = 0.5;
let mut light_params = LightParams {
network_id: network_id,
config: Default::default(),
capabilities: Capabilities {
serve_headers: true,
serve_chain_since: Some(pruning_info.earliest_chain),
serve_state_since: Some(pruning_info.earliest_state),
tx_relay: true,
},
sample_store: sample_store,
};
let max_peers = ::std::cmp::max(max_peers, 1);
light_params.config.load_share = MAX_LIGHTSERV_LOAD / max_peers as f64;
light_params
}
impl EthSync {
/// Creates and register protocol with the network service
pub fn new(params: Params, connection_filter: Option<Arc<ConnectionFilter>>) -> Result<Arc<EthSync>, Error> {
const MAX_LIGHTSERV_LOAD: f64 = 0.5;
let pruning_info = params.chain.pruning_info();
let light_proto = match params.config.serve_light {
false => None,
@ -271,20 +300,12 @@ impl EthSync {
.map(|mut p| { p.push("request_timings"); light_net::FileStore(p) })
.map(|store| Box::new(store) as Box<_>);
let mut light_params = LightParams {
network_id: params.config.network_id,
config: Default::default(),
capabilities: Capabilities {
serve_headers: true,
serve_chain_since: Some(pruning_info.earliest_chain),
serve_state_since: Some(pruning_info.earliest_state),
tx_relay: true,
},
sample_store: sample_store,
};
let max_peers = ::std::cmp::min(params.network_config.max_peers, 1);
light_params.config.load_share = MAX_LIGHTSERV_LOAD / max_peers as f64;
let light_params = light_params(
params.config.network_id,
params.network_config.max_peers,
pruning_info,
sample_store,
);
let mut light_proto = LightProtocol::new(params.provider, light_params);
light_proto.add_handler(Arc::new(TxRelay(params.chain.clone())));
@ -916,3 +937,19 @@ impl LightSyncProvider for LightSync {
Default::default() // TODO
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn light_params_load_share_depends_on_max_peers() {
let pruning_info = PruningInfo {
earliest_chain: 0,
earliest_state: 0,
};
let params1 = light_params(0, 10, pruning_info.clone(), None);
let params2 = light_params(0, 20, pruning_info, None);
assert!(params1.config.load_share > params2.config.load_share)
}
}

View File

@ -23,11 +23,11 @@ use std::cmp;
use heapsize::HeapSizeOf;
use ethereum_types::H256;
use rlp::Rlp;
use ethcore::block::Block;
use ethcore::views::BlockView;
use ethcore::header::{BlockNumber, Header as BlockHeader};
use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind};
use ethcore::block::Block;
use ethcore::error::{ImportErrorKind, BlockError};
use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError};
use sync_io::SyncIo;
use blocks::BlockCollection;
@ -527,6 +527,10 @@ impl BlockDownloader {
debug!(target: "sync", "Block temporarily invalid, restarting sync");
break;
},
Err(BlockImportError(BlockImportErrorKind::Queue(QueueErrorKind::Full(limit)), _)) => {
debug!(target: "sync", "Block import queue full ({}), restarting sync", limit);
break;
},
Err(e) => {
debug!(target: "sync", "Bad block {:?} : {:?}", h, e);
bad = true;

View File

@ -149,12 +149,6 @@ const MAX_NEW_HASHES: usize = 64;
const MAX_NEW_BLOCK_AGE: BlockNumber = 20;
// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation).
const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
// Maximal number of transactions queried from miner to propagate.
// This set is used to diff with transactions known by the peer and
// we will send a difference of length up to `MAX_TRANSACTIONS_TO_PROPAGATE`.
const MAX_TRANSACTIONS_TO_QUERY: usize = 4096;
// Maximal number of transactions in sent in single packet.
const MAX_TRANSACTIONS_TO_PROPAGATE: usize = 64;
// Min number of blocks to be behind for a snapshot sync
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
const SNAPSHOT_MIN_PEERS: usize = 3;
@ -761,14 +755,24 @@ impl ChainSync {
}
}
// Only ask for old blocks if the peer has a higher difficulty
if force || higher_difficulty {
// Only ask for old blocks if the peer has a higher difficulty than the last imported old block
let last_imported_old_block_difficulty = self.old_blocks.as_mut().and_then(|d| {
io.chain().block_total_difficulty(BlockId::Number(d.last_imported_block_number()))
});
if force || last_imported_old_block_difficulty.map_or(true, |ld| peer_difficulty.map_or(true, |pd| pd > ld)) {
if let Some(request) = self.old_blocks.as_mut().and_then(|d| d.request_blocks(io, num_active_peers)) {
SyncRequester::request_blocks(self, io, peer_id, request, BlockSet::OldBlocks);
return;
}
} else {
trace!(target: "sync", "peer {} is not suitable for asking old blocks", peer_id);
trace!(
target: "sync",
"peer {:?} is not suitable for requesting old blocks, last_imported_old_block_difficulty={:?}, peer_difficulty={:?}",
peer_id,
last_imported_old_block_difficulty,
peer_difficulty
);
self.deactivate_peer(io, peer_id);
}
},

View File

@ -29,11 +29,9 @@ use transaction::SignedTransaction;
use super::{
random,
ChainSync,
MAX_TRANSACTION_PACKET_SIZE,
MAX_PEER_LAG_PROPAGATION,
MAX_PEERS_PROPAGATION,
MAX_TRANSACTION_PACKET_SIZE,
MAX_TRANSACTIONS_TO_PROPAGATE,
MAX_TRANSACTIONS_TO_QUERY,
MIN_PEERS_PROPAGATION,
CONSENSUS_DATA_PACKET,
NEW_BLOCK_HASHES_PACKET,
@ -121,7 +119,7 @@ impl SyncPropagator {
return 0;
}
let transactions = io.chain().ready_transactions(MAX_TRANSACTIONS_TO_QUERY);
let transactions = io.chain().transactions_to_propagate();
if transactions.is_empty() {
return 0;
}
@ -184,7 +182,6 @@ impl SyncPropagator {
// Get hashes of all transactions to send to this peer
let to_send = all_transactions_hashes.difference(&peer_info.last_sent_transactions)
.take(MAX_TRANSACTIONS_TO_PROPAGATE)
.cloned()
.collect::<HashSet<_>>();
if to_send.is_empty() {

View File

@ -21,6 +21,7 @@
//! https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol
//!
extern crate common_types as types;
extern crate ethcore_network as network;
extern crate ethcore_network_devp2p as devp2p;
extern crate parity_bytes as bytes;

View File

@ -1,53 +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/>.
//! Dapps settings de/serialization.
use hash;
/// Settings for specific dapp.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct DappsSettings {
/// A list of accounts this Dapp can see.
pub accounts: Option<Vec<hash::Address>>,
/// Default account
pub default: Option<hash::Address>,
}
impl_serialization!(String => DappsSettings);
/// History for specific dapp.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct DappsHistory {
/// Last accessed timestamp
pub last_accessed: u64,
}
impl_serialization!(String => DappsHistory);
/// Accounts policy for new dapps.
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum NewDappsPolicy {
/// All accounts are exposed by default.
AllAccounts {
/// Default account, which should be returned as the first one.
default: hash::Address,
},
/// Only accounts listed here are exposed by default for new dapps.
Whitelist(Vec<hash::Address>),
}
impl_serialization!(String => NewDappsPolicy);

View File

@ -48,7 +48,5 @@ macro_rules! impl_serialization {
}
mod account_meta;
mod dapps_settings;
pub use self::dapps_settings::{DappsSettings, DappsHistory, NewDappsPolicy};
pub use self::account_meta::AccountMeta;

View File

@ -24,6 +24,7 @@ use hash::Address;
pub struct EthashParams {
/// See main EthashParams docs.
#[serde(rename="minimumDifficulty")]
#[serde(deserialize_with="uint::validate_non_zero")]
pub minimum_difficulty: Uint,
/// See main EthashParams docs.
#[serde(rename="difficultyBoundDivisor")]

View File

@ -67,19 +67,10 @@ impl WorkPoster {
}
}
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
fn difficulty_to_boundary(difficulty: &U256) -> H256 {
if *difficulty <= U256::one() {
U256::max_value().into()
} else {
(((U256::one() << 255) / *difficulty) << 1).into()
}
}
impl NotifyWork for WorkPoster {
fn notify(&self, pow_hash: H256, difficulty: U256, number: u64) {
// TODO: move this to engine
let target = difficulty_to_boundary(&difficulty);
let target = ethash::difficulty_to_boundary(&difficulty);
let seed_hash = &self.seed_compute.lock().hash_block_number(number);
let seed_hash = H256::from_slice(&seed_hash[..]);
let body = format!(

View File

@ -288,7 +288,7 @@ usage! {
ARG arg_chain: (String) = "foundation", or |c: &Config| c.parity.as_ref()?.chain.clone(),
"--chain=[CHAIN]",
"Specify the blockchain type. CHAIN may be either a JSON chain specification file or olympic, frontier, homestead, mainnet, morden, ropsten, classic, expanse, tobalaba, musicoin, ellaism, easthub, social, testnet, kovan or dev.",
"Specify the blockchain type. CHAIN may be either a JSON chain specification file or ethereum, classic, poacore, tobalaba, expanse, musicoin, ellaism, easthub, social, olympic, morden, ropsten, kovan, poasokol, testnet, or dev.",
ARG arg_keys_path: (String) = "$BASE/keys", or |c: &Config| c.parity.as_ref()?.keys_path.clone(),
"--keys-path=[PATH]",

View File

@ -79,9 +79,6 @@ extern crate log as rlog;
#[cfg(feature = "secretstore")]
extern crate ethcore_secretstore;
#[cfg(feature = "dapps")]
extern crate parity_dapps;
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

View File

@ -32,17 +32,19 @@ use user_defaults::UserDefaults;
#[derive(Debug, PartialEq)]
pub enum SpecType {
Foundation,
Morden,
Ropsten,
Tobalaba,
Kovan,
Olympic,
Classic,
Poanet,
Tobalaba,
Expanse,
Musicoin,
Ellaism,
Easthub,
Social,
Olympic,
Morden,
Ropsten,
Kovan,
Sokol,
Dev,
Custom(String),
}
@ -58,18 +60,20 @@ impl str::FromStr for SpecType {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let spec = match s {
"foundation" | "frontier" | "homestead" | "mainnet" => SpecType::Foundation,
"frontier-dogmatic" | "homestead-dogmatic" | "classic" => SpecType::Classic,
"morden" | "classic-testnet" => SpecType::Morden,
"ropsten" => SpecType::Ropsten,
"kovan" | "testnet" => SpecType::Kovan,
"ethereum" | "frontier" | "homestead" | "byzantium" | "foundation" | "mainnet" => SpecType::Foundation,
"classic" | "frontier-dogmatic" | "homestead-dogmatic" => SpecType::Classic,
"poanet" | "poacore" => SpecType::Poanet,
"tobalaba" => SpecType::Tobalaba,
"olympic" => SpecType::Olympic,
"expanse" => SpecType::Expanse,
"musicoin" => SpecType::Musicoin,
"ellaism" => SpecType::Ellaism,
"easthub" => SpecType::Easthub,
"social" => SpecType::Social,
"olympic" => SpecType::Olympic,
"morden" | "classic-testnet" => SpecType::Morden,
"ropsten" => SpecType::Ropsten,
"kovan" | "testnet" => SpecType::Kovan,
"sokol" | "poasokol" => SpecType::Sokol,
"dev" => SpecType::Dev,
other => SpecType::Custom(other.into()),
};
@ -81,17 +85,19 @@ impl fmt::Display for SpecType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
SpecType::Foundation => "foundation",
SpecType::Morden => "morden",
SpecType::Ropsten => "ropsten",
SpecType::Olympic => "olympic",
SpecType::Classic => "classic",
SpecType::Poanet => "poanet",
SpecType::Tobalaba => "tobalaba",
SpecType::Expanse => "expanse",
SpecType::Musicoin => "musicoin",
SpecType::Ellaism => "ellaism",
SpecType::Easthub => "easthub",
SpecType::Social => "social",
SpecType::Olympic => "olympic",
SpecType::Morden => "morden",
SpecType::Ropsten => "ropsten",
SpecType::Kovan => "kovan",
SpecType::Tobalaba => "tobalaba",
SpecType::Sokol => "sokol",
SpecType::Dev => "dev",
SpecType::Custom(ref custom) => custom,
})
@ -103,17 +109,19 @@ impl SpecType {
let params = params.into();
match *self {
SpecType::Foundation => Ok(ethereum::new_foundation(params)),
SpecType::Morden => Ok(ethereum::new_morden(params)),
SpecType::Ropsten => Ok(ethereum::new_ropsten(params)),
SpecType::Olympic => Ok(ethereum::new_olympic(params)),
SpecType::Classic => Ok(ethereum::new_classic(params)),
SpecType::Poanet => Ok(ethereum::new_poanet(params)),
SpecType::Tobalaba => Ok(ethereum::new_tobalaba(params)),
SpecType::Expanse => Ok(ethereum::new_expanse(params)),
SpecType::Musicoin => Ok(ethereum::new_musicoin(params)),
SpecType::Ellaism => Ok(ethereum::new_ellaism(params)),
SpecType::Easthub => Ok(ethereum::new_easthub(params)),
SpecType::Social => Ok(ethereum::new_social(params)),
SpecType::Tobalaba => Ok(ethereum::new_tobalaba(params)),
SpecType::Olympic => Ok(ethereum::new_olympic(params)),
SpecType::Morden => Ok(ethereum::new_morden(params)),
SpecType::Ropsten => Ok(ethereum::new_ropsten(params)),
SpecType::Kovan => Ok(ethereum::new_kovan(params)),
SpecType::Sokol => Ok(ethereum::new_sokol(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))?;
@ -345,17 +353,31 @@ mod tests {
#[test]
fn test_spec_type_parsing() {
assert_eq!(SpecType::Foundation, "foundation".parse().unwrap());
assert_eq!(SpecType::Foundation, "frontier".parse().unwrap());
assert_eq!(SpecType::Foundation, "homestead".parse().unwrap());
assert_eq!(SpecType::Foundation, "byzantium".parse().unwrap());
assert_eq!(SpecType::Foundation, "mainnet".parse().unwrap());
assert_eq!(SpecType::Foundation, "foundation".parse().unwrap());
assert_eq!(SpecType::Kovan, "testnet".parse().unwrap());
assert_eq!(SpecType::Kovan, "kovan".parse().unwrap());
assert_eq!(SpecType::Morden, "morden".parse().unwrap());
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
assert_eq!(SpecType::Foundation, "ethereum".parse().unwrap());
assert_eq!(SpecType::Classic, "classic".parse().unwrap());
assert_eq!(SpecType::Classic, "frontier-dogmatic".parse().unwrap());
assert_eq!(SpecType::Classic, "homestead-dogmatic".parse().unwrap());
assert_eq!(SpecType::Poanet, "poanet".parse().unwrap());
assert_eq!(SpecType::Poanet, "poacore".parse().unwrap());
assert_eq!(SpecType::Tobalaba, "tobalaba".parse().unwrap());
assert_eq!(SpecType::Expanse, "expanse".parse().unwrap());
assert_eq!(SpecType::Musicoin, "musicoin".parse().unwrap());
assert_eq!(SpecType::Ellaism, "ellaism".parse().unwrap());
assert_eq!(SpecType::Easthub, "easthub".parse().unwrap());
assert_eq!(SpecType::Social, "social".parse().unwrap());
assert_eq!(SpecType::Olympic, "olympic".parse().unwrap());
assert_eq!(SpecType::Morden, "morden".parse().unwrap());
assert_eq!(SpecType::Morden, "classic-testnet".parse().unwrap());
assert_eq!(SpecType::Ropsten, "ropsten".parse().unwrap());
assert_eq!(SpecType::Kovan, "kovan".parse().unwrap());
assert_eq!(SpecType::Kovan, "testnet".parse().unwrap());
assert_eq!(SpecType::Sokol, "sokol".parse().unwrap());
assert_eq!(SpecType::Sokol, "poasokol".parse().unwrap());
}
#[test]
@ -366,13 +388,19 @@ mod tests {
#[test]
fn test_spec_type_display() {
assert_eq!(format!("{}", SpecType::Foundation), "foundation");
assert_eq!(format!("{}", SpecType::Ropsten), "ropsten");
assert_eq!(format!("{}", SpecType::Morden), "morden");
assert_eq!(format!("{}", SpecType::Olympic), "olympic");
assert_eq!(format!("{}", SpecType::Classic), "classic");
assert_eq!(format!("{}", SpecType::Poanet), "poanet");
assert_eq!(format!("{}", SpecType::Tobalaba), "tobalaba");
assert_eq!(format!("{}", SpecType::Expanse), "expanse");
assert_eq!(format!("{}", SpecType::Musicoin), "musicoin");
assert_eq!(format!("{}", SpecType::Ellaism), "ellaism");
assert_eq!(format!("{}", SpecType::Easthub), "easthub");
assert_eq!(format!("{}", SpecType::Social), "social");
assert_eq!(format!("{}", SpecType::Olympic), "olympic");
assert_eq!(format!("{}", SpecType::Morden), "morden");
assert_eq!(format!("{}", SpecType::Ropsten), "ropsten");
assert_eq!(format!("{}", SpecType::Kovan), "kovan");
assert_eq!(format!("{}", SpecType::Sokol), "sokol");
assert_eq!(format!("{}", SpecType::Dev), "dev");
assert_eq!(format!("{}", SpecType::Custom("foo/bar".into())), "foo/bar");
}

View File

@ -944,7 +944,7 @@ fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str,
hardware_wallet_classic_key: spec == &SpecType::Classic,
unlock_keep_secret: cfg.enable_fast_unlock,
blacklisted_accounts: match *spec {
SpecType::Morden | SpecType::Ropsten | SpecType::Kovan | SpecType::Dev => vec![],
SpecType::Morden | SpecType::Ropsten | SpecType::Kovan | SpecType::Sokol | SpecType::Dev => vec![],
_ => vec![
"00a329c0648769a73afac7f9381e08fb43dbea72".into()
],

View File

@ -58,6 +58,7 @@ parity-reactor = { path = "../util/reactor" }
parity-updater = { path = "../updater" }
parity-version = { path = "../util/version" }
patricia-trie = { git = "https://github.com/paritytech/parity-common" }
plain_hasher = { git = "https://github.com/paritytech/parity-common" }
rlp = { git = "https://github.com/paritytech/parity-common" }
stats = { path = "../util/stats" }
vm = { path = "../ethcore/vm" }

View File

@ -25,7 +25,7 @@ pub trait HttpMetaExtractor: Send + Sync + 'static {
/// Type of Metadata
type Metadata: jsonrpc_core::Metadata;
/// Extracts metadata from given params.
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>, dapps_origin: Option<String>) -> Self::Metadata;
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>) -> Self::Metadata;
}
pub struct MetaExtractor<T> {
@ -49,7 +49,6 @@ impl<M, T> http::MetaExtractor<M> for MetaExtractor<T> where
let origin = as_string(req.headers().get_raw("origin"));
let user_agent = as_string(req.headers().get_raw("user-agent"));
let dapps_origin = as_string(req.headers().get_raw("x-parity-origin"));
self.extractor.read_metadata(origin, user_agent, dapps_origin)
self.extractor.read_metadata(origin, user_agent)
}
}

View File

@ -64,6 +64,7 @@ extern crate parity_reactor;
extern crate parity_updater as updater;
extern crate parity_version as version;
extern crate patricia_trie as trie;
extern crate plain_hasher;
extern crate rlp;
extern crate stats;
extern crate vm;

View File

@ -73,7 +73,7 @@ mod testsing {
// when
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
let expected = "34\n{\"jsonrpc\":\"2.0\",\"result\":\"unknown via RPC\",\"id\":1}\n\n0\n\n";
let expected = "4B\n{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / unknown agent via RPC\",\"id\":1}\n\n0\n\n";
let res = request(server,
&format!("\
POST / HTTP/1.1\r\n\
@ -98,7 +98,7 @@ mod testsing {
// when
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
let expected = "38\n{\"jsonrpc\":\"2.0\",\"result\":\"curl/7.16.3 via RPC\",\"id\":1}\n\n0\n\n";
let expected = "49\n{\"jsonrpc\":\"2.0\",\"result\":\"unknown origin / curl/7.16.3 via RPC\",\"id\":1}\n\n0\n\n";
let res = request(server,
&format!("\
POST / HTTP/1.1\r\n\
@ -116,59 +116,4 @@ mod testsing {
res.assert_status("HTTP/1.1 200 OK");
assert_eq!(res.body, expected);
}
#[test]
fn should_extract_dapp_origin() {
// given
let (server, address) = serve();
// when
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
let expected = "3A\n{\"jsonrpc\":\"2.0\",\"result\":\"Dapp http://parity.io\",\"id\":1}\n\n0\n\n";
let res = request(server,
&format!("\
POST / HTTP/1.1\r\n\
Host: {}\r\n\
Content-Type: application/json\r\n\
Content-Length: {}\r\n\
Origin: http://parity.io\r\n\
Connection: close\r\n\
User-Agent: curl/7.16.3\r\n\
\r\n\
{}
", address, req.len(), req)
);
// then
res.assert_status("HTTP/1.1 200 OK");
assert_eq!(res.body, expected);
}
#[test]
fn should_extract_dapp_origin_from_extension() {
// given
let (server, address) = serve();
// when
let req = r#"{"method":"hello","params":[],"jsonrpc":"2.0","id":1}"#;
let expected = "44\n{\"jsonrpc\":\"2.0\",\"result\":\"Dapp http://wallet.ethereum.org\",\"id\":1}\n\n0\n\n";
let res = request(server,
&format!("\
POST / HTTP/1.1\r\n\
Host: {}\r\n\
Content-Type: application/json\r\n\
Content-Length: {}\r\n\
Origin: null\r\n\
X-Parity-Origin: http://wallet.ethereum.org\r\n\
Connection: close\r\n\
User-Agent: curl/7.16.3\r\n\
\r\n\
{}
", address, req.len(), req)
);
// then
res.assert_status("HTTP/1.1 200 OK");
assert_eq!(res.body, expected);
}
}

View File

@ -36,14 +36,13 @@ pub struct RpcExtractor;
impl HttpMetaExtractor for RpcExtractor {
type Metadata = Metadata;
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>, dapps_origin: Option<String>) -> Metadata {
fn read_metadata(&self, origin: Option<String>, user_agent: Option<String>) -> Metadata {
Metadata {
origin: match (origin.as_ref().map(|s| s.as_str()), user_agent, dapps_origin) {
(Some("null"), _, Some(dapp)) => Origin::Dapps(dapp.into()),
(Some(dapp), _, _) => Origin::Dapps(dapp.to_owned().into()),
(None, Some(service), _) => Origin::Rpc(service.into()),
(None, _, _) => Origin::Rpc("unknown".into()),
},
origin: Origin::Rpc(
format!("{} / {}",
origin.unwrap_or("unknown origin".to_string()),
user_agent.unwrap_or("unknown agent".to_string()))
),
session: None,
}
}
@ -76,16 +75,15 @@ impl ws::MetaExtractor<Metadata> for WsExtractor {
fn extract(&self, req: &ws::RequestContext) -> Metadata {
let id = req.session_id as u64;
let dapp = req.origin.as_ref().map(|origin| (&**origin).into()).unwrap_or_default();
let origin = match self.authcodes_path {
Some(ref path) => {
let authorization = req.protocols.get(0).and_then(|p| auth_token_hash(&path, p, true));
match authorization {
Some(id) => Origin::Signer { session: id.into(), dapp: dapp },
None => Origin::Ws { session: id.into(), dapp: dapp },
Some(id) => Origin::Signer { session: id.into() },
None => Origin::Ws { session: id.into() },
}
},
None => Origin::Ws { session: id.into(), dapp: dapp },
None => Origin::Ws { session: id.into() },
};
let session = Some(Arc::new(Session::new(req.sender())));
Metadata {
@ -253,26 +251,13 @@ mod tests {
let extractor = RpcExtractor;
// when
let meta1 = extractor.read_metadata(None, None, None);
let meta2 = extractor.read_metadata(None, Some("http://parity.io".to_owned()), None);
let meta3 = extractor.read_metadata(None, Some("http://parity.io".to_owned()), Some("ignored".into()));
let meta1 = extractor.read_metadata(None, None);
let meta2 = extractor.read_metadata(None, Some("http://parity.io".to_owned()));
let meta3 = extractor.read_metadata(None, Some("http://parity.io".to_owned()));
// then
assert_eq!(meta1.origin, Origin::Rpc("unknown".into()));
assert_eq!(meta2.origin, Origin::Rpc("http://parity.io".into()));
assert_eq!(meta3.origin, Origin::Rpc("http://parity.io".into()));
}
#[test]
fn should_dapps_origin() {
// given
let extractor = RpcExtractor;
let dapp = "https://wallet.ethereum.org".to_owned();
// when
let meta = extractor.read_metadata(Some("null".into()), None, Some(dapp.clone()));
// then
assert_eq!(meta.origin, Origin::Dapps(dapp.into()));
assert_eq!(meta1.origin, Origin::Rpc("unknown origin / unknown agent".into()));
assert_eq!(meta2.origin, Origin::Rpc("unknown origin / http://parity.io".into()));
assert_eq!(meta3.origin, Origin::Rpc("unknown origin / http://parity.io".into()));
}
}

View File

@ -19,6 +19,7 @@
use std::fmt;
use ethcore::account_provider::{SignError as AccountError};
use ethcore::client::BlockId;
use ethcore::error::{Error as EthcoreError, ErrorKind, CallError};
use jsonrpc_core::{futures, Error, ErrorCode, Value};
use rlp::DecoderError;
@ -100,6 +101,14 @@ pub fn request_rejected_limit() -> Error {
}
}
pub fn request_rejected_param_limit(limit: u64, items_desc: &str) -> Error {
Error {
code: ErrorCode::ServerError(codes::REQUEST_REJECTED_LIMIT),
message: format!("Requested data size exceeds limit of {} {}.", limit, items_desc),
data: None,
}
}
pub fn account<T: fmt::Debug>(error: &str, details: T) -> Error {
Error {
code: ErrorCode::ServerError(codes::ACCOUNT_ERROR),
@ -422,6 +431,19 @@ pub fn filter_not_found() -> Error {
}
}
pub fn filter_block_not_found(id: BlockId) -> Error {
Error {
code: ErrorCode::ServerError(codes::UNSUPPORTED_REQUEST), // Specified in EIP-234.
message: "One of the blocks specified in filter (fromBlock, toBlock or blockHash) cannot be found".into(),
data: Some(Value::String(match id {
BlockId::Hash(hash) => format!("0x{:x}", hash),
BlockId::Number(number) => format!("0x{:x}", number),
BlockId::Earliest => "earliest".to_string(),
BlockId::Latest => "latest".to_string(),
})),
}
}
// on-demand sender cancelled.
pub fn on_demand_cancel(_cancel: futures::sync::oneshot::Canceled) -> Error {
internal("on-demand sender cancelled", "")

View File

@ -16,18 +16,14 @@
use transaction::{Transaction, SignedTransaction, Action};
use ethereum_types::U256;
use jsonrpc_core::Error;
use v1::helpers::CallRequest;
pub fn sign_call(request: CallRequest, gas_cap: bool) -> Result<SignedTransaction, Error> {
let max_gas = 50_000_000.into();
pub fn sign_call(request: CallRequest) -> Result<SignedTransaction, Error> {
let max_gas = U256::from(50_000_000);
let gas = match request.gas {
Some(gas) if gas_cap && gas > max_gas => {
warn!("Gas limit capped to {} (from {})", max_gas, gas);
max_gas
}
Some(gas) => gas,
None if gas_cap => max_gas,
None => max_gas * 10,
};
let from = request.from.unwrap_or(0.into());

View File

@ -16,6 +16,7 @@
//! Helpers for fetching blockchain data either from the light client or the network.
use std::cmp;
use std::sync::Arc;
use ethcore::basic_account::BasicAccount;
@ -31,7 +32,7 @@ use jsonrpc_macros::Trailing;
use light::cache::Cache;
use light::client::LightChainClient;
use light::cht;
use light::{cht, MAX_HEADERS_PER_REQUEST};
use light::on_demand::{
request, OnDemand, HeaderRef, Request as OnDemandRequest,
Response as OnDemandResponse, ExecutionResult,
@ -42,12 +43,13 @@ use sync::LightSync;
use ethereum_types::{U256, Address};
use hash::H256;
use parking_lot::Mutex;
use plain_hasher::H256FastMap;
use transaction::{Action, Transaction as EthTransaction, SignedTransaction, LocalizedTransaction};
use v1::helpers::{CallRequest as CallRequestHelper, errors, dispatch};
use v1::types::{BlockNumber, CallRequest, Log, Transaction};
const NO_INVALID_BACK_REFS: &'static str = "Fails only on invalid back-references; back-references here known to be valid; qed";
const NO_INVALID_BACK_REFS: &str = "Fails only on invalid back-references; back-references here known to be valid; qed";
/// Helper for fetching blockchain data either from the light client or the network
/// as necessary.
@ -207,7 +209,7 @@ impl LightFetch {
}
};
let from = req.from.unwrap_or(Address::zero());
let from = req.from.unwrap_or_else(|| Address::zero());
let nonce_fut = match req.nonce {
Some(nonce) => Either::A(future::ok(Some(nonce))),
None => Either::B(self.account(from, id).map(|acc| acc.map(|a| a.nonce))),
@ -232,29 +234,16 @@ impl LightFetch {
// fetch missing transaction fields from the network.
Box::new(nonce_fut.join(gas_price_fut).and_then(move |(nonce, gas_price)| {
let action = req.to.map_or(Action::Create, Action::Call);
let value = req.value.unwrap_or_else(U256::zero);
let data = req.data.unwrap_or_default();
future::done(match (nonce, req.gas) {
(Some(n), Some(gas)) => Ok((true, EthTransaction {
nonce: n,
action: action,
gas: gas,
gas_price: gas_price,
value: value,
data: data,
})),
(Some(n), None) => Ok((false, EthTransaction {
nonce: n,
action: action,
gas: START_GAS.into(),
gas_price: gas_price,
value: value,
data: data,
})),
(None, _) => Err(errors::unknown_block()),
})
future::done(
Ok((req.gas.is_some(), EthTransaction {
nonce: nonce.unwrap_or_default(),
action: req.to.map_or(Action::Create, Action::Call),
gas: req.gas.unwrap_or_else(|| START_GAS.into()),
gas_price,
value: req.value.unwrap_or_else(U256::zero),
data: req.data.unwrap_or_default(),
}))
)
}).join(header_fut).and_then(move |((gas_known, tx), hdr)| {
// then request proved execution.
// TODO: get last-hashes from network.
@ -312,55 +301,67 @@ impl LightFetch {
use std::collections::BTreeMap;
use jsonrpc_core::futures::stream::{self, Stream};
// early exit for "to" block before "from" block.
let best_number = self.client.chain_info().best_block_number;
let block_number = |id| match id {
BlockId::Earliest => Some(0),
BlockId::Latest => Some(best_number),
BlockId::Hash(h) => self.client.block_header(BlockId::Hash(h)).map(|hdr| hdr.number()),
BlockId::Number(x) => Some(x),
};
const MAX_BLOCK_RANGE: u64 = 1000;
match (block_number(filter.to_block), block_number(filter.from_block)) {
(Some(to), Some(from)) if to < from => return Either::A(future::ok(Vec::new())),
(Some(_), Some(_)) => {},
_ => return Either::A(future::err(errors::unknown_block())),
}
let fetcher = self.clone();
self.headers_range_by_block_id(filter.from_block, filter.to_block, MAX_BLOCK_RANGE)
.and_then(move |mut headers| {
if headers.is_empty() {
return Either::A(future::ok(Vec::new()));
}
let maybe_future = self.sync.with_context(move |ctx| {
// find all headers which match the filter, and fetch the receipts for each one.
// match them with their numbers for easy sorting later.
let bit_combos = filter.bloom_possibilities();
let receipts_futures: Vec<_> = self.client.ancestry_iter(filter.to_block)
.take_while(|ref hdr| BlockId::Number(hdr.number()) != filter.from_block)
.take_while(|ref hdr| BlockId::Hash(hdr.hash()) != filter.from_block)
.filter(|ref hdr| {
let hdr_bloom = hdr.log_bloom();
bit_combos.iter().find(|&bloom| hdr_bloom & *bloom == *bloom).is_some()
})
.map(|hdr| (hdr.number(), request::BlockReceipts(hdr.into())))
.map(|(num, req)| self.on_demand.request(ctx, req).expect(NO_INVALID_BACK_REFS).map(move |x| (num, x)))
.collect();
let on_demand = &fetcher.on_demand;
// as the receipts come in, find logs within them which match the filter.
// insert them into a BTreeMap to maintain order by number and block index.
stream::futures_unordered(receipts_futures)
.fold(BTreeMap::new(), move |mut matches, (num, receipts)| {
for (block_index, log) in receipts.into_iter().flat_map(|r| r.logs).enumerate() {
if filter.matches(&log) {
matches.insert((num, block_index), log.into());
}
}
future::ok(matches)
}) // and then collect them into a vector.
.map(|matches| matches.into_iter().map(|(_, v)| v).collect())
.map_err(errors::on_demand_cancel)
});
let maybe_future = fetcher.sync.with_context(move |ctx| {
// find all headers which match the filter, and fetch the receipts for each one.
// match them with their numbers for easy sorting later.
let bit_combos = filter.bloom_possibilities();
let receipts_futures: Vec<_> = headers.drain(..)
.filter(|ref hdr| {
let hdr_bloom = hdr.log_bloom();
bit_combos.iter().any(|bloom| hdr_bloom.contains_bloom(bloom))
})
.map(|hdr| (hdr.number(), hdr.hash(), request::BlockReceipts(hdr.into())))
.map(|(num, hash, req)| on_demand.request(ctx, req).expect(NO_INVALID_BACK_REFS).map(move |x| (num, hash, x)))
.collect();
match maybe_future {
Some(fut) => Either::B(Either::A(fut)),
None => Either::B(Either::B(future::err(errors::network_disabled()))),
}
// as the receipts come in, find logs within them which match the filter.
// insert them into a BTreeMap to maintain order by number and block index.
stream::futures_unordered(receipts_futures)
.fold(BTreeMap::new(), move |mut matches, (num, hash, receipts)| {
let mut block_index = 0;
for (transaction_index, receipt) in receipts.into_iter().enumerate() {
for (transaction_log_index, log) in receipt.logs.into_iter().enumerate() {
if filter.matches(&log) {
matches.insert((num, block_index), Log {
address: log.address.into(),
topics: log.topics.into_iter().map(Into::into).collect(),
data: log.data.into(),
block_hash: Some(hash.into()),
block_number: Some(num.into()),
// No way to easily retrieve transaction hash, so let's just skip it.
transaction_hash: None,
transaction_index: Some(transaction_index.into()),
log_index: Some(block_index.into()),
transaction_log_index: Some(transaction_log_index.into()),
log_type: "mined".into(),
removed: false,
});
}
block_index += 1;
}
}
future::ok(matches)
}) // and then collect them into a vector.
.map(|matches| matches.into_iter().map(|(_, v)| v).collect())
.map_err(errors::on_demand_cancel)
});
match maybe_future {
Some(fut) => Either::B(Either::A(fut)),
None => Either::B(Either::B(future::err(errors::network_disabled()))),
}
})
}
// Get a transaction by hash. also returns the index in the block.
@ -438,6 +439,150 @@ impl LightFetch {
None => Box::new(future::err(errors::network_disabled())) as Box<Future<Item = _, Error = _> + Send>
}
}
fn headers_range_by_block_id(
&self,
from_block: BlockId,
to_block: BlockId,
max: u64
) -> impl Future<Item = Vec<encoded::Header>, Error = Error> {
let fetch_hashes = [from_block, to_block].iter()
.filter_map(|block_id| match block_id {
BlockId::Hash(hash) => Some(hash.clone()),
_ => None,
})
.collect::<Vec<_>>();
let best_number = self.client.chain_info().best_block_number;
let fetcher = self.clone();
self.headers_by_hash(&fetch_hashes[..]).and_then(move |mut header_map| {
let (from_block_num, to_block_num) = {
let block_number = |id| match id {
&BlockId::Earliest => 0,
&BlockId::Latest => best_number,
&BlockId::Hash(ref h) =>
header_map.get(h).map(|hdr| hdr.number())
.expect("from_block and to_block headers are fetched by hash; this closure is only called on from_block and to_block; qed"),
&BlockId::Number(x) => x,
};
(block_number(&from_block), block_number(&to_block))
};
if to_block_num < from_block_num {
// early exit for "to" block before "from" block.
return Either::A(future::err(errors::filter_block_not_found(to_block)));
} else if to_block_num - from_block_num >= max {
return Either::A(future::err(errors::request_rejected_param_limit(max, "blocks")));
}
let to_header_hint = match to_block {
BlockId::Hash(ref h) => header_map.remove(h),
_ => None,
};
let headers_fut = fetcher.headers_range(from_block_num, to_block_num, to_header_hint);
Either::B(headers_fut.map(move |headers| {
// Validate from_block if it's a hash
let last_hash = headers.last().map(|hdr| hdr.hash());
match (last_hash, from_block) {
(Some(h1), BlockId::Hash(h2)) if h1 != h2 => Vec::new(),
_ => headers,
}
}))
})
}
fn headers_by_hash(&self, hashes: &[H256]) -> impl Future<Item = H256FastMap<encoded::Header>, Error = Error> {
let mut refs = H256FastMap::with_capacity_and_hasher(hashes.len(), Default::default());
let mut reqs = Vec::with_capacity(hashes.len());
for hash in hashes {
refs.entry(*hash).or_insert_with(|| {
self.make_header_requests(BlockId::Hash(*hash), &mut reqs)
.expect("make_header_requests never fails for BlockId::Hash; qed")
});
}
self.send_requests(reqs, move |res| {
let headers = refs.drain()
.map(|(hash, header_ref)| {
let hdr = extract_header(&res, header_ref)
.expect("these responses correspond to requests that header_ref belongs to; \
qed");
(hash, hdr)
})
.collect();
headers
})
}
fn headers_range(
&self,
from_number: u64,
to_number: u64,
to_header_hint: Option<encoded::Header>
) -> impl Future<Item = Vec<encoded::Header>, Error = Error> {
let range_length = (to_number - from_number + 1) as usize;
let mut headers: Vec<encoded::Header> = Vec::with_capacity(range_length);
let iter_start = match to_header_hint {
Some(hdr) => {
let block_id = BlockId::Hash(hdr.parent_hash());
headers.push(hdr);
block_id
}
None => BlockId::Number(to_number),
};
headers.extend(self.client.ancestry_iter(iter_start)
.take_while(|hdr| hdr.number() >= from_number));
let fetcher = self.clone();
future::loop_fn(headers, move |mut headers| {
let remaining = range_length - headers.len();
if remaining == 0 {
return Either::A(future::ok(future::Loop::Break(headers)));
}
let mut reqs: Vec<request::Request> = Vec::with_capacity(2);
let start_hash = if let Some(hdr) = headers.last() {
hdr.parent_hash().into()
} else {
let cht_root = cht::block_to_cht_number(to_number)
.and_then(|cht_num| fetcher.client.cht_root(cht_num as usize));
let cht_root = match cht_root {
Some(cht_root) => cht_root,
None => return Either::A(future::err(errors::unknown_block())),
};
let header_proof = request::HeaderProof::new(to_number, cht_root)
.expect("HeaderProof::new is Some(_) if cht::block_to_cht_number() is Some(_); \
this would return above if block_to_cht_number returned None; qed");
let idx = reqs.len();
let hash_ref = Field::back_ref(idx, 0);
reqs.push(header_proof.into());
hash_ref
};
let max = cmp::min(remaining as u64, MAX_HEADERS_PER_REQUEST);
reqs.push(request::HeaderWithAncestors {
block_hash: start_hash,
ancestor_count: max - 1,
}.into());
Either::B(fetcher.send_requests(reqs, |mut res| {
match res.last_mut() {
Some(&mut OnDemandResponse::HeaderWithAncestors(ref mut res_headers)) =>
headers.extend(res_headers.drain(..)),
_ => panic!("reqs has at least one entry; each request maps to a response; qed"),
};
future::Loop::Continue(headers)
}))
})
}
}
#[derive(Clone)]

View File

@ -17,9 +17,8 @@
use std::collections::BTreeMap;
use ethereum_types::{U256, Address};
use parking_lot::{Mutex, RwLock};
use ethcore::account_provider::DappId;
use v1::helpers::{ConfirmationRequest, ConfirmationPayload, oneshot, errors};
use v1::types::{ConfirmationResponse, H160 as RpcH160, Origin, DappId as RpcDappId};
use v1::types::{ConfirmationResponse, H160 as RpcH160, Origin};
use jsonrpc_core::Error;
@ -30,14 +29,6 @@ pub type ConfirmationResult = Result<ConfirmationResponse, Error>;
pub enum DefaultAccount {
/// Default account is known
Provided(Address),
/// Should use default account for dapp
ForDapp(DappId),
}
impl From<RpcDappId> for DefaultAccount {
fn from(dapp_id: RpcDappId) -> Self {
DefaultAccount::ForDapp(dapp_id.into())
}
}
impl From<RpcH160> for DefaultAccount {

View File

@ -21,13 +21,12 @@ use std::time::{Instant, Duration, SystemTime, UNIX_EPOCH};
use std::sync::Arc;
use rlp::{self, Rlp};
use ethereum_types::{U256, H64, H160, H256, Address};
use ethereum_types::{U256, H64, H256, Address};
use parking_lot::Mutex;
use ethash::SeedHashCompute;
use ethcore::account_provider::{AccountProvider, DappId};
use ethash::{self, SeedHashCompute};
use ethcore::account_provider::AccountProvider;
use ethcore::client::{BlockChainClient, BlockId, TransactionId, UncleId, StateOrBlock, StateClient, StateInfo, Call, EngineInfo};
use ethcore::ethereum::Ethash;
use ethcore::filter::Filter as EthcoreFilter;
use ethcore::header::{BlockNumber as EthBlockNumber};
use ethcore::log_entry::LogEntry;
@ -400,13 +399,6 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> EthClient<C, SN, S
Ok(Some(block))
}
fn dapp_accounts(&self, dapp: DappId) -> Result<Vec<H160>> {
self.accounts
.note_dapp_used(dapp.clone())
.and_then(|_| self.accounts.dapp_addresses(dapp))
.map_err(|e| errors::account("Could not fetch accounts.", e))
}
fn get_state(&self, number: BlockNumber) -> StateOrBlock {
match number {
BlockNumber::Num(num) => BlockId::Number(num).into(),
@ -509,12 +501,10 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
}
}
fn author(&self, meta: Metadata) -> Result<RpcH160> {
let dapp = meta.dapp_id();
fn author(&self) -> Result<RpcH160> {
let mut miner = self.miner.authoring_params().author;
if miner == 0.into() {
miner = self.dapp_accounts(dapp.into())?.get(0).cloned().unwrap_or_default();
miner = self.accounts.accounts().ok().and_then(|a| a.get(0).cloned()).unwrap_or_default();
}
Ok(RpcH160::from(miner))
@ -532,10 +522,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner, self.options.gas_price_percentile)))
}
fn accounts(&self, meta: Metadata) -> Result<Vec<RpcH160>> {
let dapp = meta.dapp_id();
let accounts = self.dapp_accounts(dapp.into())?;
fn accounts(&self) -> Result<Vec<RpcH160>> {
let accounts = self.accounts.accounts()
.map_err(|e| errors::account("Could not fetch accounts.", e))?;
Ok(accounts.into_iter().map(Into::into).collect())
}
@ -744,9 +733,11 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
// check if we're still syncing and return empty strings in that case
{
//TODO: check if initial sync is complete here
//let sync = self.sync;
if /*sync.status().state != SyncState::Idle ||*/ self.client.queue_info().total_queue_size() > MAX_QUEUE_SIZE_TO_MINE_ON {
let sync_status = self.sync.status();
let queue_info = self.client.queue_info();
let total_queue_size = queue_info.total_queue_size();
if is_major_importing(Some(sync_status.state), queue_info) || total_queue_size > MAX_QUEUE_SIZE_TO_MINE_ON {
trace!(target: "miner", "Syncing. Cannot give any work.");
return Err(errors::no_work());
}
@ -769,7 +760,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
})?;
let (pow_hash, number, timestamp, difficulty) = work;
let target = Ethash::difficulty_to_boundary(&difficulty);
let target = ethash::difficulty_to_boundary(&difficulty);
let seed_hash = self.seed_compute.lock().hash_block_number(number);
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap_or_default().as_secs();
@ -836,9 +827,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
self.send_raw_transaction(raw)
}
fn call(&self, meta: Self::Metadata, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
fn call(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
let request = CallRequest::into(request);
let signed = try_bf!(fake_sign::sign_call(request, meta.is_dapp()));
let signed = try_bf!(fake_sign::sign_call(request));
let num = num.unwrap_or_default();
@ -876,9 +867,9 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
))
}
fn estimate_gas(&self, meta: Self::Metadata, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
fn estimate_gas(&self, request: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
let request = CallRequest::into(request);
let signed = try_bf!(fake_sign::sign_call(request, meta.is_dapp()));
let signed = try_bf!(fake_sign::sign_call(request));
let num = num.unwrap_or_default();
let (state, header) = if num == BlockNumber::Pending {

View File

@ -29,7 +29,7 @@ use light::client::LightChainClient;
use light::{cht, TransactionQueue};
use light::on_demand::{request, OnDemand};
use ethcore::account_provider::{AccountProvider, DappId};
use ethcore::account_provider::AccountProvider;
use ethcore::encoded;
use ethcore::filter::Filter as EthcoreFilter;
use ethcore::ids::BlockId;
@ -252,7 +252,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
}
}
fn author(&self, _meta: Self::Metadata) -> Result<RpcH160> {
fn author(&self) -> Result<RpcH160> {
Ok(Default::default())
}
@ -271,12 +271,8 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
.unwrap_or_else(Default::default))
}
fn accounts(&self, meta: Metadata) -> Result<Vec<RpcH160>> {
let dapp: DappId = meta.dapp_id().into();
self.accounts
.note_dapp_used(dapp.clone())
.and_then(|_| self.accounts.dapp_addresses(dapp))
fn accounts(&self) -> Result<Vec<RpcH160>> {
self.accounts.accounts()
.map_err(|e| errors::account("Could not fetch accounts.", e))
.map(|accs| accs.into_iter().map(Into::<RpcH160>::into).collect())
}
@ -398,7 +394,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
self.send_raw_transaction(raw)
}
fn call(&self, _meta: Self::Metadata, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
fn call(&self, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<Bytes> {
Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
match res {
Ok(exec) => Ok(exec.output.into()),
@ -407,7 +403,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
}))
}
fn estimate_gas(&self, _meta: Self::Metadata, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
fn estimate_gas(&self, req: CallRequest, num: Trailing<BlockNumber>) -> BoxFuture<RpcU256> {
// TODO: binary chop for more accurate estimates.
Box::new(self.fetcher().proved_execution(req, num).and_then(|res| {
match res {

View File

@ -43,7 +43,7 @@ use v1::types::{
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, DappId, ChainStatus,
OperationsInfo, ChainStatus,
AccountInfo, HwAccountInfo, Header, RichHeader,
};
use Host;
@ -101,13 +101,10 @@ impl ParityClient {
impl Parity for ParityClient {
type Metadata = Metadata;
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>> {
let dapp = dapp.unwrap_or_default();
fn accounts_info(&self) -> Result<BTreeMap<H160, AccountInfo>> {
let store = &self.accounts;
let dapp_accounts = store
.note_dapp_used(dapp.clone().into())
.and_then(|_| store.dapp_addresses(dapp.into()))
.accounts()
.map_err(|e| errors::account("Could not fetch accounts.", e))?
.into_iter().collect::<HashSet<_>>();
@ -138,10 +135,9 @@ impl Parity for ParityClient {
Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?)
}
fn default_account(&self, meta: Self::Metadata) -> Result<H160> {
let dapp_id = meta.dapp_id();
fn default_account(&self) -> Result<H160> {
Ok(self.accounts
.dapp_addresses(dapp_id.into())
.accounts()
.ok()
.and_then(|accounts| accounts.get(0).cloned())
.map(|acc| acc.into())
@ -425,7 +421,7 @@ impl Parity for ParityClient {
ipfs::cid(content)
}
fn call(&self, _meta: Self::Metadata, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
fn call(&self, _requests: Vec<CallRequest>, _block: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
Err(errors::light_unimplemented(None))
}
}

View File

@ -46,11 +46,11 @@ impl Traces for TracesClient {
Err(errors::light_unimplemented(None))
}
fn call(&self, _meta: Self::Metadata, _request: CallRequest, _flags: TraceOptions, _block: Trailing<BlockNumber>) -> Result<TraceResults> {
fn call(&self, _request: CallRequest, _flags: TraceOptions, _block: Trailing<BlockNumber>) -> Result<TraceResults> {
Err(errors::light_unimplemented(None))
}
fn call_many(&self, _meta: Self::Metadata, _request: Vec<(CallRequest, TraceOptions)>, _block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
fn call_many(&self, _request: Vec<(CallRequest, TraceOptions)>, _block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
Err(errors::light_unimplemented(None))
}

View File

@ -44,7 +44,7 @@ use v1::types::{
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, DappId, ChainStatus,
OperationsInfo, ChainStatus,
AccountInfo, HwAccountInfo, RichHeader,
block_number_to_id
};
@ -106,12 +106,8 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
{
type Metadata = Metadata;
fn accounts_info(&self, dapp: Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>> {
let dapp = dapp.unwrap_or_default();
let dapp_accounts = self.accounts
.note_dapp_used(dapp.clone().into())
.and_then(|_| self.accounts.dapp_addresses(dapp.into()))
fn accounts_info(&self) -> Result<BTreeMap<H160, AccountInfo>> {
let dapp_accounts = self.accounts.accounts()
.map_err(|e| errors::account("Could not fetch accounts.", e))?
.into_iter().collect::<HashSet<_>>();
@ -140,11 +136,8 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
self.accounts.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))
}
fn default_account(&self, meta: Self::Metadata) -> Result<H160> {
let dapp_id = meta.dapp_id();
Ok(self.accounts
.dapp_default_address(dapp_id.into())
fn default_account(&self) -> Result<H160> {
Ok(self.accounts.default_account()
.map(Into::into)
.ok()
.unwrap_or_default())
@ -427,11 +420,11 @@ impl<C, M, U, S> Parity for ParityClient<C, M, U> where
ipfs::cid(content)
}
fn call(&self, meta: Self::Metadata, requests: Vec<CallRequest>, num: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
fn call(&self, requests: Vec<CallRequest>, num: Trailing<BlockNumber>) -> Result<Vec<Bytes>> {
let requests = requests
.into_iter()
.map(|request| Ok((
fake_sign::sign_call(request.into(), meta.is_dapp())?,
fake_sign::sign_call(request.into())?,
Default::default()
)))
.collect::<Result<Vec<_>>>()?;

View File

@ -25,7 +25,7 @@ use ethcore::account_provider::AccountProvider;
use jsonrpc_core::Result;
use v1::helpers::errors;
use v1::traits::ParityAccounts;
use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, DappId, Derive, DeriveHierarchical, DeriveHash, ExtAccountInfo};
use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, Derive, DeriveHierarchical, DeriveHash, ExtAccountInfo};
use ethkey::Password;
/// Account management (personal) rpc implementation.
@ -143,61 +143,6 @@ impl ParityAccounts for ParityAccountsClient {
Ok(true)
}
fn set_dapp_addresses(&self, dapp: DappId, addresses: Option<Vec<RpcH160>>) -> Result<bool> {
self.accounts.set_dapp_addresses(dapp.into(), addresses.map(into_vec))
.map_err(|e| errors::account("Couldn't set dapp addresses.", e))
.map(|_| true)
}
fn dapp_addresses(&self, dapp: DappId) -> Result<Vec<RpcH160>> {
self.accounts.dapp_addresses(dapp.into())
.map_err(|e| errors::account("Couldn't get dapp addresses.", e))
.map(into_vec)
}
fn set_dapp_default_address(&self, dapp: DappId, address: RpcH160) -> Result<bool> {
self.accounts.set_dapp_default_address(dapp.into(), address.into())
.map_err(|e| errors::account("Couldn't set dapp default address.", e))
.map(|_| true)
}
fn dapp_default_address(&self, dapp: DappId) -> Result<RpcH160> {
self.accounts.dapp_default_address(dapp.into())
.map_err(|e| errors::account("Couldn't get dapp default address.", e))
.map(Into::into)
}
fn set_new_dapps_addresses(&self, addresses: Option<Vec<RpcH160>>) -> Result<bool> {
self.accounts
.set_new_dapps_addresses(addresses.map(into_vec))
.map_err(|e| errors::account("Couldn't set dapps addresses.", e))
.map(|_| true)
}
fn new_dapps_addresses(&self) -> Result<Option<Vec<RpcH160>>> {
self.accounts.new_dapps_addresses()
.map_err(|e| errors::account("Couldn't get dapps addresses.", e))
.map(|accounts| accounts.map(into_vec))
}
fn set_new_dapps_default_address(&self, address: RpcH160) -> Result<bool> {
self.accounts.set_new_dapps_default_address(address.into())
.map_err(|e| errors::account("Couldn't set new dapps default address.", e))
.map(|_| true)
}
fn new_dapps_default_address(&self) -> Result<RpcH160> {
self.accounts.new_dapps_default_address()
.map_err(|e| errors::account("Couldn't get new dapps default address.", e))
.map(Into::into)
}
fn recent_dapps(&self) -> Result<BTreeMap<DappId, u64>> {
self.accounts.recent_dapps()
.map_err(|e| errors::account("Couldn't get recent dapps.", e))
.map(|map| map.into_iter().map(|(k, v)| (k.into(), v)).collect())
}
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>> {
self.accounts
.import_geth_accounts(into_vec(addresses), false)

View File

@ -58,14 +58,14 @@ impl<D: Dispatcher> PersonalClient<D> {
}
impl<D: Dispatcher + 'static> PersonalClient<D> {
fn do_sign_transaction(&self, meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<(PendingTransaction, D)> {
fn do_sign_transaction(&self, _meta: Metadata, request: TransactionRequest, password: String) -> BoxFuture<(PendingTransaction, D)> {
let dispatcher = self.dispatcher.clone();
let accounts = self.accounts.clone();
let default = match request.from.as_ref() {
Some(account) => Ok(account.clone().into()),
None => accounts
.dapp_default_address(meta.dapp_id().into())
.default_account()
.map_err(|e| errors::account("Cannot find default account.", e)),
};

View File

@ -100,14 +100,14 @@ impl Private for PrivateClient {
})
}
fn private_call(&self, meta: Self::Metadata, block_number: BlockNumber, request: CallRequest) -> Result<Bytes, Error> {
fn private_call(&self, block_number: BlockNumber, request: CallRequest) -> Result<Bytes, Error> {
let id = match block_number {
BlockNumber::Pending => return Err(errors::private_message_block_id_not_supported()),
num => block_number_to_id(num)
};
let request = CallRequest::into(request);
let signed = fake_sign::sign_call(request, meta.is_dapp())?;
let signed = fake_sign::sign_call(request)?;
let client = self.unwrap_manager()?;
let executed_result = client.private_call(id, &signed).map_err(|e| errors::private_message(e))?;
Ok(executed_result.output.into())

View File

@ -112,7 +112,6 @@ impl<D: Dispatcher + 'static> SigningQueueClient<D> {
let accounts = self.accounts.clone();
let default_account = match default_account {
DefaultAccount::Provided(acc) => acc,
DefaultAccount::ForDapp(dapp) => accounts.dapp_default_address(dapp).ok().unwrap_or_default(),
};
let dispatcher = self.dispatcher.clone();
@ -138,8 +137,8 @@ impl<D: Dispatcher + 'static> SigningQueueClient<D> {
impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
type Metadata = Metadata;
fn compose_transaction(&self, meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
let default_account = self.accounts.dapp_default_address(meta.dapp_id().into()).ok().unwrap_or_default();
fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
let default_account = self.accounts.default_account().ok().unwrap_or_default();
Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into))
}
@ -164,7 +163,7 @@ impl<D: Dispatcher + 'static> ParitySigning for SigningQueueClient<D> {
let remote = self.remote.clone();
let confirmations = self.confirmations.clone();
Box::new(self.dispatch(RpcConfirmationPayload::SendTransaction(request), meta.dapp_id().into(), meta.origin)
Box::new(self.dispatch(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()), meta.origin)
.map(|result| match result {
DispatchResult::Value(v) => RpcEither::Or(v),
DispatchResult::Future(id, future) => {
@ -221,7 +220,7 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
let res = self.dispatch(
RpcConfirmationPayload::SendTransaction(request),
meta.dapp_id().into(),
DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()),
meta.origin,
);
@ -236,7 +235,7 @@ impl<D: Dispatcher + 'static> EthSigning for SigningQueueClient<D> {
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
let res = self.dispatch(
RpcConfirmationPayload::SignTransaction(request),
meta.dapp_id().into(),
DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()),
meta.origin,
);

View File

@ -55,7 +55,6 @@ impl<D: Dispatcher + 'static> SigningUnsafeClient<D> {
let accounts = self.accounts.clone();
let default = match account {
DefaultAccount::Provided(acc) => acc,
DefaultAccount::ForDapp(dapp) => accounts.dapp_default_address(dapp).ok().unwrap_or_default(),
};
let dis = self.dispatcher.clone();
@ -80,8 +79,8 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
}))
}
fn send_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), meta.dapp_id().into())
fn send_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcH256> {
Box::new(self.handle(RpcConfirmationPayload::SendTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()))
.then(|res| match res {
Ok(RpcConfirmationResponse::SendTransaction(hash)) => Ok(hash),
Err(e) => Err(e),
@ -89,8 +88,8 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
}))
}
fn sign_transaction(&self, meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), meta.dapp_id().into())
fn sign_transaction(&self, _meta: Metadata, request: RpcTransactionRequest) -> BoxFuture<RpcRichRawTransaction> {
Box::new(self.handle(RpcConfirmationPayload::SignTransaction(request), DefaultAccount::Provided(self.accounts.default_account().ok().unwrap_or_default()))
.then(|res| match res {
Ok(RpcConfirmationResponse::SignTransaction(tx)) => Ok(tx),
Err(e) => Err(e),
@ -102,9 +101,9 @@ impl<D: Dispatcher + 'static> EthSigning for SigningUnsafeClient<D>
impl<D: Dispatcher + 'static> ParitySigning for SigningUnsafeClient<D> {
type Metadata = Metadata;
fn compose_transaction(&self, meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
fn compose_transaction(&self, _meta: Metadata, transaction: RpcTransactionRequest) -> BoxFuture<RpcTransactionRequest> {
let accounts = self.accounts.clone();
let default_account = accounts.dapp_default_address(meta.dapp_id().into()).ok().unwrap_or_default();
let default_account = accounts.default_account().ok().unwrap_or_default();
Box::new(self.dispatcher.fill_optional_fields(transaction.into(), default_account, true).map(Into::into))
}

View File

@ -87,11 +87,11 @@ impl<C, S> Traces for TracesClient<C> where
.map(LocalizedTrace::from))
}
fn call(&self, meta: Self::Metadata, request: CallRequest, flags: TraceOptions, block: Trailing<BlockNumber>) -> Result<TraceResults> {
fn call(&self, request: CallRequest, flags: TraceOptions, block: Trailing<BlockNumber>) -> Result<TraceResults> {
let block = block.unwrap_or_default();
let request = CallRequest::into(request);
let signed = fake_sign::sign_call(request, meta.is_dapp())?;
let signed = fake_sign::sign_call(request)?;
let id = match block {
BlockNumber::Num(num) => BlockId::Number(num),
@ -109,13 +109,13 @@ impl<C, S> Traces for TracesClient<C> where
.map_err(errors::call)
}
fn call_many(&self, meta: Self::Metadata, requests: Vec<(CallRequest, TraceOptions)>, block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
fn call_many(&self, requests: Vec<(CallRequest, TraceOptions)>, block: Trailing<BlockNumber>) -> Result<Vec<TraceResults>> {
let block = block.unwrap_or_default();
let requests = requests.into_iter()
.map(|(request, flags)| {
let request = CallRequest::into(request);
let signed = fake_sign::sign_call(request, meta.is_dapp())?;
let signed = fake_sign::sign_call(request)?;
Ok((signed, to_call_analytics(flags)))
})
.collect::<Result<Vec<_>>>()?;

View File

@ -20,7 +20,7 @@ use std::sync::Arc;
use jsonrpc_core;
use jsonrpc_pubsub::{Session, PubSubMetadata};
use v1::types::{DappId, Origin};
use v1::types::Origin;
/// RPC methods metadata.
#[derive(Clone, Default, Debug)]
@ -31,28 +31,6 @@ pub struct Metadata {
pub session: Option<Arc<Session>>,
}
impl Metadata {
/// Returns dapp id if this request is coming from a Dapp or default `DappId` otherwise.
pub fn dapp_id(&self) -> DappId {
// TODO [ToDr] Extract dapp info from Ws connections.
match self.origin {
Origin::Dapps(ref dapp) => dapp.clone(),
Origin::Ws { ref dapp, .. } => dapp.clone(),
Origin::Signer { ref dapp, .. } => dapp.clone(),
_ => DappId::default(),
}
}
/// Returns true if the request originates from a Dapp.
pub fn is_dapp(&self) -> bool {
if let Origin::Dapps(_) = self.origin {
true
} else {
false
}
}
}
impl jsonrpc_core::Metadata for Metadata {}
impl PubSubMetadata for Metadata {
fn session(&self) -> Option<Arc<Session>> {

View File

@ -39,7 +39,6 @@ use v1::helpers::nonce;
use v1::helpers::dispatch::FullDispatcher;
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
use v1::metadata::Metadata;
use v1::types::Origin;
fn blockchain_client() -> Arc<TestBlockChainClient> {
let client = TestBlockChainClient::new();
@ -395,7 +394,6 @@ fn rpc_eth_gas_price() {
fn rpc_eth_accounts() {
let tester = EthTester::default();
let address = tester.accounts_provider.new_account(&"".into()).unwrap();
tester.accounts_provider.set_new_dapps_addresses(None).unwrap();
tester.accounts_provider.set_address_name(1.into(), "1".into());
tester.accounts_provider.set_address_name(10.into(), "10".into());
@ -403,20 +401,6 @@ fn rpc_eth_accounts() {
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:x}", address) + r#""],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
tester.accounts_provider.set_new_dapps_addresses(Some(vec![1.into()])).unwrap();
// even with some account it should return empty list (no dapp detected)
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x0000000000000000000000000000000000000001"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// when we add visible address it should return that.
tester.accounts_provider.set_dapp_addresses("app1".into(), Some(vec![10.into()])).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "eth_accounts", "params": [], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
let mut meta = Metadata::default();
meta.origin = Origin::Dapps("app1".into());
assert_eq!((*tester.io).handle_request_sync(request, meta), Some(response.to_owned()));
}
#[test]

View File

@ -115,13 +115,6 @@ fn rpc_parity_accounts_info() {
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"Test\"}}}},\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
// Change the whitelist
let address = Address::from(1);
deps.accounts.set_new_dapps_addresses(Some(vec![address.clone()])).unwrap();
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{:x}\":{{\"name\":\"XX\"}}}},\"id\":1}}", address);
assert_eq!(io.handle_request_sync(request), Some(response));
}
#[test]

View File

@ -121,106 +121,6 @@ fn should_be_able_to_set_meta() {
assert_eq!(res, Some(response));
}
#[test]
fn rpc_parity_set_and_get_dapps_accounts() {
// given
let tester = setup();
tester.accounts.set_address_name(10.into(), "10".into());
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![]);
// when
let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappAddresses","params":["app1",["0x000000000000000000000000000000000000000a","0x0000000000000000000000000000000000000001"]], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![10.into()]);
let request = r#"{"jsonrpc": "2.0", "method": "parity_getDappAddresses","params":["app1"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_set_and_get_dapp_default_address() {
// given
let tester = setup();
tester.accounts.set_address_name(10.into(), "10".into());
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![]);
// when
let request = r#"{"jsonrpc": "2.0", "method": "parity_setDappDefaultAddress","params":["app1", "0x000000000000000000000000000000000000000a"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.dapp_addresses("app1".into()).unwrap(), vec![10.into()]);
let request = r#"{"jsonrpc": "2.0", "method": "parity_getDappDefaultAddress","params":["app1"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000a","id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_set_and_get_new_dapps_whitelist() {
// given
let tester = setup();
// when set to whitelist
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsAddresses","params":[["0x000000000000000000000000000000000000000a"]], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.new_dapps_addresses().unwrap(), Some(vec![10.into()]));
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsAddresses","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":["0x000000000000000000000000000000000000000a"],"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// when set to empty
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsAddresses","params":[null], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.new_dapps_addresses().unwrap(), None);
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsAddresses","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_set_and_get_new_dapps_default_address() {
// given
let tester = setup();
tester.accounts.set_address_name(10.into(), "10".into());
assert_eq!(tester.accounts.new_dapps_default_address().unwrap(), 0.into());
// when
let request = r#"{"jsonrpc": "2.0", "method": "parity_setNewDappsDefaultAddress","params":["0x000000000000000000000000000000000000000a"], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
// then
assert_eq!(tester.accounts.new_dapps_default_address().unwrap(), 10.into());
let request = r#"{"jsonrpc": "2.0", "method": "parity_getNewDappsDefaultAddress","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":"0x000000000000000000000000000000000000000a","id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn rpc_parity_recent_dapps() {
// given
let tester = setup();
// when
// trigger dapp usage
tester.accounts.note_dapp_used("dapp1".into()).unwrap();
// then
let request = r#"{"jsonrpc": "2.0", "method": "parity_listRecentDapps","params":[], "id": 1}"#;
let response = r#"{"jsonrpc":"2.0","result":{"dapp1":1},"id":1}"#;
assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned()));
}
#[test]
fn should_be_able_to_kill_account() {
let tester = setup();

View File

@ -89,14 +89,14 @@ fn should_return_list_of_items_to_confirm() {
data: vec![],
nonce: None,
condition: None,
}), Origin::Dapps("http://parity.io".into())).unwrap();
}), Origin::Unknown).unwrap();
let _sign_future = tester.signer.add_request(ConfirmationPayload::EthSignMessage(1.into(), vec![5].into()), Origin::Unknown).unwrap();
// when
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
let response = concat!(
r#"{"jsonrpc":"2.0","result":["#,
r#"{"id":"0x1","origin":{"dapp":"http://parity.io"},"payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
r#"{"id":"0x1","origin":"unknown","payload":{"sendTransaction":{"condition":null,"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
r#"{"id":"0x2","origin":"unknown","payload":{"sign":{"address":"0x0000000000000000000000000000000000000001","data":"0x05"}}}"#,
r#"],"id":1}"#
);

View File

@ -40,8 +40,8 @@ build_rpc_trait! {
fn hashrate(&self) -> Result<U256>;
/// Returns block author.
#[rpc(meta, name = "eth_coinbase")]
fn author(&self, Self::Metadata) -> Result<H160>;
#[rpc(name = "eth_coinbase")]
fn author(&self) -> Result<H160>;
/// Returns true if client is actively mining new blocks.
#[rpc(name = "eth_mining")]
@ -52,8 +52,8 @@ build_rpc_trait! {
fn gas_price(&self) -> Result<U256>;
/// Returns accounts list.
#[rpc(meta, name = "eth_accounts")]
fn accounts(&self, Self::Metadata) -> Result<Vec<H160>>;
#[rpc(name = "eth_accounts")]
fn accounts(&self) -> Result<Vec<H160>>;
/// Returns highest block number.
#[rpc(name = "eth_blockNumber")]
@ -108,12 +108,12 @@ build_rpc_trait! {
fn submit_transaction(&self, Bytes) -> Result<H256>;
/// Call contract, returning the output data.
#[rpc(meta, name = "eth_call")]
fn call(&self, Self::Metadata, CallRequest, Trailing<BlockNumber>) -> BoxFuture<Bytes>;
#[rpc(name = "eth_call")]
fn call(&self, CallRequest, Trailing<BlockNumber>) -> BoxFuture<Bytes>;
/// Estimate gas needed for execution of given contract.
#[rpc(meta, name = "eth_estimateGas")]
fn estimate_gas(&self, Self::Metadata, CallRequest, Trailing<BlockNumber>) -> BoxFuture<U256>;
#[rpc(name = "eth_estimateGas")]
fn estimate_gas(&self, CallRequest, Trailing<BlockNumber>) -> BoxFuture<U256>;
/// Get transaction by its hash.
#[rpc(name = "eth_getTransactionByHash")]

View File

@ -26,7 +26,7 @@ use v1::types::{
Peers, Transaction, RpcSettings, Histogram,
TransactionStats, LocalTransactionStatus,
BlockNumber, ConsensusCapability, VersionInfo,
OperationsInfo, DappId, ChainStatus,
OperationsInfo, ChainStatus,
AccountInfo, HwAccountInfo, RichHeader,
};
@ -37,7 +37,7 @@ build_rpc_trait! {
/// Returns accounts information.
#[rpc(name = "parity_accountsInfo")]
fn accounts_info(&self, Trailing<DappId>) -> Result<BTreeMap<H160, AccountInfo>>;
fn accounts_info(&self) -> Result<BTreeMap<H160, AccountInfo>>;
/// Returns hardware accounts information.
#[rpc(name = "parity_hardwareAccountsInfo")]
@ -48,8 +48,8 @@ build_rpc_trait! {
fn locked_hardware_accounts_info(&self) -> Result<Vec<String>>;
/// Returns default account for dapp.
#[rpc(meta, name = "parity_defaultAccount")]
fn default_account(&self, Self::Metadata) -> Result<H160>;
#[rpc(name = "parity_defaultAccount")]
fn default_account(&self) -> Result<H160>;
/// Returns current transactions limit.
#[rpc(name = "parity_transactionsLimit")]
@ -178,7 +178,7 @@ build_rpc_trait! {
#[rpc(name = "parity_chainId")]
fn chain_id(&self) -> Result<Option<U64>>;
/// Get the chain name. Returns one of: "foundation", "kovan", &c. of a filename.
/// Get the chain name. Returns one of the pre-configured chain names or a filename.
#[rpc(name = "parity_chain")]
fn chain(&self) -> Result<String>;
@ -216,7 +216,7 @@ build_rpc_trait! {
fn ipfs_cid(&self, Bytes) -> Result<String>;
/// Call contract, returning the output data.
#[rpc(meta, name = "parity_call")]
fn call(&self, Self::Metadata, Vec<CallRequest>, Trailing<BlockNumber>) -> Result<Vec<Bytes>>;
#[rpc(name = "parity_call")]
fn call(&self, Vec<CallRequest>, Trailing<BlockNumber>) -> Result<Vec<Bytes>>;
}
}

View File

@ -20,7 +20,7 @@ use std::collections::BTreeMap;
use jsonrpc_core::Result;
use ethkey::Password;
use ethstore::KeyFile;
use v1::types::{H160, H256, H520, DappId, DeriveHash, DeriveHierarchical, ExtAccountInfo};
use v1::types::{H160, H256, H520, DeriveHash, DeriveHierarchical, ExtAccountInfo};
build_rpc_trait! {
/// Personal Parity rpc interface.
@ -72,57 +72,6 @@ build_rpc_trait! {
#[rpc(name = "parity_setAccountMeta")]
fn set_account_meta(&self, H160, String) -> Result<bool>;
/// Sets addresses exposed for particular dapp.
/// Setting a non-empty list will also override default account.
/// Setting `None` will resets visible account to what's visible for new dapps
/// (does not affect default account though)
#[rpc(name = "parity_setDappAddresses")]
fn set_dapp_addresses(&self, DappId, Option<Vec<H160>>) -> Result<bool>;
/// Gets accounts exposed for particular dapp.
#[rpc(name = "parity_getDappAddresses")]
fn dapp_addresses(&self, DappId) -> Result<Vec<H160>>;
/// Changes dapp default address.
/// Does not affect other accounts exposed for this dapp, but
/// default account will always be retured as the first one.
#[rpc(name = "parity_setDappDefaultAddress")]
fn set_dapp_default_address(&self, DappId, H160) -> Result<bool>;
/// Returns current dapp default address.
/// If not set explicite for the dapp will return global default.
#[rpc(name = "parity_getDappDefaultAddress")]
fn dapp_default_address(&self, DappId) -> Result<H160>;
/// Sets accounts exposed for new dapps.
/// Setting a non-empty list will also override default account.
/// Setting `None` exposes all internal-managed accounts.
/// (does not affect default account though)
#[rpc(name = "parity_setNewDappsAddresses")]
fn set_new_dapps_addresses(&self, Option<Vec<H160>>) -> Result<bool>;
/// Gets accounts exposed for new dapps.
/// `None` means that all accounts are exposes.
#[rpc(name = "parity_getNewDappsAddresses")]
fn new_dapps_addresses(&self) -> Result<Option<Vec<H160>>>;
/// Changes default address for new dapps (global default address)
/// Does not affect other accounts exposed for new dapps, but
/// default account will always be retured as the first one.
#[rpc(name = "parity_setNewDappsDefaultAddress")]
fn set_new_dapps_default_address(&self, H160) -> Result<bool>;
/// Returns current default address for new dapps (global default address)
/// In case it's not set explicite will return first available account.
/// If no accounts are available will return `0x0`
#[rpc(name = "parity_getNewDappsDefaultAddress")]
fn new_dapps_default_address(&self) -> Result<H160>;
/// Returns identified dapps that recently used RPC
/// Includes last usage timestamp.
#[rpc(name = "parity_listRecentDapps")]
fn recent_dapps(&self) -> Result<BTreeMap<DappId, u64>>;
/// Imports a number of Geth accounts, with the list provided as the argument.
#[rpc(name = "parity_importGethAccounts")]
fn import_geth_accounts(&self, Vec<H160>) -> Result<Vec<H160>>;

View File

@ -87,7 +87,7 @@ build_rpc_trait! {
#[rpc(name = "parity_setMode")]
fn set_mode(&self, String) -> Result<bool>;
/// Set the network spec. Argument must be one of: "foundation", "ropsten", "morden", "kovan", "olympic", "classic", "dev", "expanse", "musicoin" or a filename.
/// Set the network spec. Argument must be one of pre-configured chains or a filename.
#[rpc(name = "parity_setChain")]
fn set_spec_name(&self, String) -> Result<bool>;

View File

@ -35,8 +35,8 @@ build_rpc_trait! {
fn compose_deployment_transaction(&self, BlockNumber, Bytes, Vec<H160>, U256) -> Result<PrivateTransactionReceiptAndTransaction, Error>;
/// Make a call to the private contract
#[rpc(meta, name = "private_call")]
fn private_call(&self, Self::Metadata, BlockNumber, CallRequest) -> Result<Bytes, Error>;
#[rpc(name = "private_call")]
fn private_call(&self, BlockNumber, CallRequest) -> Result<Bytes, Error>;
/// Retrieve the id of the key associated with the contract
#[rpc(name = "private_contractKey")]

View File

@ -42,12 +42,12 @@ build_rpc_trait! {
fn block_traces(&self, BlockNumber) -> Result<Option<Vec<LocalizedTrace>>>;
/// Executes the given call and returns a number of possible traces for it.
#[rpc(meta, name = "trace_call")]
fn call(&self, Self::Metadata, CallRequest, TraceOptions, Trailing<BlockNumber>) -> Result<TraceResults>;
#[rpc(name = "trace_call")]
fn call(&self, CallRequest, TraceOptions, Trailing<BlockNumber>) -> Result<TraceResults>;
/// Executes all given calls and returns a number of possible traces for each of it.
#[rpc(meta, name = "trace_callMany")]
fn call_many(&self, Self::Metadata, Vec<(CallRequest, TraceOptions)>, Trailing<BlockNumber>) -> Result<Vec<TraceResults>>;
#[rpc(name = "trace_callMany")]
fn call_many(&self, Vec<(CallRequest, TraceOptions)>, Trailing<BlockNumber>) -> Result<Vec<TraceResults>>;
/// Executes the given raw transaction and returns a number of possible traces for it.
#[rpc(name = "trace_rawTransaction")]

View File

@ -285,14 +285,13 @@ mod tests {
condition: None,
}),
origin: Origin::Signer {
dapp: "http://parity.io".into(),
session: 5.into(),
}
};
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"dapp":"http://parity.io","session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#;
let expected = r#"{"id":"0xf","payload":{"sendTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"signer":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());
@ -314,12 +313,12 @@ mod tests {
nonce: Some(1.into()),
condition: None,
}),
origin: Origin::Dapps("http://parity.io".into()),
origin: Origin::Unknown,
};
// when
let res = serde_json::to_string(&ConfirmationRequest::from(request));
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":{"dapp":"http://parity.io"}}"#;
let expected = r#"{"id":"0xf","payload":{"signTransaction":{"from":"0x0000000000000000000000000000000000000000","to":null,"gasPrice":"0x2710","gas":"0x3a98","value":"0x186a0","data":"0x010203","nonce":"0x1","condition":null}},"origin":"unknown"}"#;
// then
assert_eq!(res.unwrap(), expected.to_owned());

View File

@ -63,7 +63,7 @@ pub use self::histogram::Histogram;
pub use self::index::Index;
pub use self::log::Log;
pub use self::node_kind::{NodeKind, Availability, Capability};
pub use self::provenance::{Origin, DappId};
pub use self::provenance::Origin;
pub use self::receipt::Receipt;
pub use self::rpc_settings::RpcSettings;
pub use self::secretstore::EncryptedDocumentKey;

View File

@ -17,7 +17,6 @@
//! Request Provenance
use std::fmt;
use ethcore::account_provider::DappId as EthDappId;
use v1::types::H256;
/// RPC request origin
@ -27,25 +26,18 @@ pub enum Origin {
/// RPC server (includes request origin)
#[serde(rename="rpc")]
Rpc(String),
/// Dapps server (includes DappId)
#[serde(rename="dapp")]
Dapps(DappId),
/// IPC server (includes session hash)
#[serde(rename="ipc")]
Ipc(H256),
/// WS server
#[serde(rename="ws")]
Ws {
/// Dapp id
dapp: DappId,
/// Session id
session: H256,
},
/// Signer (authorized WS server)
#[serde(rename="signer")]
Signer {
/// Dapp id
dapp: DappId,
/// Session id
session: H256
},
@ -67,80 +59,35 @@ impl fmt::Display for Origin {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Origin::Rpc(ref origin) => write!(f, "{} via RPC", origin),
Origin::Dapps(ref origin) => write!(f, "Dapp {}", origin),
Origin::Ipc(ref session) => write!(f, "IPC (session: {})", session),
Origin::Ws { ref session, ref dapp } => write!(f, "{} via WebSocket (session: {})", dapp, session),
Origin::Signer { ref session, ref dapp } => write!(f, "{} via UI (session: {})", dapp, session),
Origin::Ws { ref session } => write!(f, "WebSocket (session: {})", session),
Origin::Signer { ref session } => write!(f, "Secure Session (session: {})", session),
Origin::CApi => write!(f, "C API"),
Origin::Unknown => write!(f, "unknown origin"),
}
}
}
/// Dapplication Internal Id
#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize)]
pub struct DappId(pub String);
impl fmt::Display for DappId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Into<String> for DappId {
fn into(self) -> String {
self.0
}
}
impl From<String> for DappId {
fn from(s: String) -> Self {
DappId(s)
}
}
impl<'a> From<&'a str> for DappId {
fn from(s: &'a str) -> Self {
DappId(s.to_owned())
}
}
impl From<EthDappId> for DappId {
fn from(id: EthDappId) -> Self {
DappId(id.into())
}
}
impl Into<EthDappId> for DappId {
fn into(self) -> EthDappId {
Into::<String>::into(self).into()
}
}
#[cfg(test)]
mod tests {
use serde_json;
use super::{DappId, Origin};
use super::Origin;
#[test]
fn should_serialize_origin() {
// given
let o1 = Origin::Rpc("test service".into());
let o2 = Origin::Dapps("http://parity.io".into());
let o3 = Origin::Ipc(5.into());
let o4 = Origin::Signer {
dapp: "http://parity.io".into(),
session: 10.into(),
};
let o5 = Origin::Unknown;
let o6 = Origin::Ws {
dapp: "http://parity.io".into(),
session: 5.into(),
};
// when
let res1 = serde_json::to_string(&o1).unwrap();
let res2 = serde_json::to_string(&o2).unwrap();
let res3 = serde_json::to_string(&o3).unwrap();
let res4 = serde_json::to_string(&o4).unwrap();
let res5 = serde_json::to_string(&o5).unwrap();
@ -148,34 +95,9 @@ mod tests {
// then
assert_eq!(res1, r#"{"rpc":"test service"}"#);
assert_eq!(res2, r#"{"dapp":"http://parity.io"}"#);
assert_eq!(res3, r#"{"ipc":"0x0000000000000000000000000000000000000000000000000000000000000005"}"#);
assert_eq!(res4, r#"{"signer":{"dapp":"http://parity.io","session":"0x000000000000000000000000000000000000000000000000000000000000000a"}}"#);
assert_eq!(res4, r#"{"signer":{"session":"0x000000000000000000000000000000000000000000000000000000000000000a"}}"#);
assert_eq!(res5, r#""unknown""#);
assert_eq!(res6, r#"{"ws":{"dapp":"http://parity.io","session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}"#);
}
#[test]
fn should_serialize_dapp_id() {
// given
let id = DappId("testapp".into());
// when
let res = serde_json::to_string(&id).unwrap();
// then
assert_eq!(res, r#""testapp""#);
}
#[test]
fn should_deserialize_dapp_id() {
// given
let id = r#""testapp""#;
// when
let res: DappId = serde_json::from_str(id).unwrap();
// then
assert_eq!(res, DappId("testapp".into()));
assert_eq!(res6, r#"{"ws":{"session":"0x0000000000000000000000000000000000000000000000000000000000000005"}}"#);
}
}

53
scripts/gitlab-rpc-docs.sh Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/env bash
clone_repos() {
git clone https://github.com/parity-js/jsonrpc.git jsonrpc
git clone https://github.com/paritytech/wiki.git wiki
}
build_docs() {
npm install
npm run build:markdown
}
update_wiki_docs() {
for file in $(ls jsonrpc/docs); do
module_name=${file:0:-3}
mv jsonrpc/docs/$file wiki/JSONRPC-$module_name-module.md
done
}
set_remote_wiki() {
git config remote.origin.url "https://${GITHUB_TOKEN}@github.com/paritytech/wiki.git"
}
setup_git() {
git config --global user.email "devops@parity.com"
git config --global user.name "Devops Parity"
}
commit_files() {
git checkout -b rpcdoc-update-${CI_COMMIT_REF_NAME}
git add .
git commit -m "Update docs to ${CI_COMMIT_REF_NAME}"
git tag -a "${CI_COMMIT_REF_NAME}" -m "Updated to ${CI_COMMIT_REF_NAME}"
}
upload_files() {
git push --tags
}
PROJECT_DIR=$(pwd)
setup_git
cd ..
clone_repos
cp -r $PROJECT_DIR jsonrpc/.parity
cd jsonrpc
build_docs
cd ..
update_wiki_docs
cd wiki
set_remote_wiki
commit_files
upload_files

View File

@ -33,8 +33,8 @@ parts:
# rust-channel: stable # @TODO enable after https://bugs.launchpad.net/snapcraft/+bug/1778530
rust-revision: 1.26.2 # @TODO remove after https://bugs.launchpad.net/snapcraft/+bug/1778530
build-attributes: [no-system-libraries]
build-packages: [g++, libudev-dev, libssl-dev, make, pkg-config, cmake]
stage-packages: [libc6, libssl1.0.0, libudev1, libstdc++6]
build-packages: [g++, libudev-dev, make, pkg-config, cmake]
stage-packages: [libc6, libudev1, libstdc++6]
df:
plugin: nil
stage-packages: [coreutils]

View File

@ -54,7 +54,7 @@ impl<T> UsingQueue<T> where T: Clone {
/// Return a reference to the item at the top of the queue (or `None` if the queue is empty);
/// this constitutes using the item and will remain in the queue for at least another
/// `max_size` invocations of `push()`.
/// `max_size` invocations of `set_pending() + use_last_ref()`.
pub fn use_last_ref(&mut self) -> Option<&T> {
if let Some(x) = self.pending.take() {
self.in_use.push(x);
@ -65,9 +65,9 @@ impl<T> UsingQueue<T> where T: Clone {
self.in_use.last()
}
/// Place an item on the end of the queue. The previously `push()`ed item will be removed
/// if `use_last_ref()` since it was `push()`ed.
pub fn push(&mut self, b: T) {
/// Place an item on the end of the queue. The previously pending item will be removed
/// if `use_last_ref()` since it was set.
pub fn set_pending(&mut self, b: T) {
self.pending = Some(b);
}
@ -100,17 +100,16 @@ impl<T> UsingQueue<T> where T: Clone {
}
}
/// Returns the most recently pushed block if `f` returns `true` with a reference to it as
/// Returns a clone of the pending block if `f` returns `true` with a reference to it as
/// a parameter, otherwise `None`.
/// Will not destroy a block if a reference to it has previously been returned by `use_last_ref`,
/// but rather clone it.
pub fn pop_if<P>(&mut self, predicate: P) -> Option<T> where P: Fn(&T) -> bool {
///
/// If pending block is not available will clone the first of the used blocks that match the predicate.
pub fn get_pending_if<P>(&mut self, predicate: P) -> Option<T> where P: Fn(&T) -> bool, T: Clone {
// a bit clumsy - TODO: think about a nicer way of expressing this.
if let Some(x) = self.pending.take() {
if predicate(&x) {
Some(x)
if let Some(ref x) = self.pending {
if predicate(x) {
Some(x.clone())
} else {
self.pending = Some(x);
None
}
} else {
@ -122,21 +121,21 @@ impl<T> UsingQueue<T> where T: Clone {
#[test]
fn should_not_find_when_pushed() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
assert!(q.take_used_if(|i| i == &1).is_none());
}
#[test]
fn should_not_find_when_pushed_with_clone() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
assert!(q.clone_used_if(|i| i == &1).is_none());
}
#[test]
fn should_find_when_pushed_and_used() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
q.use_last_ref();
assert!(q.take_used_if(|i| i == &1).unwrap() == 1);
}
@ -144,7 +143,7 @@ fn should_find_when_pushed_and_used() {
#[test]
fn should_have_same_semantics_for_get_take_clone() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
assert!(q.get_used_if(GetAction::Clone, |i| i == &1).is_none());
assert!(q.get_used_if(GetAction::Take, |i| i == &1).is_none());
q.use_last_ref();
@ -158,7 +157,7 @@ fn should_have_same_semantics_for_get_take_clone() {
#[test]
fn should_find_when_pushed_and_used_with_clone() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
q.use_last_ref();
assert!(q.clone_used_if(|i| i == &1).unwrap() == 1);
}
@ -166,7 +165,7 @@ fn should_find_when_pushed_and_used_with_clone() {
#[test]
fn should_not_find_again_when_pushed_and_taken() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
q.use_last_ref();
assert!(q.take_used_if(|i| i == &1).unwrap() == 1);
assert!(q.clone_used_if(|i| i == &1).is_none());
@ -175,7 +174,7 @@ fn should_not_find_again_when_pushed_and_taken() {
#[test]
fn should_find_again_when_pushed_and_cloned() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
q.use_last_ref();
assert!(q.clone_used_if(|i| i == &1).unwrap() == 1);
assert!(q.clone_used_if(|i| i == &1).unwrap() == 1);
@ -185,9 +184,9 @@ fn should_find_again_when_pushed_and_cloned() {
#[test]
fn should_find_when_others_used() {
let mut q = UsingQueue::new(2);
q.push(1);
q.set_pending(1);
q.use_last_ref();
q.push(2);
q.set_pending(2);
q.use_last_ref();
assert!(q.take_used_if(|i| i == &1).is_some());
}
@ -195,9 +194,9 @@ fn should_find_when_others_used() {
#[test]
fn should_not_find_when_too_many_used() {
let mut q = UsingQueue::new(1);
q.push(1);
q.set_pending(1);
q.use_last_ref();
q.push(2);
q.set_pending(2);
q.use_last_ref();
assert!(q.take_used_if(|i| i == &1).is_none());
}
@ -205,8 +204,8 @@ fn should_not_find_when_too_many_used() {
#[test]
fn should_not_find_when_not_used_and_then_pushed() {
let mut q = UsingQueue::new(3);
q.push(1);
q.push(2);
q.set_pending(1);
q.set_pending(2);
q.use_last_ref();
assert!(q.take_used_if(|i| i == &1).is_none());
}
@ -214,19 +213,19 @@ fn should_not_find_when_not_used_and_then_pushed() {
#[test]
fn should_peek_correctly_after_push() {
let mut q = UsingQueue::new(3);
q.push(1);
q.set_pending(1);
assert_eq!(q.peek_last_ref(), Some(&1));
q.push(2);
q.set_pending(2);
assert_eq!(q.peek_last_ref(), Some(&2));
}
#[test]
fn should_inspect_correctly() {
let mut q = UsingQueue::new(3);
q.push(1);
q.set_pending(1);
assert_eq!(q.use_last_ref(), Some(&1));
assert_eq!(q.peek_last_ref(), Some(&1));
q.push(2);
q.set_pending(2);
assert_eq!(q.use_last_ref(), Some(&2));
assert_eq!(q.peek_last_ref(), Some(&2));
}
@ -234,9 +233,9 @@ fn should_inspect_correctly() {
#[test]
fn should_not_find_when_not_used_peeked_and_then_pushed() {
let mut q = UsingQueue::new(3);
q.push(1);
q.set_pending(1);
q.peek_last_ref();
q.push(2);
q.set_pending(2);
q.use_last_ref();
assert!(q.take_used_if(|i| i == &1).is_none());
}
@ -244,34 +243,34 @@ fn should_not_find_when_not_used_peeked_and_then_pushed() {
#[test]
fn should_pop_used() {
let mut q = UsingQueue::new(3);
q.push(1);
q.set_pending(1);
q.use_last_ref();
let popped = q.pop_if(|i| i == &1);
let popped = q.get_pending_if(|i| i == &1);
assert_eq!(popped, Some(1));
}
#[test]
fn should_pop_unused() {
fn should_not_pop_last_pending() {
let mut q = UsingQueue::new(3);
q.push(1);
assert_eq!(q.pop_if(|i| i == &1), Some(1));
assert_eq!(q.pop_if(|i| i == &1), None);
q.set_pending(1);
assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
}
#[test]
fn should_not_pop_unused_before_used() {
let mut q = UsingQueue::new(3);
q.push(1);
q.push(2);
let popped = q.pop_if(|i| i == &1);
q.set_pending(1);
q.set_pending(2);
let popped = q.get_pending_if(|i| i == &1);
assert_eq!(popped, None);
}
#[test]
fn should_not_remove_used_popped() {
let mut q = UsingQueue::new(3);
q.push(1);
q.set_pending(1);
q.use_last_ref();
assert_eq!(q.pop_if(|i| i == &1), Some(1));
assert_eq!(q.pop_if(|i| i == &1), Some(1));
assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
}

View File

@ -3,7 +3,7 @@
[package]
name = "parity-version"
# NOTE: this value is used for Parity version string (via env CARGO_PKG_VERSION)
version = "2.0.1"
version = "2.0.3"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"