ci: merge master

This commit is contained in:
5chdn 2018-08-24 15:51:02 -04:00
commit 200a82608a
No known key found for this signature in database
GPG Key ID: 1A40871B597F5F80
199 changed files with 3048 additions and 2947 deletions

View File

@ -1,12 +1,16 @@
stages:
- test
- build
<<<<<<< HEAD
- package
- publish
- docs
image: parity/rust:gitlab-ci
=======
- docs
>>>>>>> master
variables:
CI_SERVER_NAME: "GitLab CI"
CARGO_HOME: "${CI_PROJECT_DIR}/cargo"
@ -284,6 +288,7 @@ publish:github:s3:
script:
- scripts/gitlab/push.sh
tags:
<<<<<<< HEAD
- shell
allow_failure: true
@ -292,6 +297,22 @@ publish:github:s3:
json:rpc:docs:
stage: docs
=======
- 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
>>>>>>> master
only:
- tags
- gitlab-next

210
Cargo.lock generated
View File

@ -357,10 +357,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "dir"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"journaldb 0.2.0",
]
@ -401,11 +402,14 @@ dependencies = [
[[package]]
name = "env_logger"
version = "0.4.3"
version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -470,8 +474,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)",
@ -528,7 +533,7 @@ dependencies = [
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0",
"memory-cache 0.1.0",
@ -577,7 +582,7 @@ version = "1.12.0"
dependencies = [
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -597,6 +602,7 @@ dependencies = [
"ethcore-network 1.12.0",
"ethcore-transaction 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fastmap 0.1.0",
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -605,20 +611,19 @@ dependencies = [
"keccak-hasher 0.1.0",
"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)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memory-cache 0.1.0",
"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)",
"patricia-trie-ethereum 0.1.0",
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
"rlp_derive 0.1.0",
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"stats 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash-ethereum 0.2.0",
@ -632,9 +637,9 @@ dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
@ -645,7 +650,7 @@ name = "ethcore-miner"
version = "1.12.0"
dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.12.0",
"ethcore-transaction 0.1.0",
@ -658,14 +663,14 @@ dependencies = [
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"price-info 1.12.0",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"trace-time 0.1.0",
"transaction-pool 1.12.1",
"transaction-pool 1.13.1",
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -702,7 +707,7 @@ dependencies = [
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -740,7 +745,7 @@ dependencies = [
"fetch 0.1.0",
"futures 0.1.21 (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)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -778,7 +783,7 @@ dependencies = [
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -808,7 +813,7 @@ dependencies = [
"ethcore-sync 1.12.0",
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 0.1.0 (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)",
"stop-guard 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"trace-time 0.1.0",
@ -818,14 +823,14 @@ dependencies = [
name = "ethcore-stratum"
version = "1.12.0"
dependencies = [
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.12 (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)",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.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)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -835,7 +840,8 @@ dependencies = [
name = "ethcore-sync"
version = "1.12.0"
dependencies = [
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0",
"ethcore-io 1.12.0",
"ethcore-light 1.12.0",
@ -845,6 +851,7 @@ dependencies = [
"ethcore-transaction 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0",
"fastmap 0.1.0",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -852,16 +859,15 @@ dependencies = [
"keccak-hasher 0.1.0",
"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)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0",
"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)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"trace-time 0.1.0",
"triehash-ethereum 0.2.0",
]
@ -923,7 +929,7 @@ dependencies = [
"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)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mem 0.1.0",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -940,7 +946,7 @@ name = "ethkey-cli"
version = "0.1.0"
dependencies = [
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0",
"panic_hook 0.1.0",
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -954,12 +960,12 @@ dependencies = [
name = "ethstore"
version = "0.2.0"
dependencies = [
"dir 0.1.1",
"dir 0.1.2",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -969,7 +975,7 @@ dependencies = [
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -979,7 +985,7 @@ dependencies = [
name = "ethstore-cli"
version = "0.1.0"
dependencies = [
"dir 0.1.1",
"dir 0.1.2",
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethstore 0.2.0",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1000,8 +1006,9 @@ dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memory-cache 0.1.0",
"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)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
@ -1012,6 +1019,7 @@ name = "evmbin"
version = "0.1.0"
dependencies = [
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0",
"ethcore-transaction 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1044,6 +1052,14 @@ dependencies = [
"ethkey 0.3.0",
]
[[package]]
name = "fastmap"
version = "0.1.0"
dependencies = [
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
]
[[package]]
name = "fdlimit"
version = "0.1.1"
@ -1161,7 +1177,7 @@ dependencies = [
"ethkey 0.3.0",
"hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)",
"libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1208,11 +1224,28 @@ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "home"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "httparse"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "humantime"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hyper"
version = "0.11.24"
@ -1323,17 +1356,17 @@ version = "0.2.0"
dependencies = [
"ethcore-logger 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"fastmap 0.1.0",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"keccak-hasher 0.1.0",
"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)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
]
@ -1668,7 +1701,7 @@ version = "0.1.0"
dependencies = [
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 0.1.0 (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)",
"macros 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1797,7 +1830,7 @@ dependencies = [
"ethcore-network-devp2p 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"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)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1826,7 +1859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -1928,6 +1961,7 @@ source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c9
name = "parity-clib"
version = "1.12.0"
dependencies = [
"panic_hook 0.1.0",
"parity-ethereum 2.1.0",
]
@ -1953,9 +1987,9 @@ dependencies = [
"clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
"daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)",
"dir 0.1.1",
"dir 0.1.2",
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0",
"ethcore-io 1.12.0",
"ethcore-light 1.12.0",
@ -1979,7 +2013,7 @@ dependencies = [
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 0.1.0 (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)",
"mem 0.1.0",
"migration-rocksdb 0.1.0",
"node-filter 1.12.0",
@ -2031,7 +2065,7 @@ dependencies = [
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.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)",
"mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -2067,7 +2101,7 @@ dependencies = [
"ethkey 0.3.0",
"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)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2125,7 +2159,7 @@ dependencies = [
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.2 (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)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0",
"multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2148,7 +2182,7 @@ dependencies = [
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"transaction-pool 1.12.1",
"transaction-pool 1.13.1",
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
]
@ -2161,7 +2195,7 @@ dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"keccak-hash 0.1.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)",
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.12.0",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2199,7 +2233,7 @@ 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)",
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"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",
@ -2245,7 +2279,7 @@ dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"mem 0.1.0",
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -2256,7 +2290,7 @@ dependencies = [
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2289,7 +2323,7 @@ dependencies = [
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2401,7 +2435,7 @@ dependencies = [
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -2445,7 +2479,7 @@ dependencies = [
"hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"primal-bit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
"primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2562,7 +2596,7 @@ dependencies = [
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -2590,11 +2624,31 @@ dependencies = [
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex-syntax"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "registrar"
version = "0.0.1"
@ -2887,7 +2941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "smallvec"
version = "0.4.3"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2931,7 +2985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "stats"
version = "0.1.0"
dependencies = [
"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)",
]
[[package]]
@ -2993,6 +3047,14 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termion"
version = "1.5.1"
@ -3274,17 +3336,17 @@ dependencies = [
name = "trace-time"
version = "0.1.0"
dependencies = [
"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)",
]
[[package]]
name = "transaction-pool"
version = "1.12.1"
version = "1.13.1"
dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"trace-time 0.1.0",
]
@ -3335,6 +3397,11 @@ dependencies = [
"triehash 0.2.0 (git+https://github.com/paritytech/parity-common)",
]
[[package]]
name = "ucd-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uint"
version = "0.2.1"
@ -3462,7 +3529,7 @@ dependencies = [
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethjson 0.1.0",
"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)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
"patricia-trie-ethereum 0.1.0",
@ -3482,7 +3549,7 @@ dependencies = [
"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)",
"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)",
"parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0",
@ -3529,7 +3596,7 @@ dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"panic_hook 0.1.0",
"parity-whisper 0.1.0",
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
@ -3565,6 +3632,14 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "wincolor"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ws"
version = "0.7.5"
@ -3657,7 +3732,7 @@ dependencies = [
"checksum edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a34f5204fbc13582de418611cf3a7dcdd07c6d312a5b631597ba72c06b9d9c9"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
"checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
@ -3685,7 +3760,9 @@ dependencies = [
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
"checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "<none>"
"checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff"
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
"checksum hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)" = "df4dd5dae401458087396b6db7fabc4d6760aa456a5fa8e92bda549f39cae661"
"checksum hyper-rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6cdc1751771a14b8175764394f025e309a28c825ed9eaf97fa62bb831dc8c5"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
@ -3792,7 +3869,9 @@ dependencies = [
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814"
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
"checksum ring 0.12.1 (git+https://github.com/paritytech/ring)" = "<none>"
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity-common)" = "<none>"
@ -3826,7 +3905,7 @@ dependencies = [
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
"checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d"
"checksum smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10"
"checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
"checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
"checksum socket2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "06dc9f86ee48652b7c80f3d254e3b9accb67a928c562c64d10d7b016d3d98dab"
@ -3838,6 +3917,7 @@ dependencies = [
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
"checksum tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11ce2fe9db64b842314052e2421ac61a73ce41b898dc8e3750398b219c5fc1e0"
"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"
"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836"
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
@ -3867,6 +3947,7 @@ dependencies = [
"checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "<none>"
"checksum trie-standardmap 0.1.0 (git+https://github.com/paritytech/parity-common)" = "<none>"
"checksum triehash 0.2.0 (git+https://github.com/paritytech/parity-common)" = "<none>"
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273"
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a"
@ -3892,6 +3973,7 @@ dependencies = [
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9dc3aa9dcda98b5a16150c54619c1ead22e3d3a5d458778ae914be760aa981a"
"checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "<none>"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61"

View File

@ -8,8 +8,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
blooms-db = { path = "util/blooms-db" }
log = "0.3"
env_logger = "0.4"
log = "0.4"
env_logger = "0.5"
rustc-hex = "1.0"
docopt = "0.8"
clap = "2"
@ -136,6 +136,7 @@ members = [
"util/triehash-ethereum",
"util/keccak-hasher",
"util/patricia-trie-ethereum",
"util/fastmap",
]
[patch.crates-io]

View File

@ -3,7 +3,7 @@
### [» Download the latest release «](https://github.com/paritytech/parity-ethereum/releases/latest)
[![build status](https://gitlab.parity.io/parity/parity/badges/master/build.svg)](https://gitlab.parity.io/parity/parity/commits/master)
[![codecov](https://codecov.io/gh/paritytech/parity/branch/master/graph/badge.svg)](https://codecov.io/gh/paritytech/parity)
[![codecov](https://codecov.io/gh/paritytech/parity-ethereum/branch/master/graph/badge.svg)](https://codecov.io/gh/paritytech/parity-ethereum)
[![Snap Status](https://build.snapcraft.io/badge/paritytech/parity.svg)](https://build.snapcraft.io/user/paritytech/parity)
[![GPLv3](https://img.shields.io/badge/license-GPL%20v3-green.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)
@ -64,7 +64,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
Once you have rustup installed, then you need to install:
* [Perl](https://www.perl.org)
* [Yasm](http://yasm.tortall.net)
* [Yasm](https://yasm.tortall.net)
Make sure that these binaries are in your `PATH`. After that you should be able to build Parity-Ethereum from source.

View File

@ -1,3 +1,42 @@
Usage
## Usage
```docker build -f docker/ubuntu/Dockerfile --tag ethcore/parity:branch_or_tag_name .```
## Usage - CentOS
Builds a lightweight non-root Parity docker image:
```
git clone https://github.com/paritytech/parity-ethereum.git
cd parity-ethereum
./docker/centos/build.sh
```
Fully customised build:
```
PARITY_IMAGE_REPO=my-personal/parity \
PARITY_BUILDER_IMAGE_TAG=build-latest \
PARITY_RUNNER_IMAGE_TAG=centos-parity-experimental \
./docker/centos/build.sh
```
Default values:
```
# The image name
PARITY_IMAGE_REPO - parity/parity
# The tag to be used for builder image, git commit sha will be appended
PARITY_BUILDER_IMAGE_TAG - build
# The tag to be used for runner image
PARITY_RUNNER_IMAGE_TAG - latest
```
All default ports you might use will be exposed:
```
# secret
# ipfs store ui rpc ws listener discovery
# ↓ ↓ ↓ ↓ ↓ ↓ ↓
EXPOSE 5001 8082 8083 8180 8545 8546 30303/tcp 30303/udp
```

View File

@ -1,29 +1,43 @@
FROM alpine:edge
WORKDIR /build
# install tools and dependencies
RUN apk add --no-cache gcc musl-dev pkgconfig g++ make curl \
eudev-dev rust cargo git file binutils \
libusb-dev linux-headers perl cmake
FROM alpine:edge AS builder
# show backtraces
ENV RUST_BACKTRACE 1
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
RUN apk add --no-cache \
build-base \
cargo \
cmake \
eudev-dev \
linux-headers \
perl \
rust
# build parity
ADD . /build/parity
RUN cd parity && \
cargo build --release --verbose && \
ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
WORKDIR /parity
COPY . /parity
RUN cargo build --release --target x86_64-alpine-linux-musl --verbose
RUN strip target/x86_64-alpine-linux-musl/release/parity
RUN file /build/parity/target/release/parity
FROM alpine:edge
# show backtraces
ENV RUST_BACKTRACE 1
RUN apk add --no-cache \
libstdc++ \
eudev-libs \
libgcc
RUN addgroup -g 1000 parity \
&& adduser -u 1000 -G parity -s /bin/sh -D parity
USER parity
EXPOSE 8080 8545 8180
ENTRYPOINT ["/build/parity/target/release/parity"]
WORKDIR /home/parity
RUN mkdir -p /home/parity/.local/share/io.parity.ethereum/
COPY --chown=parity:parity --from=builder /parity/target/x86_64-alpine-linux-musl/release/parity ./
ENTRYPOINT ["./parity"]

View File

@ -1,36 +1,28 @@
FROM centos:latest
WORKDIR /build
# install tools and dependencies
RUN yum -y update&& \
yum install -y git make gcc-c++ gcc file binutils cmake
RUN mkdir -p /opt/parity/data && \
chmod g+rwX /opt/parity/data && \
mkdir -p /opt/parity/release
# install rustup
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
ls&&\
sh rustup.sh --disable-sudo
COPY parity/parity /opt/parity/release
# show backtraces
ENV RUST_BACKTRACE 1
WORKDIR /opt/parity/data
# set compiler
ENV CXX g++
ENV CC gcc
# exposing default ports
#
# secret
# ipfs store ui rpc ws listener discovery
# ↓ ↓ ↓ ↓ ↓ ↓ ↓
EXPOSE 5001 8082 8083 8180 8545 8546 30303/tcp 30303/udp
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# switch to non-root user
USER 1001
# build parity
ADD . /build/parity
RUN cd parity&&\
cargo build --release --verbose && \
ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
#if no base path provided, assume it's current workdir
CMD ["--base-path","."]
ENTRYPOINT ["/opt/parity/release/parity"]
RUN file /build/parity/target/release/parity
EXPOSE 8080 8545 8180
ENTRYPOINT ["/build/parity/target/release/parity"]

View File

@ -0,0 +1,25 @@
FROM centos:latest
WORKDIR /build
ADD . /build/parity-ethereum
RUN yum -y update && \
yum install -y systemd-devel git make gcc-c++ gcc file binutils && \
curl -L "https://cmake.org/files/v3.12/cmake-3.12.0-Linux-x86_64.tar.gz" -o cmake.tar.gz && \
tar -xzf cmake.tar.gz && \
cp -r cmake-3.12.0-Linux-x86_64/* /usr/ && \
curl https://sh.rustup.rs -sSf | sh -s -- -y && \
PATH=/root/.cargo/bin:$PATH && \
RUST_BACKTRACE=1 && \
rustc -vV && \
cargo -V && \
gcc -v && \
g++ -v && \
cmake --version && \
cd parity-ethereum && \
cargo build --verbose --release --features final && \
strip /build/parity-ethereum/target/release/parity && \
file /build/parity-ethereum/target/release/parity

29
docker/centos/build.sh Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env sh
# The image name
PARITY_IMAGE_REPO=${PARITY_IMAGE_REPO:-parity/parity}
# The tag to be used for builder image
PARITY_BUILDER_IMAGE_TAG=${PARITY_BUILDER_IMAGE_TAG:-build}
# The tag to be used for runner image
PARITY_RUNNER_IMAGE_TAG=${PARITY_RUNNER_IMAGE_TAG:-latest}
echo Building $PARITY_IMAGE_REPO:$PARITY_BUILDER_IMAGE_TAG-$(git log -1 --format="%H")
docker build --no-cache -t $PARITY_IMAGE_REPO:$PARITY_BUILDER_IMAGE_TAG-$(git log -1 --format="%H") . -f docker/centos/Dockerfile.build
echo Creating $PARITY_BUILDER_IMAGE_TAG-$(git log -1 --format="%H"), extracting binary
docker create --name extract $PARITY_IMAGE_REPO:$PARITY_BUILDER_IMAGE_TAG-$(git log -1 --format="%H")
mkdir docker/centos/parity
docker cp extract:/build/parity-ethereum/target/release/parity docker/centos/parity
echo Building $PARITY_IMAGE_REPO:$PARITY_RUNNER_IMAGE_TAG
docker build --no-cache -t $PARITY_IMAGE_REPO:$PARITY_RUNNER_IMAGE_TAG docker/centos/ -f docker/centos/Dockerfile
echo Cleaning up ...
rm -rf docker/centos/parity
docker rm -f extract
docker rmi -f $PARITY_IMAGE_REPO:$PARITY_BUILDER_IMAGE_TAG-$(git log -1 --format="%H")
echo Echoing Parity version:
docker run $PARITY_IMAGE_REPO:$PARITY_RUNNER_IMAGE_TAG --version
echo Done.

View File

@ -1,42 +0,0 @@
FROM ubuntu:14.04
WORKDIR /build
# install tools and dependencies
RUN apt-get update && \
apt-get install -y \
g++ \
build-essential \
cmake \
curl \
git \
file \
binutils \
pkg-config \
libudev-dev
# install rustup
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
# rustup directory
ENV PATH /root/.cargo/bin:$PATH
# show backtraces
ENV RUST_BACKTRACE 1
# show tools
RUN rustc -vV && \
cargo -V && \
gcc -v &&\
g++ -v
# build parity
ADD . /build/parity
RUN cd parity && \
cargo build --release --verbose && \
ls /build/parity/target/release/parity && \
strip /build/parity/target/release/parity
RUN file /build/parity/target/release/parity
EXPOSE 8080 8545 8180
ENTRYPOINT ["/build/parity/target/release/parity"]

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

@ -39,7 +39,7 @@ evm = { path = "evm" }
heapsize = "0.4"
itertools = "0.5"
lazy_static = "1.0"
log = "0.3"
log = "0.4"
lru-cache = "0.1"
num = { version = "0.1", default-features = false, features = ["bigint"] }
num_cpus = "1.2"

View File

@ -5,10 +5,11 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
bit-set = "0.4"
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
ethereum-types = "0.3"
heapsize = "0.4"
lazy_static = "1.0"
log = "0.3"
log = "0.4"
vm = { path = "../vm" }
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
parking_lot = "0.6"

View File

@ -45,7 +45,7 @@ impl Finalize for Result<GasLeft> {
fn finalize<E: Ext>(self, ext: E) -> Result<FinalizationResult> {
match self {
Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }),
Ok(GasLeft::NeedsReturn {gas_left, data, apply_state}) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult {
Ok(GasLeft::NeedsReturn { gas_left, data, apply_state }) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult {
gas_left: gas_left,
apply_state: apply_state,
return_data: data,
@ -55,6 +55,12 @@ impl Finalize for Result<GasLeft> {
}
}
impl Finalize for Error {
fn finalize<E: Ext>(self, _ext: E) -> Result<FinalizationResult> {
Err(self)
}
}
/// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256
pub trait CostType: Sized + From<usize> + Copy
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> +ops::Sub<Output=Self>

View File

@ -17,8 +17,9 @@
//! Evm factory.
//!
use std::sync::Arc;
use vm::Vm;
use vm::{Vm, Schedule};
use ethereum_types::U256;
use super::vm::ActionParams;
use super::interpreter::SharedCache;
use super::vmtype::VMType;
@ -32,12 +33,12 @@ pub struct Factory {
impl Factory {
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
pub fn create(&self, gas: &U256) -> Box<Vm> {
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
VMType::Interpreter => if Self::can_fit_in_usize(&params.gas) {
Box::new(super::interpreter::Interpreter::<usize>::new(params, self.evm_cache.clone(), schedule, depth))
} else {
Box::new(super::interpreter::Interpreter::<U256>::new(self.evm_cache.clone()))
Box::new(super::interpreter::Interpreter::<U256>::new(params, self.evm_cache.clone(), schedule, depth))
}
}
}
@ -68,7 +69,14 @@ impl Default for Factory {
#[test]
fn test_create_vm() {
let _vm = Factory::default().create(&U256::zero());
use vm::Ext;
use vm::tests::FakeExt;
use bytes::Bytes;
let mut params = ActionParams::default();
params.code = Some(Arc::new(Bytes::default()));
let ext = FakeExt::new();
let _vm = Factory::default().create(params, ext.schedule(), ext.depth());
}
/// Create tests by injecting different VM factories

View File

@ -119,14 +119,19 @@ impl Memory for Vec<u8> {
fn into_return_data(mut self, offset: U256, size: U256) -> ReturnData {
let mut offset = offset.low_u64() as usize;
let size = size.low_u64() as usize;
if !is_valid_range(offset, size) {
return ReturnData::empty()
return ReturnData::empty();
}
if self.len() - size > MAX_RETURN_WASTE_BYTES {
{ let _ = self.drain(..offset); }
self.truncate(size);
self.shrink_to_fit();
offset = 0;
if offset == 0 {
self.truncate(size);
self.shrink_to_fit();
} else {
self = self[offset..(offset + size)].to_vec();
offset = 0;
}
}
ReturnData::new(self, offset, size)
}

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,7 @@ extern crate heapsize;
extern crate vm;
extern crate keccak_hash as hash;
extern crate memory_cache;
extern crate parity_bytes as bytes;
#[macro_use]
extern crate lazy_static;

View File

@ -21,7 +21,7 @@ use std::sync::Arc;
use std::collections::{HashMap, HashSet};
use rustc_hex::FromHex;
use ethereum_types::{U256, H256, Address};
use vm::{self, ActionParams, ActionValue};
use vm::{self, ActionParams, ActionValue, Ext};
use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
use factory::Factory;
use vmtype::VMType;
@ -38,8 +38,8 @@ fn test_add(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_988));
@ -58,8 +58,8 @@ fn test_sha3(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_961));
@ -78,8 +78,8 @@ fn test_address(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -100,8 +100,8 @@ fn test_origin(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -122,8 +122,8 @@ fn test_sender(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -157,8 +157,8 @@ fn test_extcodecopy(factory: super::Factory) {
ext.codes.insert(sender, Arc::new(sender_code));
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_935));
@ -177,8 +177,8 @@ fn test_log_empty(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(99_619));
@ -209,8 +209,8 @@ fn test_log_sender(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(98_974));
@ -234,8 +234,8 @@ fn test_blockhash(factory: super::Factory) {
ext.blockhashes.insert(U256::zero(), blockhash.clone());
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_974));
@ -256,8 +256,8 @@ fn test_calldataload(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_991));
@ -277,8 +277,8 @@ fn test_author(factory: super::Factory) {
ext.info.author = author;
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -297,8 +297,8 @@ fn test_timestamp(factory: super::Factory) {
ext.info.timestamp = timestamp;
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -317,8 +317,8 @@ fn test_number(factory: super::Factory) {
ext.info.number = number;
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -337,8 +337,8 @@ fn test_difficulty(factory: super::Factory) {
ext.info.difficulty = difficulty;
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -357,8 +357,8 @@ fn test_gas_limit(factory: super::Factory) {
ext.info.gas_limit = gas_limit;
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(79_995));
@ -375,8 +375,8 @@ fn test_mul(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000734349397b853383");
@ -393,8 +393,8 @@ fn test_sub(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000012364ad0302");
@ -411,8 +411,8 @@ fn test_div(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
@ -429,8 +429,8 @@ fn test_div_zero(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@ -447,8 +447,8 @@ fn test_mod(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
@ -466,8 +466,8 @@ fn test_smod(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
@ -485,8 +485,8 @@ fn test_sdiv(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
@ -504,8 +504,8 @@ fn test_exp(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "90fd23767b60204c3d6fc8aec9e70a42a3f127140879c133a20129a597ed0c59");
@ -524,8 +524,8 @@ fn test_comparison(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@ -545,8 +545,8 @@ fn test_signed_comparison(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@ -566,8 +566,8 @@ fn test_bitops(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
@ -589,8 +589,8 @@ fn test_addmod_mulmod(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000001");
@ -610,8 +610,8 @@ fn test_byte(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
@ -629,8 +629,8 @@ fn test_signextend(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000fff");
@ -649,8 +649,8 @@ fn test_badinstruction_int() {
let mut ext = FakeExt::new();
let err = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap_err()
};
match err {
@ -669,8 +669,8 @@ fn test_pop(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
@ -689,8 +689,8 @@ fn test_extops(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000004"); // PC / CALLDATASIZE
@ -712,8 +712,8 @@ fn test_jumps(factory: super::Factory) {
let mut ext = FakeExt::new();
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_eq!(ext.sstore_clears, 1);
@ -740,12 +740,13 @@ fn test_calls(factory: super::Factory) {
};
let gas_left = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_set_contains(&ext.calls, &FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(2556),
sender_address: Some(address.clone()),
receive_address: Some(code_address.clone()),
@ -755,6 +756,7 @@ fn test_calls(factory: super::Factory) {
});
assert_set_contains(&ext.calls, &FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(2556),
sender_address: Some(address.clone()),
receive_address: Some(address.clone()),
@ -779,8 +781,8 @@ fn test_create_in_staticcall(factory: super::Factory) {
ext.is_static = true;
let err = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap_err()
};
assert_eq!(err, vm::Error::MutableCallInStaticContext);
@ -1047,8 +1049,8 @@ fn push_two_pop_one_constantinople_test(factory: &super::Factory, opcode: u8, pu
let mut ext = FakeExt::new_constantinople();
let _ = {
let mut vm = factory.create(&params.gas);
test_finalize(vm.exec(params, &mut ext)).unwrap()
let mut vm = factory.create(params, ext.schedule(), ext.depth());
test_finalize(vm.exec(&mut ext)).unwrap()
};
assert_store(&ext, 0, result);

View File

@ -7,7 +7,7 @@ version = "1.12.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
log = "0.3"
log = "0.4"
ethcore = { path = ".."}
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
ethcore-transaction = { path = "../transaction" }
@ -20,7 +20,7 @@ ethcore-io = { path = "../../util/io" }
hashdb = { git = "https://github.com/paritytech/parity-common" }
heapsize = "0.4"
vm = { path = "../vm" }
plain_hasher = { git = "https://github.com/paritytech/parity-common" }
fastmap = { path = "../../util/fastmap" }
rlp = { git = "https://github.com/paritytech/parity-common" }
rlp_derive = { path = "../../util/rlp_derive" }
smallvec = "0.4"

View File

@ -41,7 +41,7 @@ use ethereum_types::{H256, H264, U256};
use heapsize::HeapSizeOf;
use kvdb::{DBTransaction, KeyValueDB};
use parking_lot::{Mutex, RwLock};
use plain_hasher::H256FastMap;
use fastmap::H256FastMap;
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
use smallvec::SmallVec;

View File

@ -68,7 +68,7 @@ extern crate keccak_hasher;
extern crate memorydb;
extern crate patricia_trie as trie;
extern crate patricia_trie_ethereum as ethtrie;
extern crate plain_hasher;
extern crate fastmap;
extern crate rand;
extern crate rlp;
extern crate parking_lot;

View File

@ -120,17 +120,15 @@ impl LoadDistribution {
pub fn expected_time(&self, kind: Kind) -> Duration {
let samples = self.samples.read();
samples.get(&kind).and_then(|s| {
if s.len() == 0 { return None }
if s.is_empty() { return None }
let alpha: f64 = 1f64 / s.len() as f64;
let start = s.front().expect("length known to be non-zero; qed").clone();
let ema = s.iter().skip(1).fold(start as f64, |a, &c| {
let alpha: f64 = 1_f64 / s.len() as f64;
let start = *s.front().expect("length known to be non-zero; qed") as f64;
let ema = s.iter().skip(1).fold(start, |a, &c| {
(alpha * c as f64) + ((1.0 - alpha) * a)
});
// TODO: use `Duration::from_nanos` once stable (https://github.com/rust-lang/rust/issues/46507)
let ema = ema as u64;
Some(Duration::new(ema / 1_000_000_000, (ema % 1_000_000_000) as u32))
Some(Duration::from_nanos(ema as u64))
}).unwrap_or_else(move || hardcoded_serve_time(kind))
}

View File

@ -823,7 +823,7 @@ impl LightProtocol {
self.peers.write().insert(*peer, Mutex::new(Peer {
local_credits: local_flow.create_credits(),
status: status.clone(),
capabilities: capabilities.clone(),
capabilities,
remote_flow: remote_flow,
sent_head: pending.sent_head,
last_update: pending.last_update,

View File

@ -169,7 +169,7 @@ impl Status {
}
/// Peer capabilities.
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Capabilities {
/// Whether this peer can serve headers
pub serve_headers: bool,

View File

@ -222,7 +222,7 @@ fn status(chain_info: BlockChainInfo) -> Status {
fn handshake_expected() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let status = status(provider.client.chain_info());
@ -236,7 +236,7 @@ fn handshake_expected() {
fn genesis_mismatch() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let mut status = status(provider.client.chain_info());
status.genesis_hash = H256::default();
@ -250,7 +250,7 @@ fn genesis_mismatch() {
fn credit_overflow() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let status = status(provider.client.chain_info());
@ -283,7 +283,7 @@ fn credit_overflow() {
fn get_block_headers() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());
@ -335,7 +335,7 @@ fn get_block_headers() {
fn get_block_bodies() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());
@ -383,7 +383,7 @@ fn get_block_bodies() {
fn get_block_receipts() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());
@ -438,7 +438,7 @@ fn get_block_receipts() {
fn get_state_proofs() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let provider = TestProvider(provider);
@ -497,7 +497,7 @@ fn get_state_proofs() {
fn get_contract_code() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());
@ -540,7 +540,7 @@ fn get_contract_code() {
fn epoch_signal() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());
@ -583,7 +583,7 @@ fn epoch_signal() {
fn proof_of_execution() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());
@ -643,7 +643,7 @@ fn id_guard() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let req_id_1 = ReqId(5143);
@ -666,7 +666,7 @@ fn id_guard() {
proto.peers.write().insert(peer_id, ::parking_lot::Mutex::new(Peer {
local_credits: flow_params.create_credits(),
status: status(provider.client.chain_info()),
capabilities: capabilities.clone(),
capabilities,
remote_flow: Some((flow_params.create_credits(), (&*flow_params).clone())),
sent_head: provider.client.chain_info().best_block_hash,
last_update: Instant::now(),
@ -723,7 +723,7 @@ fn id_guard() {
fn get_transaction_index() {
let capabilities = capabilities();
let (provider, proto) = setup(capabilities.clone());
let (provider, proto) = setup(capabilities);
let flow_params = proto.flow_params.read().clone();
let cur_status = status(provider.client.chain_info());

View File

@ -418,7 +418,7 @@ impl Handler for OnDemand {
) -> PeerStatus {
self.peers.write().insert(
ctx.peer(),
Peer { status: status.clone(), capabilities: capabilities.clone() }
Peer { status: status.clone(), capabilities: *capabilities }
);
self.attempt_dispatch(ctx.as_basic());
PeerStatus::Kept

View File

@ -38,7 +38,7 @@ use transaction::SignedTransaction;
use trie::Trie;
use vm::EnvInfo;
const SUPPLIED_MATCHES: &'static str = "supplied responses always match produced requests; enforced by `check_response`; qed";
const SUPPLIED_MATCHES: &str = "supplied responses always match produced requests; enforced by `check_response`; qed";
/// Core unit of the API: submit batches of these to be answered with `Response`s.
#[derive(Clone)]
@ -265,30 +265,35 @@ impl From<Request> for CheckedRequest {
max: 1,
reverse: false,
};
trace!(target: "on_demand", "HeaderByHash Request, {:?}", net_req);
CheckedRequest::HeaderByHash(req, net_req)
}
Request::HeaderProof(req) => {
let net_req = net_request::IncompleteHeaderProofRequest {
num: req.num().into(),
};
trace!(target: "on_demand", "HeaderProof Request, {:?}", net_req);
CheckedRequest::HeaderProof(req, net_req)
}
Request::TransactionIndex(req) => {
let net_req = net_request::IncompleteTransactionIndexRequest {
hash: req.0.clone(),
};
trace!(target: "on_demand", "TransactionIndex Request, {:?}", net_req);
CheckedRequest::TransactionIndex(req, net_req)
}
Request::Body(req) => {
Request::Body(req) => {
let net_req = net_request::IncompleteBodyRequest {
hash: req.0.field(),
};
trace!(target: "on_demand", "Body Request, {:?}", net_req);
CheckedRequest::Body(req, net_req)
}
Request::Receipts(req) => {
let net_req = net_request::IncompleteReceiptsRequest {
hash: req.0.field(),
};
trace!(target: "on_demand", "Receipt Request, {:?}", net_req);
CheckedRequest::Receipts(req, net_req)
}
Request::Account(req) => {
@ -296,6 +301,7 @@ impl From<Request> for CheckedRequest {
block_hash: req.header.field(),
address_hash: ::hash::keccak(&req.address).into(),
};
trace!(target: "on_demand", "Account Request, {:?}", net_req);
CheckedRequest::Account(req, net_req)
}
Request::Code(req) => {
@ -303,6 +309,7 @@ impl From<Request> for CheckedRequest {
block_hash: req.header.field(),
code_hash: req.code_hash.into(),
};
trace!(target: "on_demand", "Code Request, {:?}", net_req);
CheckedRequest::Code(req, net_req)
}
Request::Execution(req) => {
@ -315,12 +322,14 @@ impl From<Request> for CheckedRequest {
value: req.tx.value,
data: req.tx.data.clone(),
};
trace!(target: "on_demand", "Execution request, {:?}", net_req);
CheckedRequest::Execution(req, net_req)
}
Request::Signal(req) => {
let net_req = net_request::IncompleteSignalRequest {
block_hash: req.hash.into(),
};
trace!(target: "on_demand", "Signal Request, {:?}", net_req);
CheckedRequest::Signal(req, net_req)
}
}
@ -507,15 +516,42 @@ 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::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)
}
}
}
@ -772,11 +808,13 @@ impl Body {
let header = self.0.as_ref()?;
let tx_root = ::triehash::ordered_trie_root(body.transactions_rlp().iter().map(|r| r.as_raw()));
if tx_root != header.transactions_root() {
trace!(target: "on_demand", "Body Response: \"WrongTrieRoot\" tx_root: {:?} header_root: {:?}", tx_root, header.transactions_root());
return Err(Error::WrongTrieRoot(header.transactions_root(), tx_root));
}
let uncles_hash = keccak(body.uncles_rlp().as_raw());
if uncles_hash != header.uncles_hash() {
trace!(target: "on_demand", "Body Response: \"WrongHash\" tx_root: {:?} header_root: {:?}", uncles_hash, header.uncles_hash());
return Err(Error::WrongHash(header.uncles_hash(), uncles_hash));
}
@ -784,7 +822,6 @@ impl Body {
let block = encoded::Block::new_from_header_and_body(&header.view(), &body.view());
cache.lock().insert_block_body(header.hash(), body.clone());
Ok(block)
}
}
@ -804,7 +841,10 @@ impl BlockReceipts {
cache.lock().insert_block_receipts(receipts_root, receipts.to_vec());
Ok(receipts.to_vec())
}
false => Err(Error::WrongTrieRoot(receipts_root, found_root)),
false => {
trace!(target: "on_demand", "Receipt Reponse: \"WrongTrieRoot\" receipts_root: {:?} found_root: {:?}", receipts_root, found_root);
Err(Error::WrongTrieRoot(receipts_root, found_root))
}
}
}
}
@ -837,7 +877,10 @@ impl Account {
code_hash: rlp.val_at(3)?,
}))
},
None => Ok(None),
None => {
trace!(target: "on_demand", "Account {:?} not found", self.address);
Ok(None)
}
}
}
}
@ -899,9 +942,18 @@ impl TransactionProof {
);
match proved_execution {
ProvedExecution::BadProof => Err(Error::BadProof),
ProvedExecution::Failed(e) => Ok(Err(e)),
ProvedExecution::Complete(e) => Ok(Ok(e)),
ProvedExecution::BadProof => {
trace!(target: "on_demand", "BadExecution Proof");
Err(Error::BadProof)
}
ProvedExecution::Failed(e) => {
trace!(target: "on_demand", "Execution Proof failed: {:?}", e);
Ok(Err(e))
}
ProvedExecution::Complete(e) => {
trace!(target: "on_demand", "Execution successful: {:?}", e);
Ok(Ok(e))
}
}
}
}

View File

@ -29,7 +29,7 @@ use std::collections::hash_map::Entry;
use transaction::{self, Condition, PendingTransaction, SignedTransaction};
use ethereum_types::{H256, U256, Address};
use plain_hasher::H256FastMap;
use fastmap::H256FastMap;
// Knowledge of an account's current nonce.
#[derive(Debug, Clone, PartialEq, Eq)]

View File

@ -11,7 +11,7 @@ ethcore = { path = ".."}
ethcore-network = { path = "../../util/network" }
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
ethereum-types = "0.3"
log = "0.3"
log = "0.4"
parking_lot = "0.6"
ethabi = "5.1"
ethabi-derive = "5.0"

View File

@ -23,7 +23,7 @@ ethkey = { path = "../../ethkey" }
fetch = { path = "../../util/fetch" }
futures = "0.1"
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
log = "0.3"
log = "0.4"
parking_lot = "0.6"
patricia-trie = { git = "https://github.com/paritytech/parity-common" }
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }

View File

@ -19,7 +19,7 @@
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
]
},
"validateScoreTransition": 1000000,
"validateScoreTransition": 4301764,
"validateStepTransition": 1500000,
"maximumUncleCountTransition": 5067000,
"maximumUncleCount": 0

View File

@ -16,7 +16,16 @@
"gasLimitBoundDivisor": "0x400",
"minGasLimit": "0x1388",
"networkID": "0x62121",
"wasmActivationTransition": 4000000
"wasmActivationTransition": 6666666,
"eip140Transition": 6666666,
"eip211Transition": 6666666,
"eip214Transition": 6666666,
"eip658Transition": 6666666,
"maxCodeSize": 24576,
"maxCodeSizeTransition": 6666666,
"registrar": "0xb8624dc8cb3ca3147c178ac4c21734eb49e04071"
},
"genesis": {
"seal": {
@ -43,12 +52,22 @@
},
"0x4ba15b56452521c0826a35a6f2022e1210fc519b": {
"balance": "0x7E37BE2022B2B09472D89C0000"
}
},
"0x0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "activate_at": 6666666, "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0x0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "activate_at": 6666666, "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0x0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "activate_at": 6666666, "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0x0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "activate_at": 6666666, "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 6666666, "pricing": { "modexp": { "divisor": 20 } } } },
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 6666666, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 6666666, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 6666666, "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

@ -17,7 +17,8 @@
"minGasLimit": "0x1388",
"networkID" : "0x69",
"gasLimitBoundDivisor": "0x0400",
"transactionPermissionContract": "0x0000000000000000000000000000000000000005"
"transactionPermissionContract": "0x0000000000000000000000000000000000000005",
"transactionPermissionContractTransition": "1"
},
"genesis": {
"seal": {

View File

@ -17,7 +17,8 @@
"minGasLimit": "0x1388",
"networkID" : "0x69",
"gasLimitBoundDivisor": "0x0400",
"transactionPermissionContract": "0x0000000000000000000000000000000000000005"
"transactionPermissionContract": "0x0000000000000000000000000000000000000005",
"transactionPermissionContractTransition": "1"
},
"genesis": {
"seal": {

@ -1 +1 @@
Subproject commit 474110de59a0f632b20615256c913b144c49354c
Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd

View File

@ -11,7 +11,7 @@ ethcore-io = { path = "../../util/io" }
ethcore-private-tx = { path = "../private-tx" }
ethcore-sync = { path = "../sync" }
kvdb = { git = "https://github.com/paritytech/parity-common" }
log = "0.3"
log = "0.4"
stop-guard = { path = "../../util/stop-guard" }
trace-time = { path = "../../util/trace-time" }

View File

@ -95,6 +95,7 @@ impl ClientService {
let pruning = config.pruning;
let client = Client::new(config, &spec, blockchain_db.clone(), miner.clone(), io_service.channel())?;
miner.set_io_channel(io_service.channel());
miner.set_in_chain_checker(&client.clone());
let snapshot_params = SnapServiceParams {
engine: spec.engine.clone(),

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

@ -564,7 +564,7 @@ fn enact(
ancestry: &mut Iterator<Item=ExtendedHeader>,
) -> Result<LockedBlock, Error> {
{
if ::log::max_log_level() >= ::log::LogLevel::Trace {
if ::log::max_level() >= ::log::Level::Trace {
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?;
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
header.number(), s.root(), header.author(), s.balance(&header.author())?);
@ -637,10 +637,11 @@ mod tests {
use ethereum_types::Address;
use std::sync::Arc;
use transaction::SignedTransaction;
use verification::queue::kind::blocks::Unverified;
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
fn enact_bytes(
block_bytes: &[u8],
block_bytes: Vec<u8>,
engine: &EthEngine,
tracing: bool,
db: StateDB,
@ -648,10 +649,10 @@ mod tests {
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<LockedBlock, Error> {
let block = view!(BlockView, block_bytes);
let header = block.header();
let block = Unverified::from_rlp(block_bytes)?;
let header = block.header;
let transactions: Result<Vec<_>, Error> = block
.transactions()
.transactions
.into_iter()
.map(SignedTransaction::new)
.map(|r| r.map_err(Into::into))
@ -659,7 +660,7 @@ mod tests {
let transactions = transactions?;
{
if ::log::max_log_level() >= ::log::LogLevel::Trace {
if ::log::max_level() >= ::log::Level::Trace {
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?;
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
header.number(), s.root(), header.author(), s.balance(&header.author())?);
@ -683,8 +684,8 @@ mod tests {
b.populate_from(&header);
b.push_transactions(transactions)?;
for u in &block.uncles() {
b.push_uncle(u.clone())?;
for u in block.uncles {
b.push_uncle(u)?;
}
b.close_and_lock()
@ -692,7 +693,7 @@ mod tests {
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
fn enact_and_seal(
block_bytes: &[u8],
block_bytes: Vec<u8>,
engine: &EthEngine,
tracing: bool,
db: StateDB,
@ -700,8 +701,9 @@ mod tests {
last_hashes: Arc<LastHashes>,
factories: Factories,
) -> Result<SealedBlock, Error> {
let header = view!(BlockView, block_bytes).header_view();
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?.seal(engine, header.seal())?)
let header = Unverified::from_rlp(block_bytes.clone())?.header;
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?
.seal(engine, header.seal().to_vec())?)
}
#[test]
@ -731,7 +733,7 @@ mod tests {
let orig_db = b.drain().state.drop().1;
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let e = enact_and_seal(orig_bytes.clone(), engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
assert_eq!(e.rlp_bytes(), orig_bytes);
@ -762,7 +764,7 @@ mod tests {
let orig_db = b.drain().state.drop().1;
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let e = enact_and_seal(orig_bytes.clone(), engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
let bytes = e.rlp_bytes();
assert_eq!(bytes, orig_bytes);

View File

@ -16,7 +16,6 @@
use std::collections::{HashSet, BTreeMap, VecDeque};
use std::cmp;
use std::fmt;
use std::str::FromStr;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::sync::{Arc, Weak};
@ -50,13 +49,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;
@ -1813,76 +1815,100 @@ impl BlockChainClient for Client {
self.engine.additional_params().into_iter().collect()
}
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
// Wrap the logic inside a closure so that we can take advantage of question mark syntax.
let fetch_logs = || {
let chain = self.chain.read();
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
let chain = self.chain.read();
// First, check whether `filter.from_block` and `filter.to_block` is on the canon chain. If so, we can use the
// optimized version.
let is_canon = |id| {
match id {
// If it is referred by number, then it is always on the canon chain.
&BlockId::Earliest | &BlockId::Latest | &BlockId::Number(_) => true,
// If it is referred by hash, we see whether a hash -> number -> hash conversion gives us the same
// result.
&BlockId::Hash(ref hash) => chain.is_canon(hash),
}
};
let blocks = if is_canon(&filter.from_block) && is_canon(&filter.to_block) {
// If we are on the canon chain, use bloom filter to fetch required hashes.
let from = self.block_number_ref(&filter.from_block)?;
let to = self.block_number_ref(&filter.to_block)?;
chain.blocks_with_bloom(&filter.bloom_possibilities(), from, to)
.into_iter()
.filter_map(|n| chain.block_hash(n))
.collect::<Vec<H256>>()
} else {
// Otherwise, we use a slower version that finds a link between from_block and to_block.
let from_hash = Self::block_hash(&chain, filter.from_block)?;
let from_number = chain.block_number(&from_hash)?;
let to_hash = Self::block_hash(&chain, filter.from_block)?;
let blooms = filter.bloom_possibilities();
let bloom_match = |header: &encoded::Header| {
blooms.iter().any(|bloom| header.log_bloom().contains_bloom(bloom))
};
let (blocks, last_hash) = {
let mut blocks = Vec::new();
let mut current_hash = to_hash;
loop {
let header = chain.block_header_data(&current_hash)?;
if bloom_match(&header) {
blocks.push(current_hash);
}
// Stop if `from` block is reached.
if header.number() <= from_number {
break;
}
current_hash = header.parent_hash();
}
blocks.reverse();
(blocks, current_hash)
};
// Check if we've actually reached the expected `from` block.
if last_hash != from_hash || blocks.is_empty() {
return None;
}
blocks
};
Some(self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit))
// First, check whether `filter.from_block` and `filter.to_block` is on the canon chain. If so, we can use the
// optimized version.
let is_canon = |id| {
match id {
// If it is referred by number, then it is always on the canon chain.
&BlockId::Earliest | &BlockId::Latest | &BlockId::Number(_) => true,
// If it is referred by hash, we see whether a hash -> number -> hash conversion gives us the same
// result.
&BlockId::Hash(ref hash) => chain.is_canon(hash),
}
};
fetch_logs().unwrap_or_default()
let blocks = if is_canon(&filter.from_block) && is_canon(&filter.to_block) {
// If we are on the canon chain, use bloom filter to fetch required hashes.
//
// If we are sure the block does not exist (where val > best_block_number), then return error. Note that we
// don't need to care about pending blocks here because RPC query sets pending back to latest (or handled
// pending logs themselves).
let from = match self.block_number_ref(&filter.from_block) {
Some(val) if val <= chain.best_block_number() => val,
_ => return Err(filter.from_block.clone()),
};
let to = match self.block_number_ref(&filter.to_block) {
Some(val) if val <= chain.best_block_number() => val,
_ => return Err(filter.to_block.clone()),
};
// If from is greater than to, then the current bloom filter behavior is to just return empty
// result. There's no point to continue here.
if from > to {
return Err(filter.to_block.clone());
}
chain.blocks_with_bloom(&filter.bloom_possibilities(), from, to)
.into_iter()
.filter_map(|n| chain.block_hash(n))
.collect::<Vec<H256>>()
} else {
// Otherwise, we use a slower version that finds a link between from_block and to_block.
let from_hash = match Self::block_hash(&chain, filter.from_block) {
Some(val) => val,
None => return Err(filter.from_block.clone()),
};
let from_number = match chain.block_number(&from_hash) {
Some(val) => val,
None => return Err(BlockId::Hash(from_hash)),
};
let to_hash = match Self::block_hash(&chain, filter.to_block) {
Some(val) => val,
None => return Err(filter.to_block.clone()),
};
let blooms = filter.bloom_possibilities();
let bloom_match = |header: &encoded::Header| {
blooms.iter().any(|bloom| header.log_bloom().contains_bloom(bloom))
};
let (blocks, last_hash) = {
let mut blocks = Vec::new();
let mut current_hash = to_hash;
loop {
let header = match chain.block_header_data(&current_hash) {
Some(val) => val,
None => return Err(BlockId::Hash(current_hash)),
};
if bloom_match(&header) {
blocks.push(current_hash);
}
// Stop if `from` block is reached.
if header.number() <= from_number {
break;
}
current_hash = header.parent_hash();
}
blocks.reverse();
(blocks, current_hash)
};
// Check if we've actually reached the expected `from` block.
if last_hash != from_hash || blocks.is_empty() {
// In this case, from_hash is the cause (for not matching last_hash).
return Err(BlockId::Hash(from_hash));
}
blocks
};
Ok(self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit))
}
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
@ -2071,7 +2097,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.
@ -2095,10 +2121,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) {
@ -2514,21 +2539,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>,
@ -2547,7 +2557,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| {
@ -2560,7 +2570,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

@ -19,7 +19,7 @@
use std::fmt;
use std::sync::Arc;
use ethereum_types::{H256, U256, H160};
use {factory, journaldb, trie, kvdb_memorydb, bytes};
use {factory, journaldb, trie, kvdb_memorydb};
use kvdb::{self, KeyValueDB};
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt};
use factory::Factories;
@ -183,14 +183,12 @@ impl<'a> EvmTestClient<'a> {
gas_limit: *genesis.gas_limit(),
};
let mut substate = state::Substate::new();
let mut output = vec![];
let machine = self.spec.engine.machine();
let schedule = machine.schedule(info.number);
let mut executive = executive::Executive::new(&mut self.state, &info, &machine, &schedule);
executive.call(
params,
&mut substate,
bytes::BytesRef::Flexible(&mut output),
tracer,
vm_tracer,
).map_err(EvmTestError::Evm)

View File

@ -94,6 +94,8 @@ pub struct TestBlockChainClient {
pub receipts: RwLock<HashMap<TransactionId, LocalizedReceipt>>,
/// Logs
pub logs: RwLock<Vec<LocalizedLogEntry>>,
/// Should return errors on logs.
pub error_on_logs: RwLock<Option<BlockId>>,
/// Block queue size.
pub queue_size: AtomicUsize,
/// Miner
@ -178,6 +180,7 @@ impl TestBlockChainClient {
traces: RwLock::new(None),
history: RwLock::new(None),
disabled: AtomicBool::new(false),
error_on_logs: RwLock::new(None),
};
// insert genesis hash.
@ -233,6 +236,11 @@ impl TestBlockChainClient {
*self.logs.write() = logs;
}
/// Set return errors on logs.
pub fn set_error_on_logs(&self, val: Option<BlockId>) {
*self.error_on_logs.write() = val;
}
/// Add blocks to test client.
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
let len = self.numbers.read().len();
@ -665,13 +673,18 @@ impl BlockChainClient for TestBlockChainClient {
self.receipts.read().get(&id).cloned()
}
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
match self.error_on_logs.read().as_ref() {
Some(id) => return Err(id.clone()),
None => (),
}
let mut logs = self.logs.read().clone();
let len = logs.len();
match filter.limit {
Ok(match filter.limit {
Some(limit) if limit <= len => logs.split_off(len - limit),
_ => logs,
}
})
}
fn last_hashes(&self) -> LastHashes {

View File

@ -297,8 +297,8 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
/// Get the registrar address, if it exists.
fn additional_params(&self) -> BTreeMap<String, String>;
/// Returns logs matching given filter.
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
/// Returns logs matching given filter. If one of the filtering block cannot be found, returns the block id that caused the error.
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId>;
/// Replays a given transaction for inspection.
fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError>;

View File

@ -150,6 +150,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;
@ -183,6 +201,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

@ -30,7 +30,8 @@ pub use self::denominations::*;
use machine::EthereumMachine;
use super::spec::*;
fn load<'a, T: Into<Option<SpecParams<'a>>>>(params: T, b: &[u8]) -> Spec {
/// Load chain spec from `SpecParams` and JSON.
pub fn load<'a, T: Into<Option<SpecParams<'a>>>>(params: T, b: &[u8]) -> Spec {
match params.into() {
Some(params) => Spec::load(params, b),
None => Spec::load(&::std::env::temp_dir(), b)

View File

@ -204,7 +204,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
&'any mut self,
origin_info: OriginInfo,
substate: &'any mut Substate,
output: OutputPolicy<'any, 'any>,
output: OutputPolicy,
tracer: &'any mut T,
vm_tracer: &'any mut V,
static_call: bool,
@ -312,8 +312,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
call_type: CallType::None,
params_type: vm::ParamsType::Embedded,
};
let mut out = if output_from_create { Some(vec![]) } else { None };
(self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new))
let res = self.create(params, &mut substate, &mut tracer, &mut vm_tracer);
let out = match &res {
Ok(res) if output_from_create => res.return_data.to_vec(),
_ => Vec::new(),
};
(res, out)
},
Action::Call(ref address) => {
let params = ActionParams {
@ -330,8 +334,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
call_type: CallType::Call,
params_type: vm::ParamsType::Separate,
};
let mut out = vec![];
(self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out)
let res = self.call(params, &mut substate, &mut tracer, &mut vm_tracer);
let out = match &res {
Ok(res) => res.return_data.to_vec(),
_ => Vec::new(),
};
(res, out)
}
};
@ -354,23 +362,22 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// Ordinary execution - keep VM in same thread
if self.depth != depth_threshold {
let vm_factory = self.state.vm_factory();
let wasm = self.schedule.wasm.is_some();
let origin_info = OriginInfo::from(&params);
trace!(target: "executive", "ext.schedule.have_delegate_call: {}", self.schedule.have_delegate_call);
let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
let mut vm = vm_factory.create(&params, wasm);
return vm.exec(params, &mut ext).finalize(ext);
let mut vm = vm_factory.create(params, self.schedule, self.depth);
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
return vm.exec(&mut ext).finalize(ext);
}
// Start in new thread with stack size needed up to max depth
crossbeam::scope(|scope| {
let vm_factory = self.state.vm_factory();
let max_depth = self.schedule.max_depth;
let wasm = self.schedule.wasm.is_some();
let mut ext = self.as_externalities(OriginInfo::from(&params), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
let origin_info = OriginInfo::from(&params);
scope.builder().stack_size(::std::cmp::max(max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
let mut vm = vm_factory.create(&params, wasm);
vm.exec(params, &mut ext).finalize(ext)
scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
let mut vm = vm_factory.create(params, self.schedule, self.depth);
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
vm.exec(&mut ext).finalize(ext)
}).expect("Sub-thread creation cannot fail; the host might run out of resources; qed")
}).join()
}
@ -383,7 +390,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
&mut self,
params: ActionParams,
substate: &mut Substate,
mut output: BytesRef,
tracer: &mut T,
vm_tracer: &mut V
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
@ -417,8 +423,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let default = [];
let data = if let Some(ref d) = params.data { d as &[u8] } else { &default as &[u8] };
let trace_info = tracer.prepare_trace_call(&params);
let cost = builtin.cost(data);
if cost <= params.gas {
let mut builtin_out_buffer = Vec::new();
@ -429,11 +433,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
if let Err(e) = result {
self.state.revert_to_checkpoint();
let evm_err: vm::Error = e.into();
tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into());
let trace_info = tracer.prepare_trace_call(&params);
tracer.trace_failed_call(
trace_info,
vec![],
evm_err.clone().into()
);
Err(evm_err)
} else {
self.state.discard_checkpoint();
output.write(0, &builtin_out_buffer);
// Trace only top level calls and calls with balance transfer to builtins. The reason why we don't
// trace all internal calls to builtin contracts is that memcpy (IDENTITY) is a heavily used
@ -443,15 +451,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
ActionValue::Apparent(_) => false,
};
if self.depth == 0 || is_transferred {
let mut trace_output = tracer.prepare_trace_output();
if let Some(out) = trace_output.as_mut() {
*out = output.to_owned();
}
let trace_info = tracer.prepare_trace_call(&params);
tracer.trace_call(
trace_info,
cost,
trace_output,
&builtin_out_buffer,
vec![]
);
}
@ -467,13 +471,17 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// just drain the whole gas
self.state.revert_to_checkpoint();
tracer.trace_failed_call(trace_info, vec![], vm::Error::OutOfGas.into());
let trace_info = tracer.prepare_trace_call(&params);
tracer.trace_failed_call(
trace_info,
vec![],
vm::Error::OutOfGas.into()
);
Err(vm::Error::OutOfGas)
}
} else {
let trace_info = tracer.prepare_trace_call(&params);
let mut trace_output = tracer.prepare_trace_output();
let mut subtracer = tracer.subtracer();
let gas = params.gas;
@ -486,7 +494,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed"));
let res = {
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return, &mut subtracer, &mut subvmtracer)
};
vm_tracer.done_subtrace(subvmtracer);
@ -495,12 +503,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let traces = subtracer.drain();
match res {
Ok(ref res) if res.apply_state => tracer.trace_call(
trace_info,
gas - res.gas_left,
trace_output,
traces
),
Ok(ref res) if res.apply_state => {
tracer.trace_call(
trace_info,
gas - res.gas_left,
&res.return_data,
traces
);
},
Ok(_) => tracer.trace_failed_call(trace_info, traces, vm::Error::Reverted.into()),
Err(ref e) => tracer.trace_failed_call(trace_info, traces, e.into()),
};
@ -514,7 +524,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
// otherwise it's just a basic transaction, only do tracing, if necessary.
self.state.discard_checkpoint();
tracer.trace_call(trace_info, U256::zero(), trace_output, vec![]);
tracer.trace_call(trace_info, U256::zero(), &[], vec![]);
Ok(FinalizationResult {
gas_left: params.gas,
return_data: ReturnData::empty(),
@ -531,7 +541,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
&mut self,
params: ActionParams,
substate: &mut Substate,
output: &mut Option<Bytes>,
tracer: &mut T,
vm_tracer: &mut V,
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
@ -570,7 +579,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
}
let trace_info = tracer.prepare_trace_create(&params);
let mut trace_output = tracer.prepare_trace_output();
let mut subtracer = tracer.subtracer();
let gas = params.gas;
let created = params.address.clone();
@ -580,7 +588,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let res = self.exec_vm(
params,
&mut unconfirmed_substate,
OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())),
OutputPolicy::InitContract,
&mut subtracer,
&mut subvmtracer
);
@ -588,13 +596,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
vm_tracer.done_subtrace(subvmtracer);
match res {
Ok(ref res) if res.apply_state => tracer.trace_create(
trace_info,
gas - res.gas_left,
trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)),
created,
subtracer.drain()
),
Ok(ref res) if res.apply_state => {
tracer.trace_create(
trace_info,
gas - res.gas_left,
&res.return_data,
created,
subtracer.drain()
);
}
Ok(_) => tracer.trace_failed_create(trace_info, subtracer.drain(), vm::Error::Reverted.into()),
Err(ref e) => tracer.trace_failed_create(trace_info, subtracer.drain(), e.into())
};
@ -716,7 +726,6 @@ mod tests {
use ethkey::{Generator, Random};
use super::*;
use ethereum_types::{H256, U256, U512, Address};
use bytes::BytesRef;
use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress};
use evm::{Factory, VMType};
use error::ExecutionError;
@ -767,7 +776,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(79_975));
@ -825,7 +834,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(62_976));
@ -869,8 +878,7 @@ mod tests {
let mut vm_tracer = ExecutiveVMTracer::toplevel();
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let output = BytesRef::Fixed(&mut[0u8;0]);
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap();
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap();
assert_eq!(tracer.drain(), vec![FlatTrace {
action: trace::Action::Call(trace::Call {
@ -897,7 +905,7 @@ mod tests {
call_type: CallType::Call
}), result: trace::Res::Call(trace::CallResult {
gas_used: 600.into(),
output: vec![]
output: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 17, 133, 165, 197, 233, 252, 84, 97, 40, 8, 151, 126, 232, 245, 72, 178, 37, 141, 49]
}),
subtraces: 0,
trace_address: vec![0].into_iter().collect(),
@ -955,8 +963,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let output = BytesRef::Fixed(&mut[0u8;0]);
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap()
};
assert_eq!(gas_left, U256::from(44_752));
@ -1072,8 +1079,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
let output = BytesRef::Fixed(&mut[0u8;0]);
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap()
};
assert_eq!(gas_left, U256::from(62967));
@ -1145,7 +1151,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap()
ex.create(params.clone(), &mut substate, &mut tracer, &mut vm_tracer).unwrap()
};
assert_eq!(gas_left, U256::from(96_776));
@ -1231,7 +1237,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(62_976));
@ -1283,7 +1289,7 @@ mod tests {
{
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap();
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap();
}
assert_eq!(substate.contracts_created.len(), 1);
@ -1344,7 +1350,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(73_237));
@ -1389,7 +1395,7 @@ mod tests {
let FinalizationResult { gas_left, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
assert_eq!(gas_left, U256::from(59_870));
@ -1563,7 +1569,7 @@ mod tests {
let result = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer)
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer)
};
match result {
@ -1596,10 +1602,11 @@ mod tests {
let mut substate = Substate::new();
let mut output = [0u8; 14];
let FinalizationResult { gas_left: result, .. } = {
let FinalizationResult { gas_left: result, return_data, .. } = {
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
(&mut output).copy_from_slice(&return_data[..(cmp::min(14, return_data.len()))]);
assert_eq!(result, U256::from(1));
assert_eq!(output[..], returns[..]);
@ -1639,11 +1646,12 @@ mod tests {
let machine = ::ethereum::new_kovan_wasm_test_machine();
let mut output = [0u8; 20];
let FinalizationResult { gas_left: result, .. } = {
let FinalizationResult { gas_left: result, return_data, .. } = {
let schedule = machine.schedule(info.number);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params.clone(), &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.call(params.clone(), &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
(&mut output).copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]);
assert_eq!(result, U256::from(18433));
// Transaction successfully returned sender
@ -1653,11 +1661,12 @@ mod tests {
info.number = 1;
let mut output = [0u8; 20];
let FinalizationResult { gas_left: result, .. } = {
let FinalizationResult { gas_left: result, return_data, .. } = {
let schedule = machine.schedule(info.number);
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
ex.call(params, &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
ex.call(params, &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer).unwrap()
};
(&mut output[..((cmp::min(20, return_data.len())))]).copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]);
assert_eq!(result, U256::from(20025));
// Since transaction errored due to wasm was not activated, result is just empty

View File

@ -18,7 +18,7 @@
use std::cmp;
use std::sync::Arc;
use ethereum_types::{H256, U256, Address};
use bytes::{Bytes, BytesRef};
use bytes::Bytes;
use state::{Backend as StateBackend, State, Substate, CleanupMode};
use machine::EthereumMachine as Machine;
use executive::*;
@ -32,12 +32,12 @@ use transaction::UNSIGNED_SENDER;
use trace::{Tracer, VMTracer};
/// Policy for handling output data on `RETURN` opcode.
pub enum OutputPolicy<'a, 'b> {
pub enum OutputPolicy {
/// Return reference to fixed sized output.
/// Used for message calls.
Return(BytesRef<'a>, Option<&'b mut Bytes>),
Return,
/// Init new contract as soon as `RETURN` is called.
InitContract(Option<&'b mut Bytes>),
InitContract,
}
/// Transaction properties that externalities need to know about.
@ -71,7 +71,7 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> {
substate: &'a mut Substate,
machine: &'a Machine,
schedule: &'a Schedule,
output: OutputPolicy<'a, 'a>,
output: OutputPolicy,
tracer: &'a mut T,
vm_tracer: &'a mut V,
static_flag: bool,
@ -89,7 +89,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
depth: usize,
origin_info: OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy<'a, 'a>,
output: OutputPolicy,
tracer: &'a mut T,
vm_tracer: &'a mut V,
static_flag: bool,
@ -171,9 +171,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
params_type: vm::ParamsType::Separate,
};
let mut output = H256::new();
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
let r = ex.call(params, self.substate, BytesRef::Fixed(&mut output), self.tracer, self.vm_tracer);
let r = ex.call(params, self.substate, self.tracer, self.vm_tracer);
let output = match &r {
Ok(ref r) => H256::from(&r.return_data[..32]),
_ => H256::new(),
};
trace!("ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", number, r, output, self.env_info.number);
output
} else {
@ -194,7 +197,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
}
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address_scheme: CreateContractAddress) -> ContractCreateResult {
fn create(
&mut self,
gas: &U256,
value: &U256,
code: &[u8],
address_scheme: CreateContractAddress
) -> ContractCreateResult {
// create new contract address
let (address, code_hash) = match self.state.nonce(&self.origin_info.address) {
Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code),
@ -231,7 +240,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
// TODO: handle internal error separately
match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) {
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => {
self.substate.contracts_created.push(address.clone());
ContractCreateResult::Created(address, gas_left)
@ -243,14 +252,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
}
}
fn call(&mut self,
fn call(
&mut self,
gas: &U256,
sender_address: &Address,
receive_address: &Address,
value: Option<U256>,
data: &[u8],
code_address: &Address,
output: &mut [u8],
call_type: CallType
) -> MessageCallResult {
trace!(target: "externalities", "call");
@ -284,7 +293,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) {
match ex.call(params, self.substate, self.tracer, self.vm_tracer) {
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
_ => MessageCallResult::Failed
@ -303,27 +312,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
Ok(self.state.code_size(address)?)
}
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
where Self: Sized {
let handle_copy = |to: &mut Option<&mut Bytes>| {
to.as_mut().map(|b| **b = data.to_vec());
};
match self.output {
OutputPolicy::Return(BytesRef::Fixed(ref mut slice), ref mut copy) => {
handle_copy(copy);
let len = cmp::min(slice.len(), data.len());
(&mut slice[..len]).copy_from_slice(&data[..len]);
OutputPolicy::Return => {
Ok(*gas)
},
OutputPolicy::Return(BytesRef::Flexible(ref mut vec), ref mut copy) => {
handle_copy(copy);
vec.clear();
vec.extend_from_slice(&*data);
Ok(*gas)
},
OutputPolicy::InitContract(ref mut copy) if apply_state => {
OutputPolicy::InitContract if apply_state => {
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
if return_cost > *gas || data.len() > self.schedule.create_data_limit {
return match self.schedule.exceptional_failed_code_deposit {
@ -331,11 +326,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
false => Ok(*gas)
}
}
handle_copy(copy);
self.state.init_code(&self.origin_info.address, data.to_vec())?;
Ok(*gas - return_cost)
},
OutputPolicy::InitContract(_) => {
OutputPolicy::InitContract => {
Ok(*gas)
},
}
@ -479,7 +473,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
assert_eq!(ext.env_info().number, 100);
}
@ -491,7 +485,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
@ -515,7 +509,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
@ -530,9 +524,7 @@ mod tests {
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut output = vec![];
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
// this should panic because we have no balance on any account
ext.call(
@ -542,7 +534,6 @@ mod tests {
Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
&[],
&Address::new(),
&mut output,
CallType::Call
);
}
@ -558,7 +549,7 @@ mod tests {
let mut vm_tracer = NoopVMTracer;
{
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
ext.log(log_topics, &log_data).unwrap();
}
@ -575,7 +566,7 @@ mod tests {
let mut vm_tracer = NoopVMTracer;
{
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
ext.suicide(refund_account).unwrap();
}
@ -592,7 +583,7 @@ mod tests {
let mut vm_tracer = NoopVMTracer;
let address = {
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
ContractCreateResult::Created(address, _) => address,
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
@ -612,8 +603,8 @@ mod tests {
let mut vm_tracer = NoopVMTracer;
let address = {
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
ContractCreateResult::Created(address, _) => address,
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),

View File

@ -18,7 +18,7 @@ use trie::TrieFactory;
use ethtrie::RlpCodec;
use account_db::Factory as AccountFactory;
use evm::{Factory as EvmFactory, VMType};
use vm::{Vm, ActionParams};
use vm::{Vm, ActionParams, Schedule};
use wasm::WasmInterpreter;
use keccak_hasher::KeccakHasher;
@ -31,11 +31,11 @@ pub struct VmFactory {
}
impl VmFactory {
pub fn create(&self, params: &ActionParams, wasm: bool) -> Box<Vm> {
if wasm && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(WasmInterpreter)
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
Box::new(WasmInterpreter::new(params))
} else {
self.evm.create(&params.gas)
self.evm.create(params, schedule, depth)
}
}

View File

@ -30,7 +30,7 @@ use test_helpers::get_temp_state;
use ethjson;
use trace::{Tracer, NoopTracer};
use trace::{VMTracer, NoopVMTracer};
use bytes::{Bytes, BytesRef};
use bytes::Bytes;
use ethtrie;
use rlp::RlpStream;
use hash::keccak;
@ -90,7 +90,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
depth: usize,
origin_info: OriginInfo,
substate: &'a mut Substate,
output: OutputPolicy<'a, 'a>,
output: OutputPolicy,
address: Address,
tracer: &'a mut T,
vm_tracer: &'a mut V,
@ -154,7 +154,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
value: Option<U256>,
data: &[u8],
_code_address: &Address,
_output: &mut [u8],
_call_type: CallType
) -> MessageCallResult {
self.callcreates.push(CallCreate {
@ -262,7 +261,6 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
let mut substate = Substate::new();
let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer;
let mut output = vec![];
let vm_factory = state.vm_factory();
// execute
@ -276,18 +274,23 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
0,
OriginInfo::from(&params),
&mut substate,
OutputPolicy::Return(BytesRef::Flexible(&mut output), None),
OutputPolicy::Return,
params.address.clone(),
&mut tracer,
&mut vm_tracer,
));
let mut evm = vm_factory.create(&params, schedule.wasm.is_some());
let res = evm.exec(params, &mut ex);
let mut evm = vm_factory.create(params, &schedule, 0);
let res = evm.exec(&mut ex);
// a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone();
(res.finalize(ex), callcreates)
};
let output = match &res {
Ok(res) => res.return_data.to_vec(),
Err(_) => Vec::new(),
};
let log_hash = {
let mut rlp = RlpStream::new_list(substate.logs.len());
for l in &substate.logs {

View File

@ -33,7 +33,6 @@ use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction
use tx_filter::TransactionFilter;
use ethereum_types::{U256, Address};
use bytes::BytesRef;
use rlp::Rlp;
use vm::{CallType, ActionParams, ActionValue, ParamsType};
use vm::{EnvInfo, Schedule, CreateContractAddress};
@ -148,10 +147,14 @@ impl EthereumMachine {
let schedule = self.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
let mut substate = Substate::new();
let mut output = Vec::new();
if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
warn!("Encountered error on making system call: {}", e);
}
let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
let output = match res {
Ok(res) => res.return_data.to_vec(),
Err(e) => {
warn!("Encountered error on making system call: {}", e);
Vec::new()
}
};
Ok(output)
}
@ -343,7 +346,7 @@ impl EthereumMachine {
-> Result<(), transaction::Error>
{
if let Some(ref filter) = self.tx_filter.as_ref() {
if !filter.transaction_allowed(header.parent_hash(), t, client) {
if !filter.transaction_allowed(header.parent_hash(), header.number(), t, client) {
return Err(transaction::Error::NotAllowed.into())
}
}

View File

@ -43,7 +43,7 @@ use using_queue::{UsingQueue, GetAction};
use account_provider::{AccountProvider, SignError as AccountError};
use block::{ClosedBlock, IsBlock, Block, SealedBlock};
use client::{
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
};
use client::{BlockId, ClientIoMessage};
use executive::contract_address;
@ -296,6 +296,19 @@ impl Miner {
*self.io_channel.write() = Some(io_channel);
}
/// Sets in-blockchain checker for transactions.
pub fn set_in_chain_checker<C>(&self, chain: &Arc<C>) where
C: TransactionInfo + Send + Sync + 'static,
{
let client = Arc::downgrade(chain);
self.transaction_queue.set_in_chain_checker(move |hash| {
match client.upgrade() {
Some(info) => info.transaction_block(TransactionId::Hash(*hash)).is_some(),
None => false,
}
});
}
/// Clear all pending block states
pub fn clear(&self) {
self.sealing.lock().queue.reset();
@ -319,14 +332,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
@ -365,7 +379,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
@ -628,7 +642,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();
}
@ -690,7 +704,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")]
{
@ -1108,7 +1122,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

@ -125,6 +125,10 @@ pub struct CommonParams {
pub remove_dust_contracts: bool,
/// Wasm activation blocknumber, if any disabled initially.
pub wasm_activation_transition: BlockNumber,
/// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated.
pub kip4_transition: BlockNumber,
/// Number of first block where KIP-6 rules begin. Only has effect if Wasm is activated.
pub kip6_transition: BlockNumber,
/// Gas limit bound divisor (how much gas limit can change per block)
pub gas_limit_bound_divisor: U256,
/// Registrar contract address.
@ -137,6 +141,8 @@ pub struct CommonParams {
pub max_code_size_transition: BlockNumber,
/// Transaction permission managing contract address.
pub transaction_permission_contract: Option<Address>,
/// Block at which the transaction permission contract should start being used.
pub transaction_permission_contract_transition: BlockNumber,
/// Maximum size of transaction's RLP payload
pub max_transaction_size: usize,
}
@ -187,7 +193,14 @@ impl CommonParams {
};
}
if block_number >= self.wasm_activation_transition {
schedule.wasm = Some(Default::default());
let mut wasm = ::vm::WasmCosts::default();
if block_number >= self.kip4_transition {
wasm.have_create2 = true;
}
if block_number >= self.kip6_transition {
wasm.have_gasleft = true;
}
schedule.wasm = Some(wasm);
}
}
@ -290,10 +303,20 @@ impl From<ethjson::spec::Params> for CommonParams {
max_transaction_size: p.max_transaction_size.map_or(MAX_TRANSACTION_SIZE, Into::into),
max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into),
transaction_permission_contract: p.transaction_permission_contract.map(Into::into),
transaction_permission_contract_transition:
p.transaction_permission_contract_transition.map_or(0, Into::into),
wasm_activation_transition: p.wasm_activation_transition.map_or_else(
BlockNumber::max_value,
Into::into
),
kip4_transition: p.kip4_transition.map_or_else(
BlockNumber::max_value,
Into::into
),
kip6_transition: p.kip6_transition.map_or_else(
BlockNumber::max_value,
Into::into
),
}
}
}
@ -641,7 +664,7 @@ impl Spec {
let machine = self.engine.machine();
let schedule = machine.schedule(env_info.number);
let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule);
if let Err(e) = exec.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) {
if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
}
}
@ -756,6 +779,11 @@ impl Spec {
Ok(())
}
/// Return genesis state as Plain old data.
pub fn genesis_state(&self) -> &PodState {
&self.genesis_state
}
/// Returns `false` if the memoized state root is invalid. `true` otherwise.
pub fn is_state_root_valid(&self) -> bool {
// TODO: get rid of this function and ensure state root always is valid.

View File

@ -150,7 +150,7 @@ fn returns_logs() {
address: None,
topics: vec![],
limit: None,
});
}).unwrap();
assert_eq!(logs.len(), 0);
}
@ -164,7 +164,7 @@ fn returns_logs_with_limit() {
address: None,
topics: vec![],
limit: None,
});
}).unwrap();
assert_eq!(logs.len(), 0);
}

View File

@ -29,7 +29,6 @@ use transaction::SYSTEM_ADDRESS;
use rustc_hex::FromHex;
use ethereum_types::{H256, Address};
use bytes::BytesRef;
evm_test!{test_blockhash_eip210: test_blockhash_eip210_int}
fn test_blockhash_eip210(factory: Factory) {
@ -65,8 +64,7 @@ fn test_blockhash_eip210(factory: Factory) {
let schedule = machine.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
let mut substate = Substate::new();
let mut output = [];
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
if let Err(e) = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
panic!("Encountered error on updating last hashes: {}", e);
}
}
@ -89,9 +87,12 @@ fn test_blockhash_eip210(factory: Factory) {
let schedule = machine.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
let mut substate = Substate::new();
let mut output = H256::new();
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
panic!("Encountered error on getting last hash: {}", e);
}
let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
let output = match res {
Ok(res) => H256::from(&res.return_data[..32]),
Err(e) => {
panic!("Encountered error on getting last hash: {}", e);
},
};
assert_eq!(output, 255.into());
}

View File

@ -17,7 +17,6 @@
//! Simple executive tracer.
use ethereum_types::{U256, Address};
use bytes::Bytes;
use vm::ActionParams;
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType};
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
@ -92,18 +91,14 @@ impl Tracer for ExecutiveTracer {
Some(Create::from(params.clone()))
}
fn prepare_trace_output(&self) -> Option<Bytes> {
Some(vec![])
}
fn trace_call(&mut self, call: Option<Call>, gas_used: U256, output: Option<Bytes>, subs: Vec<FlatTrace>) {
fn trace_call(&mut self, call: Option<Call>, gas_used: U256, output: &[u8], subs: Vec<FlatTrace>) {
let trace = FlatTrace {
trace_address: Default::default(),
subtraces: top_level_subtraces(&subs),
action: Action::Call(call.expect("self.prepare_trace_call().is_some(): so we must be tracing: qed")),
result: Res::Call(CallResult {
gas_used: gas_used,
output: output.expect("self.prepare_trace_output().is_some(): so we must be tracing: qed")
output: output.into()
}),
};
debug!(target: "trace", "Traced call {:?}", trace);
@ -111,13 +106,13 @@ impl Tracer for ExecutiveTracer {
self.traces.extend(prefix_subtrace_addresses(subs));
}
fn trace_create(&mut self, create: Option<Create>, gas_used: U256, code: Option<Bytes>, address: Address, subs: Vec<FlatTrace>) {
fn trace_create(&mut self, create: Option<Create>, gas_used: U256, code: &[u8], address: Address, subs: Vec<FlatTrace>) {
let trace = FlatTrace {
subtraces: top_level_subtraces(&subs),
action: Action::Create(create.expect("self.prepare_trace_create().is_some(): so we must be tracing: qed")),
result: Res::Create(CreateResult {
gas_used: gas_used,
code: code.expect("self.prepare_trace_output.is_some(): so we must be tracing: qed"),
code: code.into(),
address: address
}),
trace_address: Default::default(),

View File

@ -38,7 +38,6 @@ pub use self::types::filter::{Filter, AddressesFilter};
use ethereum_types::{H256, U256, Address};
use kvdb::DBTransaction;
use bytes::Bytes;
use self::trace::{Call, Create};
use vm::ActionParams;
use header::BlockNumber;
@ -58,9 +57,6 @@ pub trait Tracer: Send {
/// This is called before a create has been executed.
fn prepare_trace_create(&self, params: &ActionParams) -> Option<Create>;
/// Prepare trace output. Noop tracer should return None.
fn prepare_trace_output(&self) -> Option<Bytes>;
/// Stores trace call info.
///
/// This is called after a call has completed successfully.
@ -68,7 +64,7 @@ pub trait Tracer: Send {
&mut self,
call: Option<Call>,
gas_used: U256,
output: Option<Bytes>,
output: &[u8],
subs: Vec<Self::Output>,
);
@ -79,7 +75,7 @@ pub trait Tracer: Send {
&mut self,
create: Option<Create>,
gas_used: U256,
code: Option<Bytes>,
code: &[u8],
address: Address,
subs: Vec<Self::Output>
);

View File

@ -17,7 +17,6 @@
//! Nonoperative tracer.
use ethereum_types::{U256, Address};
use bytes::Bytes;
use vm::ActionParams;
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
use trace::trace::{Call, Create, VMTrace, RewardType};
@ -36,18 +35,12 @@ impl Tracer for NoopTracer {
None
}
fn prepare_trace_output(&self) -> Option<Bytes> {
None
}
fn trace_call(&mut self, call: Option<Call>, _: U256, output: Option<Bytes>, _: Vec<FlatTrace>) {
fn trace_call(&mut self, call: Option<Call>, _: U256, _: &[u8], _: Vec<FlatTrace>) {
assert!(call.is_none(), "self.prepare_trace_call().is_none(): so we can't be tracing: qed");
assert!(output.is_none(), "self.prepare_trace_output().is_none(): so we can't be tracing: qed");
}
fn trace_create(&mut self, create: Option<Create>, _: U256, code: Option<Bytes>, _: Address, _: Vec<FlatTrace>) {
fn trace_create(&mut self, create: Option<Create>, _: U256, _: &[u8], _: Address, _: Vec<FlatTrace>) {
assert!(create.is_none(), "self.prepare_trace_create().is_none(): so we can't be tracing: qed");
assert!(code.is_none(), "self.prepare_trace_output().is_none(): so we can't be tracing: qed");
}
fn trace_failed_call(&mut self, call: Option<Call>, _: Vec<FlatTrace>, _: TraceError) {

View File

@ -23,6 +23,7 @@ use client::{BlockInfo, CallContract, BlockId};
use parking_lot::Mutex;
use spec::CommonParams;
use transaction::{Action, SignedTransaction};
use types::BlockNumber;
use hash::KECCAK_EMPTY;
use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json");
@ -44,6 +45,7 @@ pub struct TransactionFilter {
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated,
contract: transact_acl::TransactAcl,
contract_address: Address,
transition_block: BlockNumber,
permission_cache: Mutex<LruCache<(H256, Address), u32>>,
contract_version_cache: Mutex<LruCache<(H256), Option<U256>>>
}
@ -56,6 +58,7 @@ impl TransactionFilter {
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(),
contract: transact_acl::TransactAcl::default(),
contract_address: address,
transition_block: params.transaction_permission_contract_transition,
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
contract_version_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
}
@ -63,7 +66,9 @@ impl TransactionFilter {
}
/// Check if transaction is allowed at given block.
pub fn transaction_allowed<C: BlockInfo + CallContract>(&self, parent_hash: &H256, transaction: &SignedTransaction, client: &C) -> bool {
pub fn transaction_allowed<C: BlockInfo + CallContract>(&self, parent_hash: &H256, block_number: BlockNumber, transaction: &SignedTransaction, client: &C) -> bool {
if block_number < self.transition_block { return true; }
let mut permission_cache = self.permission_cache.lock();
let mut contract_version_cache = self.contract_version_cache.lock();
@ -196,33 +201,38 @@ mod test {
basic_tx_with_ether_and_to_key6.value = U256::from(123123);
let genesis = client.block_hash(BlockId::Latest).unwrap();
let block_number = 1;
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
// same tx but request is allowed because the contract only enables at block #1
assert!(filter.transaction_allowed(&genesis, 0, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key3.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key7.clone().sign(key5.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key6.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key7.clone().sign(key6.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx_to_key6.clone().sign(key7.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key5.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key6.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key6.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx_to_key6.clone().sign(key7.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
}
/// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a
@ -254,21 +264,26 @@ mod test {
call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005"));
let genesis = client.block_hash(BlockId::Latest).unwrap();
let block_number = 1;
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
// same tx but request is allowed because the contract only enables at block #1
assert!(filter.transaction_allowed(&genesis, 0, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key4.secret(), None), &*client));
}
}

View File

@ -113,6 +113,7 @@ pub mod blocks {
}
/// An unverified block.
#[derive(PartialEq, Debug)]
pub struct Unverified {
/// Unverified block header.
pub header: Header,

View File

@ -19,7 +19,7 @@
use std::thread::{self, JoinHandle};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
use std::sync::{Condvar as SCondvar, Mutex as SMutex, Arc};
use std::sync::Arc;
use std::cmp;
use std::collections::{VecDeque, HashSet, HashMap};
use heapsize::HeapSizeOf;
@ -141,11 +141,11 @@ struct Sizes {
/// Keeps them in the same order as inserted, minus invalid items.
pub struct VerificationQueue<K: Kind> {
engine: Arc<EthEngine>,
more_to_verify: Arc<SCondvar>,
more_to_verify: Arc<Condvar>,
verification: Arc<Verification<K>>,
deleting: Arc<AtomicBool>,
ready_signal: Arc<QueueSignal>,
empty: Arc<SCondvar>,
empty: Arc<Condvar>,
processing: RwLock<HashMap<H256, U256>>, // hash to difficulty
ticks_since_adjustment: AtomicUsize,
max_queue_size: usize,
@ -202,8 +202,6 @@ struct Verification<K: Kind> {
verifying: Mutex<VecDeque<Verifying<K>>>,
verified: Mutex<VecDeque<K::Verified>>,
bad: Mutex<HashSet<H256>>,
more_to_verify: SMutex<()>,
empty: SMutex<()>,
sizes: Sizes,
check_seal: bool,
}
@ -216,8 +214,6 @@ impl<K: Kind> VerificationQueue<K> {
verifying: Mutex::new(VecDeque::new()),
verified: Mutex::new(VecDeque::new()),
bad: Mutex::new(HashSet::new()),
more_to_verify: SMutex::new(()),
empty: SMutex::new(()),
sizes: Sizes {
unverified: AtomicUsize::new(0),
verifying: AtomicUsize::new(0),
@ -225,14 +221,14 @@ impl<K: Kind> VerificationQueue<K> {
},
check_seal: check_seal,
});
let more_to_verify = Arc::new(SCondvar::new());
let more_to_verify = Arc::new(Condvar::new());
let deleting = Arc::new(AtomicBool::new(false));
let ready_signal = Arc::new(QueueSignal {
deleting: deleting.clone(),
signalled: AtomicBool::new(false),
message_channel: Mutex::new(message_channel),
});
let empty = Arc::new(SCondvar::new());
let empty = Arc::new(Condvar::new());
let scale_verifiers = config.verifier_settings.scale_verifiers;
let num_cpus = ::num_cpus::get();
@ -292,9 +288,9 @@ impl<K: Kind> VerificationQueue<K> {
fn verify(
verification: Arc<Verification<K>>,
engine: Arc<EthEngine>,
wait: Arc<SCondvar>,
wait: Arc<Condvar>,
ready: Arc<QueueSignal>,
empty: Arc<SCondvar>,
empty: Arc<Condvar>,
state: Arc<(Mutex<State>, Condvar)>,
id: usize,
) {
@ -319,19 +315,19 @@ impl<K: Kind> VerificationQueue<K> {
// wait for work if empty.
{
let mut more_to_verify = verification.more_to_verify.lock().unwrap();
let mut unverified = verification.unverified.lock();
if verification.unverified.lock().is_empty() && verification.verifying.lock().is_empty() {
if unverified.is_empty() && verification.verifying.lock().is_empty() {
empty.notify_all();
}
while verification.unverified.lock().is_empty() {
while unverified.is_empty() {
if let State::Exit = *state.0.lock() {
debug!(target: "verification", "verifier {} exiting", id);
return;
}
more_to_verify = wait.wait(more_to_verify).unwrap();
wait.wait(&mut unverified);
}
if let State::Exit = *state.0.lock() {
@ -450,9 +446,9 @@ impl<K: Kind> VerificationQueue<K> {
/// Wait for unverified queue to be empty
pub fn flush(&self) {
let mut lock = self.verification.empty.lock().unwrap();
while !self.verification.unverified.lock().is_empty() || !self.verification.verifying.lock().is_empty() {
lock = self.empty.wait(lock).unwrap();
let mut unverified = self.verification.unverified.lock();
while !unverified.is_empty() || !self.verification.verifying.lock().is_empty() {
self.empty.wait(&mut unverified);
}
}
@ -712,7 +708,7 @@ impl<K: Kind> Drop for VerificationQueue<K> {
// acquire this lock to force threads to reach the waiting point
// if they're in-between the exit check and the more_to_verify wait.
{
let _more = self.verification.more_to_verify.lock().unwrap();
let _unverified = self.verification.unverified.lock();
self.more_to_verify.notify_all();
}

View File

@ -376,7 +376,6 @@ mod tests {
use types::log_entry::{LogEntry, LocalizedLogEntry};
use rlp;
use triehash::ordered_trie_root;
use views::BlockView;
fn check_ok(result: Result<(), Error>) {
result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e));
@ -420,10 +419,10 @@ mod tests {
}
pub fn insert(&mut self, bytes: Bytes) {
let number = view!(BlockView, &bytes).header_view().number();
let hash = view!(BlockView, &bytes).header_view().hash();
self.blocks.insert(hash.clone(), bytes);
self.numbers.insert(number, hash.clone());
let header = Unverified::from_rlp(bytes.clone()).unwrap().header;
let hash = header.hash();
self.blocks.insert(hash, bytes);
self.numbers.insert(header.number(), hash);
}
}
@ -460,11 +459,11 @@ mod tests {
/// Get the familial details concerning a block.
fn block_details(&self, hash: &H256) -> Option<BlockDetails> {
self.blocks.get(hash).map(|bytes| {
let header = view!(BlockView, bytes).header();
let header = Unverified::from_rlp(bytes.to_vec()).unwrap().header;
BlockDetails {
number: header.number(),
total_difficulty: header.difficulty().clone(),
parent: header.parent_hash().clone(),
total_difficulty: *header.difficulty(),
parent: *header.parent_hash(),
children: Vec::new(),
is_finalized: false,
}
@ -501,9 +500,9 @@ mod tests {
}
fn family_test<BC>(bytes: &[u8], engine: &EthEngine, bc: &BC) -> Result<(), Error> where BC: BlockProvider {
let view = view!(BlockView, bytes);
let header = view.header();
let transactions: Vec<_> = view.transactions()
let block = Unverified::from_rlp(bytes.to_vec()).unwrap();
let header = block.header;
let transactions: Vec<_> = block.transactions
.into_iter()
.map(SignedTransaction::new)
.collect::<Result<_,_>>()?;
@ -520,7 +519,7 @@ mod tests {
let block = PreverifiedBlock {
header,
transactions,
uncles: view.uncles(),
uncles: block.uncles,
bytes: bytes.to_vec(),
};
@ -533,7 +532,6 @@ mod tests {
}
fn unordered_test(bytes: &[u8], engine: &EthEngine) -> Result<(), Error> {
use verification::queue::kind::blocks::Unverified;
let un = Unverified::from_rlp(bytes.to_vec())?;
verify_block_unordered(un, engine, false)?;
Ok(())

View File

@ -11,11 +11,11 @@ keccak-hash = { git = "https://github.com/paritytech/parity-common" }
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
jsonrpc-tcp-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
log = "0.3"
log = "0.4"
parking_lot = "0.6"
[dev-dependencies]
env_logger = "0.4"
env_logger = "0.5"
tokio-core = "0.1"
tokio-io = "0.1"
ethcore-logger = { path = "../../logger" }

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" }
@ -17,7 +18,7 @@ ethcore-transaction = { path = "../transaction" }
ethcore = { path = ".." }
ethereum-types = "0.3"
hashdb = { git = "https://github.com/paritytech/parity-common" }
plain_hasher = { git = "https://github.com/paritytech/parity-common" }
fastmap = { path = "../../util/fastmap" }
rlp = { git = "https://github.com/paritytech/parity-common" }
rustc-hex = "1.0"
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
@ -25,8 +26,8 @@ keccak-hasher = { path = "../../util/keccak-hasher" }
triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" }
kvdb = { git = "https://github.com/paritytech/parity-common" }
macros = { path = "../../util/macros" }
log = "0.3"
env_logger = "0.4"
log = "0.4"
env_logger = "0.5"
rand = "0.4"
heapsize = "0.4"
semver = "0.9"

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,12 +23,11 @@ use std::cmp;
use heapsize::HeapSizeOf;
use ethereum_types::H256;
use rlp::{self, Rlp};
use ethcore::header::{BlockNumber, Header as BlockHeader};
use ethcore::header::BlockNumber;
use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind};
use ethcore::error::{ImportErrorKind, BlockError};
use ethcore::verification::queue::kind::blocks::Unverified;
use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError};
use sync_io::SyncIo;
use blocks::BlockCollection;
use blocks::{BlockCollection, SyncBody, SyncHeader};
const MAX_HEADERS_TO_REQUEST: usize = 128;
const MAX_BODIES_TO_REQUEST: usize = 32;
@ -236,45 +235,39 @@ impl BlockDownloader {
let mut valid_response = item_count == 0; //empty response is valid
let mut any_known = false;
for i in 0..item_count {
let info: BlockHeader = r.val_at(i).map_err(|e| {
trace!(target: "sync", "Error decoding block header RLP: {:?}", e);
BlockDownloaderImportError::Invalid
})?;
let number = BlockNumber::from(info.number());
let info = SyncHeader::from_rlp(r.at(i)?.as_raw().to_vec())?;
let number = BlockNumber::from(info.header.number());
let hash = info.header.hash();
// Check if any of the headers matches the hash we requested
if !valid_response {
if let Some(expected) = expected_hash {
valid_response = expected == info.hash()
valid_response = expected == hash;
}
}
any_known = any_known || self.blocks.contains_head(&info.hash());
if self.blocks.contains(&info.hash()) {
trace!(target: "sync", "Skipping existing block header {} ({:?})", number, info.hash());
any_known = any_known || self.blocks.contains_head(&hash);
if self.blocks.contains(&hash) {
trace!(target: "sync", "Skipping existing block header {} ({:?})", number, hash);
continue;
}
if self.highest_block.as_ref().map_or(true, |n| number > *n) {
self.highest_block = Some(number);
}
let hash = info.hash();
let hdr = r.at(i).map_err(|e| {
trace!(target: "sync", "Error decoding block header RLP: {:?}", e);
BlockDownloaderImportError::Invalid
})?;
match io.chain().block_status(BlockId::Hash(hash.clone())) {
BlockStatus::InChain | BlockStatus::Queued => {
match self.state {
State::Blocks => trace!(target: "sync", "Header already in chain {} ({})", number, hash),
_ => trace!(target: "sync", "Header already in chain {} ({}), state = {:?}", number, hash, self.state),
}
headers.push(hdr.as_raw().to_vec());
headers.push(info);
hashes.push(hash);
},
BlockStatus::Bad => {
return Err(BlockDownloaderImportError::Invalid);
},
BlockStatus::Unknown | BlockStatus::Pending => {
headers.push(hdr.as_raw().to_vec());
headers.push(info);
hashes.push(hash);
}
}
@ -325,19 +318,15 @@ impl BlockDownloader {
let item_count = r.item_count().unwrap_or(0);
if item_count == 0 {
return Err(BlockDownloaderImportError::Useless);
}
else if self.state != State::Blocks {
} else if self.state != State::Blocks {
trace!(target: "sync", "Ignored unexpected block bodies");
}
else {
} else {
let mut bodies = Vec::with_capacity(item_count);
for i in 0..item_count {
let body = r.at(i).map_err(|e| {
trace!(target: "sync", "Error decoding block boides RLP: {:?}", e);
BlockDownloaderImportError::Invalid
})?;
bodies.push(body.as_raw().to_vec());
let body = SyncBody::from_rlp(r.at(i)?.as_raw())?;
bodies.push(body);
}
if self.blocks.insert_bodies(bodies) != item_count {
trace!(target: "sync", "Deactivating peer for giving invalid block bodies");
return Err(BlockDownloaderImportError::Invalid);
@ -483,15 +472,6 @@ impl BlockDownloader {
let block = block_and_receipts.block;
let receipts = block_and_receipts.receipts;
let block = match Unverified::from_rlp(block) {
Ok(block) => block,
Err(_) => {
debug!(target: "sync", "Bad block rlp");
bad = true;
break;
}
};
let h = block.header.hash();
let number = block.header.number();
let parent = *block.header.parent_hash();
@ -533,6 +513,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

@ -23,28 +23,86 @@ use triehash_ethereum::ordered_trie_root;
use bytes::Bytes;
use rlp::{Rlp, RlpStream, DecoderError};
use network;
use ethcore::encoded::Block;
use ethcore::views::{HeaderView, BodyView};
use ethcore::header::Header as BlockHeader;
use ethcore::verification::queue::kind::blocks::Unverified;
use transaction::UnverifiedTransaction;
known_heap_size!(0, HeaderId);
type SmallHashVec = SmallVec<[H256; 1]>;
/// Block data with optional body.
struct SyncBlock {
header: Bytes,
body: Option<Bytes>,
receipts: Option<Bytes>,
receipts_root: H256,
#[derive(PartialEq, Debug, Clone)]
pub struct SyncHeader {
pub bytes: Bytes,
pub header: BlockHeader,
}
/// Block with optional receipt
pub struct BlockAndReceipts {
/// Block data.
pub block: Bytes,
/// Block receipts RLP list.
pub receipts: Option<Bytes>,
impl HeapSizeOf for SyncHeader {
fn heap_size_of_children(&self) -> usize {
self.bytes.heap_size_of_children()
+ self.header.heap_size_of_children()
}
}
impl SyncHeader {
pub fn from_rlp(bytes: Bytes) -> Result<Self, DecoderError> {
let result = SyncHeader {
header: ::rlp::decode(&bytes)?,
bytes,
};
Ok(result)
}
}
pub struct SyncBody {
pub transactions_bytes: Bytes,
pub transactions: Vec<UnverifiedTransaction>,
pub uncles_bytes: Bytes,
pub uncles: Vec<BlockHeader>,
}
impl SyncBody {
pub fn from_rlp(bytes: &[u8]) -> Result<Self, DecoderError> {
let rlp = Rlp::new(bytes);
let transactions_rlp = rlp.at(0)?;
let uncles_rlp = rlp.at(1)?;
let result = SyncBody {
transactions_bytes: transactions_rlp.as_raw().to_vec(),
transactions: transactions_rlp.as_list()?,
uncles_bytes: uncles_rlp.as_raw().to_vec(),
uncles: uncles_rlp.as_list()?,
};
Ok(result)
}
fn empty_body() -> Self {
SyncBody {
transactions_bytes: ::rlp::EMPTY_LIST_RLP.to_vec(),
transactions: Vec::with_capacity(0),
uncles_bytes: ::rlp::EMPTY_LIST_RLP.to_vec(),
uncles: Vec::with_capacity(0),
}
}
}
impl HeapSizeOf for SyncBody {
fn heap_size_of_children(&self) -> usize {
self.transactions_bytes.heap_size_of_children()
+ self.transactions.heap_size_of_children()
+ self.uncles_bytes.heap_size_of_children()
+ self.uncles.heap_size_of_children()
}
}
/// Block data with optional body.
struct SyncBlock {
header: SyncHeader,
body: Option<SyncBody>,
receipts: Option<Bytes>,
receipts_root: H256,
}
impl HeapSizeOf for SyncBlock {
@ -53,6 +111,29 @@ impl HeapSizeOf for SyncBlock {
}
}
fn unverified_from_sync(header: SyncHeader, body: Option<SyncBody>) -> Unverified {
let mut stream = RlpStream::new_list(3);
stream.append_raw(&header.bytes, 1);
let body = body.unwrap_or_else(SyncBody::empty_body);
stream.append_raw(&body.transactions_bytes, 1);
stream.append_raw(&body.uncles_bytes, 1);
Unverified {
header: header.header,
transactions: body.transactions,
uncles: body.uncles,
bytes: stream.out().to_vec(),
}
}
/// Block with optional receipt
pub struct BlockAndReceipts {
/// Block data.
pub block: Unverified,
/// Block receipts RLP list.
pub receipts: Option<Bytes>,
}
/// Used to identify header by transactions and uncles hashes
#[derive(Eq, PartialEq, Hash)]
struct HeaderId {
@ -124,7 +205,7 @@ impl BlockCollection {
}
/// Insert a set of headers into collection and advance subchain head pointers.
pub fn insert_headers(&mut self, headers: Vec<Bytes>) {
pub fn insert_headers(&mut self, headers: Vec<SyncHeader>) {
for h in headers {
if let Err(e) = self.insert_header(h) {
trace!(target: "sync", "Ignored invalid header: {:?}", e);
@ -134,7 +215,7 @@ impl BlockCollection {
}
/// Insert a collection of block bodies for previously downloaded headers.
pub fn insert_bodies(&mut self, bodies: Vec<Bytes>) -> usize {
pub fn insert_bodies(&mut self, bodies: Vec<SyncBody>) -> usize {
let mut inserted = 0;
for b in bodies {
if let Err(e) = self.insert_body(b) {
@ -278,30 +359,33 @@ impl BlockCollection {
while let Some(h) = head {
head = self.parents.get(&h).cloned();
if let Some(head) = head {
match self.blocks.get(&head) {
Some(block) if block.body.is_some() && (!self.need_receipts || block.receipts.is_some()) => {
blocks.push(block);
hashes.push(head);
self.head = Some(head);
}
_ => break,
match self.blocks.remove(&head) {
Some(block) => {
if block.body.is_some() && (!self.need_receipts || block.receipts.is_some()) {
blocks.push(block);
hashes.push(head);
self.head = Some(head);
} else {
self.blocks.insert(head, block);
break;
}
},
_ => {
break;
},
}
}
}
for block in blocks {
let body = view!(BodyView, block.body.as_ref().expect("blocks contains only full blocks; qed"));
let header = view!(HeaderView, &block.header);
let block_view = Block::new_from_header_and_body(&header, &body);
for block in blocks.into_iter() {
let unverified = unverified_from_sync(block.header, block.body);
drained.push(BlockAndReceipts {
block: block_view.into_inner(),
block: unverified,
receipts: block.receipts.clone(),
});
}
}
for h in hashes {
self.blocks.remove(&h);
}
trace!(target: "sync", "Drained {} blocks, new head :{:?}", drained.len(), self.head);
drained
}
@ -337,26 +421,23 @@ impl BlockCollection {
self.downloading_headers.contains(hash) || self.downloading_bodies.contains(hash)
}
fn insert_body(&mut self, b: Bytes) -> Result<(), network::Error> {
fn insert_body(&mut self, body: SyncBody) -> Result<(), network::Error> {
let header_id = {
let body = Rlp::new(&b);
let tx = body.at(0)?;
let tx_root = ordered_trie_root(tx.iter().map(|r| r.as_raw()));
let uncles = keccak(body.at(1)?.as_raw());
let tx_root = ordered_trie_root(Rlp::new(&body.transactions_bytes).iter().map(|r| r.as_raw()));
let uncles = keccak(&body.uncles_bytes);
HeaderId {
transactions_root: tx_root,
uncles: uncles
}
};
match self.header_ids.get(&header_id).cloned() {
match self.header_ids.remove(&header_id) {
Some(h) => {
self.header_ids.remove(&header_id);
self.downloading_bodies.remove(&h);
match self.blocks.get_mut(&h) {
Some(ref mut block) => {
trace!(target: "sync", "Got body {}", h);
block.body = Some(b);
block.body = Some(body);
Ok(())
},
None => {
@ -401,54 +482,63 @@ impl BlockCollection {
}
}
fn insert_header(&mut self, header: Bytes) -> Result<H256, DecoderError> {
let info: BlockHeader = Rlp::new(&header).as_val()?;
let hash = info.hash();
fn insert_header(&mut self, info: SyncHeader) -> Result<H256, DecoderError> {
let hash = info.header.hash();
if self.blocks.contains_key(&hash) {
return Ok(hash);
}
match self.head {
None if hash == self.heads[0] => {
trace!(target: "sync", "New head {}", hash);
self.head = Some(info.parent_hash().clone());
self.head = Some(info.header.parent_hash().clone());
},
_ => ()
}
let mut block = SyncBlock {
header: header,
body: None,
receipts: None,
receipts_root: H256::new(),
};
let header_id = HeaderId {
transactions_root: info.transactions_root().clone(),
uncles: info.uncles_hash().clone(),
transactions_root: *info.header.transactions_root(),
uncles: *info.header.uncles_hash(),
};
if header_id.transactions_root == KECCAK_NULL_RLP && header_id.uncles == KECCAK_EMPTY_LIST_RLP {
let body = if header_id.transactions_root == KECCAK_NULL_RLP && header_id.uncles == KECCAK_EMPTY_LIST_RLP {
// empty body, just mark as downloaded
let mut body_stream = RlpStream::new_list(2);
body_stream.append_raw(&::rlp::EMPTY_LIST_RLP, 1);
body_stream.append_raw(&::rlp::EMPTY_LIST_RLP, 1);
block.body = Some(body_stream.out());
}
else {
trace!("Queueing body tx_root = {:?}, uncles = {:?}, block = {:?}, number = {}", header_id.transactions_root, header_id.uncles, hash, info.number());
self.header_ids.insert(header_id, hash.clone());
}
if self.need_receipts {
let receipt_root = info.receipts_root().clone();
Some(SyncBody::empty_body())
} else {
trace!(
"Queueing body tx_root = {:?}, uncles = {:?}, block = {:?}, number = {}",
header_id.transactions_root,
header_id.uncles,
hash,
info.header.number()
);
self.header_ids.insert(header_id, hash);
None
};
let (receipts, receipts_root) = if self.need_receipts {
let receipt_root = *info.header.receipts_root();
if receipt_root == KECCAK_NULL_RLP {
let receipts_stream = RlpStream::new_list(0);
block.receipts = Some(receipts_stream.out());
(Some(receipts_stream.out()), receipt_root)
} else {
self.receipt_ids.entry(receipt_root).or_insert_with(|| SmallHashVec::new()).push(hash.clone());
self.receipt_ids.entry(receipt_root).or_insert_with(|| SmallHashVec::new()).push(hash);
(None, receipt_root)
}
block.receipts_root = receipt_root;
}
} else {
(None, H256::new())
};
self.parents.insert(info.parent_hash().clone(), hash.clone());
self.blocks.insert(hash.clone(), block);
self.parents.insert(*info.header.parent_hash(), hash);
let block = SyncBlock {
header: info,
body,
receipts,
receipts_root,
};
self.blocks.insert(hash, block);
trace!(target: "sync", "New header: {:x}", hash);
Ok(hash)
}
@ -485,10 +575,10 @@ impl BlockCollection {
#[cfg(test)]
mod test {
use super::BlockCollection;
use super::{BlockCollection, SyncHeader};
use ethcore::client::{TestBlockChainClient, EachBlockWith, BlockId, BlockChainClient};
use ethcore::views::HeaderView;
use ethcore::header::BlockNumber;
use ethcore::verification::queue::kind::blocks::Unverified;
use rlp::*;
fn is_empty(bc: &BlockCollection) -> bool {
@ -524,9 +614,9 @@ mod test {
let blocks: Vec<_> = (0..nblocks)
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).unwrap().into_inner())
.collect();
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect();
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(*h) } else { None }).collect();
bc.reset_to(heads);
assert!(!bc.is_empty());
assert_eq!(hashes[0], bc.heads[0]);
@ -541,7 +631,7 @@ mod test {
assert_eq!(bc.downloading_headers.len(), 1);
assert!(bc.drain().is_empty());
bc.insert_headers(headers[0..6].to_vec());
bc.insert_headers(headers[0..6].into_iter().map(Clone::clone).collect());
assert_eq!(hashes[5], bc.heads[0]);
for h in &hashes[0..6] {
bc.clear_header_download(h)
@ -550,7 +640,10 @@ mod test {
assert!(!bc.is_downloading(&hashes[0]));
assert!(bc.contains(&hashes[0]));
assert_eq!(&bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>()[..], &blocks[0..6]);
assert_eq!(
bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>(),
blocks[0..6].iter().map(|b| Unverified::from_rlp(b.to_vec()).unwrap()).collect::<Vec<_>>()
);
assert!(!bc.contains(&hashes[0]));
assert_eq!(hashes[5], bc.head.unwrap());
@ -558,13 +651,17 @@ mod test {
assert_eq!(hashes[5], h);
let (h, _) = bc.needed_headers(6, false).unwrap();
assert_eq!(hashes[20], h);
bc.insert_headers(headers[10..16].to_vec());
bc.insert_headers(headers[10..16].into_iter().map(Clone::clone).collect());
assert!(bc.drain().is_empty());
bc.insert_headers(headers[5..10].to_vec());
assert_eq!(&bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>()[..], &blocks[6..16]);
bc.insert_headers(headers[5..10].into_iter().map(Clone::clone).collect());
assert_eq!(
bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>(),
blocks[6..16].iter().map(|b| Unverified::from_rlp(b.to_vec()).unwrap()).collect::<Vec<_>>()
);
assert_eq!(hashes[15], bc.heads[0]);
bc.insert_headers(headers[15..].to_vec());
bc.insert_headers(headers[15..].into_iter().map(Clone::clone).collect());
bc.drain();
assert!(bc.is_empty());
}
@ -579,16 +676,16 @@ mod test {
let blocks: Vec<_> = (0..nblocks)
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).unwrap().into_inner())
.collect();
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect();
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(*h) } else { None }).collect();
bc.reset_to(heads);
bc.insert_headers(headers[2..22].to_vec());
bc.insert_headers(headers[2..22].into_iter().map(Clone::clone).collect());
assert_eq!(hashes[0], bc.heads[0]);
assert_eq!(hashes[21], bc.heads[1]);
assert!(bc.head.is_none());
bc.insert_headers(headers[0..2].to_vec());
bc.insert_headers(headers[0..2].into_iter().map(Clone::clone).collect());
assert!(bc.head.is_some());
assert_eq!(hashes[21], bc.heads[0]);
}
@ -603,14 +700,14 @@ mod test {
let blocks: Vec<_> = (0..nblocks)
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).unwrap().into_inner())
.collect();
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect();
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(*h) } else { None }).collect();
bc.reset_to(heads);
bc.insert_headers(headers[1..2].to_vec());
bc.insert_headers(headers[1..2].into_iter().map(Clone::clone).collect());
assert!(bc.drain().is_empty());
bc.insert_headers(headers[0..1].to_vec());
bc.insert_headers(headers[0..1].into_iter().map(Clone::clone).collect());
assert_eq!(bc.drain().len(), 2);
}
}

View File

@ -99,7 +99,7 @@ use std::time::{Duration, Instant};
use hash::keccak;
use heapsize::HeapSizeOf;
use ethereum_types::{H256, U256};
use plain_hasher::H256FastMap;
use fastmap::H256FastMap;
use parking_lot::RwLock;
use bytes::Bytes;
use rlp::{Rlp, RlpStream, DecoderError};
@ -148,7 +148,8 @@ const MAX_PEER_LAG_PROPAGATION: BlockNumber = 20;
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;
// keep it under 8MB as well, cause it seems that it may result oversized after compression.
const MAX_TRANSACTION_PACKET_SIZE: usize = 5 * 1024 * 1024;
// Min number of blocks to be behind for a snapshot sync
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
const SNAPSHOT_MIN_PEERS: usize = 3;

View File

@ -237,8 +237,9 @@ impl SyncPropagator {
let lucky_peers_len = lucky_peers.len();
for (peer_id, sent, rlp) in lucky_peers {
peers.insert(peer_id);
let size = rlp.len();
SyncPropagator::send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp);
trace!(target: "sync", "{:02} <- Transactions ({} entries)", peer_id, sent);
trace!(target: "sync", "{:02} <- Transactions ({} entries; {} bytes)", peer_id, sent, size);
max_sent = cmp::max(max_sent, sent);
}
debug!(target: "sync", "Sent up to {} transactions to {} peers.", max_sent, lucky_peers_len);

View File

@ -307,11 +307,11 @@ mod test {
use bytes::Bytes;
use rlp::{Rlp, RlpStream};
use super::{*, super::tests::*};
use blocks::SyncHeader;
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient};
#[test]
fn return_block_headers() {
use ethcore::views::HeaderView;
fn make_hash_req(h: &H256, count: usize, skip: usize, reverse: bool) -> Bytes {
let mut rlp = RlpStream::new_list(4);
rlp.append(h);
@ -329,16 +329,16 @@ mod test {
rlp.append(&if reverse {1u32} else {0u32});
rlp.out()
}
fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<Bytes> {
Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| r.as_raw().to_vec()).collect()
fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<SyncHeader> {
Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| SyncHeader::from_rlp(r.as_raw().to_vec()).unwrap()).collect()
}
let mut client = TestBlockChainClient::new();
client.add_blocks(100, EachBlockWith::Nothing);
let blocks: Vec<_> = (0 .. 100)
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).map(|b| b.into_inner()).unwrap()).collect();
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let queue = RwLock::new(VecDeque::new());
let ss = TestSnapshotService::new();

View File

@ -21,17 +21,17 @@
//! 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;
extern crate ethcore_io as io;
extern crate ethcore_transaction as transaction;
#[macro_use]
extern crate ethcore;
extern crate ethereum_types;
extern crate env_logger;
extern crate hashdb;
extern crate plain_hasher;
extern crate fastmap;
extern crate rand;
extern crate semver;
extern crate parking_lot;

View File

@ -22,7 +22,7 @@ use {SyncConfig, WarpSync};
#[test]
fn two_peers() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(3);
net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle);
net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle);
@ -33,7 +33,7 @@ fn two_peers() {
#[test]
fn long_chain() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(2);
net.peer(1).chain.add_blocks(50000, EachBlockWith::Nothing);
net.sync();
@ -43,7 +43,7 @@ fn long_chain() {
#[test]
fn status_after_sync() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(3);
net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle);
net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle);
@ -63,7 +63,7 @@ fn takes_few_steps() {
#[test]
fn empty_blocks() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(3);
for n in 0..200 {
let with = if n % 2 == 0 { EachBlockWith::Nothing } else { EachBlockWith::Uncle };
@ -77,7 +77,7 @@ fn empty_blocks() {
#[test]
fn forked() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(3);
net.peer(0).chain.add_blocks(30, EachBlockWith::Uncle);
net.peer(1).chain.add_blocks(30, EachBlockWith::Uncle);
@ -98,7 +98,7 @@ fn forked() {
#[test]
fn forked_with_misbehaving_peer() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(3);
let mut alt_spec = ::ethcore::spec::Spec::new_test();
@ -122,7 +122,7 @@ fn forked_with_misbehaving_peer() {
#[test]
fn net_hard_fork() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let ref_client = TestBlockChainClient::new();
ref_client.add_blocks(50, EachBlockWith::Uncle);
{
@ -141,7 +141,7 @@ fn net_hard_fork() {
#[test]
fn restart() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(3);
net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle);
net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle);
@ -255,7 +255,7 @@ fn high_td_attach() {
#[test]
fn disconnect_on_unrelated_chain() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut net = TestNet::new(2);
net.peer(0).chain.set_history(Some(20));
net.peer(1).chain.set_history(Some(20));

View File

@ -141,7 +141,7 @@ impl SnapshotService for TestSnapshotService {
#[test]
fn snapshot_sync() {
::env_logger::init().ok();
::env_logger::try_init().ok();
let mut config = SyncConfig::default();
config.warp_sync = WarpSync::Enabled;
let mut net = TestNet::new_with_config(5, config);

View File

@ -17,7 +17,7 @@
use api::TransactionStats;
use std::collections::{HashSet, HashMap};
use ethereum_types::{H256, H512};
use plain_hasher::H256FastMap;
use fastmap::H256FastMap;
type NodeId = H512;
type BlockNumber = u64;

View File

@ -9,7 +9,7 @@ parity-bytes = { git = "https://github.com/paritytech/parity-common" }
ethereum-types = "0.3"
patricia-trie = { git = "https://github.com/paritytech/parity-common" }
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
log = "0.3"
log = "0.4"
common-types = { path = "../types" }
ethjson = { path = "../../json" }
rlp = { git = "https://github.com/paritytech/parity-common" }

View File

@ -51,7 +51,7 @@ pub enum MessageCallResult {
}
/// Specifies how an address is calculated for a new contract.
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum CreateContractAddress {
/// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis)
FromSenderAndNonce,
@ -101,7 +101,6 @@ pub trait Ext {
value: Option<U256>,
data: &[u8],
code_address: &Address,
output: &mut [u8],
call_type: CallType
) -> MessageCallResult;

View File

@ -48,5 +48,5 @@ pub trait Vm {
/// This function should be used to execute transaction.
/// It returns either an error, a known amount of gas left, or parameters to be used
/// to compute the final gas left.
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
fn exec(&mut self, ext: &mut Ext) -> Result<GasLeft>;
}

View File

@ -149,6 +149,10 @@ pub struct WasmCosts {
pub opcodes_mul: u32,
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
pub opcodes_div: u32,
/// Whether create2 extern function is activated.
pub have_create2: bool,
/// Whether gasleft extern function is activated.
pub have_gasleft: bool,
}
impl Default for WasmCosts {
@ -166,6 +170,8 @@ impl Default for WasmCosts {
max_stack_height: 64*1024,
opcodes_mul: 3,
opcodes_div: 8,
have_create2: false,
have_gasleft: false,
}
}
}

View File

@ -39,6 +39,7 @@ pub enum FakeCallType {
#[derive(PartialEq, Eq, Hash, Debug)]
pub struct FakeCall {
pub call_type: FakeCallType,
pub create_scheme: Option<CreateContractAddress>,
pub gas: U256,
pub sender_address: Option<Address>,
pub receive_address: Option<Address>,
@ -133,9 +134,10 @@ impl Ext for FakeExt {
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
}
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Create,
create_scheme: Some(address),
gas: *gas,
sender_address: None,
receive_address: None,
@ -153,12 +155,12 @@ impl Ext for FakeExt {
value: Option<U256>,
data: &[u8],
code_address: &Address,
_output: &mut [u8],
_call_type: CallType
) -> MessageCallResult {
self.calls.insert(FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: *gas,
sender_address: Some(sender_address.clone()),
receive_address: Some(receive_address.clone()),

View File

@ -6,7 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
byteorder = "1.0"
ethereum-types = "0.3"
log = "0.3"
log = "0.4"
parity-wasm = "0.31"
libc = "0.2"
pwasm-utils = "0.2.2"

View File

@ -31,8 +31,8 @@ fn load_code<P: AsRef<path::Path>>(p: P) -> io::Result<Vec<u8>> {
Ok(result)
}
fn wasm_interpreter() -> WasmInterpreter {
WasmInterpreter
fn wasm_interpreter(params: ActionParams) -> WasmInterpreter {
WasmInterpreter::new(params)
}
#[derive(Debug)]
@ -131,7 +131,7 @@ pub fn construct(
params.params_type = ParamsType::Separate;
Ok(
match wasm_interpreter().exec(params, ext)? {
match wasm_interpreter(params).exec(ext)? {
GasLeft::Known(_) => Vec::new(),
GasLeft::NeedsReturn { data, .. } => data.to_vec(),
}
@ -192,9 +192,9 @@ pub fn run_fixture(fixture: &Fixture) -> Vec<Fail> {
}
}
let mut interpreter = wasm_interpreter();
let mut interpreter = wasm_interpreter(params);
let interpreter_return = match interpreter.exec(params, &mut ext) {
let interpreter_return = match interpreter.exec(&mut ext) {
Ok(ret) => ret,
Err(e) => { return Fail::runtime(e); }
};

View File

@ -17,6 +17,7 @@
//! Env module glue for wasmi interpreter
use std::cell::RefCell;
use vm::WasmCosts;
use wasmi::{
self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor,
MemoryRef, MemoryInstance, memory_units,
@ -47,6 +48,8 @@ pub mod ids {
pub const SENDER_FUNC: usize = 190;
pub const ORIGIN_FUNC: usize = 200;
pub const ELOG_FUNC: usize = 210;
pub const CREATE2_FUNC: usize = 220;
pub const GASLEFT_FUNC: usize = 230;
pub const PANIC_FUNC: usize = 1000;
pub const DEBUG_FUNC: usize = 1010;
@ -125,6 +128,11 @@ pub mod signatures {
Some(I32),
);
pub const CREATE2: StaticSignature = StaticSignature(
&[I32, I32, I32, I32, I32],
Some(I32),
);
pub const SUICIDE: StaticSignature = StaticSignature(
&[I32],
None,
@ -150,6 +158,11 @@ pub mod signatures {
None,
);
pub const GASLEFT: StaticSignature = StaticSignature(
&[],
Some(I64),
);
pub const GASLIMIT: StaticSignature = StaticSignature(
&[I32],
None,
@ -195,18 +208,23 @@ fn host(signature: signatures::StaticSignature, idx: usize) -> FuncRef {
/// Maps all functions that runtime support to the corresponding contract import
/// entries.
/// Also manages initial memory request from the runtime.
#[derive(Default)]
pub struct ImportResolver {
max_memory: u32,
memory: RefCell<Option<MemoryRef>>,
have_create2: bool,
have_gasleft: bool,
}
impl ImportResolver {
/// New import resolver with specifed maximum amount of inital memory (in wasm pages = 64kb)
pub fn with_limit(max_memory: u32) -> ImportResolver {
pub fn with_limit(max_memory: u32, schedule: &WasmCosts) -> ImportResolver {
ImportResolver {
max_memory: max_memory,
memory: RefCell::new(None),
have_create2: schedule.have_create2,
have_gasleft: schedule.have_gasleft,
}
}
@ -263,6 +281,8 @@ impl wasmi::ModuleImportResolver for ImportResolver {
"sender" => host(signatures::SENDER, ids::SENDER_FUNC),
"origin" => host(signatures::ORIGIN, ids::ORIGIN_FUNC),
"elog" => host(signatures::ELOG, ids::ELOG_FUNC),
"create2" if self.have_create2 => host(signatures::CREATE2, ids::CREATE2_FUNC),
"gasleft" if self.have_gasleft => host(signatures::GASLEFT, ids::GASLEFT_FUNC),
_ => {
return Err(wasmi::Error::Instantiation(
format!("Export {} not found", field_name),

View File

@ -69,7 +69,15 @@ impl From<Error> for vm::Error {
}
/// Wasm interpreter instance
pub struct WasmInterpreter;
pub struct WasmInterpreter {
params: ActionParams,
}
impl WasmInterpreter {
pub fn new(params: ActionParams) -> Self {
WasmInterpreter { params }
}
}
impl From<runtime::Error> for vm::Error {
fn from(e: runtime::Error) -> Self {
@ -85,19 +93,19 @@ enum ExecutionOutcome {
impl vm::Vm for WasmInterpreter {
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
let (module, data) = parser::payload(&params, ext.schedule().wasm())?;
fn exec(&mut self, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
let (module, data) = parser::payload(&self.params, ext.schedule().wasm())?;
let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?;
let instantiation_resolver = env::ImportResolver::with_limit(16);
let instantiation_resolver = env::ImportResolver::with_limit(16, ext.schedule().wasm());
let module_instance = wasmi::ModuleInstance::new(
&loaded_module,
&wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolver)
).map_err(Error::Interpreter)?;
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
let adjusted_gas = self.params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
U256::from(ext.schedule().wasm().opcodes_mul);
if adjusted_gas > ::std::u64::MAX.into()
@ -116,11 +124,11 @@ impl vm::Vm for WasmInterpreter {
adjusted_gas.low_u64(),
data.to_vec(),
RuntimeContext {
address: params.address,
sender: params.sender,
origin: params.origin,
code_address: params.code_address,
value: params.value.value(),
address: self.params.address,
sender: self.params.sender,
origin: self.params.origin,
code_address: self.params.code_address,
value: self.params.value.value(),
},
);

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::cmp;
use ethereum_types::{U256, H256, Address};
use vm::{self, CallType};
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind};
@ -321,7 +322,7 @@ impl<'a> Runtime<'a> {
if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); }
Ok(self.gas_limit - self.gas_counter)
}
/// General gas charging extern.
fn gas(&mut self, args: RuntimeArgs) -> Result<()> {
let amount: u32 = args.nth_checked(0)?;
@ -447,12 +448,14 @@ impl<'a> Runtime<'a> {
val,
&payload,
&address,
&mut result[..],
call_type,
);
match call_result {
vm::MessageCallResult::Success(gas_left, _) => {
vm::MessageCallResult::Success(gas_left, data) => {
let len = cmp::min(result.len(), data.len());
(&mut result[..len]).copy_from_slice(&data[..len]);
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
@ -461,7 +464,10 @@ impl<'a> Runtime<'a> {
self.memory.set(result_ptr, &result)?;
Ok(0i32.into())
},
vm::MessageCallResult::Reverted(gas_left, _) => {
vm::MessageCallResult::Reverted(gas_left, data) => {
let len = cmp::min(result.len(), data.len());
(&mut result[..len]).copy_from_slice(&data[..len]);
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
@ -511,29 +517,7 @@ impl<'a> Runtime<'a> {
self.return_u256_ptr(args.nth_checked(0)?, val)
}
/// Creates a new contract
///
/// Arguments:
/// * endowment - how much value (in Wei) transfer to the newly created contract
/// * code_ptr - pointer to the code data
/// * code_len - lenght of the code data
/// * result_ptr - pointer to write an address of the newly created contract
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue>
{
//
// method signature:
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
//
trace!(target: "wasm", "runtime: CREATE");
let endowment = self.u256_at(args.nth_checked(0)?)?;
trace!(target: "wasm", " val: {:?}", endowment);
let code_ptr: u32 = args.nth_checked(1)?;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let code_len: u32 = args.nth_checked(2)?;
trace!(target: "wasm", " code_len: {:?}", code_len);
let result_ptr: u32 = args.nth_checked(3)?;
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result<RuntimeValue> {
let code = self.memory.get(code_ptr, code_len as usize)?;
self.adjusted_charge(|schedule| schedule.create_gas as u64)?;
@ -543,7 +527,7 @@ impl<'a> Runtime<'a> {
* U256::from(self.ext.schedule().wasm().opcodes_mul)
/ U256::from(self.ext.schedule().wasm().opcodes_div);
match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
match self.ext.create(&gas_left, &endowment, &code, scheme) {
vm::ContractCreateResult::Created(address, gas_left) => {
self.memory.set(result_ptr, &*address)?;
self.gas_counter = self.gas_limit -
@ -571,6 +555,59 @@ impl<'a> Runtime<'a> {
}
}
/// Creates a new contract
///
/// Arguments:
/// * endowment - how much value (in Wei) transfer to the newly created contract
/// * code_ptr - pointer to the code data
/// * code_len - lenght of the code data
/// * result_ptr - pointer to write an address of the newly created contract
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
//
// method signature:
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
//
trace!(target: "wasm", "runtime: CREATE");
let endowment = self.u256_at(args.nth_checked(0)?)?;
trace!(target: "wasm", " val: {:?}", endowment);
let code_ptr: u32 = args.nth_checked(1)?;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let code_len: u32 = args.nth_checked(2)?;
trace!(target: "wasm", " code_len: {:?}", code_len);
let result_ptr: u32 = args.nth_checked(3)?;
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderAndCodeHash)
}
/// Creates a new contract using FromSenderSaltAndCodeHash scheme
///
/// Arguments:
/// * endowment - how much value (in Wei) transfer to the newly created contract
/// * salt - salt to be used in contract creation address
/// * code_ptr - pointer to the code data
/// * code_len - lenght of the code data
/// * result_ptr - pointer to write an address of the newly created contract
pub fn create2(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
//
// method signature:
// fn create2(endowment: *const u8, salt: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
//
trace!(target: "wasm", "runtime: CREATE2");
let endowment = self.u256_at(args.nth_checked(0)?)?;
trace!(target: "wasm", " val: {:?}", endowment);
let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into();
trace!(target: "wasm", " salt: {:?}", salt);
let code_ptr: u32 = args.nth_checked(2)?;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let code_len: u32 = args.nth_checked(3)?;
trace!(target: "wasm", " code_len: {:?}", code_len);
let result_ptr: u32 = args.nth_checked(4)?;
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderSaltAndCodeHash(salt))
}
fn debug(&mut self, args: RuntimeArgs) -> Result<()>
{
trace!(target: "wasm", "Contract debug message: {}", {
@ -629,6 +666,15 @@ impl<'a> Runtime<'a> {
self.return_u256_ptr(args.nth_checked(0)?, difficulty)
}
/// Signature: `fn gasleft() -> i64`
pub fn gasleft(&mut self) -> Result<RuntimeValue> {
Ok(RuntimeValue::from(
self.gas_left()? * self.ext.schedule().wasm().opcodes_mul as u64
/ self.ext.schedule().wasm().opcodes_div as u64
)
)
}
/// Signature: `fn gaslimit(dest: *mut u8)`
pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> {
let gas_limit = self.ext.env_info().gas_limit;
@ -744,6 +790,8 @@ mod ext_impl {
SENDER_FUNC => void!(self.sender(args)),
ORIGIN_FUNC => void!(self.origin(args)),
ELOG_FUNC => void!(self.elog(args)),
CREATE2_FUNC => some!(self.create2(args)),
GASLEFT_FUNC => some!(self.gasleft()),
_ => panic!("env module doesn't provide function at index {}", index),
}
}

View File

@ -20,7 +20,7 @@ use byteorder::{LittleEndian, ByteOrder};
use ethereum_types::{H256, U256, Address};
use super::WasmInterpreter;
use vm::{self, Vm, GasLeft, ActionParams, ActionValue};
use vm::{self, Vm, GasLeft, ActionParams, ActionValue, CreateContractAddress};
use vm::tests::{FakeCall, FakeExt, FakeCallType};
macro_rules! load_sample {
@ -47,8 +47,8 @@ macro_rules! reqrep_test {
fake_ext.info = $info;
fake_ext.blockhashes = $block_hashes;
let mut interpreter = wasm_interpreter();
interpreter.exec(params, &mut fake_ext)
let mut interpreter = wasm_interpreter(params);
interpreter.exec(&mut fake_ext)
.map(|result| match result {
GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -65,8 +65,8 @@ fn test_finalize(res: Result<GasLeft, vm::Error>) -> Result<U256, vm::Error> {
}
}
fn wasm_interpreter() -> WasmInterpreter {
WasmInterpreter
fn wasm_interpreter(params: ActionParams) -> WasmInterpreter {
WasmInterpreter::new(params)
}
/// Empty contract does almost nothing except producing 1 (one) local node debug log message
@ -82,8 +82,8 @@ fn empty() {
let mut ext = FakeExt::new().with_wasm();
let gas_left = {
let mut interpreter = wasm_interpreter();
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(&mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(96_926));
@ -111,8 +111,8 @@ fn logger() {
let mut ext = FakeExt::new().with_wasm();
let gas_left = {
let mut interpreter = wasm_interpreter();
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(&mut ext)).unwrap()
};
let address_val: H256 = address.into();
@ -138,7 +138,7 @@ fn logger() {
U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value"
);
assert_eq!(gas_left, U256::from(16_181));
assert_eq!(gas_left, U256::from(17_716));
}
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
@ -160,8 +160,8 @@ fn identity() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Identity contract should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -173,7 +173,7 @@ fn identity() {
sender,
"Idenity test contract does not return the sender passed"
);
assert_eq!(gas_left, U256::from(96_883));
assert_eq!(gas_left, U256::from(98_419));
}
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
@ -195,8 +195,8 @@ fn dispersion() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Dispersion routine should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -207,7 +207,7 @@ fn dispersion() {
result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
);
assert_eq!(gas_left, U256::from(92_371));
assert_eq!(gas_left, U256::from(92_377));
}
#[test]
@ -223,8 +223,8 @@ fn suicide_not() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Suicidal contract should return payload when had not actualy killed himself"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -256,8 +256,8 @@ fn suicide() {
let mut ext = FakeExt::new().with_wasm();
let gas_left = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(gas) => gas,
GasLeft::NeedsReturn { .. } => {
@ -267,7 +267,7 @@ fn suicide() {
};
assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(93_348));
assert_eq!(gas_left, U256::from(93_346));
}
#[test]
@ -281,14 +281,19 @@ fn create() {
params.value = ActionValue::transfer(1_000_000_000);
let mut ext = FakeExt::new().with_wasm();
ext.schedule.wasm.as_mut().unwrap().have_create2 = true;
let gas_left = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(gas) => gas,
GasLeft::NeedsReturn { .. } => {
panic!("Create contract should not return anthing because ext always fails on creation");
GasLeft::Known(_) => {
panic!("Create contract always return 40 bytes of the creation address, or in the case where it fails, return 40 bytes of zero.");
},
GasLeft::NeedsReturn { gas_left, data, apply_state } => {
assert!(apply_state);
assert_eq!(data.as_ref(), [0u8; 40].as_ref()); // FakeExt never succeeds in create.
gas_left
},
}
};
@ -297,15 +302,28 @@ fn create() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
gas: U256::from(59_269),
create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash),
gas: U256::from(49_674),
sender_address: None,
receive_address: None,
value: Some(1_000_000_000.into()),
value: Some((1_000_000_000 / 2).into()),
data: vec![0u8, 2, 4, 8, 16, 32, 64, 128],
code_address: None,
}
));
assert_eq!(gas_left, U256::from(59_212));
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
create_scheme: Some(CreateContractAddress::FromSenderSaltAndCodeHash(H256::from([5u8].as_ref()))),
gas: U256::from(6039),
sender_address: None,
receive_address: None,
value: Some((1_000_000_000 / 2).into()),
data: vec![0u8, 2, 4, 8, 16, 32, 64, 128],
code_address: None,
}
));
assert_eq!(gas_left, U256::from(5974));
}
#[test]
@ -328,8 +346,8 @@ fn call_msg() {
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
let gas_left = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(gas_left) => gas_left,
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
@ -340,6 +358,7 @@ fn call_msg() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(33_000),
sender_address: Some(receiver),
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
@ -352,6 +371,54 @@ fn call_msg() {
assert_eq!(gas_left, U256::from(91_672));
}
// The same as `call_msg`, but send a `pwasm_ethereum::gasleft`
// value as `gas` argument to the inner pwasm_ethereum::call
#[test]
fn call_msg_gasleft() {
::ethcore_logger::init_log();
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
let mut params = ActionParams::default();
params.sender = sender.clone();
params.address = receiver.clone();
params.code_address = contract_address.clone();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("call_gasleft.wasm")));
params.data = Some(Vec::new());
let mut ext = FakeExt::new().with_wasm();
ext.schedule.wasm.as_mut().unwrap().have_gasleft = true;
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
let gas_left = {
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(gas_left) => gas_left,
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
}
};
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(91_165),
sender_address: Some(receiver),
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
value: Some(1000000000.into()),
data: vec![129u8, 123, 113, 107, 101, 97],
code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
}
));
assert_eq!(gas_left, U256::from(91_671));
}
#[test]
fn call_code() {
::ethcore_logger::init_log();
@ -370,8 +437,8 @@ fn call_code() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Call test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -382,6 +449,7 @@ fn call_code() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(20_000),
sender_address: Some(sender),
receive_address: Some(receiver),
@ -394,7 +462,7 @@ fn call_code() {
// siphash result
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(90_038));
assert_eq!(gas_left, U256::from(90_037));
}
#[test]
@ -417,8 +485,8 @@ fn call_static() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Static call test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -429,6 +497,7 @@ fn call_static() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(20_000),
sender_address: Some(receiver),
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
@ -442,7 +511,7 @@ fn call_static() {
let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590);
assert_eq!(gas_left, U256::from(90_043));
assert_eq!(gas_left, U256::from(90_042));
}
// Realloc test
@ -457,15 +526,15 @@ fn realloc() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("Realloc should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(92_842));
assert_eq!(gas_left, U256::from(92_848));
}
#[test]
@ -479,15 +548,15 @@ fn alloc() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("alloc test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(result, vec![5u8; 1024*400]);
assert_eq!(gas_left, U256::from(6_893_883));
assert_eq!(gas_left, U256::from(6_893_881));
}
// Tests that contract's ability to read from a storage
@ -506,8 +575,8 @@ fn storage_read() {
ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into());
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("storage_read should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -515,7 +584,7 @@ fn storage_read() {
};
assert_eq!(Address::from(&result[12..32]), address);
assert_eq!(gas_left, U256::from(96_833));
assert_eq!(gas_left, U256::from(98_369));
}
// Tests keccak calculation
@ -532,8 +601,8 @@ fn keccak() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("keccak should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -541,7 +610,7 @@ fn keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_134));
assert_eq!(gas_left, U256::from(85_949));
}
// math_* tests check the ability of wasm contract to perform big integer operations
@ -570,7 +639,7 @@ fn math_add() {
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(92_086));
assert_eq!(gas_left, U256::from(92_072));
}
// multiplication
@ -592,7 +661,7 @@ fn math_mul() {
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(91_414));
assert_eq!(gas_left, U256::from(91_400));
}
// subtraction
@ -614,7 +683,7 @@ fn math_sub() {
U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(92_086));
assert_eq!(gas_left, U256::from(92_072));
}
// subtraction with overflow
@ -656,7 +725,7 @@ fn math_div() {
U256::from_dec_str("1125000").unwrap(),
(&result[..]).into()
);
assert_eq!(gas_left, U256::from(87_376));
assert_eq!(gas_left, U256::from(85_700));
}
#[test]
@ -679,12 +748,12 @@ fn storage_metering() {
]);
let gas_left = {
let mut interpreter = wasm_interpreter();
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(&mut ext)).unwrap()
};
// 0 -> not 0
assert_eq!(gas_left, U256::from(72_399));
assert_eq!(gas_left, U256::from(72_164));
// #2
@ -698,12 +767,12 @@ fn storage_metering() {
]);
let gas_left = {
let mut interpreter = wasm_interpreter();
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(&mut ext)).unwrap()
};
// not 0 -> not 0
assert_eq!(gas_left, U256::from(87_399));
assert_eq!(gas_left, U256::from(87_164));
}
// This test checks the ability of wasm contract to invoke
@ -791,7 +860,48 @@ fn externs() {
"Gas limit requested and returned does not match"
);
assert_eq!(gas_left, U256::from(90_435));
assert_eq!(gas_left, U256::from(90_428));
}
// This test checks the ability of wasm contract to invoke gasleft
#[test]
fn gasleft() {
::ethcore_logger::init_log();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("gasleft.wasm")));
let mut ext = FakeExt::new().with_wasm();
ext.schedule.wasm.as_mut().unwrap().have_gasleft = true;
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => {},
GasLeft::NeedsReturn { gas_left, data, .. } => {
let gas = LittleEndian::read_u64(data.as_ref());
assert_eq!(gas, 93_423);
assert_eq!(gas_left, U256::from(93_349));
},
}
}
// This test should fail because
// ext.schedule.wasm.as_mut().unwrap().have_gasleft = false;
#[test]
fn gasleft_fail() {
::ethcore_logger::init_log();
let mut params = ActionParams::default();
params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample!("gasleft.wasm")));
let mut ext = FakeExt::new().with_wasm();
let mut interpreter = wasm_interpreter(params);
match interpreter.exec(&mut ext) {
Err(_) => {},
Ok(_) => panic!("interpreter.exec should return Err if ext.schedule.wasm.have_gasleft = false")
}
}
#[test]
@ -808,8 +918,8 @@ fn embedded_keccak() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("keccak should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -817,7 +927,7 @@ fn embedded_keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_134));
assert_eq!(gas_left, U256::from(85_949));
}
/// This test checks the correctness of log extern
@ -836,8 +946,8 @@ fn events() {
let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = {
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result {
GasLeft::Known(_) => { panic!("events should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -852,7 +962,7 @@ fn events() {
assert_eq!(&log_entry.data, b"gnihtemos");
assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(81_351));
assert_eq!(gas_left, U256::from(83_161));
}
#[test]
@ -876,8 +986,8 @@ fn recursive() {
let mut ext = FakeExt::new().with_wasm();
let mut interpreter = wasm_interpreter();
let result = interpreter.exec(params, &mut ext);
let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(&mut ext);
// We expect that stack overflow will occur and it should be generated by
// deterministic stack metering. Exceeding deterministic stack height limit

View File

@ -10,7 +10,7 @@ parity-crypto = { git = "https://github.com/paritytech/parity-common" }
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethereum-types = "0.3"
lazy_static = "1.0"
log = "0.3"
log = "0.4"
mem = { path = "../util/mem" }
parity-wordlist = "1.2"
quick-error = "1.2.2"

View File

@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
docopt = "0.8"
env_logger = "0.4"
env_logger = "0.5"
ethkey = { path = "../" }
panic_hook = { path = "../../util/panic_hook" }
parity-wordlist="1.2"

View File

@ -162,7 +162,7 @@ impl DisplayMode {
fn main() {
panic_hook::set_abort();
env_logger::init().expect("Logger initialized only once.");
env_logger::try_init().expect("Logger initialized only once.");
match execute(env::args()) {
Ok(ok) => println!("{}", ok),

View File

@ -4,7 +4,7 @@ version = "0.2.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
log = "0.3"
log = "0.4"
libc = "0.2"
rand = "0.4"
ethkey = { path = "../ethkey" }

View File

@ -10,6 +10,7 @@ path = "./src/main.rs"
[dependencies]
docopt = "0.8"
env_logger = "0.5"
ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests"] }
ethjson = { path = "../json" }
parity-bytes = { git = "https://github.com/paritytech/parity-common" }

38
evmbin/res/testchain.json Normal file
View File

@ -0,0 +1,38 @@
{
"name": "lab",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x1",
"difficultyBoundDivisor": "0x800"
}
}
},
"accounts": {
"0000000000000000000000000000000000000020": {
"nonce": "0x0",
"balance": "0x64",
"code": "0x62aaaaaa60aa60aa5060aa60aa60aa60aa60aa60aa"
}
},
"params":{
"networkID": "0x42",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1",
"gasLimitBoundDivisor": "0x400"
},
"genesis": {
"gasLimit": "0x8000000",
"seal": {
"ethereum": {
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000042"
}
},
"difficulty": "0x400",
"extraData": "0x0",
"author": "0x3333333333333333333333333333333333333333",
"timestamp": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
}

View File

@ -167,13 +167,13 @@ impl<T: Writer> trace::VMTracer for Informant<T> {
}
#[cfg(test)]
mod tests {
pub mod tests {
use std::sync::{Arc, Mutex};
use super::*;
use info::tests::run_test;
#[derive(Debug, Clone, Default)]
struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
pub struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
impl Writer for TestWriter {
fn clone(&self) -> Self { Clone::clone(self) }
@ -189,7 +189,7 @@ mod tests {
}
}
fn informant() -> (Informant<TestWriter>, Arc<Mutex<Vec<u8>>>) {
pub fn informant() -> (Informant<TestWriter>, Arc<Mutex<Vec<u8>>>) {
let writer = TestWriter::default();
let res = writer.0.clone();
(Informant::new(writer), res)

View File

@ -68,11 +68,19 @@ pub type RunResult<T> = Result<Success<T>, Failure<T>>;
/// Execute given `ActionParams` and return the result.
pub fn run_action<T: Informant>(
spec: &spec::Spec,
params: ActionParams,
mut params: ActionParams,
mut informant: T,
) -> RunResult<T::Output> {
informant.set_gas(params.gas);
run(spec, params.gas, None, |mut client| {
// if the code is not overwritten from CLI, use code from spec file.
if params.code.is_none() {
if let Some(acc) = spec.genesis_state().get().get(&params.code_address) {
params.code = acc.code.clone().map(::std::sync::Arc::new);
params.code_hash = None;
}
}
run(spec, params.gas, spec.genesis_state(), |mut client| {
let result = client
.call(params, &mut trace::NoopTracer, &mut informant)
.map(|r| (0.into(), r.gas_left, r.return_data.to_vec()));
@ -130,24 +138,21 @@ pub fn run_transaction<T: Informant>(
}
/// Execute VM with given `ActionParams`
pub fn run<'a, F, T, X>(
pub fn run<'a, F, X>(
spec: &'a spec::Spec,
initial_gas: U256,
pre_state: T,
pre_state: &'a pod_state::PodState,
run: F,
) -> RunResult<X> where
F: FnOnce(EvmTestClient) -> (Result<(H256, U256, Vec<u8>), EvmTestError>, Option<X>),
T: Into<Option<&'a pod_state::PodState>>,
{
let test_client = match pre_state.into() {
Some(pre_state) => EvmTestClient::from_pod_state(spec, pre_state.clone()),
None => EvmTestClient::new(spec),
}.map_err(|error| Failure {
gas_used: 0.into(),
error,
time: Duration::from_secs(0),
traces: None,
})?;
let test_client = EvmTestClient::from_pod_state(spec, pre_state.clone())
.map_err(|error| Failure {
gas_used: 0.into(),
error,
time: Duration::from_secs(0),
traces: None,
})?;
let start = Instant::now();
let result = run(test_client);
@ -204,4 +209,31 @@ pub mod tests {
},
}
}
#[test]
fn should_call_account_from_spec() {
use display::std_json::tests::informant;
let (inf, res) = informant();
let mut params = ActionParams::default();
params.code_address = 0x20.into();
params.gas = 0xffff.into();
let spec = ::ethcore::ethereum::load(None, include_bytes!("../res/testchain.json"));
let _result = run_action(&spec, params, inf);
assert_eq!(
&String::from_utf8_lossy(&**res.lock().unwrap()),
r#"{"pc":0,"op":98,"opName":"PUSH3","gas":"0xffff","stack":[],"storage":{},"depth":1}
{"pc":4,"op":96,"opName":"PUSH1","gas":"0xfffc","stack":["0xaaaaaa"],"storage":{},"depth":1}
{"pc":6,"op":96,"opName":"PUSH1","gas":"0xfff9","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
{"pc":8,"op":80,"opName":"POP","gas":"0xfff6","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":9,"op":96,"opName":"PUSH1","gas":"0xfff4","stack":["0xaaaaaa","0xaa"],"storage":{},"depth":1}
{"pc":11,"op":96,"opName":"PUSH1","gas":"0xfff1","stack":["0xaaaaaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":13,"op":96,"opName":"PUSH1","gas":"0xffee","stack":["0xaaaaaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":15,"op":96,"opName":"PUSH1","gas":"0xffeb","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":17,"op":96,"opName":"PUSH1","gas":"0xffe8","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
{"pc":19,"op":96,"opName":"PUSH1","gas":"0xffe5","stack":["0xaaaaaa","0xaa","0xaa","0xaa","0xaa","0xaa","0xaa"],"storage":{},"depth":1}
"#);
}
}

View File

@ -31,6 +31,7 @@ extern crate ethereum_types;
extern crate vm;
extern crate evm;
extern crate panic_hook;
extern crate env_logger;
#[cfg(test)]
#[macro_use]
@ -92,6 +93,7 @@ General options:
fn main() {
panic_hook::set_abort();
env_logger::init();
let args: Args = Docopt::new(USAGE).and_then(|d| d.deserialize()).unwrap_or_else(|e| e.exit());

View File

@ -9,7 +9,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
futures = "0.1"
futures-cpupool = "0.1"
log = "0.3"
log = "0.4"
mime = "0.3"
mime_guess = "2.0.0-alpha.2"
rand = "0.4"

View File

@ -7,7 +7,7 @@ version = "1.12.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
log = "0.3"
log = "0.4"
parking_lot = "0.6"
protobuf = "1.4"
hidapi = { git = "https://github.com/paritytech/hidapi-rs" }

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