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

210
Cargo.lock generated
View File

@ -357,10 +357,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "dir" name = "dir"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)", "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)", "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", "journaldb 0.2.0",
] ]
@ -401,11 +402,14 @@ dependencies = [
[[package]] [[package]]
name = "env_logger" name = "env_logger"
version = "0.4.3" version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (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]] [[package]]
@ -470,8 +474,9 @@ version = "1.12.0"
dependencies = [ dependencies = [
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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)", "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-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 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)", "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)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"macros 0.1.0", "macros 0.1.0",
"memory-cache 0.1.0", "memory-cache 0.1.0",
@ -577,7 +582,7 @@ version = "1.12.0"
dependencies = [ dependencies = [
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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-network 1.12.0",
"ethcore-transaction 0.1.0", "ethcore-transaction 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)", "hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -605,20 +611,19 @@ dependencies = [
"keccak-hasher 0.1.0", "keccak-hasher 0.1.0",
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-memorydb 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", "memory-cache 0.1.0",
"memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)", "memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)", "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)", "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 0.2.1 (git+https://github.com/paritytech/parity-common)",
"patricia-trie-ethereum 0.1.0", "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)", "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 0.2.1 (git+https://github.com/paritytech/parity-common)",
"rlp_derive 0.1.0", "rlp_derive 0.1.0",
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "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_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", "stats 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash-ethereum 0.2.0", "triehash-ethereum 0.2.0",
@ -632,9 +637,9 @@ dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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)", "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)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
@ -645,7 +650,7 @@ name = "ethcore-miner"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.12.0", "ethash 1.12.0",
"ethcore-transaction 0.1.0", "ethcore-transaction 0.1.0",
@ -658,14 +663,14 @@ dependencies = [
"hyper 0.11.24 (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)", "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)", "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", "parity-reactor 0.1.0",
"parking_lot 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)",
"price-info 1.12.0", "price-info 1.12.0",
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)", "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)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"trace-time 0.1.0", "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)", "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)", "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)", "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)", "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)", "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-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-crypto 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", "fetch 0.1.0",
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-crypto 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)", "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 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-rocksdb 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)", "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-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-crypto 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)", "parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -808,7 +813,7 @@ dependencies = [
"ethcore-sync 1.12.0", "ethcore-sync 1.12.0",
"kvdb 0.1.0 (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)", "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", "stop-guard 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"trace-time 0.1.0", "trace-time 0.1.0",
@ -818,14 +823,14 @@ dependencies = [
name = "ethcore-stratum" name = "ethcore-stratum"
version = "1.12.0" version = "1.12.0"
dependencies = [ 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", "ethcore-logger 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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-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-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)", "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)", "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)", "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-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)", "tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
@ -835,7 +840,8 @@ dependencies = [
name = "ethcore-sync" name = "ethcore-sync"
version = "1.12.0" version = "1.12.0"
dependencies = [ 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 1.12.0",
"ethcore-io 1.12.0", "ethcore-io 1.12.0",
"ethcore-light 1.12.0", "ethcore-light 1.12.0",
@ -845,6 +851,7 @@ dependencies = [
"ethcore-transaction 0.1.0", "ethcore-transaction 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0", "ethkey 0.3.0",
"fastmap 0.1.0",
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)", "hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -852,16 +859,15 @@ dependencies = [
"keccak-hasher 0.1.0", "keccak-hasher 0.1.0",
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-memorydb 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", "macros 0.1.0",
"parity-bytes 0.1.0 (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)", "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)", "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 0.2.1 (git+https://github.com/paritytech/parity-common)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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", "trace-time 0.1.0",
"triehash-ethereum 0.2.0", "triehash-ethereum 0.2.0",
] ]
@ -923,7 +929,7 @@ dependencies = [
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)", "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)", "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)", "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", "mem 0.1.0",
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)", "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)", "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" version = "0.1.0"
dependencies = [ dependencies = [
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "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", "ethkey 0.3.0",
"panic_hook 0.1.0", "panic_hook 0.1.0",
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -954,12 +960,12 @@ dependencies = [
name = "ethstore" name = "ethstore"
version = "0.2.0" version = "0.2.0"
dependencies = [ dependencies = [
"dir 0.1.1", "dir 0.1.2",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethkey 0.3.0", "ethkey 0.3.0",
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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-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)", "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 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_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)", "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)", "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)", "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)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -979,7 +985,7 @@ dependencies = [
name = "ethstore-cli" name = "ethstore-cli"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"dir 0.1.1", "dir 0.1.2",
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
"ethstore 0.2.0", "ethstore 0.2.0",
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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-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)", "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", "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)", "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)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0", "vm 0.1.0",
@ -1012,6 +1019,7 @@ name = "evmbin"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "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 1.12.0",
"ethcore-transaction 0.1.0", "ethcore-transaction 0.1.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1044,6 +1052,14 @@ dependencies = [
"ethkey 0.3.0", "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]] [[package]]
name = "fdlimit" name = "fdlimit"
version = "0.1.1" version = "0.1.1"
@ -1161,7 +1177,7 @@ dependencies = [
"ethkey 0.3.0", "ethkey 0.3.0",
"hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)", "hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)",
"libusb 0.3.0 (git+https://github.com/paritytech/libusb-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)", "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)", "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)", "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)", "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]] [[package]]
name = "httparse" name = "httparse"
version = "1.2.3" version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "hyper" name = "hyper"
version = "0.11.24" version = "0.11.24"
@ -1323,17 +1356,17 @@ version = "0.2.0"
dependencies = [ dependencies = [
"ethcore-logger 1.12.0", "ethcore-logger 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "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-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"keccak-hasher 0.1.0", "keccak-hasher 0.1.0",
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-memorydb 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)", "memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
"parity-bytes 0.1.0 (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)", "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)", "rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
] ]
@ -1668,7 +1701,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"kvdb 0.1.0 (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)", "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", "macros 0.1.0",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1797,7 +1830,7 @@ dependencies = [
"ethcore-network-devp2p 1.12.0", "ethcore-network-devp2p 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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 = [ dependencies = [
"num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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" name = "parity-clib"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"panic_hook 0.1.0",
"parity-ethereum 2.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)", "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)", "ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
"daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)", "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)", "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 1.12.0",
"ethcore-io 1.12.0", "ethcore-io 1.12.0",
"ethcore-light 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)", "keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"kvdb 0.1.0 (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)", "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", "mem 0.1.0",
"migration-rocksdb 0.1.0", "migration-rocksdb 0.1.0",
"node-filter 1.12.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)", "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)", "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)", "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 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)", "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)", "parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
@ -2067,7 +2101,7 @@ dependencies = [
"ethkey 0.3.0", "ethkey 0.3.0",
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)", "kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
"kvdb-memorydb 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)", "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 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_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)", "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)", "keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
"kvdb-memorydb 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", "macros 0.1.0",
"multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "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)", "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)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0", "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-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)", "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)", "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)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.12.0", "parity-rpc 1.12.0",
"parking_lot 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)",
@ -2199,7 +2233,7 @@ dependencies = [
"ethereum-types 0.3.2 (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)", "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)", "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)", "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-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
"parity-hash-fetch 1.12.0", "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-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-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)", "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", "mem 0.1.0",
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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_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)", "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)", "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)", "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)", "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)", "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)", "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)", "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)", "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 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)", "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)", "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)", "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)", "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)", "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-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)", "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]] [[package]]
@ -2562,7 +2596,7 @@ dependencies = [
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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]] [[package]]
@ -2590,11 +2624,31 @@ dependencies = [
"utf8-ranges 1.0.0 (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"
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]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.4.1" version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "registrar" name = "registrar"
version = "0.0.1" version = "0.0.1"
@ -2887,7 +2941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "0.4.3" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "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" name = "stats"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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]] [[package]]
@ -2993,6 +3047,14 @@ dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "termion" name = "termion"
version = "1.5.1" version = "1.5.1"
@ -3274,17 +3336,17 @@ dependencies = [
name = "trace-time" name = "trace-time"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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]] [[package]]
name = "transaction-pool" name = "transaction-pool"
version = "1.12.1" version = "1.13.1"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "log 0.4.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)",
"trace-time 0.1.0", "trace-time 0.1.0",
] ]
@ -3335,6 +3397,11 @@ dependencies = [
"triehash 0.2.0 (git+https://github.com/paritytech/parity-common)", "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]] [[package]]
name = "uint" name = "uint"
version = "0.2.1" version = "0.2.1"
@ -3462,7 +3529,7 @@ dependencies = [
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethjson 0.1.0", "ethjson 0.1.0",
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)", "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-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 0.2.1 (git+https://github.com/paritytech/parity-common)",
"patricia-trie-ethereum 0.1.0", "patricia-trie-ethereum 0.1.0",
@ -3482,7 +3549,7 @@ dependencies = [
"ethcore-logger 1.12.0", "ethcore-logger 1.12.0",
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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)", "pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"vm 0.1.0", "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-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-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)", "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", "panic_hook 0.1.0",
"parity-whisper 0.1.0", "parity-whisper 0.1.0",
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)", "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" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "ws" name = "ws"
version = "0.7.5" 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 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 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 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.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 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>" "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 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 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 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 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 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 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" "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_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 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 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.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 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 ring 0.12.1 (git+https://github.com/paritytech/ring)" = "<none>"
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity-common)" = "<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.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 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.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 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 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" "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 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 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 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 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 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" "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 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 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 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 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 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" "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-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-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 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 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 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" "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] [dependencies]
blooms-db = { path = "util/blooms-db" } blooms-db = { path = "util/blooms-db" }
log = "0.3" log = "0.4"
env_logger = "0.4" env_logger = "0.5"
rustc-hex = "1.0" rustc-hex = "1.0"
docopt = "0.8" docopt = "0.8"
clap = "2" clap = "2"
@ -136,6 +136,7 @@ members = [
"util/triehash-ethereum", "util/triehash-ethereum",
"util/keccak-hasher", "util/keccak-hasher",
"util/patricia-trie-ethereum", "util/patricia-trie-ethereum",
"util/fastmap",
] ]
[patch.crates-io] [patch.crates-io]

View File

@ -3,7 +3,7 @@
### [» Download the latest release «](https://github.com/paritytech/parity-ethereum/releases/latest) ### [» 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) [![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) [![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) [![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: Once you have rustup installed, then you need to install:
* [Perl](https://www.perl.org) * [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. 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 .``` ```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 FROM alpine:edge AS builder
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
# show backtraces # show backtraces
ENV RUST_BACKTRACE 1 ENV RUST_BACKTRACE 1
# show tools RUN apk add --no-cache \
RUN rustc -vV && \ build-base \
cargo -V && \ cargo \
gcc -v &&\ cmake \
g++ -v eudev-dev \
linux-headers \
perl \
rust
# build parity WORKDIR /parity
ADD . /build/parity COPY . /parity
RUN cd parity && \ RUN cargo build --release --target x86_64-alpine-linux-musl --verbose
cargo build --release --verbose && \ RUN strip target/x86_64-alpine-linux-musl/release/parity
ls /build/parity/target/release/parity && \
strip /build/parity/target/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 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 FROM centos:latest
WORKDIR /build
# install tools and dependencies RUN mkdir -p /opt/parity/data && \
RUN yum -y update&& \ chmod g+rwX /opt/parity/data && \
yum install -y git make gcc-c++ gcc file binutils cmake mkdir -p /opt/parity/release
# install rustup COPY parity/parity /opt/parity/release
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
ls&&\
sh rustup.sh --disable-sudo
# show backtraces WORKDIR /opt/parity/data
ENV RUST_BACKTRACE 1
# set compiler # exposing default ports
ENV CXX g++ #
ENV CC gcc # secret
# ipfs store ui rpc ws listener discovery
# ↓ ↓ ↓ ↓ ↓ ↓ ↓
EXPOSE 5001 8082 8083 8180 8545 8546 30303/tcp 30303/udp
# show tools # switch to non-root user
RUN rustc -vV && \ USER 1001
cargo -V && \
gcc -v &&\
g++ -v
# build parity #if no base path provided, assume it's current workdir
ADD . /build/parity CMD ["--base-path","."]
RUN cd parity&&\ ENTRYPOINT ["/opt/parity/release/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

@ -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] [lib]
[dependencies] [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" crunchy = "0.1.0"
memmap = "0.6"
either = "1.0.0" 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] [dev-dependencies]
tempdir = "0.3" tempdir = "0.3"

View File

@ -16,10 +16,11 @@
#![cfg_attr(feature = "benches", feature(test))] #![cfg_attr(feature = "benches", feature(test))]
extern crate primal;
extern crate parking_lot;
extern crate either; extern crate either;
extern crate ethereum_types;
extern crate memmap; extern crate memmap;
extern crate parking_lot;
extern crate primal;
#[macro_use] #[macro_use]
extern crate crunchy; extern crate crunchy;
@ -38,6 +39,7 @@ mod shared;
pub use cache::{NodeCacheBuilder, OptimizeFor}; pub use cache::{NodeCacheBuilder, OptimizeFor};
pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number}; pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number};
use compute::Light; use compute::Light;
use ethereum_types::{U256, U512};
use keccak::H256; use keccak::H256;
use parking_lot::Mutex; use parking_lot::Mutex;
pub use seed_compute::SeedHashCompute; 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] #[test]
fn test_lru() { fn test_lru() {
use tempdir::TempDir; use tempdir::TempDir;
@ -155,6 +180,43 @@ fn test_lru() {
assert_eq!(ethash.cache.lock().prev_epoch.unwrap(), 0); 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")] #[cfg(feature = "benches")]
mod benchmarks { mod benchmarks {
extern crate test; extern crate test;

View File

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

View File

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

View File

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

View File

@ -17,8 +17,9 @@
//! Evm factory. //! Evm factory.
//! //!
use std::sync::Arc; use std::sync::Arc;
use vm::Vm; use vm::{Vm, Schedule};
use ethereum_types::U256; use ethereum_types::U256;
use super::vm::ActionParams;
use super::interpreter::SharedCache; use super::interpreter::SharedCache;
use super::vmtype::VMType; use super::vmtype::VMType;
@ -32,12 +33,12 @@ pub struct Factory {
impl Factory { impl Factory {
/// Create fresh instance of VM /// Create fresh instance of VM
/// Might choose implementation depending on supplied gas. /// 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 { match self.evm {
VMType::Interpreter => if Self::can_fit_in_usize(gas) { VMType::Interpreter => if Self::can_fit_in_usize(&params.gas) {
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone())) Box::new(super::interpreter::Interpreter::<usize>::new(params, self.evm_cache.clone(), schedule, depth))
} else { } 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] #[test]
fn test_create_vm() { 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 /// 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 { fn into_return_data(mut self, offset: U256, size: U256) -> ReturnData {
let mut offset = offset.low_u64() as usize; let mut offset = offset.low_u64() as usize;
let size = size.low_u64() as usize; let size = size.low_u64() as usize;
if !is_valid_range(offset, size) { if !is_valid_range(offset, size) {
return ReturnData::empty() return ReturnData::empty();
} }
if self.len() - size > MAX_RETURN_WASTE_BYTES { if self.len() - size > MAX_RETURN_WASTE_BYTES {
{ let _ = self.drain(..offset); } if offset == 0 {
self.truncate(size); self.truncate(size);
self.shrink_to_fit(); self.shrink_to_fit();
offset = 0; } else {
self = self[offset..(offset + size)].to_vec();
offset = 0;
}
} }
ReturnData::new(self, offset, size) 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 vm;
extern crate keccak_hash as hash; extern crate keccak_hash as hash;
extern crate memory_cache; extern crate memory_cache;
extern crate parity_bytes as bytes;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -38,7 +38,7 @@ use transaction::SignedTransaction;
use trie::Trie; use trie::Trie;
use vm::EnvInfo; 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. /// Core unit of the API: submit batches of these to be answered with `Response`s.
#[derive(Clone)] #[derive(Clone)]
@ -265,30 +265,35 @@ impl From<Request> for CheckedRequest {
max: 1, max: 1,
reverse: false, reverse: false,
}; };
trace!(target: "on_demand", "HeaderByHash Request, {:?}", net_req);
CheckedRequest::HeaderByHash(req, net_req) CheckedRequest::HeaderByHash(req, net_req)
} }
Request::HeaderProof(req) => { Request::HeaderProof(req) => {
let net_req = net_request::IncompleteHeaderProofRequest { let net_req = net_request::IncompleteHeaderProofRequest {
num: req.num().into(), num: req.num().into(),
}; };
trace!(target: "on_demand", "HeaderProof Request, {:?}", net_req);
CheckedRequest::HeaderProof(req, net_req) CheckedRequest::HeaderProof(req, net_req)
} }
Request::TransactionIndex(req) => { Request::TransactionIndex(req) => {
let net_req = net_request::IncompleteTransactionIndexRequest { let net_req = net_request::IncompleteTransactionIndexRequest {
hash: req.0.clone(), hash: req.0.clone(),
}; };
trace!(target: "on_demand", "TransactionIndex Request, {:?}", net_req);
CheckedRequest::TransactionIndex(req, net_req) CheckedRequest::TransactionIndex(req, net_req)
} }
Request::Body(req) => { Request::Body(req) => {
let net_req = net_request::IncompleteBodyRequest { let net_req = net_request::IncompleteBodyRequest {
hash: req.0.field(), hash: req.0.field(),
}; };
trace!(target: "on_demand", "Body Request, {:?}", net_req);
CheckedRequest::Body(req, net_req) CheckedRequest::Body(req, net_req)
} }
Request::Receipts(req) => { Request::Receipts(req) => {
let net_req = net_request::IncompleteReceiptsRequest { let net_req = net_request::IncompleteReceiptsRequest {
hash: req.0.field(), hash: req.0.field(),
}; };
trace!(target: "on_demand", "Receipt Request, {:?}", net_req);
CheckedRequest::Receipts(req, net_req) CheckedRequest::Receipts(req, net_req)
} }
Request::Account(req) => { Request::Account(req) => {
@ -296,6 +301,7 @@ impl From<Request> for CheckedRequest {
block_hash: req.header.field(), block_hash: req.header.field(),
address_hash: ::hash::keccak(&req.address).into(), address_hash: ::hash::keccak(&req.address).into(),
}; };
trace!(target: "on_demand", "Account Request, {:?}", net_req);
CheckedRequest::Account(req, net_req) CheckedRequest::Account(req, net_req)
} }
Request::Code(req) => { Request::Code(req) => {
@ -303,6 +309,7 @@ impl From<Request> for CheckedRequest {
block_hash: req.header.field(), block_hash: req.header.field(),
code_hash: req.code_hash.into(), code_hash: req.code_hash.into(),
}; };
trace!(target: "on_demand", "Code Request, {:?}", net_req);
CheckedRequest::Code(req, net_req) CheckedRequest::Code(req, net_req)
} }
Request::Execution(req) => { Request::Execution(req) => {
@ -315,12 +322,14 @@ impl From<Request> for CheckedRequest {
value: req.tx.value, value: req.tx.value,
data: req.tx.data.clone(), data: req.tx.data.clone(),
}; };
trace!(target: "on_demand", "Execution request, {:?}", net_req);
CheckedRequest::Execution(req, net_req) CheckedRequest::Execution(req, net_req)
} }
Request::Signal(req) => { Request::Signal(req) => {
let net_req = net_request::IncompleteSignalRequest { let net_req = net_request::IncompleteSignalRequest {
block_hash: req.hash.into(), block_hash: req.hash.into(),
}; };
trace!(target: "on_demand", "Signal Request, {:?}", net_req);
CheckedRequest::Signal(req, net_req) CheckedRequest::Signal(req, net_req)
} }
} }
@ -507,15 +516,42 @@ impl IncompleteRequest for CheckedRequest {
fn complete(self) -> Result<Self::Complete, net_request::NoSuchOutput> { fn complete(self) -> Result<Self::Complete, net_request::NoSuchOutput> {
match self { match self {
CheckedRequest::HeaderProof(_, req) => req.complete().map(CompleteRequest::HeaderProof), CheckedRequest::HeaderProof(_, req) => {
CheckedRequest::HeaderByHash(_, req) => req.complete().map(CompleteRequest::Headers), trace!(target: "on_demand", "HeaderProof request completed {:?}", req);
CheckedRequest::TransactionIndex(_, req) => req.complete().map(CompleteRequest::TransactionIndex), req.complete().map(CompleteRequest::HeaderProof)
CheckedRequest::Receipts(_, req) => req.complete().map(CompleteRequest::Receipts), }
CheckedRequest::Body(_, req) => req.complete().map(CompleteRequest::Body), CheckedRequest::HeaderByHash(_, req) => {
CheckedRequest::Account(_, req) => req.complete().map(CompleteRequest::Account), trace!(target: "on_demand", "HeaderByHash request completed {:?}", req);
CheckedRequest::Code(_, req) => req.complete().map(CompleteRequest::Code), req.complete().map(CompleteRequest::Headers)
CheckedRequest::Execution(_, req) => req.complete().map(CompleteRequest::Execution), }
CheckedRequest::Signal(_, req) => req.complete().map(CompleteRequest::Signal), 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 header = self.0.as_ref()?;
let tx_root = ::triehash::ordered_trie_root(body.transactions_rlp().iter().map(|r| r.as_raw())); let tx_root = ::triehash::ordered_trie_root(body.transactions_rlp().iter().map(|r| r.as_raw()));
if tx_root != header.transactions_root() { 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)); return Err(Error::WrongTrieRoot(header.transactions_root(), tx_root));
} }
let uncles_hash = keccak(body.uncles_rlp().as_raw()); let uncles_hash = keccak(body.uncles_rlp().as_raw());
if uncles_hash != header.uncles_hash() { 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)); 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()); let block = encoded::Block::new_from_header_and_body(&header.view(), &body.view());
cache.lock().insert_block_body(header.hash(), body.clone()); cache.lock().insert_block_body(header.hash(), body.clone());
Ok(block) Ok(block)
} }
} }
@ -804,7 +841,10 @@ impl BlockReceipts {
cache.lock().insert_block_receipts(receipts_root, receipts.to_vec()); cache.lock().insert_block_receipts(receipts_root, receipts.to_vec());
Ok(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)?, 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 { match proved_execution {
ProvedExecution::BadProof => Err(Error::BadProof), ProvedExecution::BadProof => {
ProvedExecution::Failed(e) => Ok(Err(e)), trace!(target: "on_demand", "BadExecution Proof");
ProvedExecution::Complete(e) => Ok(Ok(e)), 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 transaction::{self, Condition, PendingTransaction, SignedTransaction};
use ethereum_types::{H256, U256, Address}; use ethereum_types::{H256, U256, Address};
use plain_hasher::H256FastMap; use fastmap::H256FastMap;
// Knowledge of an account's current nonce. // Knowledge of an account's current nonce.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]

View File

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

View File

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

View File

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

View File

@ -16,7 +16,16 @@
"gasLimitBoundDivisor": "0x400", "gasLimitBoundDivisor": "0x400",
"minGasLimit": "0x1388", "minGasLimit": "0x1388",
"networkID": "0x62121", "networkID": "0x62121",
"wasmActivationTransition": 4000000 "wasmActivationTransition": 6666666,
"eip140Transition": 6666666,
"eip211Transition": 6666666,
"eip214Transition": 6666666,
"eip658Transition": 6666666,
"maxCodeSize": 24576,
"maxCodeSizeTransition": 6666666,
"registrar": "0xb8624dc8cb3ca3147c178ac4c21734eb49e04071"
}, },
"genesis": { "genesis": {
"seal": { "seal": {
@ -43,12 +52,22 @@
}, },
"0x4ba15b56452521c0826a35a6f2022e1210fc519b": { "0x4ba15b56452521c0826a35a6f2022e1210fc519b": {
"balance": "0x7E37BE2022B2B09472D89C0000" "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": [ "nodes": [
"enode://147573f46fe9f5cc38fbe070089a31390baec5dd2827c8f2ef168833e4d0254fbee3969a02c5b9910ea5d5b23d86a6ed5eabcda17cc12007b7d9178b6c697aa5@37.120.168.56:30303", "enode://eda34244538d72f42605a6fc8b8a34b15714c683989e8b29dc9e7a2b2088da490a5b32f2c149bec5a5c482bf03ec2c4f38b833ae31e36fcb26fb05fd094b2a88@18.197.33.9:30303",
"enode://a370d5fd55959f20af6d1565b151a760c1372f5a2aaf674d4892cd4fd2de0d1f672781cd40e0d4e4b51c5823527ddec73b31cc14ac685449d9f0866996a16b9f@13.76.165.180:30303", "enode://12e903e900137b02b22e01f7918bd6e7310773c313e4e577281f35597e394a3e0b54c7314a8970a9776c5a3e5dc4daee289215dea3897bcb6d5cf0bb1dd2d356@18.197.31.231:30303",
"enode://da019fa5fb1fda105100d68a986938ec15ac5c6ff69d6e4ad3e350e377057f3e67e33aea5feb22d5cdcfc22041d141c8453c77baa64a216fff98f191ca76b3ec@18.220.108.238:30303", "enode://423fdb91b37ec0714af0c19f625ec4af3ada2844367a36e45a05703577a84f7f0e9483585d4950a35c9e3738dba8c6abd7e1ce278d9a1f3f28065bc009f409cd@52.221.203.209:30303",
"enode://49498fb8cdcd79c813ccdaa9496a3a4be0a187a3183e99adbc04d9c90b9a62ad59f0b6832f6e43b48e63fbebf74ec5438eb0d6d9098330edf36413d276fedf81@13.80.148.117:30303" "enode://a9327d37d07799817d4a3e13d49fb4f5cc1486d4adf3ec8a6b98be62c4d7a5453914a5139dbe124809a388514cb0be37f9fa799539abe2250672f6d3d778b821@18.191.209.251:30303"
] ]
} }

View File

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

View File

@ -17,7 +17,8 @@
"minGasLimit": "0x1388", "minGasLimit": "0x1388",
"networkID" : "0x69", "networkID" : "0x69",
"gasLimitBoundDivisor": "0x0400", "gasLimitBoundDivisor": "0x0400",
"transactionPermissionContract": "0x0000000000000000000000000000000000000005" "transactionPermissionContract": "0x0000000000000000000000000000000000000005",
"transactionPermissionContractTransition": "1"
}, },
"genesis": { "genesis": {
"seal": { "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-private-tx = { path = "../private-tx" }
ethcore-sync = { path = "../sync" } ethcore-sync = { path = "../sync" }
kvdb = { git = "https://github.com/paritytech/parity-common" } kvdb = { git = "https://github.com/paritytech/parity-common" }
log = "0.3" log = "0.4"
stop-guard = { path = "../../util/stop-guard" } stop-guard = { path = "../../util/stop-guard" }
trace-time = { path = "../../util/trace-time" } trace-time = { path = "../../util/trace-time" }

View File

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

View File

@ -18,9 +18,9 @@
mod stores; 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::fmt;
use std::time::{Instant, Duration}; use std::time::{Instant, Duration};
@ -96,20 +96,6 @@ impl From<SSError> for SignError {
/// `AccountProvider` errors. /// `AccountProvider` errors.
pub type Error = SSError; 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 { fn transient_sstore() -> EthMultiStore {
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed") EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
} }
@ -125,8 +111,6 @@ pub struct AccountProvider {
unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>, unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>,
/// Address book. /// Address book.
address_book: RwLock<AddressBook>, address_book: RwLock<AddressBook>,
/// Dapps settings.
dapps_settings: RwLock<DappsSettingsStore>,
/// Accounts on disk /// Accounts on disk
sstore: Box<SecretStore>, sstore: Box<SecretStore>,
/// Accounts unlocked with rolling tokens /// Accounts unlocked with rolling tokens
@ -167,7 +151,7 @@ impl AccountProvider {
/// Creates new account provider. /// Creates new account provider.
pub fn new(sstore: Box<SecretStore>, settings: AccountProviderSettings) -> Self { pub fn new(sstore: Box<SecretStore>, settings: AccountProviderSettings) -> Self {
let mut hardware_store = None; let mut hardware_store = None;
if settings.enable_hardware_wallets { if settings.enable_hardware_wallets {
match HardwareWalletManager::new() { match HardwareWalletManager::new() {
Ok(manager) => { Ok(manager) => {
@ -195,7 +179,6 @@ impl AccountProvider {
unlocked_secrets: RwLock::new(HashMap::new()), unlocked_secrets: RwLock::new(HashMap::new()),
unlocked: RwLock::new(HashMap::new()), unlocked: RwLock::new(HashMap::new()),
address_book: RwLock::new(address_book), address_book: RwLock::new(address_book),
dapps_settings: RwLock::new(DappsSettingsStore::new(&sstore.local_path())),
sstore: sstore, sstore: sstore,
transient_sstore: transient_sstore(), transient_sstore: transient_sstore(),
hardware_store: hardware_store, hardware_store: hardware_store,
@ -210,7 +193,6 @@ impl AccountProvider {
unlocked_secrets: RwLock::new(HashMap::new()), unlocked_secrets: RwLock::new(HashMap::new()),
unlocked: RwLock::new(HashMap::new()), unlocked: RwLock::new(HashMap::new()),
address_book: RwLock::new(AddressBook::transient()), 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")), sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
transient_sstore: transient_sstore(), transient_sstore: transient_sstore(),
hardware_store: None, 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. /// Returns addresses of hardware accounts.
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> { 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() { if !accounts.is_empty() {
return Ok(accounts.into_iter().map(|a| a.address).collect()); return Ok(accounts.into_iter().map(|a| a.address).collect());
} }
@ -308,7 +295,7 @@ impl AccountProvider {
Some(Ok(s)) => Ok(s), Some(Ok(s)) => Ok(s),
} }
} }
/// Provide a pin to a locked hardware wallet on USB path to unlock it /// 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> { 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)) { 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. /// Returns each address along with metadata.
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> { pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
self.address_book.read().get() self.address_book.read().get()
@ -849,7 +667,7 @@ impl AccountProvider {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{AccountProvider, Unlock, DappId}; use super::{AccountProvider, Unlock};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use ethstore::ethkey::{Generator, Random, Address}; use ethstore::ethkey::{Generator, Random, Address};
use ethstore::{StoreAccountRef, Derivation}; 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."); 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] #[test]
fn should_not_return_blacklisted_account() { fn should_not_return_blacklisted_account() {
// given // given

View File

@ -14,21 +14,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with 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::{fs, fmt, hash, ops};
use std::sync::atomic::{self, AtomicUsize};
use std::collections::HashMap; use std::collections::HashMap;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use ethstore::ethkey::Address; use ethstore::ethkey::Address;
use ethjson::misc::{ use ethjson::misc::AccountMeta;
AccountMeta,
DappsSettings as JsonSettings,
DappsHistory as JsonDappsHistory,
NewDappsPolicy as JsonNewDappsPolicy,
};
use account_provider::DappId;
/// Disk-backed map from Address to String. Uses JSON. /// Disk-backed map from Address to String. Uses JSON.
pub struct AddressBook { 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 /// Disk-serializable HashMap
#[derive(Debug)] #[derive(Debug)]
struct DiskMap<K: hash::Hash + Eq, V> { struct DiskMap<K: hash::Hash + Eq, V> {
@ -366,8 +151,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{AddressBook, DappsSettingsStore, DappsSettings, NewDappsPolicy}; use super::AddressBook;
use account_provider::DappId;
use std::collections::HashMap; use std::collections::HashMap;
use ethjson::misc::AccountMeta; use ethjson::misc::AccountMeta;
use tempdir::TempDir; use tempdir::TempDir;
@ -398,63 +182,4 @@ mod tests {
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None} 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>, ancestry: &mut Iterator<Item=ExtendedHeader>,
) -> Result<LockedBlock, Error> { ) -> 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())?; 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", trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
header.number(), s.root(), header.author(), s.balance(&header.author())?); header.number(), s.root(), header.author(), s.balance(&header.author())?);
@ -637,10 +637,11 @@ mod tests {
use ethereum_types::Address; use ethereum_types::Address;
use std::sync::Arc; use std::sync::Arc;
use transaction::SignedTransaction; 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 /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
fn enact_bytes( fn enact_bytes(
block_bytes: &[u8], block_bytes: Vec<u8>,
engine: &EthEngine, engine: &EthEngine,
tracing: bool, tracing: bool,
db: StateDB, db: StateDB,
@ -648,10 +649,10 @@ mod tests {
last_hashes: Arc<LastHashes>, last_hashes: Arc<LastHashes>,
factories: Factories, factories: Factories,
) -> Result<LockedBlock, Error> { ) -> Result<LockedBlock, Error> {
let block = view!(BlockView, block_bytes); let block = Unverified::from_rlp(block_bytes)?;
let header = block.header(); let header = block.header;
let transactions: Result<Vec<_>, Error> = block let transactions: Result<Vec<_>, Error> = block
.transactions() .transactions
.into_iter() .into_iter()
.map(SignedTransaction::new) .map(SignedTransaction::new)
.map(|r| r.map_err(Into::into)) .map(|r| r.map_err(Into::into))
@ -659,7 +660,7 @@ mod tests {
let transactions = transactions?; 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())?; 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", trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
header.number(), s.root(), header.author(), s.balance(&header.author())?); header.number(), s.root(), header.author(), s.balance(&header.author())?);
@ -683,8 +684,8 @@ mod tests {
b.populate_from(&header); b.populate_from(&header);
b.push_transactions(transactions)?; b.push_transactions(transactions)?;
for u in &block.uncles() { for u in block.uncles {
b.push_uncle(u.clone())?; b.push_uncle(u)?;
} }
b.close_and_lock() 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 /// 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( fn enact_and_seal(
block_bytes: &[u8], block_bytes: Vec<u8>,
engine: &EthEngine, engine: &EthEngine,
tracing: bool, tracing: bool,
db: StateDB, db: StateDB,
@ -700,8 +701,9 @@ mod tests {
last_hashes: Arc<LastHashes>, last_hashes: Arc<LastHashes>,
factories: Factories, factories: Factories,
) -> Result<SealedBlock, Error> { ) -> Result<SealedBlock, Error> {
let header = view!(BlockView, block_bytes).header_view(); 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())?) Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?
.seal(engine, header.seal().to_vec())?)
} }
#[test] #[test]
@ -731,7 +733,7 @@ mod tests {
let orig_db = b.drain().state.drop().1; let orig_db = b.drain().state.drop().1;
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); 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); assert_eq!(e.rlp_bytes(), orig_bytes);
@ -762,7 +764,7 @@ mod tests {
let orig_db = b.drain().state.drop().1; let orig_db = b.drain().state.drop().1;
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); 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(); let bytes = e.rlp_bytes();
assert_eq!(bytes, orig_bytes); assert_eq!(bytes, orig_bytes);

View File

@ -16,7 +16,6 @@
use std::collections::{HashSet, BTreeMap, VecDeque}; use std::collections::{HashSet, BTreeMap, VecDeque};
use std::cmp; use std::cmp;
use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
@ -50,13 +49,16 @@ use client::{
}; };
use encoded; use encoded;
use engines::{EthEngine, EpochTransition, ForkChoice}; 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 vm::{EnvInfo, LastHashes};
use evm::Schedule; use evm::Schedule;
use executive::{Executive, Executed, TransactOptions, contract_address}; use executive::{Executive, Executed, TransactOptions, contract_address};
use factory::{Factories, VmFactory}; use factory::{Factories, VmFactory};
use header::{BlockNumber, Header, ExtendedHeader}; use header::{BlockNumber, Header, ExtendedHeader};
use io::{IoChannel, IoError}; use io::IoChannel;
use log_entry::LocalizedLogEntry; use log_entry::LocalizedLogEntry;
use miner::{Miner, MinerService}; use miner::{Miner, MinerService};
use ethcore_miner::pool::VerifiedTransaction; use ethcore_miner::pool::VerifiedTransaction;
@ -1813,76 +1815,100 @@ impl BlockChainClient for Client {
self.engine.additional_params().into_iter().collect() self.engine.additional_params().into_iter().collect()
} }
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> { fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
// Wrap the logic inside a closure so that we can take advantage of question mark syntax. let chain = self.chain.read();
let fetch_logs = || {
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 // First, check whether `filter.from_block` and `filter.to_block` is on the canon chain. If so, we can use the
// optimized version. // optimized version.
let is_canon = |id| { let is_canon = |id| {
match id { match id {
// If it is referred by number, then it is always on the canon chain. // If it is referred by number, then it is always on the canon chain.
&BlockId::Earliest | &BlockId::Latest | &BlockId::Number(_) => true, &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 // If it is referred by hash, we see whether a hash -> number -> hash conversion gives us the same
// result. // result.
&BlockId::Hash(ref hash) => chain.is_canon(hash), &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))
}; };
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>> { 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 queued = self.queued_ancient_blocks.clone();
let lock = self.ancient_blocks_import_lock.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"); trace_time!("import_ancient_block");
// Make sure to hold the lock here to prevent importing out of order. // 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. // We use separate lock, cause we don't want to block queueing.
@ -2095,10 +2121,9 @@ impl IoClient for Client {
break; break;
} }
} }
}) { })?;
Ok(_) => Ok(hash),
Err(e) => bail!(BlockImportErrorKind::Other(format!("{}", e))), Ok(hash)
}
} }
fn queue_consensus_message(&self, message: Bytes) { 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. /// Queue some items to be processed by IO client.
struct IoChannelQueue { struct IoChannelQueue {
currently_queued: Arc<AtomicUsize>, currently_queued: Arc<AtomicUsize>,
@ -2547,7 +2557,7 @@ impl IoChannelQueue {
F: Fn(&Client) + Send + Sync + 'static, F: Fn(&Client) + Send + Sync + 'static,
{ {
let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed); 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 currently_queued = self.currently_queued.clone();
let result = channel.send(ClientIoMessage::execute(move |client| { let result = channel.send(ClientIoMessage::execute(move |client| {
@ -2560,7 +2570,7 @@ impl IoChannelQueue {
self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst); self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst);
Ok(()) Ok(())
}, },
Err(e) => Err(QueueError::Channel(e)), Err(e) => bail!(QueueErrorKind::Channel(e)),
} }
} }
} }

View File

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

View File

@ -94,6 +94,8 @@ pub struct TestBlockChainClient {
pub receipts: RwLock<HashMap<TransactionId, LocalizedReceipt>>, pub receipts: RwLock<HashMap<TransactionId, LocalizedReceipt>>,
/// Logs /// Logs
pub logs: RwLock<Vec<LocalizedLogEntry>>, pub logs: RwLock<Vec<LocalizedLogEntry>>,
/// Should return errors on logs.
pub error_on_logs: RwLock<Option<BlockId>>,
/// Block queue size. /// Block queue size.
pub queue_size: AtomicUsize, pub queue_size: AtomicUsize,
/// Miner /// Miner
@ -178,6 +180,7 @@ impl TestBlockChainClient {
traces: RwLock::new(None), traces: RwLock::new(None),
history: RwLock::new(None), history: RwLock::new(None),
disabled: AtomicBool::new(false), disabled: AtomicBool::new(false),
error_on_logs: RwLock::new(None),
}; };
// insert genesis hash. // insert genesis hash.
@ -233,6 +236,11 @@ impl TestBlockChainClient {
*self.logs.write() = logs; *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. /// Add blocks to test client.
pub fn add_blocks(&self, count: usize, with: EachBlockWith) { pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
let len = self.numbers.read().len(); let len = self.numbers.read().len();
@ -665,13 +673,18 @@ impl BlockChainClient for TestBlockChainClient {
self.receipts.read().get(&id).cloned() 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 mut logs = self.logs.read().clone();
let len = logs.len(); let len = logs.len();
match filter.limit { Ok(match filter.limit {
Some(limit) if limit <= len => logs.split_off(len - limit), Some(limit) if limit <= len => logs.split_off(len - limit),
_ => logs, _ => logs,
} })
} }
fn last_hashes(&self) -> LastHashes { 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. /// Get the registrar address, if it exists.
fn additional_params(&self) -> BTreeMap<String, String>; fn additional_params(&self) -> BTreeMap<String, String>;
/// Returns logs matching given filter. /// 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) -> Vec<LocalizedLogEntry>; fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId>;
/// Replays a given transaction for inspection. /// Replays a given transaction for inspection.
fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError>; 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! { error_chain! {
types { types {
ImportError, ImportErrorKind, ImportErrorResultExt, ImportErrorResult; ImportError, ImportErrorKind, ImportErrorResultExt, ImportErrorResult;
@ -183,6 +201,7 @@ error_chain! {
links { links {
Import(ImportError, ImportErrorKind) #[doc = "Import error"]; Import(ImportError, ImportErrorKind) #[doc = "Import error"];
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
} }
foreign_links { foreign_links {

View File

@ -20,7 +20,7 @@ use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use hash::{KECCAK_EMPTY_LIST_RLP}; use hash::{KECCAK_EMPTY_LIST_RLP};
use engines::block_reward::{self, RewardKind}; 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 ethereum_types::{H256, H64, U256, Address};
use unexpected::{OutOfBounds, Mismatch}; use unexpected::{OutOfBounds, Mismatch};
use block::*; 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() }))) 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, &header.bare_hash().0,
seal.nonce.low_u64(), seal.nonce.low_u64(),
&seal.mix_hash.0 &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 result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, seal.nonce.low_u64());
let mix = H256(result.mix_hash); 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}", trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}",
num = header.number() as u64, num = header.number() as u64,
seed = H256(slow_hash_block_number(header.number() as u64)), seed = H256(slow_hash_block_number(header.number() as u64)),
@ -447,25 +447,6 @@ impl Ethash {
} }
target 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) { 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] #[test]
fn difficulty_frontier() { fn difficulty_frontier() {
let machine = new_homestead_test_machine(); let machine = new_homestead_test_machine();

View File

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

View File

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

View File

@ -18,7 +18,7 @@ use trie::TrieFactory;
use ethtrie::RlpCodec; use ethtrie::RlpCodec;
use account_db::Factory as AccountFactory; use account_db::Factory as AccountFactory;
use evm::{Factory as EvmFactory, VMType}; use evm::{Factory as EvmFactory, VMType};
use vm::{Vm, ActionParams}; use vm::{Vm, ActionParams, Schedule};
use wasm::WasmInterpreter; use wasm::WasmInterpreter;
use keccak_hasher::KeccakHasher; use keccak_hasher::KeccakHasher;
@ -31,11 +31,11 @@ pub struct VmFactory {
} }
impl VmFactory { impl VmFactory {
pub fn create(&self, params: &ActionParams, wasm: bool) -> Box<Vm> { pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
if wasm && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) { 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) Box::new(WasmInterpreter::new(params))
} else { } 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 ethjson;
use trace::{Tracer, NoopTracer}; use trace::{Tracer, NoopTracer};
use trace::{VMTracer, NoopVMTracer}; use trace::{VMTracer, NoopVMTracer};
use bytes::{Bytes, BytesRef}; use bytes::Bytes;
use ethtrie; use ethtrie;
use rlp::RlpStream; use rlp::RlpStream;
use hash::keccak; use hash::keccak;
@ -90,7 +90,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
depth: usize, depth: usize,
origin_info: OriginInfo, origin_info: OriginInfo,
substate: &'a mut Substate, substate: &'a mut Substate,
output: OutputPolicy<'a, 'a>, output: OutputPolicy,
address: Address, address: Address,
tracer: &'a mut T, tracer: &'a mut T,
vm_tracer: &'a mut V, 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>, value: Option<U256>,
data: &[u8], data: &[u8],
_code_address: &Address, _code_address: &Address,
_output: &mut [u8],
_call_type: CallType _call_type: CallType
) -> MessageCallResult { ) -> MessageCallResult {
self.callcreates.push(CallCreate { 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 substate = Substate::new();
let mut tracer = NoopTracer; let mut tracer = NoopTracer;
let mut vm_tracer = NoopVMTracer; let mut vm_tracer = NoopVMTracer;
let mut output = vec![];
let vm_factory = state.vm_factory(); let vm_factory = state.vm_factory();
// execute // execute
@ -276,18 +274,23 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
0, 0,
OriginInfo::from(&params), OriginInfo::from(&params),
&mut substate, &mut substate,
OutputPolicy::Return(BytesRef::Flexible(&mut output), None), OutputPolicy::Return,
params.address.clone(), params.address.clone(),
&mut tracer, &mut tracer,
&mut vm_tracer, &mut vm_tracer,
)); ));
let mut evm = vm_factory.create(&params, schedule.wasm.is_some()); let mut evm = vm_factory.create(params, &schedule, 0);
let res = evm.exec(params, &mut ex); let res = evm.exec(&mut ex);
// a return in finalize will not alter callcreates // a return in finalize will not alter callcreates
let callcreates = ex.callcreates.clone(); let callcreates = ex.callcreates.clone();
(res.finalize(ex), callcreates) (res.finalize(ex), callcreates)
}; };
let output = match &res {
Ok(res) => res.return_data.to_vec(),
Err(_) => Vec::new(),
};
let log_hash = { let log_hash = {
let mut rlp = RlpStream::new_list(substate.logs.len()); let mut rlp = RlpStream::new_list(substate.logs.len());
for l in &substate.logs { for l in &substate.logs {

View File

@ -33,7 +33,6 @@ use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction
use tx_filter::TransactionFilter; use tx_filter::TransactionFilter;
use ethereum_types::{U256, Address}; use ethereum_types::{U256, Address};
use bytes::BytesRef;
use rlp::Rlp; use rlp::Rlp;
use vm::{CallType, ActionParams, ActionValue, ParamsType}; use vm::{CallType, ActionParams, ActionValue, ParamsType};
use vm::{EnvInfo, Schedule, CreateContractAddress}; use vm::{EnvInfo, Schedule, CreateContractAddress};
@ -148,10 +147,14 @@ impl EthereumMachine {
let schedule = self.schedule(env_info.number); let schedule = self.schedule(env_info.number);
let mut ex = Executive::new(&mut state, &env_info, self, &schedule); let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
let mut substate = Substate::new(); let mut substate = Substate::new();
let mut output = Vec::new(); let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) { let output = match res {
warn!("Encountered error on making system call: {}", e); Ok(res) => res.return_data.to_vec(),
} Err(e) => {
warn!("Encountered error on making system call: {}", e);
Vec::new()
}
};
Ok(output) Ok(output)
} }
@ -343,7 +346,7 @@ impl EthereumMachine {
-> Result<(), transaction::Error> -> Result<(), transaction::Error>
{ {
if let Some(ref filter) = self.tx_filter.as_ref() { 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()) 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 account_provider::{AccountProvider, SignError as AccountError};
use block::{ClosedBlock, IsBlock, Block, SealedBlock}; use block::{ClosedBlock, IsBlock, Block, SealedBlock};
use client::{ use client::{
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
}; };
use client::{BlockId, ClientIoMessage}; use client::{BlockId, ClientIoMessage};
use executive::contract_address; use executive::contract_address;
@ -296,6 +296,19 @@ impl Miner {
*self.io_channel.write() = Some(io_channel); *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 /// Clear all pending block states
pub fn clear(&self) { pub fn clear(&self) {
self.sealing.lock().queue.reset(); 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. /// 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. /// 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 fn map_existing_pending_block<F, T>(&self, f: F, latest_block_number: BlockNumber) -> Option<T> where
F: FnOnce(&ClosedBlock) -> T, F: FnOnce(&ClosedBlock) -> T,
{ {
self.sealing.lock().queue self.sealing.lock().queue
.peek_last_ref() .peek_last_ref()
.and_then(|b| { .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)) Some(f(b))
} else { } else {
None None
@ -365,7 +379,7 @@ impl Miner {
// if at least one was pushed successfully, close and enqueue new ClosedBlock; // if at least one was pushed successfully, close and enqueue new ClosedBlock;
// otherwise, leave everything alone. // otherwise, leave everything alone.
// otherwise, author a fresh block. // 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) => { Some(old_block) => {
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning"); trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
// add transactions to old_block // add transactions to old_block
@ -628,7 +642,7 @@ impl Miner {
{ {
let mut sealing = self.sealing.lock(); let mut sealing = self.sealing.lock();
sealing.next_mandatory_reseal = Instant::now() + self.options.reseal_max_period; 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(); sealing.queue.use_last_ref();
} }
@ -690,7 +704,7 @@ impl Miner {
); );
let is_new = original_work_hash.map_or(true, |h| h != block_hash); 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")] #[cfg(feature = "work-notify")]
{ {
@ -1108,7 +1122,7 @@ impl miner::MinerService for Miner {
Some(false) => { Some(false) => {
trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now"); trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now");
// anyway, save the block for later use // anyway, save the block for later use
self.sealing.lock().queue.push(block); self.sealing.lock().queue.set_pending(block);
}, },
None => { None => {
trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work"); 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 client::{Client, ImportSealedBlock};
use ethereum_types::{H64, H256, clean_0x, U256}; use ethereum_types::{H64, H256, clean_0x, U256};
use ethereum::ethash::Ethash; use ethash::{self, SeedHashCompute};
use ethash::SeedHashCompute;
#[cfg(feature = "work-notify")] #[cfg(feature = "work-notify")]
use ethcore_miner::work_notify::NotifyWork; use ethcore_miner::work_notify::NotifyWork;
#[cfg(feature = "work-notify")] #[cfg(feature = "work-notify")]
@ -167,7 +166,7 @@ impl StratumJobDispatcher {
/// Serializes payload for stratum service /// Serializes payload for stratum service
fn payload(&self, pow_hash: H256, difficulty: U256, number: u64) -> String { fn payload(&self, pow_hash: H256, difficulty: U256, number: u64) -> String {
// TODO: move this to engine // 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 = &self.seed_compute.lock().hash_block_number(number);
let seed_hash = H256::from_slice(&seed_hash[..]); let seed_hash = H256::from_slice(&seed_hash[..]);
format!( format!(

View File

@ -125,6 +125,10 @@ pub struct CommonParams {
pub remove_dust_contracts: bool, pub remove_dust_contracts: bool,
/// Wasm activation blocknumber, if any disabled initially. /// Wasm activation blocknumber, if any disabled initially.
pub wasm_activation_transition: BlockNumber, 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) /// Gas limit bound divisor (how much gas limit can change per block)
pub gas_limit_bound_divisor: U256, pub gas_limit_bound_divisor: U256,
/// Registrar contract address. /// Registrar contract address.
@ -137,6 +141,8 @@ pub struct CommonParams {
pub max_code_size_transition: BlockNumber, pub max_code_size_transition: BlockNumber,
/// Transaction permission managing contract address. /// Transaction permission managing contract address.
pub transaction_permission_contract: Option<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 /// Maximum size of transaction's RLP payload
pub max_transaction_size: usize, pub max_transaction_size: usize,
} }
@ -187,7 +193,14 @@ impl CommonParams {
}; };
} }
if block_number >= self.wasm_activation_transition { 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_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), 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: 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( wasm_activation_transition: p.wasm_activation_transition.map_or_else(
BlockNumber::max_value, BlockNumber::max_value,
Into::into 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 machine = self.engine.machine();
let schedule = machine.schedule(env_info.number); let schedule = machine.schedule(env_info.number);
let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule); 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); warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
} }
} }
@ -756,6 +779,11 @@ impl Spec {
Ok(()) 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. /// Returns `false` if the memoized state root is invalid. `true` otherwise.
pub fn is_state_root_valid(&self) -> bool { pub fn is_state_root_valid(&self) -> bool {
// TODO: get rid of this function and ensure state root always is valid. // TODO: get rid of this function and ensure state root always is valid.

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,6 @@
//! Nonoperative tracer. //! Nonoperative tracer.
use ethereum_types::{U256, Address}; use ethereum_types::{U256, Address};
use bytes::Bytes;
use vm::ActionParams; use vm::ActionParams;
use trace::{Tracer, VMTracer, FlatTrace, TraceError}; use trace::{Tracer, VMTracer, FlatTrace, TraceError};
use trace::trace::{Call, Create, VMTrace, RewardType}; use trace::trace::{Call, Create, VMTrace, RewardType};
@ -36,18 +35,12 @@ impl Tracer for NoopTracer {
None None
} }
fn prepare_trace_output(&self) -> Option<Bytes> { fn trace_call(&mut self, call: Option<Call>, _: U256, _: &[u8], _: Vec<FlatTrace>) {
None
}
fn trace_call(&mut self, call: Option<Call>, _: U256, output: Option<Bytes>, _: Vec<FlatTrace>) {
assert!(call.is_none(), "self.prepare_trace_call().is_none(): so we can't be tracing: qed"); 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!(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) { 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 parking_lot::Mutex;
use spec::CommonParams; use spec::CommonParams;
use transaction::{Action, SignedTransaction}; use transaction::{Action, SignedTransaction};
use types::BlockNumber;
use hash::KECCAK_EMPTY; use hash::KECCAK_EMPTY;
use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json"); 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_deprecated: transact_acl_deprecated::TransactAclDeprecated,
contract: transact_acl::TransactAcl, contract: transact_acl::TransactAcl,
contract_address: Address, contract_address: Address,
transition_block: BlockNumber,
permission_cache: Mutex<LruCache<(H256, Address), u32>>, permission_cache: Mutex<LruCache<(H256, Address), u32>>,
contract_version_cache: Mutex<LruCache<(H256), Option<U256>>> contract_version_cache: Mutex<LruCache<(H256), Option<U256>>>
} }
@ -56,6 +58,7 @@ impl TransactionFilter {
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(), contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(),
contract: transact_acl::TransactAcl::default(), contract: transact_acl::TransactAcl::default(),
contract_address: address, contract_address: address,
transition_block: params.transaction_permission_contract_transition,
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)), permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
contract_version_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. /// 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 permission_cache = self.permission_cache.lock();
let mut contract_version_cache = self.contract_version_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); basic_tx_with_ether_and_to_key6.value = U256::from(123123);
let genesis = client.block_hash(BlockId::Latest).unwrap(); 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, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client)); // same tx but request is allowed because the contract only enables at block #1
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client)); 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, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client)); assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.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, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client)); assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.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, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client)); assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.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, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client)); assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.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, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client)); assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key6.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_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, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key5.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, &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 /// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a
@ -254,21 +264,26 @@ mod test {
call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005")); call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005"));
let genesis = client.block_hash(BlockId::Latest).unwrap(); 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, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client)); // same tx but request is allowed because the contract only enables at block #1
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client)); 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, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client)); assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.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, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client)); assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.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, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client)); assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.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. /// An unverified block.
#[derive(PartialEq, Debug)]
pub struct Unverified { pub struct Unverified {
/// Unverified block header. /// Unverified block header.
pub header: Header, pub header: Header,

View File

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

View File

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

View File

@ -8,6 +8,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[lib] [lib]
[dependencies] [dependencies]
common-types = { path = "../types" }
parity-bytes = { git = "https://github.com/paritytech/parity-common" } parity-bytes = { git = "https://github.com/paritytech/parity-common" }
ethcore-network = { path = "../../util/network" } ethcore-network = { path = "../../util/network" }
ethcore-network-devp2p = { path = "../../util/network-devp2p" } ethcore-network-devp2p = { path = "../../util/network-devp2p" }
@ -17,7 +18,7 @@ ethcore-transaction = { path = "../transaction" }
ethcore = { path = ".." } ethcore = { path = ".." }
ethereum-types = "0.3" ethereum-types = "0.3"
hashdb = { git = "https://github.com/paritytech/parity-common" } 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" } rlp = { git = "https://github.com/paritytech/parity-common" }
rustc-hex = "1.0" rustc-hex = "1.0"
keccak-hash = { git = "https://github.com/paritytech/parity-common" } 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" } triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" }
kvdb = { git = "https://github.com/paritytech/parity-common" } kvdb = { git = "https://github.com/paritytech/parity-common" }
macros = { path = "../../util/macros" } macros = { path = "../../util/macros" }
log = "0.3" log = "0.4"
env_logger = "0.4" env_logger = "0.5"
rand = "0.4" rand = "0.4"
heapsize = "0.4" heapsize = "0.4"
semver = "0.9" semver = "0.9"

View File

@ -24,6 +24,8 @@ use devp2p::NetworkService;
use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId, use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId,
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind, NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind,
ConnectionFilter}; ConnectionFilter};
use types::pruning_info::PruningInfo;
use ethereum_types::{H256, H512, U256}; use ethereum_types::{H256, H512, U256};
use io::{TimerToken}; use io::{TimerToken};
use ethcore::ethstore::ethkey::Secret; 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}; PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3};
use light::client::AsLightClient; use light::client::AsLightClient;
use light::Provider; 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 network::IpFilter;
use private_tx::PrivateTxHandler; use private_tx::PrivateTxHandler;
use transaction::UnverifiedTransaction; use transaction::UnverifiedTransaction;
@ -256,11 +261,35 @@ pub struct EthSync {
light_subprotocol_name: [u8; 3], 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 { impl EthSync {
/// Creates and register protocol with the network service /// Creates and register protocol with the network service
pub fn new(params: Params, connection_filter: Option<Arc<ConnectionFilter>>) -> Result<Arc<EthSync>, Error> { 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 pruning_info = params.chain.pruning_info();
let light_proto = match params.config.serve_light { let light_proto = match params.config.serve_light {
false => None, false => None,
@ -271,20 +300,12 @@ impl EthSync {
.map(|mut p| { p.push("request_timings"); light_net::FileStore(p) }) .map(|mut p| { p.push("request_timings"); light_net::FileStore(p) })
.map(|store| Box::new(store) as Box<_>); .map(|store| Box::new(store) as Box<_>);
let mut light_params = LightParams { let light_params = light_params(
network_id: params.config.network_id, params.config.network_id,
config: Default::default(), params.network_config.max_peers,
capabilities: Capabilities { pruning_info,
serve_headers: true, sample_store,
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 mut light_proto = LightProtocol::new(params.provider, light_params); let mut light_proto = LightProtocol::new(params.provider, light_params);
light_proto.add_handler(Arc::new(TxRelay(params.chain.clone()))); light_proto.add_handler(Arc::new(TxRelay(params.chain.clone())));
@ -916,3 +937,19 @@ impl LightSyncProvider for LightSync {
Default::default() // TODO 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 heapsize::HeapSizeOf;
use ethereum_types::H256; use ethereum_types::H256;
use rlp::{self, Rlp}; use rlp::{self, Rlp};
use ethcore::header::{BlockNumber, Header as BlockHeader}; use ethcore::header::BlockNumber;
use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind}; use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind};
use ethcore::error::{ImportErrorKind, BlockError}; use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError};
use ethcore::verification::queue::kind::blocks::Unverified;
use sync_io::SyncIo; use sync_io::SyncIo;
use blocks::BlockCollection; use blocks::{BlockCollection, SyncBody, SyncHeader};
const MAX_HEADERS_TO_REQUEST: usize = 128; const MAX_HEADERS_TO_REQUEST: usize = 128;
const MAX_BODIES_TO_REQUEST: usize = 32; 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 valid_response = item_count == 0; //empty response is valid
let mut any_known = false; let mut any_known = false;
for i in 0..item_count { for i in 0..item_count {
let info: BlockHeader = r.val_at(i).map_err(|e| { let info = SyncHeader::from_rlp(r.at(i)?.as_raw().to_vec())?;
trace!(target: "sync", "Error decoding block header RLP: {:?}", e); let number = BlockNumber::from(info.header.number());
BlockDownloaderImportError::Invalid let hash = info.header.hash();
})?;
let number = BlockNumber::from(info.number());
// Check if any of the headers matches the hash we requested // Check if any of the headers matches the hash we requested
if !valid_response { if !valid_response {
if let Some(expected) = expected_hash { 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()); any_known = any_known || self.blocks.contains_head(&hash);
if self.blocks.contains(&info.hash()) { if self.blocks.contains(&hash) {
trace!(target: "sync", "Skipping existing block header {} ({:?})", number, info.hash()); trace!(target: "sync", "Skipping existing block header {} ({:?})", number, hash);
continue; continue;
} }
if self.highest_block.as_ref().map_or(true, |n| number > *n) { if self.highest_block.as_ref().map_or(true, |n| number > *n) {
self.highest_block = Some(number); 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())) { match io.chain().block_status(BlockId::Hash(hash.clone())) {
BlockStatus::InChain | BlockStatus::Queued => { BlockStatus::InChain | BlockStatus::Queued => {
match self.state { match self.state {
State::Blocks => trace!(target: "sync", "Header already in chain {} ({})", number, hash), State::Blocks => trace!(target: "sync", "Header already in chain {} ({})", number, hash),
_ => trace!(target: "sync", "Header already in chain {} ({}), state = {:?}", number, hash, self.state), _ => 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); hashes.push(hash);
}, },
BlockStatus::Bad => { BlockStatus::Bad => {
return Err(BlockDownloaderImportError::Invalid); return Err(BlockDownloaderImportError::Invalid);
}, },
BlockStatus::Unknown | BlockStatus::Pending => { BlockStatus::Unknown | BlockStatus::Pending => {
headers.push(hdr.as_raw().to_vec()); headers.push(info);
hashes.push(hash); hashes.push(hash);
} }
} }
@ -325,19 +318,15 @@ impl BlockDownloader {
let item_count = r.item_count().unwrap_or(0); let item_count = r.item_count().unwrap_or(0);
if item_count == 0 { if item_count == 0 {
return Err(BlockDownloaderImportError::Useless); return Err(BlockDownloaderImportError::Useless);
} } else if self.state != State::Blocks {
else if self.state != State::Blocks {
trace!(target: "sync", "Ignored unexpected block bodies"); trace!(target: "sync", "Ignored unexpected block bodies");
} } else {
else {
let mut bodies = Vec::with_capacity(item_count); let mut bodies = Vec::with_capacity(item_count);
for i in 0..item_count { for i in 0..item_count {
let body = r.at(i).map_err(|e| { let body = SyncBody::from_rlp(r.at(i)?.as_raw())?;
trace!(target: "sync", "Error decoding block boides RLP: {:?}", e); bodies.push(body);
BlockDownloaderImportError::Invalid
})?;
bodies.push(body.as_raw().to_vec());
} }
if self.blocks.insert_bodies(bodies) != item_count { if self.blocks.insert_bodies(bodies) != item_count {
trace!(target: "sync", "Deactivating peer for giving invalid block bodies"); trace!(target: "sync", "Deactivating peer for giving invalid block bodies");
return Err(BlockDownloaderImportError::Invalid); return Err(BlockDownloaderImportError::Invalid);
@ -483,15 +472,6 @@ impl BlockDownloader {
let block = block_and_receipts.block; let block = block_and_receipts.block;
let receipts = block_and_receipts.receipts; 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 h = block.header.hash();
let number = block.header.number(); let number = block.header.number();
let parent = *block.header.parent_hash(); let parent = *block.header.parent_hash();
@ -533,6 +513,10 @@ impl BlockDownloader {
debug!(target: "sync", "Block temporarily invalid, restarting sync"); debug!(target: "sync", "Block temporarily invalid, restarting sync");
break; break;
}, },
Err(BlockImportError(BlockImportErrorKind::Queue(QueueErrorKind::Full(limit)), _)) => {
debug!(target: "sync", "Block import queue full ({}), restarting sync", limit);
break;
},
Err(e) => { Err(e) => {
debug!(target: "sync", "Bad block {:?} : {:?}", h, e); debug!(target: "sync", "Bad block {:?} : {:?}", h, e);
bad = true; bad = true;

View File

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

View File

@ -99,7 +99,7 @@ use std::time::{Duration, Instant};
use hash::keccak; use hash::keccak;
use heapsize::HeapSizeOf; use heapsize::HeapSizeOf;
use ethereum_types::{H256, U256}; use ethereum_types::{H256, U256};
use plain_hasher::H256FastMap; use fastmap::H256FastMap;
use parking_lot::RwLock; use parking_lot::RwLock;
use bytes::Bytes; use bytes::Bytes;
use rlp::{Rlp, RlpStream, DecoderError}; 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_HASHES: usize = 64;
const MAX_NEW_BLOCK_AGE: BlockNumber = 20; const MAX_NEW_BLOCK_AGE: BlockNumber = 20;
// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation). // 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 // Min number of blocks to be behind for a snapshot sync
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000; const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
const SNAPSHOT_MIN_PEERS: usize = 3; const SNAPSHOT_MIN_PEERS: usize = 3;

View File

@ -237,8 +237,9 @@ impl SyncPropagator {
let lucky_peers_len = lucky_peers.len(); let lucky_peers_len = lucky_peers.len();
for (peer_id, sent, rlp) in lucky_peers { for (peer_id, sent, rlp) in lucky_peers {
peers.insert(peer_id); peers.insert(peer_id);
let size = rlp.len();
SyncPropagator::send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp); 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); max_sent = cmp::max(max_sent, sent);
} }
debug!(target: "sync", "Sent up to {} transactions to {} peers.", max_sent, lucky_peers_len); 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 bytes::Bytes;
use rlp::{Rlp, RlpStream}; use rlp::{Rlp, RlpStream};
use super::{*, super::tests::*}; use super::{*, super::tests::*};
use blocks::SyncHeader;
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient}; use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient};
#[test] #[test]
fn return_block_headers() { fn return_block_headers() {
use ethcore::views::HeaderView;
fn make_hash_req(h: &H256, count: usize, skip: usize, reverse: bool) -> Bytes { fn make_hash_req(h: &H256, count: usize, skip: usize, reverse: bool) -> Bytes {
let mut rlp = RlpStream::new_list(4); let mut rlp = RlpStream::new_list(4);
rlp.append(h); rlp.append(h);
@ -329,16 +329,16 @@ mod test {
rlp.append(&if reverse {1u32} else {0u32}); rlp.append(&if reverse {1u32} else {0u32});
rlp.out() rlp.out()
} }
fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<Bytes> { fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<SyncHeader> {
Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| r.as_raw().to_vec()).collect() 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(); let mut client = TestBlockChainClient::new();
client.add_blocks(100, EachBlockWith::Nothing); client.add_blocks(100, EachBlockWith::Nothing);
let blocks: Vec<_> = (0 .. 100) let blocks: Vec<_> = (0 .. 100)
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).map(|b| b.into_inner()).unwrap()).collect(); .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 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| view!(HeaderView, h).hash()).collect(); let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
let queue = RwLock::new(VecDeque::new()); let queue = RwLock::new(VecDeque::new());
let ss = TestSnapshotService::new(); let ss = TestSnapshotService::new();

View File

@ -21,17 +21,17 @@
//! https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol //! 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 as network;
extern crate ethcore_network_devp2p as devp2p; extern crate ethcore_network_devp2p as devp2p;
extern crate parity_bytes as bytes; extern crate parity_bytes as bytes;
extern crate ethcore_io as io; extern crate ethcore_io as io;
extern crate ethcore_transaction as transaction; extern crate ethcore_transaction as transaction;
#[macro_use]
extern crate ethcore; extern crate ethcore;
extern crate ethereum_types; extern crate ethereum_types;
extern crate env_logger; extern crate env_logger;
extern crate hashdb; extern crate hashdb;
extern crate plain_hasher; extern crate fastmap;
extern crate rand; extern crate rand;
extern crate semver; extern crate semver;
extern crate parking_lot; extern crate parking_lot;

View File

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

View File

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

View File

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

View File

@ -9,7 +9,7 @@ parity-bytes = { git = "https://github.com/paritytech/parity-common" }
ethereum-types = "0.3" ethereum-types = "0.3"
patricia-trie = { git = "https://github.com/paritytech/parity-common" } patricia-trie = { git = "https://github.com/paritytech/parity-common" }
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" } patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
log = "0.3" log = "0.4"
common-types = { path = "../types" } common-types = { path = "../types" }
ethjson = { path = "../../json" } ethjson = { path = "../../json" }
rlp = { git = "https://github.com/paritytech/parity-common" } 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. /// 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 { pub enum CreateContractAddress {
/// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis) /// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis)
FromSenderAndNonce, FromSenderAndNonce,
@ -101,7 +101,6 @@ pub trait Ext {
value: Option<U256>, value: Option<U256>,
data: &[u8], data: &[u8],
code_address: &Address, code_address: &Address,
output: &mut [u8],
call_type: CallType call_type: CallType
) -> MessageCallResult; ) -> MessageCallResult;

View File

@ -48,5 +48,5 @@ pub trait Vm {
/// This function should be used to execute transaction. /// This function should be used to execute transaction.
/// It returns either an error, a known amount of gas left, or parameters to be used /// It returns either an error, a known amount of gas left, or parameters to be used
/// to compute the final gas left. /// 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, pub opcodes_mul: u32,
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div` /// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
pub opcodes_div: u32, 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 { impl Default for WasmCosts {
@ -166,6 +170,8 @@ impl Default for WasmCosts {
max_stack_height: 64*1024, max_stack_height: 64*1024,
opcodes_mul: 3, opcodes_mul: 3,
opcodes_div: 8, opcodes_div: 8,
have_create2: false,
have_gasleft: false,
} }
} }
} }

View File

@ -39,6 +39,7 @@ pub enum FakeCallType {
#[derive(PartialEq, Eq, Hash, Debug)] #[derive(PartialEq, Eq, Hash, Debug)]
pub struct FakeCall { pub struct FakeCall {
pub call_type: FakeCallType, pub call_type: FakeCallType,
pub create_scheme: Option<CreateContractAddress>,
pub gas: U256, pub gas: U256,
pub sender_address: Option<Address>, pub sender_address: Option<Address>,
pub receive_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() 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 { self.calls.insert(FakeCall {
call_type: FakeCallType::Create, call_type: FakeCallType::Create,
create_scheme: Some(address),
gas: *gas, gas: *gas,
sender_address: None, sender_address: None,
receive_address: None, receive_address: None,
@ -153,12 +155,12 @@ impl Ext for FakeExt {
value: Option<U256>, value: Option<U256>,
data: &[u8], data: &[u8],
code_address: &Address, code_address: &Address,
_output: &mut [u8],
_call_type: CallType _call_type: CallType
) -> MessageCallResult { ) -> MessageCallResult {
self.calls.insert(FakeCall { self.calls.insert(FakeCall {
call_type: FakeCallType::Call, call_type: FakeCallType::Call,
create_scheme: None,
gas: *gas, gas: *gas,
sender_address: Some(sender_address.clone()), sender_address: Some(sender_address.clone()),
receive_address: Some(receive_address.clone()), receive_address: Some(receive_address.clone()),

View File

@ -6,7 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
byteorder = "1.0" byteorder = "1.0"
ethereum-types = "0.3" ethereum-types = "0.3"
log = "0.3" log = "0.4"
parity-wasm = "0.31" parity-wasm = "0.31"
libc = "0.2" libc = "0.2"
pwasm-utils = "0.2.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) Ok(result)
} }
fn wasm_interpreter() -> WasmInterpreter { fn wasm_interpreter(params: ActionParams) -> WasmInterpreter {
WasmInterpreter WasmInterpreter::new(params)
} }
#[derive(Debug)] #[derive(Debug)]
@ -131,7 +131,7 @@ pub fn construct(
params.params_type = ParamsType::Separate; params.params_type = ParamsType::Separate;
Ok( Ok(
match wasm_interpreter().exec(params, ext)? { match wasm_interpreter(params).exec(ext)? {
GasLeft::Known(_) => Vec::new(), GasLeft::Known(_) => Vec::new(),
GasLeft::NeedsReturn { data, .. } => data.to_vec(), 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, Ok(ret) => ret,
Err(e) => { return Fail::runtime(e); } Err(e) => { return Fail::runtime(e); }
}; };

View File

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

View File

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

View File

@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::cmp;
use ethereum_types::{U256, H256, Address}; use ethereum_types::{U256, H256, Address};
use vm::{self, CallType}; use vm::{self, CallType};
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind}; 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); } if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); }
Ok(self.gas_limit - self.gas_counter) Ok(self.gas_limit - self.gas_counter)
} }
/// General gas charging extern. /// General gas charging extern.
fn gas(&mut self, args: RuntimeArgs) -> Result<()> { fn gas(&mut self, args: RuntimeArgs) -> Result<()> {
let amount: u32 = args.nth_checked(0)?; let amount: u32 = args.nth_checked(0)?;
@ -447,12 +448,14 @@ impl<'a> Runtime<'a> {
val, val,
&payload, &payload,
&address, &address,
&mut result[..],
call_type, call_type,
); );
match call_result { 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 // cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter - self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64 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)?; self.memory.set(result_ptr, &result)?;
Ok(0i32.into()) 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 // cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
self.gas_counter = self.gas_counter - self.gas_counter = self.gas_counter -
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64 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) self.return_u256_ptr(args.nth_checked(0)?, val)
} }
/// Creates a new contract fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result<RuntimeValue> {
///
/// 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);
let code = self.memory.get(code_ptr, code_len as usize)?; let code = self.memory.get(code_ptr, code_len as usize)?;
self.adjusted_charge(|schedule| schedule.create_gas as u64)?; 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_mul)
/ U256::from(self.ext.schedule().wasm().opcodes_div); / 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) => { vm::ContractCreateResult::Created(address, gas_left) => {
self.memory.set(result_ptr, &*address)?; self.memory.set(result_ptr, &*address)?;
self.gas_counter = self.gas_limit - 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<()> fn debug(&mut self, args: RuntimeArgs) -> Result<()>
{ {
trace!(target: "wasm", "Contract debug message: {}", { trace!(target: "wasm", "Contract debug message: {}", {
@ -629,6 +666,15 @@ impl<'a> Runtime<'a> {
self.return_u256_ptr(args.nth_checked(0)?, difficulty) 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)` /// Signature: `fn gaslimit(dest: *mut u8)`
pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> { pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> {
let gas_limit = self.ext.env_info().gas_limit; let gas_limit = self.ext.env_info().gas_limit;
@ -744,6 +790,8 @@ mod ext_impl {
SENDER_FUNC => void!(self.sender(args)), SENDER_FUNC => void!(self.sender(args)),
ORIGIN_FUNC => void!(self.origin(args)), ORIGIN_FUNC => void!(self.origin(args)),
ELOG_FUNC => void!(self.elog(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), _ => 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 ethereum_types::{H256, U256, Address};
use super::WasmInterpreter; use super::WasmInterpreter;
use vm::{self, Vm, GasLeft, ActionParams, ActionValue}; use vm::{self, Vm, GasLeft, ActionParams, ActionValue, CreateContractAddress};
use vm::tests::{FakeCall, FakeExt, FakeCallType}; use vm::tests::{FakeCall, FakeExt, FakeCallType};
macro_rules! load_sample { macro_rules! load_sample {
@ -47,8 +47,8 @@ macro_rules! reqrep_test {
fake_ext.info = $info; fake_ext.info = $info;
fake_ext.blockhashes = $block_hashes; fake_ext.blockhashes = $block_hashes;
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
interpreter.exec(params, &mut fake_ext) interpreter.exec(&mut fake_ext)
.map(|result| match result { .map(|result| match result {
GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); }, 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()), 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 { fn wasm_interpreter(params: ActionParams) -> WasmInterpreter {
WasmInterpreter WasmInterpreter::new(params)
} }
/// Empty contract does almost nothing except producing 1 (one) local node debug log message /// 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 mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(params, &mut ext)).unwrap() test_finalize(interpreter.exec(&mut ext)).unwrap()
}; };
assert_eq!(gas_left, U256::from(96_926)); assert_eq!(gas_left, U256::from(96_926));
@ -111,8 +111,8 @@ fn logger() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(params, &mut ext)).unwrap() test_finalize(interpreter.exec(&mut ext)).unwrap()
}; };
let address_val: H256 = address.into(); let address_val: H256 = address.into();
@ -138,7 +138,7 @@ fn logger() {
U256::from(1_000_000_000), U256::from(1_000_000_000),
"Logger sets 0x04 key to the trasferred value" "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. // 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 mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("Identity contract should return payload"); }, GasLeft::Known(_) => { panic!("Identity contract should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -173,7 +173,7 @@ fn identity() {
sender, sender,
"Idenity test contract does not return the sender passed" "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 // 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 mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("Dispersion routine should return payload"); }, GasLeft::Known(_) => { panic!("Dispersion routine should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
@ -207,7 +207,7 @@ fn dispersion() {
result, result,
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0] 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] #[test]
@ -223,8 +223,8 @@ fn suicide_not() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("Suicidal contract should return payload when had not actualy killed himself"); }, 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()), 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 mut ext = FakeExt::new().with_wasm();
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(gas) => gas, GasLeft::Known(gas) => gas,
GasLeft::NeedsReturn { .. } => { GasLeft::NeedsReturn { .. } => {
@ -267,7 +267,7 @@ fn suicide() {
}; };
assert!(ext.suicides.contains(&refund)); assert!(ext.suicides.contains(&refund));
assert_eq!(gas_left, U256::from(93_348)); assert_eq!(gas_left, U256::from(93_346));
} }
#[test] #[test]
@ -281,14 +281,19 @@ fn create() {
params.value = ActionValue::transfer(1_000_000_000); params.value = ActionValue::transfer(1_000_000_000);
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
ext.schedule.wasm.as_mut().unwrap().have_create2 = true;
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(gas) => gas, GasLeft::Known(_) => {
GasLeft::NeedsReturn { .. } => { panic!("Create contract always return 40 bytes of the creation address, or in the case where it fails, return 40 bytes of zero.");
panic!("Create contract should not return anthing because ext always fails on creation"); },
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( assert!(ext.calls.contains(
&FakeCall { &FakeCall {
call_type: FakeCallType::Create, call_type: FakeCallType::Create,
gas: U256::from(59_269), create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash),
gas: U256::from(49_674),
sender_address: None, sender_address: None,
receive_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], data: vec![0u8, 2, 4, 8, 16, 32, 64, 128],
code_address: None, 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] #[test]
@ -328,8 +346,8 @@ fn call_msg() {
ext.balances.insert(receiver.clone(), U256::from(10000000000u64)); ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(gas_left) => gas_left, GasLeft::Known(gas_left) => gas_left,
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); }, GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
@ -340,6 +358,7 @@ fn call_msg() {
assert!(ext.calls.contains( assert!(ext.calls.contains(
&FakeCall { &FakeCall {
call_type: FakeCallType::Call, call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(33_000), gas: U256::from(33_000),
sender_address: Some(receiver), 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])), 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)); 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] #[test]
fn call_code() { fn call_code() {
::ethcore_logger::init_log(); ::ethcore_logger::init_log();
@ -370,8 +437,8 @@ fn call_code() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("Call test should return payload"); }, GasLeft::Known(_) => { panic!("Call test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), 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( assert!(ext.calls.contains(
&FakeCall { &FakeCall {
call_type: FakeCallType::Call, call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(20_000), gas: U256::from(20_000),
sender_address: Some(sender), sender_address: Some(sender),
receive_address: Some(receiver), receive_address: Some(receiver),
@ -394,7 +462,7 @@ fn call_code() {
// siphash result // siphash result
let res = LittleEndian::read_u32(&result[..]); let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 4198595614); assert_eq!(res, 4198595614);
assert_eq!(gas_left, U256::from(90_038)); assert_eq!(gas_left, U256::from(90_037));
} }
#[test] #[test]
@ -417,8 +485,8 @@ fn call_static() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("Static call test should return payload"); }, GasLeft::Known(_) => { panic!("Static call test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), 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( assert!(ext.calls.contains(
&FakeCall { &FakeCall {
call_type: FakeCallType::Call, call_type: FakeCallType::Call,
create_scheme: None,
gas: U256::from(20_000), gas: U256::from(20_000),
sender_address: Some(receiver), sender_address: Some(receiver),
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
@ -442,7 +511,7 @@ fn call_static() {
let res = LittleEndian::read_u32(&result[..]); let res = LittleEndian::read_u32(&result[..]);
assert_eq!(res, 317632590); assert_eq!(res, 317632590);
assert_eq!(gas_left, U256::from(90_043)); assert_eq!(gas_left, U256::from(90_042));
} }
// Realloc test // Realloc test
@ -457,15 +526,15 @@ fn realloc() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("Realloc should return payload"); }, GasLeft::Known(_) => { panic!("Realloc should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
} }
}; };
assert_eq!(result, vec![0u8; 2]); assert_eq!(result, vec![0u8; 2]);
assert_eq!(gas_left, U256::from(92_842)); assert_eq!(gas_left, U256::from(92_848));
} }
#[test] #[test]
@ -479,15 +548,15 @@ fn alloc() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("alloc test should return payload"); }, GasLeft::Known(_) => { panic!("alloc test should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
} }
}; };
assert_eq!(result, vec![5u8; 1024*400]); 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 // Tests that contract's ability to read from a storage
@ -506,8 +575,8 @@ fn storage_read() {
ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into()); ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into());
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("storage_read should return payload"); }, GasLeft::Known(_) => { panic!("storage_read should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), 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!(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 // Tests keccak calculation
@ -532,8 +601,8 @@ fn keccak() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("keccak should return payload"); }, GasLeft::Known(_) => { panic!("keccak should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), 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!(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 // 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(), U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(92_086)); assert_eq!(gas_left, U256::from(92_072));
} }
// multiplication // multiplication
@ -592,7 +661,7 @@ fn math_mul() {
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(91_414)); assert_eq!(gas_left, U256::from(91_400));
} }
// subtraction // subtraction
@ -614,7 +683,7 @@ fn math_sub() {
U256::from_dec_str("111111111111111111111111111111").unwrap(), U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(92_086)); assert_eq!(gas_left, U256::from(92_072));
} }
// subtraction with overflow // subtraction with overflow
@ -656,7 +725,7 @@ fn math_div() {
U256::from_dec_str("1125000").unwrap(), U256::from_dec_str("1125000").unwrap(),
(&result[..]).into() (&result[..]).into()
); );
assert_eq!(gas_left, U256::from(87_376)); assert_eq!(gas_left, U256::from(85_700));
} }
#[test] #[test]
@ -679,12 +748,12 @@ fn storage_metering() {
]); ]);
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(params, &mut ext)).unwrap() test_finalize(interpreter.exec(&mut ext)).unwrap()
}; };
// 0 -> not 0 // 0 -> not 0
assert_eq!(gas_left, U256::from(72_399)); assert_eq!(gas_left, U256::from(72_164));
// #2 // #2
@ -698,12 +767,12 @@ fn storage_metering() {
]); ]);
let gas_left = { let gas_left = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
test_finalize(interpreter.exec(params, &mut ext)).unwrap() test_finalize(interpreter.exec(&mut ext)).unwrap()
}; };
// not 0 -> not 0 // 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 // This test checks the ability of wasm contract to invoke
@ -791,7 +860,48 @@ fn externs() {
"Gas limit requested and returned does not match" "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] #[test]
@ -808,8 +918,8 @@ fn embedded_keccak() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("keccak should return payload"); }, GasLeft::Known(_) => { panic!("keccak should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), 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!(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 /// This test checks the correctness of log extern
@ -836,8 +946,8 @@ fn events() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let (gas_left, result) = { let (gas_left, result) = {
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
match result { match result {
GasLeft::Known(_) => { panic!("events should return payload"); }, GasLeft::Known(_) => { panic!("events should return payload"); },
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), 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!(&log_entry.data, b"gnihtemos");
assert_eq!(&result, b"gnihtemos"); assert_eq!(&result, b"gnihtemos");
assert_eq!(gas_left, U256::from(81_351)); assert_eq!(gas_left, U256::from(83_161));
} }
#[test] #[test]
@ -876,8 +986,8 @@ fn recursive() {
let mut ext = FakeExt::new().with_wasm(); let mut ext = FakeExt::new().with_wasm();
let mut interpreter = wasm_interpreter(); let mut interpreter = wasm_interpreter(params);
let result = interpreter.exec(params, &mut ext); let result = interpreter.exec(&mut ext);
// We expect that stack overflow will occur and it should be generated by // We expect that stack overflow will occur and it should be generated by
// deterministic stack metering. Exceeding deterministic stack height limit // 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" } eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
ethereum-types = "0.3" ethereum-types = "0.3"
lazy_static = "1.0" lazy_static = "1.0"
log = "0.3" log = "0.4"
mem = { path = "../util/mem" } mem = { path = "../util/mem" }
parity-wordlist = "1.2" parity-wordlist = "1.2"
quick-error = "1.2.2" quick-error = "1.2.2"

View File

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

View File

@ -162,7 +162,7 @@ impl DisplayMode {
fn main() { fn main() {
panic_hook::set_abort(); 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()) { match execute(env::args()) {
Ok(ok) => println!("{}", ok), Ok(ok) => println!("{}", ok),

View File

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

View File

@ -10,6 +10,7 @@ path = "./src/main.rs"
[dependencies] [dependencies]
docopt = "0.8" docopt = "0.8"
env_logger = "0.5"
ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests"] } ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests"] }
ethjson = { path = "../json" } ethjson = { path = "../json" }
parity-bytes = { git = "https://github.com/paritytech/parity-common" } 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)] #[cfg(test)]
mod tests { pub mod tests {
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use super::*; use super::*;
use info::tests::run_test; use info::tests::run_test;
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
struct TestWriter(pub Arc<Mutex<Vec<u8>>>); pub struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
impl Writer for TestWriter { impl Writer for TestWriter {
fn clone(&self) -> Self { Clone::clone(self) } 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 writer = TestWriter::default();
let res = writer.0.clone(); let res = writer.0.clone();
(Informant::new(writer), res) (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. /// Execute given `ActionParams` and return the result.
pub fn run_action<T: Informant>( pub fn run_action<T: Informant>(
spec: &spec::Spec, spec: &spec::Spec,
params: ActionParams, mut params: ActionParams,
mut informant: T, mut informant: T,
) -> RunResult<T::Output> { ) -> RunResult<T::Output> {
informant.set_gas(params.gas); 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 let result = client
.call(params, &mut trace::NoopTracer, &mut informant) .call(params, &mut trace::NoopTracer, &mut informant)
.map(|r| (0.into(), r.gas_left, r.return_data.to_vec())); .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` /// Execute VM with given `ActionParams`
pub fn run<'a, F, T, X>( pub fn run<'a, F, X>(
spec: &'a spec::Spec, spec: &'a spec::Spec,
initial_gas: U256, initial_gas: U256,
pre_state: T, pre_state: &'a pod_state::PodState,
run: F, run: F,
) -> RunResult<X> where ) -> RunResult<X> where
F: FnOnce(EvmTestClient) -> (Result<(H256, U256, Vec<u8>), EvmTestError>, Option<X>), 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() { let test_client = EvmTestClient::from_pod_state(spec, pre_state.clone())
Some(pre_state) => EvmTestClient::from_pod_state(spec, pre_state.clone()), .map_err(|error| Failure {
None => EvmTestClient::new(spec), gas_used: 0.into(),
}.map_err(|error| Failure { error,
gas_used: 0.into(), time: Duration::from_secs(0),
error, traces: None,
time: Duration::from_secs(0), })?;
traces: None,
})?;
let start = Instant::now(); let start = Instant::now();
let result = run(test_client); 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 vm;
extern crate evm; extern crate evm;
extern crate panic_hook; extern crate panic_hook;
extern crate env_logger;
#[cfg(test)] #[cfg(test)]
#[macro_use] #[macro_use]
@ -92,6 +93,7 @@ General options:
fn main() { fn main() {
panic_hook::set_abort(); panic_hook::set_abort();
env_logger::init();
let args: Args = Docopt::new(USAGE).and_then(|d| d.deserialize()).unwrap_or_else(|e| e.exit()); let 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] [dependencies]
futures = "0.1" futures = "0.1"
futures-cpupool = "0.1" futures-cpupool = "0.1"
log = "0.3" log = "0.4"
mime = "0.3" mime = "0.3"
mime_guess = "2.0.0-alpha.2" mime_guess = "2.0.0-alpha.2"
rand = "0.4" rand = "0.4"

View File

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

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