ci: merge master
This commit is contained in:
commit
200a82608a
@ -1,12 +1,16 @@
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
<<<<<<< HEAD
|
||||
- package
|
||||
- publish
|
||||
- docs
|
||||
|
||||
image: parity/rust:gitlab-ci
|
||||
|
||||
=======
|
||||
- docs
|
||||
>>>>>>> master
|
||||
variables:
|
||||
CI_SERVER_NAME: "GitLab CI"
|
||||
CARGO_HOME: "${CI_PROJECT_DIR}/cargo"
|
||||
@ -284,6 +288,7 @@ publish:github:s3:
|
||||
script:
|
||||
- scripts/gitlab/push.sh
|
||||
tags:
|
||||
<<<<<<< HEAD
|
||||
- shell
|
||||
allow_failure: true
|
||||
|
||||
@ -292,6 +297,22 @@ publish:github:s3:
|
||||
|
||||
json:rpc:docs:
|
||||
stage: docs
|
||||
=======
|
||||
- rust
|
||||
- rust-nightly
|
||||
allow_failure: true
|
||||
json-rpc-docs:
|
||||
stage: docs
|
||||
only:
|
||||
- tags
|
||||
image: parity/rust:gitlab-ci
|
||||
script:
|
||||
- scripts/gitlab-rpc-docs.sh
|
||||
tags:
|
||||
- docs
|
||||
push-release:
|
||||
stage: push-release
|
||||
>>>>>>> master
|
||||
only:
|
||||
- tags
|
||||
- gitlab-next
|
||||
|
210
Cargo.lock
generated
210
Cargo.lock
generated
@ -357,10 +357,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "dir"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"app_dirs 1.2.1 (git+https://github.com/paritytech/app-dirs-rs)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"journaldb 0.2.0",
|
||||
]
|
||||
|
||||
@ -401,11 +402,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.4.3"
|
||||
version = "0.5.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -470,8 +474,9 @@ version = "1.12.0"
|
||||
dependencies = [
|
||||
"crunchy 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -528,7 +533,7 @@ dependencies = [
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"macros 0.1.0",
|
||||
"memory-cache 0.1.0",
|
||||
@ -577,7 +582,7 @@ version = "1.12.0"
|
||||
dependencies = [
|
||||
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -597,6 +602,7 @@ dependencies = [
|
||||
"ethcore-network 1.12.0",
|
||||
"ethcore-transaction 0.1.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fastmap 0.1.0",
|
||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -605,20 +611,19 @@ dependencies = [
|
||||
"keccak-hasher 0.1.0",
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memory-cache 0.1.0",
|
||||
"memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"patricia-trie-ethereum 0.1.0",
|
||||
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"rlp_derive 0.1.0",
|
||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stats 0.1.0",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"triehash-ethereum 0.2.0",
|
||||
@ -632,9 +637,9 @@ dependencies = [
|
||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -645,7 +650,7 @@ name = "ethcore-miner"
|
||||
version = "1.12.0"
|
||||
dependencies = [
|
||||
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethash 1.12.0",
|
||||
"ethcore-transaction 0.1.0",
|
||||
@ -658,14 +663,14 @@ dependencies = [
|
||||
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"linked-hash-map 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-reactor 0.1.0",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"price-info 1.12.0",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"trace-time 0.1.0",
|
||||
"transaction-pool 1.12.1",
|
||||
"transaction-pool 1.13.1",
|
||||
"url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -702,7 +707,7 @@ dependencies = [
|
||||
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
@ -740,7 +745,7 @@ dependencies = [
|
||||
"fetch 0.1.0",
|
||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -778,7 +783,7 @@ dependencies = [
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -808,7 +813,7 @@ dependencies = [
|
||||
"ethcore-sync 1.12.0",
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stop-guard 0.1.0",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"trace-time 0.1.0",
|
||||
@ -818,14 +823,14 @@ dependencies = [
|
||||
name = "ethcore-stratum"
|
||||
version = "1.12.0"
|
||||
dependencies = [
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-logger 1.12.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-tcp-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-io 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -835,7 +840,8 @@ dependencies = [
|
||||
name = "ethcore-sync"
|
||||
version = "1.12.0"
|
||||
dependencies = [
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"common-types 0.1.0",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.12.0",
|
||||
"ethcore-io 1.12.0",
|
||||
"ethcore-light 1.12.0",
|
||||
@ -845,6 +851,7 @@ dependencies = [
|
||||
"ethcore-transaction 0.1.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethkey 0.3.0",
|
||||
"fastmap 0.1.0",
|
||||
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -852,16 +859,15 @@ dependencies = [
|
||||
"keccak-hasher 0.1.0",
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"macros 0.1.0",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"trace-time 0.1.0",
|
||||
"triehash-ethereum 0.2.0",
|
||||
]
|
||||
@ -923,7 +929,7 @@ dependencies = [
|
||||
"eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mem 0.1.0",
|
||||
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -940,7 +946,7 @@ name = "ethkey-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethkey 0.3.0",
|
||||
"panic_hook 0.1.0",
|
||||
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -954,12 +960,12 @@ dependencies = [
|
||||
name = "ethstore"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"dir 0.1.1",
|
||||
"dir 0.1.2",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethkey 0.3.0",
|
||||
"itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -969,7 +975,7 @@ dependencies = [
|
||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -979,7 +985,7 @@ dependencies = [
|
||||
name = "ethstore-cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dir 0.1.1",
|
||||
"dir 0.1.2",
|
||||
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethstore 0.2.0",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1000,8 +1006,9 @@ dependencies = [
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memory-cache 0.1.0",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vm 0.1.0",
|
||||
@ -1012,6 +1019,7 @@ name = "evmbin"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.12.0",
|
||||
"ethcore-transaction 0.1.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1044,6 +1052,14 @@ dependencies = [
|
||||
"ethkey 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastmap"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fdlimit"
|
||||
version = "0.1.1"
|
||||
@ -1161,7 +1177,7 @@ dependencies = [
|
||||
"ethkey 0.3.0",
|
||||
"hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)",
|
||||
"libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"protobuf 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1208,11 +1224,28 @@ dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "0.11.24"
|
||||
@ -1323,17 +1356,17 @@ version = "0.2.0"
|
||||
dependencies = [
|
||||
"ethcore-logger 1.12.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fastmap 0.1.0",
|
||||
"hashdb 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"keccak-hasher 0.1.0",
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memorydb 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain_hasher 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
]
|
||||
|
||||
@ -1668,7 +1701,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"macros 0.1.0",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1797,7 +1830,7 @@ dependencies = [
|
||||
"ethcore-network-devp2p 1.12.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1826,7 +1859,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -1928,6 +1961,7 @@ source = "git+https://github.com/paritytech/parity-common#0045887fecd2fec39e56c9
|
||||
name = "parity-clib"
|
||||
version = "1.12.0"
|
||||
dependencies = [
|
||||
"panic_hook 0.1.0",
|
||||
"parity-ethereum 2.1.0",
|
||||
]
|
||||
|
||||
@ -1953,9 +1987,9 @@ dependencies = [
|
||||
"clap 2.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
|
||||
"daemonize 0.2.3 (git+https://github.com/paritytech/daemonize)",
|
||||
"dir 0.1.1",
|
||||
"dir 0.1.2",
|
||||
"docopt 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.12.0",
|
||||
"ethcore-io 1.12.0",
|
||||
"ethcore-light 1.12.0",
|
||||
@ -1979,7 +2013,7 @@ dependencies = [
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-rocksdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mem 0.1.0",
|
||||
"migration-rocksdb 0.1.0",
|
||||
"node-filter 1.12.0",
|
||||
@ -2031,7 +2065,7 @@ dependencies = [
|
||||
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
@ -2067,7 +2101,7 @@ dependencies = [
|
||||
"ethkey 0.3.0",
|
||||
"kvdb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rlp 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2125,7 +2159,7 @@ dependencies = [
|
||||
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"kvdb-memorydb 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"macros 0.1.0",
|
||||
"multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2148,7 +2182,7 @@ dependencies = [
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"transaction-pool 1.12.1",
|
||||
"transaction-pool 1.13.1",
|
||||
"transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vm 0.1.0",
|
||||
]
|
||||
@ -2161,7 +2195,7 @@ dependencies = [
|
||||
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-rpc 1.12.0",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2199,7 +2233,7 @@ dependencies = [
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"parity-hash-fetch 1.12.0",
|
||||
@ -2245,7 +2279,7 @@ dependencies = [
|
||||
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mem 0.1.0",
|
||||
"ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-crypto 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
@ -2256,7 +2290,7 @@ dependencies = [
|
||||
"serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -2289,7 +2323,7 @@ dependencies = [
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2401,7 +2435,7 @@ dependencies = [
|
||||
"futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -2445,7 +2479,7 @@ dependencies = [
|
||||
"hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"primal-bit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2562,7 +2596,7 @@ dependencies = [
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2590,11 +2624,31 @@ dependencies = [
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "registrar"
|
||||
version = "0.0.1"
|
||||
@ -2887,7 +2941,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.4.3"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2931,7 +2985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "stats"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2993,6 +3047,14 @@ dependencies = [
|
||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.1"
|
||||
@ -3274,17 +3336,17 @@ dependencies = [
|
||||
name = "trace-time"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "transaction-pool"
|
||||
version = "1.12.1"
|
||||
version = "1.13.1"
|
||||
dependencies = [
|
||||
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"trace-time 0.1.0",
|
||||
]
|
||||
|
||||
@ -3335,6 +3397,11 @@ dependencies = [
|
||||
"triehash 0.2.0 (git+https://github.com/paritytech/parity-common)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ucd-util"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "uint"
|
||||
version = "0.2.1"
|
||||
@ -3462,7 +3529,7 @@ dependencies = [
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethjson 0.1.0",
|
||||
"keccak-hash 0.1.2 (git+https://github.com/paritytech/parity-common)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-bytes 0.1.0 (git+https://github.com/paritytech/parity-common)",
|
||||
"patricia-trie 0.2.1 (git+https://github.com/paritytech/parity-common)",
|
||||
"patricia-trie-ethereum 0.1.0",
|
||||
@ -3482,7 +3549,7 @@ dependencies = [
|
||||
"ethcore-logger 1.12.0",
|
||||
"ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parity-wasm 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"vm 0.1.0",
|
||||
@ -3529,7 +3596,7 @@ dependencies = [
|
||||
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.11)",
|
||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"panic_hook 0.1.0",
|
||||
"parity-whisper 0.1.0",
|
||||
"serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -3565,6 +3632,14 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wincolor"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ws"
|
||||
version = "0.7.5"
|
||||
@ -3657,7 +3732,7 @@ dependencies = [
|
||||
"checksum edit-distance 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a34f5204fbc13582de418611cf3a7dcdd07c6d312a5b631597ba72c06b9d9c9"
|
||||
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
|
||||
"checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb"
|
||||
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
|
||||
"checksum env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "f4d7e69c283751083d53d01eac767407343b8b69c4bd70058e08adc2637cb257"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
|
||||
"checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
|
||||
@ -3685,7 +3760,9 @@ dependencies = [
|
||||
"checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
|
||||
"checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
|
||||
"checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "<none>"
|
||||
"checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff"
|
||||
"checksum httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "af2f2dd97457e8fb1ae7c5a420db346af389926e36f43768b96f101546b04a07"
|
||||
"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e"
|
||||
"checksum hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)" = "df4dd5dae401458087396b6db7fabc4d6760aa456a5fa8e92bda549f39cae661"
|
||||
"checksum hyper-rustls 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6cdc1751771a14b8175764394f025e309a28c825ed9eaf97fa62bb831dc8c5"
|
||||
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
|
||||
@ -3792,7 +3869,9 @@ dependencies = [
|
||||
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa"
|
||||
"checksum regex 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5bbbea44c5490a1e84357ff28b7d518b4619a159fed5d25f6c1de2d19cc42814"
|
||||
"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
|
||||
"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d"
|
||||
"checksum relay 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1576e382688d7e9deecea24417e350d3062d97e32e45d70b1cde65994ff1489a"
|
||||
"checksum ring 0.12.1 (git+https://github.com/paritytech/ring)" = "<none>"
|
||||
"checksum rlp 0.2.1 (git+https://github.com/paritytech/parity-common)" = "<none>"
|
||||
@ -3826,7 +3905,7 @@ dependencies = [
|
||||
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
|
||||
"checksum slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdeff4cd9ecff59ec7e3744cbca73dfe5ac35c2aedb2cfba8a1c715a18912e9d"
|
||||
"checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013"
|
||||
"checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d"
|
||||
"checksum smallvec 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f90c5e5fe535e48807ab94fc611d323935f39d4660c52b26b96446a7b33aef10"
|
||||
"checksum snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
|
||||
"checksum snappy-sys 0.1.0 (git+https://github.com/paritytech/rust-snappy)" = "<none>"
|
||||
"checksum socket2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "06dc9f86ee48652b7c80f3d254e3b9accb67a928c562c64d10d7b016d3d98dab"
|
||||
@ -3838,6 +3917,7 @@ dependencies = [
|
||||
"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
|
||||
"checksum tempfile 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11ce2fe9db64b842314052e2421ac61a73ce41b898dc8e3750398b219c5fc1e0"
|
||||
"checksum term_size 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e5b9a66db815dcfd2da92db471106457082577c3c278d4138ab3e3b4e189327"
|
||||
"checksum termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "722426c4a0539da2c4ffd9b419d90ad540b4cff4a053be9069c908d4d07e2836"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
|
||||
"checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
|
||||
@ -3867,6 +3947,7 @@ dependencies = [
|
||||
"checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "<none>"
|
||||
"checksum trie-standardmap 0.1.0 (git+https://github.com/paritytech/parity-common)" = "<none>"
|
||||
"checksum triehash 0.2.0 (git+https://github.com/paritytech/parity-common)" = "<none>"
|
||||
"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d"
|
||||
"checksum uint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "38051a96565903d81c9a9210ce11076b2218f3b352926baa1f5f6abbdfce8273"
|
||||
"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||
"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a"
|
||||
@ -3892,6 +3973,7 @@ dependencies = [
|
||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
"checksum wincolor 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9dc3aa9dcda98b5a16150c54619c1ead22e3d3a5d458778ae914be760aa981a"
|
||||
"checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "<none>"
|
||||
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||
"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61"
|
||||
|
@ -8,8 +8,8 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
blooms-db = { path = "util/blooms-db" }
|
||||
log = "0.3"
|
||||
env_logger = "0.4"
|
||||
log = "0.4"
|
||||
env_logger = "0.5"
|
||||
rustc-hex = "1.0"
|
||||
docopt = "0.8"
|
||||
clap = "2"
|
||||
@ -136,6 +136,7 @@ members = [
|
||||
"util/triehash-ethereum",
|
||||
"util/keccak-hasher",
|
||||
"util/patricia-trie-ethereum",
|
||||
"util/fastmap",
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
|
@ -3,7 +3,7 @@
|
||||
### [» Download the latest release «](https://github.com/paritytech/parity-ethereum/releases/latest)
|
||||
|
||||
[![build status](https://gitlab.parity.io/parity/parity/badges/master/build.svg)](https://gitlab.parity.io/parity/parity/commits/master)
|
||||
[![codecov](https://codecov.io/gh/paritytech/parity/branch/master/graph/badge.svg)](https://codecov.io/gh/paritytech/parity)
|
||||
[![codecov](https://codecov.io/gh/paritytech/parity-ethereum/branch/master/graph/badge.svg)](https://codecov.io/gh/paritytech/parity-ethereum)
|
||||
[![Snap Status](https://build.snapcraft.io/badge/paritytech/parity.svg)](https://build.snapcraft.io/user/paritytech/parity)
|
||||
[![GPLv3](https://img.shields.io/badge/license-GPL%20v3-green.svg)](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
|
||||
@ -64,7 +64,7 @@ We recommend installing Rust through [rustup](https://www.rustup.rs/). If you do
|
||||
|
||||
Once you have rustup installed, then you need to install:
|
||||
* [Perl](https://www.perl.org)
|
||||
* [Yasm](http://yasm.tortall.net)
|
||||
* [Yasm](https://yasm.tortall.net)
|
||||
|
||||
Make sure that these binaries are in your `PATH`. After that you should be able to build Parity-Ethereum from source.
|
||||
|
||||
|
@ -1,3 +1,42 @@
|
||||
Usage
|
||||
## Usage
|
||||
|
||||
```docker build -f docker/ubuntu/Dockerfile --tag ethcore/parity:branch_or_tag_name .```
|
||||
|
||||
## Usage - CentOS
|
||||
|
||||
Builds a lightweight non-root Parity docker image:
|
||||
|
||||
```
|
||||
git clone https://github.com/paritytech/parity-ethereum.git
|
||||
cd parity-ethereum
|
||||
./docker/centos/build.sh
|
||||
```
|
||||
|
||||
Fully customised build:
|
||||
```
|
||||
PARITY_IMAGE_REPO=my-personal/parity \
|
||||
PARITY_BUILDER_IMAGE_TAG=build-latest \
|
||||
PARITY_RUNNER_IMAGE_TAG=centos-parity-experimental \
|
||||
./docker/centos/build.sh
|
||||
```
|
||||
|
||||
|
||||
Default values:
|
||||
```
|
||||
# The image name
|
||||
PARITY_IMAGE_REPO - parity/parity
|
||||
|
||||
# The tag to be used for builder image, git commit sha will be appended
|
||||
PARITY_BUILDER_IMAGE_TAG - build
|
||||
|
||||
# The tag to be used for runner image
|
||||
PARITY_RUNNER_IMAGE_TAG - latest
|
||||
```
|
||||
|
||||
All default ports you might use will be exposed:
|
||||
```
|
||||
# secret
|
||||
# ipfs store ui rpc ws listener discovery
|
||||
# ↓ ↓ ↓ ↓ ↓ ↓ ↓
|
||||
EXPOSE 5001 8082 8083 8180 8545 8546 30303/tcp 30303/udp
|
||||
```
|
||||
|
@ -1,29 +1,43 @@
|
||||
FROM alpine:edge
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# install tools and dependencies
|
||||
RUN apk add --no-cache gcc musl-dev pkgconfig g++ make curl \
|
||||
eudev-dev rust cargo git file binutils \
|
||||
libusb-dev linux-headers perl cmake
|
||||
FROM alpine:edge AS builder
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
# show tools
|
||||
RUN rustc -vV && \
|
||||
cargo -V && \
|
||||
gcc -v &&\
|
||||
g++ -v
|
||||
RUN apk add --no-cache \
|
||||
build-base \
|
||||
cargo \
|
||||
cmake \
|
||||
eudev-dev \
|
||||
linux-headers \
|
||||
perl \
|
||||
rust
|
||||
|
||||
# build parity
|
||||
ADD . /build/parity
|
||||
RUN cd parity && \
|
||||
cargo build --release --verbose && \
|
||||
ls /build/parity/target/release/parity && \
|
||||
strip /build/parity/target/release/parity
|
||||
WORKDIR /parity
|
||||
COPY . /parity
|
||||
RUN cargo build --release --target x86_64-alpine-linux-musl --verbose
|
||||
RUN strip target/x86_64-alpine-linux-musl/release/parity
|
||||
|
||||
RUN file /build/parity/target/release/parity
|
||||
|
||||
FROM alpine:edge
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
|
||||
RUN apk add --no-cache \
|
||||
libstdc++ \
|
||||
eudev-libs \
|
||||
libgcc
|
||||
|
||||
RUN addgroup -g 1000 parity \
|
||||
&& adduser -u 1000 -G parity -s /bin/sh -D parity
|
||||
|
||||
USER parity
|
||||
|
||||
EXPOSE 8080 8545 8180
|
||||
ENTRYPOINT ["/build/parity/target/release/parity"]
|
||||
|
||||
WORKDIR /home/parity
|
||||
|
||||
RUN mkdir -p /home/parity/.local/share/io.parity.ethereum/
|
||||
COPY --chown=parity:parity --from=builder /parity/target/x86_64-alpine-linux-musl/release/parity ./
|
||||
|
||||
ENTRYPOINT ["./parity"]
|
||||
|
@ -1,36 +1,28 @@
|
||||
FROM centos:latest
|
||||
WORKDIR /build
|
||||
|
||||
# install tools and dependencies
|
||||
RUN yum -y update&& \
|
||||
yum install -y git make gcc-c++ gcc file binutils cmake
|
||||
RUN mkdir -p /opt/parity/data && \
|
||||
chmod g+rwX /opt/parity/data && \
|
||||
mkdir -p /opt/parity/release
|
||||
|
||||
# install rustup
|
||||
RUN curl -sSf https://static.rust-lang.org/rustup.sh -o rustup.sh &&\
|
||||
ls&&\
|
||||
sh rustup.sh --disable-sudo
|
||||
COPY parity/parity /opt/parity/release
|
||||
|
||||
# show backtraces
|
||||
ENV RUST_BACKTRACE 1
|
||||
WORKDIR /opt/parity/data
|
||||
|
||||
# exposing default ports
|
||||
#
|
||||
# secret
|
||||
# ipfs store ui rpc ws listener discovery
|
||||
# ↓ ↓ ↓ ↓ ↓ ↓ ↓
|
||||
EXPOSE 5001 8082 8083 8180 8545 8546 30303/tcp 30303/udp
|
||||
|
||||
# switch to non-root user
|
||||
USER 1001
|
||||
|
||||
#if no base path provided, assume it's current workdir
|
||||
CMD ["--base-path","."]
|
||||
ENTRYPOINT ["/opt/parity/release/parity"]
|
||||
|
||||
# set compiler
|
||||
ENV CXX g++
|
||||
ENV CC gcc
|
||||
|
||||
# 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"]
|
||||
|
25
docker/centos/Dockerfile.build
Normal file
25
docker/centos/Dockerfile.build
Normal 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
29
docker/centos/build.sh
Executable 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.
|
@ -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"]
|
@ -6,13 +6,14 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
primal = "0.2.3"
|
||||
parking_lot = "0.6"
|
||||
crunchy = "0.1.0"
|
||||
memmap = "0.6"
|
||||
either = "1.0.0"
|
||||
ethereum-types = "0.3"
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
log = "0.4"
|
||||
memmap = "0.6"
|
||||
parking_lot = "0.6"
|
||||
primal = "0.2.3"
|
||||
|
||||
[dev-dependencies]
|
||||
tempdir = "0.3"
|
||||
|
@ -16,10 +16,11 @@
|
||||
|
||||
#![cfg_attr(feature = "benches", feature(test))]
|
||||
|
||||
extern crate primal;
|
||||
extern crate parking_lot;
|
||||
extern crate either;
|
||||
extern crate ethereum_types;
|
||||
extern crate memmap;
|
||||
extern crate parking_lot;
|
||||
extern crate primal;
|
||||
|
||||
#[macro_use]
|
||||
extern crate crunchy;
|
||||
@ -38,6 +39,7 @@ mod shared;
|
||||
pub use cache::{NodeCacheBuilder, OptimizeFor};
|
||||
pub use compute::{ProofOfWork, quick_get_difficulty, slow_hash_block_number};
|
||||
use compute::Light;
|
||||
use ethereum_types::{U256, U512};
|
||||
use keccak::H256;
|
||||
use parking_lot::Mutex;
|
||||
pub use seed_compute::SeedHashCompute;
|
||||
@ -136,6 +138,29 @@ impl EthashManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn boundary_to_difficulty(boundary: ðereum_types::H256) -> U256 {
|
||||
difficulty_to_boundary_aux(&**boundary)
|
||||
}
|
||||
|
||||
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn difficulty_to_boundary(difficulty: &U256) -> ethereum_types::H256 {
|
||||
difficulty_to_boundary_aux(difficulty).into()
|
||||
}
|
||||
|
||||
fn difficulty_to_boundary_aux<T: Into<U512>>(difficulty: T) -> ethereum_types::U256 {
|
||||
let difficulty = difficulty.into();
|
||||
|
||||
assert!(!difficulty.is_zero());
|
||||
|
||||
if difficulty == U512::one() {
|
||||
U256::max_value()
|
||||
} else {
|
||||
// difficulty > 1, so result should never overflow 256 bits
|
||||
U256::from((U512::one() << 256) / difficulty)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lru() {
|
||||
use tempdir::TempDir;
|
||||
@ -155,6 +180,43 @@ fn test_lru() {
|
||||
assert_eq!(ethash.cache.lock().prev_epoch.unwrap(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary() {
|
||||
use ethereum_types::H256;
|
||||
use std::str::FromStr;
|
||||
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary_regression() {
|
||||
use ethereum_types::H256;
|
||||
|
||||
// the last bit was originally being truncated when performing the conversion
|
||||
// https://github.com/paritytech/parity-ethereum/issues/8397
|
||||
for difficulty in 1..9 {
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&difficulty_to_boundary(&difficulty.into())));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&boundary_to_difficulty(&difficulty.into())));
|
||||
assert_eq!(U256::from(difficulty), boundary_to_difficulty(&boundary_to_difficulty(&difficulty.into()).into()));
|
||||
assert_eq!(H256::from(difficulty), difficulty_to_boundary(&difficulty_to_boundary(&difficulty.into()).into()));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_difficulty_to_boundary_panics_on_zero() {
|
||||
difficulty_to_boundary(&U256::from(0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_boundary_to_difficulty_panics_on_zero() {
|
||||
boundary_to_difficulty(ðereum_types::H256::from(0));
|
||||
}
|
||||
|
||||
#[cfg(feature = "benches")]
|
||||
mod benchmarks {
|
||||
extern crate test;
|
||||
|
@ -39,7 +39,7 @@ evm = { path = "evm" }
|
||||
heapsize = "0.4"
|
||||
itertools = "0.5"
|
||||
lazy_static = "1.0"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
lru-cache = "0.1"
|
||||
num = { version = "0.1", default-features = false, features = ["bigint"] }
|
||||
num_cpus = "1.2"
|
||||
|
@ -5,10 +5,11 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
bit-set = "0.4"
|
||||
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
ethereum-types = "0.3"
|
||||
heapsize = "0.4"
|
||||
lazy_static = "1.0"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
vm = { path = "../vm" }
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
parking_lot = "0.6"
|
||||
|
@ -55,6 +55,12 @@ impl Finalize for Result<GasLeft> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Finalize for Error {
|
||||
fn finalize<E: Ext>(self, _ext: E) -> Result<FinalizationResult> {
|
||||
Err(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256
|
||||
pub trait CostType: Sized + From<usize> + Copy
|
||||
+ ops::Mul<Output=Self> + ops::Div<Output=Self> + ops::Add<Output=Self> +ops::Sub<Output=Self>
|
||||
|
@ -17,8 +17,9 @@
|
||||
//! Evm factory.
|
||||
//!
|
||||
use std::sync::Arc;
|
||||
use vm::Vm;
|
||||
use vm::{Vm, Schedule};
|
||||
use ethereum_types::U256;
|
||||
use super::vm::ActionParams;
|
||||
use super::interpreter::SharedCache;
|
||||
use super::vmtype::VMType;
|
||||
|
||||
@ -32,12 +33,12 @@ pub struct Factory {
|
||||
impl Factory {
|
||||
/// Create fresh instance of VM
|
||||
/// Might choose implementation depending on supplied gas.
|
||||
pub fn create(&self, gas: &U256) -> Box<Vm> {
|
||||
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
|
||||
match self.evm {
|
||||
VMType::Interpreter => if Self::can_fit_in_usize(gas) {
|
||||
Box::new(super::interpreter::Interpreter::<usize>::new(self.evm_cache.clone()))
|
||||
VMType::Interpreter => if Self::can_fit_in_usize(¶ms.gas) {
|
||||
Box::new(super::interpreter::Interpreter::<usize>::new(params, self.evm_cache.clone(), schedule, depth))
|
||||
} else {
|
||||
Box::new(super::interpreter::Interpreter::<U256>::new(self.evm_cache.clone()))
|
||||
Box::new(super::interpreter::Interpreter::<U256>::new(params, self.evm_cache.clone(), schedule, depth))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -68,7 +69,14 @@ impl Default for Factory {
|
||||
|
||||
#[test]
|
||||
fn test_create_vm() {
|
||||
let _vm = Factory::default().create(&U256::zero());
|
||||
use vm::Ext;
|
||||
use vm::tests::FakeExt;
|
||||
use bytes::Bytes;
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.code = Some(Arc::new(Bytes::default()));
|
||||
let ext = FakeExt::new();
|
||||
let _vm = Factory::default().create(params, ext.schedule(), ext.depth());
|
||||
}
|
||||
|
||||
/// Create tests by injecting different VM factories
|
||||
|
@ -119,15 +119,20 @@ impl Memory for Vec<u8> {
|
||||
fn into_return_data(mut self, offset: U256, size: U256) -> ReturnData {
|
||||
let mut offset = offset.low_u64() as usize;
|
||||
let size = size.low_u64() as usize;
|
||||
|
||||
if !is_valid_range(offset, size) {
|
||||
return ReturnData::empty()
|
||||
return ReturnData::empty();
|
||||
}
|
||||
|
||||
if self.len() - size > MAX_RETURN_WASTE_BYTES {
|
||||
{ let _ = self.drain(..offset); }
|
||||
if offset == 0 {
|
||||
self.truncate(size);
|
||||
self.shrink_to_fit();
|
||||
} else {
|
||||
self = self[offset..(offset + size)].to_vec();
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
ReturnData::new(self, offset, size)
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@ extern crate heapsize;
|
||||
extern crate vm;
|
||||
extern crate keccak_hash as hash;
|
||||
extern crate memory_cache;
|
||||
extern crate parity_bytes as bytes;
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
@ -21,7 +21,7 @@ use std::sync::Arc;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use rustc_hex::FromHex;
|
||||
use ethereum_types::{U256, H256, Address};
|
||||
use vm::{self, ActionParams, ActionValue};
|
||||
use vm::{self, ActionParams, ActionValue, Ext};
|
||||
use vm::tests::{FakeExt, FakeCall, FakeCallType, test_finalize};
|
||||
use factory::Factory;
|
||||
use vmtype::VMType;
|
||||
@ -38,8 +38,8 @@ fn test_add(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_988));
|
||||
@ -58,8 +58,8 @@ fn test_sha3(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_961));
|
||||
@ -78,8 +78,8 @@ fn test_address(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -100,8 +100,8 @@ fn test_origin(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -122,8 +122,8 @@ fn test_sender(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -157,8 +157,8 @@ fn test_extcodecopy(factory: super::Factory) {
|
||||
ext.codes.insert(sender, Arc::new(sender_code));
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_935));
|
||||
@ -177,8 +177,8 @@ fn test_log_empty(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(99_619));
|
||||
@ -209,8 +209,8 @@ fn test_log_sender(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(98_974));
|
||||
@ -234,8 +234,8 @@ fn test_blockhash(factory: super::Factory) {
|
||||
ext.blockhashes.insert(U256::zero(), blockhash.clone());
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_974));
|
||||
@ -256,8 +256,8 @@ fn test_calldataload(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_991));
|
||||
@ -277,8 +277,8 @@ fn test_author(factory: super::Factory) {
|
||||
ext.info.author = author;
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -297,8 +297,8 @@ fn test_timestamp(factory: super::Factory) {
|
||||
ext.info.timestamp = timestamp;
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -317,8 +317,8 @@ fn test_number(factory: super::Factory) {
|
||||
ext.info.number = number;
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -337,8 +337,8 @@ fn test_difficulty(factory: super::Factory) {
|
||||
ext.info.difficulty = difficulty;
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -357,8 +357,8 @@ fn test_gas_limit(factory: super::Factory) {
|
||||
ext.info.gas_limit = gas_limit;
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_995));
|
||||
@ -375,8 +375,8 @@ fn test_mul(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000734349397b853383");
|
||||
@ -393,8 +393,8 @@ fn test_sub(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000012364ad0302");
|
||||
@ -411,8 +411,8 @@ fn test_div(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
|
||||
@ -429,8 +429,8 @@ fn test_div_zero(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@ -447,8 +447,8 @@ fn test_mod(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
|
||||
@ -466,8 +466,8 @@ fn test_smod(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000076b4b");
|
||||
@ -485,8 +485,8 @@ fn test_sdiv(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "000000000000000000000000000000000000000000000000000000000002e0ac");
|
||||
@ -504,8 +504,8 @@ fn test_exp(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "90fd23767b60204c3d6fc8aec9e70a42a3f127140879c133a20129a597ed0c59");
|
||||
@ -524,8 +524,8 @@ fn test_comparison(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@ -545,8 +545,8 @@ fn test_signed_comparison(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@ -566,8 +566,8 @@ fn test_bitops(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
|
||||
@ -589,8 +589,8 @@ fn test_addmod_mulmod(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000001");
|
||||
@ -610,8 +610,8 @@ fn test_byte(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||
@ -629,8 +629,8 @@ fn test_signextend(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000fff");
|
||||
@ -649,8 +649,8 @@ fn test_badinstruction_int() {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let err = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap_err()
|
||||
};
|
||||
|
||||
match err {
|
||||
@ -669,8 +669,8 @@ fn test_pop(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "00000000000000000000000000000000000000000000000000000000000000f0");
|
||||
@ -689,8 +689,8 @@ fn test_extops(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000004"); // PC / CALLDATASIZE
|
||||
@ -712,8 +712,8 @@ fn test_jumps(factory: super::Factory) {
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(ext.sstore_clears, 1);
|
||||
@ -740,12 +740,13 @@ fn test_calls(factory: super::Factory) {
|
||||
};
|
||||
|
||||
let gas_left = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_set_contains(&ext.calls, &FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(2556),
|
||||
sender_address: Some(address.clone()),
|
||||
receive_address: Some(code_address.clone()),
|
||||
@ -755,6 +756,7 @@ fn test_calls(factory: super::Factory) {
|
||||
});
|
||||
assert_set_contains(&ext.calls, &FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(2556),
|
||||
sender_address: Some(address.clone()),
|
||||
receive_address: Some(address.clone()),
|
||||
@ -779,8 +781,8 @@ fn test_create_in_staticcall(factory: super::Factory) {
|
||||
ext.is_static = true;
|
||||
|
||||
let err = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap_err()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap_err()
|
||||
};
|
||||
|
||||
assert_eq!(err, vm::Error::MutableCallInStaticContext);
|
||||
@ -1047,8 +1049,8 @@ fn push_two_pop_one_constantinople_test(factory: &super::Factory, opcode: u8, pu
|
||||
let mut ext = FakeExt::new_constantinople();
|
||||
|
||||
let _ = {
|
||||
let mut vm = factory.create(¶ms.gas);
|
||||
test_finalize(vm.exec(params, &mut ext)).unwrap()
|
||||
let mut vm = factory.create(params, ext.schedule(), ext.depth());
|
||||
test_finalize(vm.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_store(&ext, 0, result);
|
||||
|
@ -7,7 +7,7 @@ version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
ethcore = { path = ".."}
|
||||
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
ethcore-transaction = { path = "../transaction" }
|
||||
@ -20,7 +20,7 @@ ethcore-io = { path = "../../util/io" }
|
||||
hashdb = { git = "https://github.com/paritytech/parity-common" }
|
||||
heapsize = "0.4"
|
||||
vm = { path = "../vm" }
|
||||
plain_hasher = { git = "https://github.com/paritytech/parity-common" }
|
||||
fastmap = { path = "../../util/fastmap" }
|
||||
rlp = { git = "https://github.com/paritytech/parity-common" }
|
||||
rlp_derive = { path = "../../util/rlp_derive" }
|
||||
smallvec = "0.4"
|
||||
|
@ -41,7 +41,7 @@ use ethereum_types::{H256, H264, U256};
|
||||
use heapsize::HeapSizeOf;
|
||||
use kvdb::{DBTransaction, KeyValueDB};
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use plain_hasher::H256FastMap;
|
||||
use fastmap::H256FastMap;
|
||||
use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
@ -68,7 +68,7 @@ extern crate keccak_hasher;
|
||||
extern crate memorydb;
|
||||
extern crate patricia_trie as trie;
|
||||
extern crate patricia_trie_ethereum as ethtrie;
|
||||
extern crate plain_hasher;
|
||||
extern crate fastmap;
|
||||
extern crate rand;
|
||||
extern crate rlp;
|
||||
extern crate parking_lot;
|
||||
|
@ -120,17 +120,15 @@ impl LoadDistribution {
|
||||
pub fn expected_time(&self, kind: Kind) -> Duration {
|
||||
let samples = self.samples.read();
|
||||
samples.get(&kind).and_then(|s| {
|
||||
if s.len() == 0 { return None }
|
||||
if s.is_empty() { return None }
|
||||
|
||||
let alpha: f64 = 1f64 / s.len() as f64;
|
||||
let start = s.front().expect("length known to be non-zero; qed").clone();
|
||||
let ema = s.iter().skip(1).fold(start as f64, |a, &c| {
|
||||
let alpha: f64 = 1_f64 / s.len() as f64;
|
||||
let start = *s.front().expect("length known to be non-zero; qed") as f64;
|
||||
let ema = s.iter().skip(1).fold(start, |a, &c| {
|
||||
(alpha * c as f64) + ((1.0 - alpha) * a)
|
||||
});
|
||||
|
||||
// TODO: use `Duration::from_nanos` once stable (https://github.com/rust-lang/rust/issues/46507)
|
||||
let ema = ema as u64;
|
||||
Some(Duration::new(ema / 1_000_000_000, (ema % 1_000_000_000) as u32))
|
||||
Some(Duration::from_nanos(ema as u64))
|
||||
}).unwrap_or_else(move || hardcoded_serve_time(kind))
|
||||
}
|
||||
|
||||
|
@ -823,7 +823,7 @@ impl LightProtocol {
|
||||
self.peers.write().insert(*peer, Mutex::new(Peer {
|
||||
local_credits: local_flow.create_credits(),
|
||||
status: status.clone(),
|
||||
capabilities: capabilities.clone(),
|
||||
capabilities,
|
||||
remote_flow: remote_flow,
|
||||
sent_head: pending.sent_head,
|
||||
last_update: pending.last_update,
|
||||
|
@ -169,7 +169,7 @@ impl Status {
|
||||
}
|
||||
|
||||
/// Peer capabilities.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Capabilities {
|
||||
/// Whether this peer can serve headers
|
||||
pub serve_headers: bool,
|
||||
|
@ -222,7 +222,7 @@ fn status(chain_info: BlockChainInfo) -> Status {
|
||||
fn handshake_expected() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
|
||||
let status = status(provider.client.chain_info());
|
||||
|
||||
@ -236,7 +236,7 @@ fn handshake_expected() {
|
||||
fn genesis_mismatch() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
|
||||
let mut status = status(provider.client.chain_info());
|
||||
status.genesis_hash = H256::default();
|
||||
@ -250,7 +250,7 @@ fn genesis_mismatch() {
|
||||
fn credit_overflow() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
|
||||
let status = status(provider.client.chain_info());
|
||||
|
||||
@ -283,7 +283,7 @@ fn credit_overflow() {
|
||||
fn get_block_headers() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
@ -335,7 +335,7 @@ fn get_block_headers() {
|
||||
fn get_block_bodies() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
@ -383,7 +383,7 @@ fn get_block_bodies() {
|
||||
fn get_block_receipts() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
@ -438,7 +438,7 @@ fn get_block_receipts() {
|
||||
fn get_state_proofs() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let provider = TestProvider(provider);
|
||||
@ -497,7 +497,7 @@ fn get_state_proofs() {
|
||||
fn get_contract_code() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
@ -540,7 +540,7 @@ fn get_contract_code() {
|
||||
fn epoch_signal() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
@ -583,7 +583,7 @@ fn epoch_signal() {
|
||||
fn proof_of_execution() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
@ -643,7 +643,7 @@ fn id_guard() {
|
||||
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let req_id_1 = ReqId(5143);
|
||||
@ -666,7 +666,7 @@ fn id_guard() {
|
||||
proto.peers.write().insert(peer_id, ::parking_lot::Mutex::new(Peer {
|
||||
local_credits: flow_params.create_credits(),
|
||||
status: status(provider.client.chain_info()),
|
||||
capabilities: capabilities.clone(),
|
||||
capabilities,
|
||||
remote_flow: Some((flow_params.create_credits(), (&*flow_params).clone())),
|
||||
sent_head: provider.client.chain_info().best_block_hash,
|
||||
last_update: Instant::now(),
|
||||
@ -723,7 +723,7 @@ fn id_guard() {
|
||||
fn get_transaction_index() {
|
||||
let capabilities = capabilities();
|
||||
|
||||
let (provider, proto) = setup(capabilities.clone());
|
||||
let (provider, proto) = setup(capabilities);
|
||||
let flow_params = proto.flow_params.read().clone();
|
||||
|
||||
let cur_status = status(provider.client.chain_info());
|
||||
|
@ -418,7 +418,7 @@ impl Handler for OnDemand {
|
||||
) -> PeerStatus {
|
||||
self.peers.write().insert(
|
||||
ctx.peer(),
|
||||
Peer { status: status.clone(), capabilities: capabilities.clone() }
|
||||
Peer { status: status.clone(), capabilities: *capabilities }
|
||||
);
|
||||
self.attempt_dispatch(ctx.as_basic());
|
||||
PeerStatus::Kept
|
||||
|
@ -38,7 +38,7 @@ use transaction::SignedTransaction;
|
||||
use trie::Trie;
|
||||
use vm::EnvInfo;
|
||||
|
||||
const SUPPLIED_MATCHES: &'static str = "supplied responses always match produced requests; enforced by `check_response`; qed";
|
||||
const SUPPLIED_MATCHES: &str = "supplied responses always match produced requests; enforced by `check_response`; qed";
|
||||
|
||||
/// Core unit of the API: submit batches of these to be answered with `Response`s.
|
||||
#[derive(Clone)]
|
||||
@ -265,30 +265,35 @@ impl From<Request> for CheckedRequest {
|
||||
max: 1,
|
||||
reverse: false,
|
||||
};
|
||||
trace!(target: "on_demand", "HeaderByHash Request, {:?}", net_req);
|
||||
CheckedRequest::HeaderByHash(req, net_req)
|
||||
}
|
||||
Request::HeaderProof(req) => {
|
||||
let net_req = net_request::IncompleteHeaderProofRequest {
|
||||
num: req.num().into(),
|
||||
};
|
||||
trace!(target: "on_demand", "HeaderProof Request, {:?}", net_req);
|
||||
CheckedRequest::HeaderProof(req, net_req)
|
||||
}
|
||||
Request::TransactionIndex(req) => {
|
||||
let net_req = net_request::IncompleteTransactionIndexRequest {
|
||||
hash: req.0.clone(),
|
||||
};
|
||||
trace!(target: "on_demand", "TransactionIndex Request, {:?}", net_req);
|
||||
CheckedRequest::TransactionIndex(req, net_req)
|
||||
}
|
||||
Request::Body(req) => {
|
||||
let net_req = net_request::IncompleteBodyRequest {
|
||||
hash: req.0.field(),
|
||||
};
|
||||
trace!(target: "on_demand", "Body Request, {:?}", net_req);
|
||||
CheckedRequest::Body(req, net_req)
|
||||
}
|
||||
Request::Receipts(req) => {
|
||||
let net_req = net_request::IncompleteReceiptsRequest {
|
||||
hash: req.0.field(),
|
||||
};
|
||||
trace!(target: "on_demand", "Receipt Request, {:?}", net_req);
|
||||
CheckedRequest::Receipts(req, net_req)
|
||||
}
|
||||
Request::Account(req) => {
|
||||
@ -296,6 +301,7 @@ impl From<Request> for CheckedRequest {
|
||||
block_hash: req.header.field(),
|
||||
address_hash: ::hash::keccak(&req.address).into(),
|
||||
};
|
||||
trace!(target: "on_demand", "Account Request, {:?}", net_req);
|
||||
CheckedRequest::Account(req, net_req)
|
||||
}
|
||||
Request::Code(req) => {
|
||||
@ -303,6 +309,7 @@ impl From<Request> for CheckedRequest {
|
||||
block_hash: req.header.field(),
|
||||
code_hash: req.code_hash.into(),
|
||||
};
|
||||
trace!(target: "on_demand", "Code Request, {:?}", net_req);
|
||||
CheckedRequest::Code(req, net_req)
|
||||
}
|
||||
Request::Execution(req) => {
|
||||
@ -315,12 +322,14 @@ impl From<Request> for CheckedRequest {
|
||||
value: req.tx.value,
|
||||
data: req.tx.data.clone(),
|
||||
};
|
||||
trace!(target: "on_demand", "Execution request, {:?}", net_req);
|
||||
CheckedRequest::Execution(req, net_req)
|
||||
}
|
||||
Request::Signal(req) => {
|
||||
let net_req = net_request::IncompleteSignalRequest {
|
||||
block_hash: req.hash.into(),
|
||||
};
|
||||
trace!(target: "on_demand", "Signal Request, {:?}", net_req);
|
||||
CheckedRequest::Signal(req, net_req)
|
||||
}
|
||||
}
|
||||
@ -507,15 +516,42 @@ impl IncompleteRequest for CheckedRequest {
|
||||
|
||||
fn complete(self) -> Result<Self::Complete, net_request::NoSuchOutput> {
|
||||
match self {
|
||||
CheckedRequest::HeaderProof(_, req) => req.complete().map(CompleteRequest::HeaderProof),
|
||||
CheckedRequest::HeaderByHash(_, req) => req.complete().map(CompleteRequest::Headers),
|
||||
CheckedRequest::TransactionIndex(_, req) => req.complete().map(CompleteRequest::TransactionIndex),
|
||||
CheckedRequest::Receipts(_, req) => req.complete().map(CompleteRequest::Receipts),
|
||||
CheckedRequest::Body(_, req) => req.complete().map(CompleteRequest::Body),
|
||||
CheckedRequest::Account(_, req) => req.complete().map(CompleteRequest::Account),
|
||||
CheckedRequest::Code(_, req) => req.complete().map(CompleteRequest::Code),
|
||||
CheckedRequest::Execution(_, req) => req.complete().map(CompleteRequest::Execution),
|
||||
CheckedRequest::Signal(_, req) => req.complete().map(CompleteRequest::Signal),
|
||||
CheckedRequest::HeaderProof(_, req) => {
|
||||
trace!(target: "on_demand", "HeaderProof request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::HeaderProof)
|
||||
}
|
||||
CheckedRequest::HeaderByHash(_, req) => {
|
||||
trace!(target: "on_demand", "HeaderByHash request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Headers)
|
||||
}
|
||||
CheckedRequest::TransactionIndex(_, req) => {
|
||||
trace!(target: "on_demand", "TransactionIndex request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::TransactionIndex)
|
||||
}
|
||||
CheckedRequest::Receipts(_, req) => {
|
||||
trace!(target: "on_demand", "Receipt request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Receipts)
|
||||
}
|
||||
CheckedRequest::Body(_, req) => {
|
||||
trace!(target: "on_demand", "Block request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Body)
|
||||
}
|
||||
CheckedRequest::Account(_, req) => {
|
||||
trace!(target: "on_demand", "Account request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Account)
|
||||
}
|
||||
CheckedRequest::Code(_, req) => {
|
||||
trace!(target: "on_demand", "Code request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Code)
|
||||
}
|
||||
CheckedRequest::Execution(_, req) => {
|
||||
trace!(target: "on_demand", "Execution request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Execution)
|
||||
}
|
||||
CheckedRequest::Signal(_, req) => {
|
||||
trace!(target: "on_demand", "Signal request completed {:?}", req);
|
||||
req.complete().map(CompleteRequest::Signal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -772,11 +808,13 @@ impl Body {
|
||||
let header = self.0.as_ref()?;
|
||||
let tx_root = ::triehash::ordered_trie_root(body.transactions_rlp().iter().map(|r| r.as_raw()));
|
||||
if tx_root != header.transactions_root() {
|
||||
trace!(target: "on_demand", "Body Response: \"WrongTrieRoot\" tx_root: {:?} header_root: {:?}", tx_root, header.transactions_root());
|
||||
return Err(Error::WrongTrieRoot(header.transactions_root(), tx_root));
|
||||
}
|
||||
|
||||
let uncles_hash = keccak(body.uncles_rlp().as_raw());
|
||||
if uncles_hash != header.uncles_hash() {
|
||||
trace!(target: "on_demand", "Body Response: \"WrongHash\" tx_root: {:?} header_root: {:?}", uncles_hash, header.uncles_hash());
|
||||
return Err(Error::WrongHash(header.uncles_hash(), uncles_hash));
|
||||
}
|
||||
|
||||
@ -784,7 +822,6 @@ impl Body {
|
||||
let block = encoded::Block::new_from_header_and_body(&header.view(), &body.view());
|
||||
|
||||
cache.lock().insert_block_body(header.hash(), body.clone());
|
||||
|
||||
Ok(block)
|
||||
}
|
||||
}
|
||||
@ -804,7 +841,10 @@ impl BlockReceipts {
|
||||
cache.lock().insert_block_receipts(receipts_root, receipts.to_vec());
|
||||
Ok(receipts.to_vec())
|
||||
}
|
||||
false => Err(Error::WrongTrieRoot(receipts_root, found_root)),
|
||||
false => {
|
||||
trace!(target: "on_demand", "Receipt Reponse: \"WrongTrieRoot\" receipts_root: {:?} found_root: {:?}", receipts_root, found_root);
|
||||
Err(Error::WrongTrieRoot(receipts_root, found_root))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -837,7 +877,10 @@ impl Account {
|
||||
code_hash: rlp.val_at(3)?,
|
||||
}))
|
||||
},
|
||||
None => Ok(None),
|
||||
None => {
|
||||
trace!(target: "on_demand", "Account {:?} not found", self.address);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -899,9 +942,18 @@ impl TransactionProof {
|
||||
);
|
||||
|
||||
match proved_execution {
|
||||
ProvedExecution::BadProof => Err(Error::BadProof),
|
||||
ProvedExecution::Failed(e) => Ok(Err(e)),
|
||||
ProvedExecution::Complete(e) => Ok(Ok(e)),
|
||||
ProvedExecution::BadProof => {
|
||||
trace!(target: "on_demand", "BadExecution Proof");
|
||||
Err(Error::BadProof)
|
||||
}
|
||||
ProvedExecution::Failed(e) => {
|
||||
trace!(target: "on_demand", "Execution Proof failed: {:?}", e);
|
||||
Ok(Err(e))
|
||||
}
|
||||
ProvedExecution::Complete(e) => {
|
||||
trace!(target: "on_demand", "Execution successful: {:?}", e);
|
||||
Ok(Ok(e))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ use std::collections::hash_map::Entry;
|
||||
|
||||
use transaction::{self, Condition, PendingTransaction, SignedTransaction};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use plain_hasher::H256FastMap;
|
||||
use fastmap::H256FastMap;
|
||||
|
||||
// Knowledge of an account's current nonce.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -11,7 +11,7 @@ ethcore = { path = ".."}
|
||||
ethcore-network = { path = "../../util/network" }
|
||||
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
|
||||
ethereum-types = "0.3"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
parking_lot = "0.6"
|
||||
ethabi = "5.1"
|
||||
ethabi-derive = "5.0"
|
||||
|
@ -23,7 +23,7 @@ ethkey = { path = "../../ethkey" }
|
||||
fetch = { path = "../../util/fetch" }
|
||||
futures = "0.1"
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
parking_lot = "0.6"
|
||||
patricia-trie = { git = "https://github.com/paritytech/parity-common" }
|
||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||
|
@ -19,7 +19,7 @@
|
||||
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
|
||||
]
|
||||
},
|
||||
"validateScoreTransition": 1000000,
|
||||
"validateScoreTransition": 4301764,
|
||||
"validateStepTransition": 1500000,
|
||||
"maximumUncleCountTransition": 5067000,
|
||||
"maximumUncleCount": 0
|
||||
|
@ -16,7 +16,16 @@
|
||||
"gasLimitBoundDivisor": "0x400",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x62121",
|
||||
"wasmActivationTransition": 4000000
|
||||
"wasmActivationTransition": 6666666,
|
||||
"eip140Transition": 6666666,
|
||||
"eip211Transition": 6666666,
|
||||
"eip214Transition": 6666666,
|
||||
"eip658Transition": 6666666,
|
||||
|
||||
"maxCodeSize": 24576,
|
||||
"maxCodeSizeTransition": 6666666,
|
||||
|
||||
"registrar": "0xb8624dc8cb3ca3147c178ac4c21734eb49e04071"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@ -43,12 +52,22 @@
|
||||
},
|
||||
"0x4ba15b56452521c0826a35a6f2022e1210fc519b": {
|
||||
"balance": "0x7E37BE2022B2B09472D89C0000"
|
||||
}
|
||||
},
|
||||
|
||||
"0x0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "activate_at": 6666666, "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "activate_at": 6666666, "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0x0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "activate_at": 6666666, "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0x0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "activate_at": 6666666, "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 6666666, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 6666666, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 6666666, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 6666666, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
|
||||
},
|
||||
|
||||
"nodes": [
|
||||
"enode://147573f46fe9f5cc38fbe070089a31390baec5dd2827c8f2ef168833e4d0254fbee3969a02c5b9910ea5d5b23d86a6ed5eabcda17cc12007b7d9178b6c697aa5@37.120.168.56:30303",
|
||||
"enode://a370d5fd55959f20af6d1565b151a760c1372f5a2aaf674d4892cd4fd2de0d1f672781cd40e0d4e4b51c5823527ddec73b31cc14ac685449d9f0866996a16b9f@13.76.165.180:30303",
|
||||
"enode://da019fa5fb1fda105100d68a986938ec15ac5c6ff69d6e4ad3e350e377057f3e67e33aea5feb22d5cdcfc22041d141c8453c77baa64a216fff98f191ca76b3ec@18.220.108.238:30303",
|
||||
"enode://49498fb8cdcd79c813ccdaa9496a3a4be0a187a3183e99adbc04d9c90b9a62ad59f0b6832f6e43b48e63fbebf74ec5438eb0d6d9098330edf36413d276fedf81@13.80.148.117:30303"
|
||||
"enode://eda34244538d72f42605a6fc8b8a34b15714c683989e8b29dc9e7a2b2088da490a5b32f2c149bec5a5c482bf03ec2c4f38b833ae31e36fcb26fb05fd094b2a88@18.197.33.9:30303",
|
||||
"enode://12e903e900137b02b22e01f7918bd6e7310773c313e4e577281f35597e394a3e0b54c7314a8970a9776c5a3e5dc4daee289215dea3897bcb6d5cf0bb1dd2d356@18.197.31.231:30303",
|
||||
"enode://423fdb91b37ec0714af0c19f625ec4af3ada2844367a36e45a05703577a84f7f0e9483585d4950a35c9e3738dba8c6abd7e1ce278d9a1f3f28065bc009f409cd@52.221.203.209:30303",
|
||||
"enode://a9327d37d07799817d4a3e13d49fb4f5cc1486d4adf3ec8a6b98be62c4d7a5453914a5139dbe124809a388514cb0be37f9fa799539abe2250672f6d3d778b821@18.191.209.251:30303"
|
||||
]
|
||||
}
|
||||
|
@ -17,7 +17,8 @@
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x69",
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"transactionPermissionContract": "0x0000000000000000000000000000000000000005"
|
||||
"transactionPermissionContract": "0x0000000000000000000000000000000000000005",
|
||||
"transactionPermissionContractTransition": "1"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -17,7 +17,8 @@
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID" : "0x69",
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"transactionPermissionContract": "0x0000000000000000000000000000000000000005"
|
||||
"transactionPermissionContract": "0x0000000000000000000000000000000000000005",
|
||||
"transactionPermissionContractTransition": "1"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 474110de59a0f632b20615256c913b144c49354c
|
||||
Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd
|
@ -11,7 +11,7 @@ ethcore-io = { path = "../../util/io" }
|
||||
ethcore-private-tx = { path = "../private-tx" }
|
||||
ethcore-sync = { path = "../sync" }
|
||||
kvdb = { git = "https://github.com/paritytech/parity-common" }
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
stop-guard = { path = "../../util/stop-guard" }
|
||||
trace-time = { path = "../../util/trace-time" }
|
||||
|
||||
|
@ -95,6 +95,7 @@ impl ClientService {
|
||||
let pruning = config.pruning;
|
||||
let client = Client::new(config, &spec, blockchain_db.clone(), miner.clone(), io_service.channel())?;
|
||||
miner.set_io_channel(io_service.channel());
|
||||
miner.set_in_chain_checker(&client.clone());
|
||||
|
||||
let snapshot_params = SnapServiceParams {
|
||||
engine: spec.engine.clone(),
|
||||
|
@ -18,9 +18,9 @@
|
||||
|
||||
mod stores;
|
||||
|
||||
use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy};
|
||||
use self::stores::AddressBook;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
@ -96,20 +96,6 @@ impl From<SSError> for SignError {
|
||||
/// `AccountProvider` errors.
|
||||
pub type Error = SSError;
|
||||
|
||||
/// Dapp identifier
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||
pub struct DappId(String);
|
||||
|
||||
impl From<DappId> for String {
|
||||
fn from(id: DappId) -> String { id.0 }
|
||||
}
|
||||
impl From<String> for DappId {
|
||||
fn from(id: String) -> DappId { DappId(id) }
|
||||
}
|
||||
impl<'a> From<&'a str> for DappId {
|
||||
fn from(id: &'a str) -> DappId { DappId(id.to_owned()) }
|
||||
}
|
||||
|
||||
fn transient_sstore() -> EthMultiStore {
|
||||
EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")
|
||||
}
|
||||
@ -125,8 +111,6 @@ pub struct AccountProvider {
|
||||
unlocked: RwLock<HashMap<StoreAccountRef, AccountData>>,
|
||||
/// Address book.
|
||||
address_book: RwLock<AddressBook>,
|
||||
/// Dapps settings.
|
||||
dapps_settings: RwLock<DappsSettingsStore>,
|
||||
/// Accounts on disk
|
||||
sstore: Box<SecretStore>,
|
||||
/// Accounts unlocked with rolling tokens
|
||||
@ -195,7 +179,6 @@ impl AccountProvider {
|
||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||
unlocked: RwLock::new(HashMap::new()),
|
||||
address_book: RwLock::new(address_book),
|
||||
dapps_settings: RwLock::new(DappsSettingsStore::new(&sstore.local_path())),
|
||||
sstore: sstore,
|
||||
transient_sstore: transient_sstore(),
|
||||
hardware_store: hardware_store,
|
||||
@ -210,7 +193,6 @@ impl AccountProvider {
|
||||
unlocked_secrets: RwLock::new(HashMap::new()),
|
||||
unlocked: RwLock::new(HashMap::new()),
|
||||
address_book: RwLock::new(AddressBook::transient()),
|
||||
dapps_settings: RwLock::new(DappsSettingsStore::transient()),
|
||||
sstore: Box::new(EthStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed")),
|
||||
transient_sstore: transient_sstore(),
|
||||
hardware_store: None,
|
||||
@ -290,6 +272,11 @@ impl AccountProvider {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the address of default account.
|
||||
pub fn default_account(&self) -> Result<Address, Error> {
|
||||
Ok(self.accounts()?.first().cloned().unwrap_or_default())
|
||||
}
|
||||
|
||||
/// Returns addresses of hardware accounts.
|
||||
pub fn hardware_accounts(&self) -> Result<Vec<Address>, Error> {
|
||||
if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) {
|
||||
@ -318,175 +305,6 @@ impl AccountProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets addresses of accounts exposed for unknown dapps.
|
||||
/// `None` means that all accounts will be visible.
|
||||
/// If not `None` or empty it will also override default account.
|
||||
pub fn set_new_dapps_addresses(&self, accounts: Option<Vec<Address>>) -> Result<(), Error> {
|
||||
let current_default = self.new_dapps_default_address()?;
|
||||
|
||||
self.dapps_settings.write().set_policy(match accounts {
|
||||
None => NewDappsPolicy::AllAccounts {
|
||||
default: current_default,
|
||||
},
|
||||
Some(accounts) => NewDappsPolicy::Whitelist(accounts),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets addresses of accounts exposed for unknown dapps.
|
||||
/// `None` means that all accounts will be visible.
|
||||
pub fn new_dapps_addresses(&self) -> Result<Option<Vec<Address>>, Error> {
|
||||
Ok(match self.dapps_settings.read().policy() {
|
||||
NewDappsPolicy::AllAccounts { .. } => None,
|
||||
NewDappsPolicy::Whitelist(accounts) => Some(accounts),
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets a default account for unknown dapps.
|
||||
/// This account will always be returned as the first one.
|
||||
pub fn set_new_dapps_default_address(&self, address: Address) -> Result<(), Error> {
|
||||
if !self.valid_addresses()?.contains(&address) {
|
||||
return Err(SSError::InvalidAccount.into());
|
||||
}
|
||||
|
||||
let mut settings = self.dapps_settings.write();
|
||||
let new_policy = match settings.policy() {
|
||||
NewDappsPolicy::AllAccounts { .. } => NewDappsPolicy::AllAccounts { default: address },
|
||||
NewDappsPolicy::Whitelist(list) => NewDappsPolicy::Whitelist(Self::insert_default(list, address)),
|
||||
};
|
||||
settings.set_policy(new_policy);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inserts given address as first in the vector, preventing duplicates.
|
||||
fn insert_default(mut addresses: Vec<Address>, default: Address) -> Vec<Address> {
|
||||
if let Some(position) = addresses.iter().position(|address| address == &default) {
|
||||
addresses.swap(0, position);
|
||||
} else {
|
||||
addresses.insert(0, default);
|
||||
}
|
||||
|
||||
addresses
|
||||
}
|
||||
|
||||
/// Returns a list of accounts that new dapp should see.
|
||||
/// First account is always the default account.
|
||||
fn new_dapps_addresses_list(&self) -> Result<Vec<Address>, Error> {
|
||||
match self.dapps_settings.read().policy() {
|
||||
NewDappsPolicy::AllAccounts { default } => if default.is_zero() {
|
||||
self.accounts()
|
||||
} else {
|
||||
Ok(Self::insert_default(self.accounts()?, default))
|
||||
},
|
||||
NewDappsPolicy::Whitelist(accounts) => {
|
||||
let addresses = self.filter_addresses(accounts)?;
|
||||
if addresses.is_empty() {
|
||||
Ok(vec![self.accounts()?.get(0).cloned().unwrap_or(0.into())])
|
||||
} else {
|
||||
Ok(addresses)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a default account for new dapps
|
||||
/// Will return zero address in case the default is not set and there are no accounts configured.
|
||||
pub fn new_dapps_default_address(&self) -> Result<Address, Error> {
|
||||
Ok(self.new_dapps_addresses_list()?
|
||||
.get(0)
|
||||
.cloned()
|
||||
.unwrap_or(0.into())
|
||||
)
|
||||
}
|
||||
|
||||
/// Gets a list of dapps recently requesting accounts.
|
||||
pub fn recent_dapps(&self) -> Result<HashMap<DappId, u64>, Error> {
|
||||
Ok(self.dapps_settings.read().recent_dapps())
|
||||
}
|
||||
|
||||
/// Marks dapp as recently used.
|
||||
pub fn note_dapp_used(&self, dapp: DappId) -> Result<(), Error> {
|
||||
let mut dapps = self.dapps_settings.write();
|
||||
dapps.mark_dapp_used(dapp.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets addresses visible for given dapp.
|
||||
pub fn dapp_addresses(&self, dapp: DappId) -> Result<Vec<Address>, Error> {
|
||||
let accounts = self.dapps_settings.read().settings().get(&dapp).map(|settings| {
|
||||
(settings.accounts.clone(), settings.default.clone())
|
||||
});
|
||||
|
||||
match accounts {
|
||||
Some((Some(accounts), Some(default))) => self.filter_addresses(Self::insert_default(accounts, default)),
|
||||
Some((Some(accounts), None)) => self.filter_addresses(accounts),
|
||||
Some((None, Some(default))) => self.filter_addresses(Self::insert_default(self.new_dapps_addresses_list()?, default)),
|
||||
_ => self.new_dapps_addresses_list(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns default account for particular dapp falling back to other allowed accounts if necessary.
|
||||
pub fn dapp_default_address(&self, dapp: DappId) -> Result<Address, Error> {
|
||||
let dapp_default = self.dapp_addresses(dapp)?
|
||||
.get(0)
|
||||
.cloned();
|
||||
|
||||
match dapp_default {
|
||||
Some(default) => Ok(default),
|
||||
None => self.new_dapps_default_address(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets default address for given dapp.
|
||||
/// Does not alter dapp addresses, but this account will always be returned as the first one.
|
||||
pub fn set_dapp_default_address(&self, dapp: DappId, address: Address) -> Result<(), Error> {
|
||||
if !self.valid_addresses()?.contains(&address) {
|
||||
return Err(SSError::InvalidAccount.into());
|
||||
}
|
||||
|
||||
self.dapps_settings.write().set_default(dapp, address);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets addresses visible for given dapp.
|
||||
/// If `None` - falls back to dapps addresses
|
||||
/// If not `None` and not empty it will also override default account.
|
||||
pub fn set_dapp_addresses(&self, dapp: DappId, addresses: Option<Vec<Address>>) -> Result<(), Error> {
|
||||
let (addresses, default) = match addresses {
|
||||
Some(addresses) => {
|
||||
let addresses = self.filter_addresses(addresses)?;
|
||||
let default = addresses.get(0).cloned();
|
||||
(Some(addresses), default)
|
||||
},
|
||||
None => (None, None),
|
||||
};
|
||||
|
||||
let mut settings = self.dapps_settings.write();
|
||||
if let Some(default) = default {
|
||||
settings.set_default(dapp.clone(), default);
|
||||
}
|
||||
settings.set_accounts(dapp, addresses);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn valid_addresses(&self) -> Result<HashSet<Address>, Error> {
|
||||
Ok(self.addresses_info().into_iter()
|
||||
.map(|(address, _)| address)
|
||||
.chain(self.accounts()?)
|
||||
.collect())
|
||||
}
|
||||
|
||||
/// Removes addresses that are neither accounts nor in address book.
|
||||
fn filter_addresses(&self, addresses: Vec<Address>) -> Result<Vec<Address>, Error> {
|
||||
let valid = self.valid_addresses()?;
|
||||
|
||||
Ok(addresses.into_iter()
|
||||
.filter(|a| valid.contains(&a))
|
||||
.collect()
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns each address along with metadata.
|
||||
pub fn addresses_info(&self) -> HashMap<Address, AccountMeta> {
|
||||
self.address_book.read().get()
|
||||
@ -849,7 +667,7 @@ impl AccountProvider {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AccountProvider, Unlock, DappId};
|
||||
use super::{AccountProvider, Unlock};
|
||||
use std::time::{Duration, Instant};
|
||||
use ethstore::ethkey::{Generator, Random, Address};
|
||||
use ethstore::{StoreAccountRef, Derivation};
|
||||
@ -977,96 +795,6 @@ mod tests {
|
||||
assert!(ap.sign_with_token(kp.address(), token, Default::default()).is_err(), "Second usage of the same token should fail.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_reset_dapp_addresses_to_default() {
|
||||
// given
|
||||
let ap = AccountProvider::transient_provider();
|
||||
let app = DappId("app1".into());
|
||||
// add accounts to address book
|
||||
ap.set_address_name(1.into(), "1".into());
|
||||
ap.set_address_name(2.into(), "2".into());
|
||||
// set `AllAccounts` policy
|
||||
ap.set_new_dapps_addresses(Some(vec![1.into(), 2.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
||||
|
||||
// Alter and check
|
||||
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 3.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
|
||||
|
||||
// Reset back to default
|
||||
ap.set_dapp_addresses(app.clone(), None).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_set_dapps_default_address() {
|
||||
// given
|
||||
let ap = AccountProvider::transient_provider();
|
||||
let app = DappId("app1".into());
|
||||
// set `AllAccounts` policy
|
||||
ap.set_new_dapps_addresses(None).unwrap();
|
||||
// add accounts to address book
|
||||
ap.set_address_name(1.into(), "1".into());
|
||||
ap.set_address_name(2.into(), "2".into());
|
||||
|
||||
ap.set_dapp_addresses(app.clone(), Some(vec![1.into(), 2.into(), 3.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into(), 2.into()]);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
||||
|
||||
// when setting empty list
|
||||
ap.set_dapp_addresses(app.clone(), Some(vec![])).unwrap();
|
||||
|
||||
// then default account is intact
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![1.into()]);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
||||
|
||||
// alter default account
|
||||
ap.set_dapp_default_address("app1".into(), 2.into()).unwrap();
|
||||
assert_eq!(ap.dapp_addresses(app.clone()).unwrap(), vec![2.into()]);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 2.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_set_dapps_policy_and_default_account() {
|
||||
// given
|
||||
let ap = AccountProvider::transient_provider();
|
||||
|
||||
// default_account should be always available
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), 0.into());
|
||||
|
||||
let address = ap.new_account(&"test".into()).unwrap();
|
||||
ap.set_address_name(1.into(), "1".into());
|
||||
|
||||
// Default account set to first account by default
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
|
||||
|
||||
// Even when returning nothing
|
||||
ap.set_new_dapps_addresses(Some(vec![])).unwrap();
|
||||
// Default account is still returned
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
||||
|
||||
// change to all
|
||||
ap.set_new_dapps_addresses(None).unwrap();
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
||||
|
||||
// change to non-existent account
|
||||
ap.set_new_dapps_addresses(Some(vec![2.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![address]);
|
||||
|
||||
// change to a addresses
|
||||
ap.set_new_dapps_addresses(Some(vec![1.into()])).unwrap();
|
||||
assert_eq!(ap.dapp_addresses("app1".into()).unwrap(), vec![1.into()]);
|
||||
|
||||
// it overrides default account
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), 1.into());
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), 1.into());
|
||||
|
||||
ap.set_new_dapps_default_address(address).unwrap();
|
||||
assert_eq!(ap.new_dapps_default_address().unwrap(), address);
|
||||
assert_eq!(ap.dapp_default_address("app1".into()).unwrap(), address);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_return_blacklisted_account() {
|
||||
// given
|
||||
|
@ -14,21 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Address Book and Dapps Settings Store
|
||||
//! Address Book Store
|
||||
|
||||
use std::{fs, fmt, hash, ops};
|
||||
use std::sync::atomic::{self, AtomicUsize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use ethstore::ethkey::Address;
|
||||
use ethjson::misc::{
|
||||
AccountMeta,
|
||||
DappsSettings as JsonSettings,
|
||||
DappsHistory as JsonDappsHistory,
|
||||
NewDappsPolicy as JsonNewDappsPolicy,
|
||||
};
|
||||
use account_provider::DappId;
|
||||
use ethjson::misc::AccountMeta;
|
||||
|
||||
/// Disk-backed map from Address to String. Uses JSON.
|
||||
pub struct AddressBook {
|
||||
@ -88,214 +81,6 @@ impl AddressBook {
|
||||
}
|
||||
}
|
||||
|
||||
/// Dapps user settings
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq)]
|
||||
pub struct DappsSettings {
|
||||
/// A list of visible accounts
|
||||
pub accounts: Option<Vec<Address>>,
|
||||
/// Default account
|
||||
pub default: Option<Address>,
|
||||
}
|
||||
|
||||
impl From<JsonSettings> for DappsSettings {
|
||||
fn from(s: JsonSettings) -> Self {
|
||||
DappsSettings {
|
||||
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
|
||||
default: s.default.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DappsSettings> for JsonSettings {
|
||||
fn from(s: DappsSettings) -> Self {
|
||||
JsonSettings {
|
||||
accounts: s.accounts.map(|accounts| accounts.into_iter().map(Into::into).collect()),
|
||||
default: s.default.map(Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dapps user settings
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum NewDappsPolicy {
|
||||
AllAccounts {
|
||||
default: Address,
|
||||
},
|
||||
Whitelist(Vec<Address>),
|
||||
}
|
||||
|
||||
impl From<JsonNewDappsPolicy> for NewDappsPolicy {
|
||||
fn from(s: JsonNewDappsPolicy) -> Self {
|
||||
match s {
|
||||
JsonNewDappsPolicy::AllAccounts { default } => NewDappsPolicy::AllAccounts {
|
||||
default: default.into(),
|
||||
},
|
||||
JsonNewDappsPolicy::Whitelist(accounts) => NewDappsPolicy::Whitelist(
|
||||
accounts.into_iter().map(Into::into).collect()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NewDappsPolicy> for JsonNewDappsPolicy {
|
||||
fn from(s: NewDappsPolicy) -> Self {
|
||||
match s {
|
||||
NewDappsPolicy::AllAccounts { default } => JsonNewDappsPolicy::AllAccounts {
|
||||
default: default.into(),
|
||||
},
|
||||
NewDappsPolicy::Whitelist(accounts) => JsonNewDappsPolicy::Whitelist(
|
||||
accounts.into_iter().map(Into::into).collect()
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Transient dapps data
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct TransientDappsData {
|
||||
/// Timestamp of last access
|
||||
pub last_accessed: u64,
|
||||
}
|
||||
|
||||
impl From<JsonDappsHistory> for TransientDappsData {
|
||||
fn from(s: JsonDappsHistory) -> Self {
|
||||
TransientDappsData {
|
||||
last_accessed: s.last_accessed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TransientDappsData> for JsonDappsHistory {
|
||||
fn from(s: TransientDappsData) -> Self {
|
||||
JsonDappsHistory {
|
||||
last_accessed: s.last_accessed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum TimeProvider {
|
||||
Clock,
|
||||
Incremenetal(AtomicUsize)
|
||||
}
|
||||
|
||||
impl TimeProvider {
|
||||
fn get(&self) -> u64 {
|
||||
match *self {
|
||||
TimeProvider::Clock => {
|
||||
::std::time::UNIX_EPOCH.elapsed()
|
||||
.expect("Correct time is required to be set")
|
||||
.as_secs()
|
||||
|
||||
},
|
||||
TimeProvider::Incremenetal(ref time) => {
|
||||
time.fetch_add(1, atomic::Ordering::SeqCst) as u64
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const MAX_RECENT_DAPPS: usize = 50;
|
||||
|
||||
/// Disk-backed map from DappId to Settings. Uses JSON.
|
||||
pub struct DappsSettingsStore {
|
||||
/// Dapps Settings
|
||||
settings: DiskMap<DappId, DappsSettings>,
|
||||
/// New Dapps Policy
|
||||
policy: DiskMap<String, NewDappsPolicy>,
|
||||
/// Transient Data of recently Accessed Dapps
|
||||
history: DiskMap<DappId, TransientDappsData>,
|
||||
/// Time
|
||||
time: TimeProvider,
|
||||
}
|
||||
|
||||
impl DappsSettingsStore {
|
||||
/// Creates new store at given directory path.
|
||||
pub fn new(path: &Path) -> Self {
|
||||
let mut r = DappsSettingsStore {
|
||||
settings: DiskMap::new(path, "dapps_accounts.json".into()),
|
||||
policy: DiskMap::new(path, "dapps_policy.json".into()),
|
||||
history: DiskMap::new(path, "dapps_history.json".into()),
|
||||
time: TimeProvider::Clock,
|
||||
};
|
||||
r.settings.revert(JsonSettings::read);
|
||||
r.policy.revert(JsonNewDappsPolicy::read);
|
||||
r.history.revert(JsonDappsHistory::read);
|
||||
r
|
||||
}
|
||||
|
||||
/// Creates transient store (no changes are saved to disk).
|
||||
pub fn transient() -> Self {
|
||||
DappsSettingsStore {
|
||||
settings: DiskMap::transient(),
|
||||
policy: DiskMap::transient(),
|
||||
history: DiskMap::transient(),
|
||||
time: TimeProvider::Incremenetal(AtomicUsize::new(1)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get copy of the dapps settings
|
||||
pub fn settings(&self) -> HashMap<DappId, DappsSettings> {
|
||||
self.settings.clone()
|
||||
}
|
||||
|
||||
/// Returns current new dapps policy
|
||||
pub fn policy(&self) -> NewDappsPolicy {
|
||||
self.policy.get("default").cloned().unwrap_or(NewDappsPolicy::AllAccounts {
|
||||
default: 0.into(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns recent dapps with last accessed timestamp
|
||||
pub fn recent_dapps(&self) -> HashMap<DappId, u64> {
|
||||
self.history.iter().map(|(k, v)| (k.clone(), v.last_accessed)).collect()
|
||||
}
|
||||
|
||||
/// Marks recent dapp as used
|
||||
pub fn mark_dapp_used(&mut self, dapp: DappId) {
|
||||
{
|
||||
let entry = self.history.entry(dapp).or_insert_with(|| Default::default());
|
||||
entry.last_accessed = self.time.get();
|
||||
}
|
||||
// Clear extraneous entries
|
||||
while self.history.len() > MAX_RECENT_DAPPS {
|
||||
let min = self.history.iter()
|
||||
.min_by_key(|&(_, ref v)| v.last_accessed)
|
||||
.map(|(ref k, _)| k.clone())
|
||||
.cloned();
|
||||
|
||||
match min {
|
||||
Some(k) => self.history.remove(&k),
|
||||
None => break,
|
||||
};
|
||||
}
|
||||
self.history.save(JsonDappsHistory::write);
|
||||
}
|
||||
|
||||
/// Sets current new dapps policy
|
||||
pub fn set_policy(&mut self, policy: NewDappsPolicy) {
|
||||
self.policy.insert("default".into(), policy);
|
||||
self.policy.save(JsonNewDappsPolicy::write);
|
||||
}
|
||||
|
||||
/// Sets accounts for specific dapp.
|
||||
pub fn set_accounts(&mut self, id: DappId, accounts: Option<Vec<Address>>) {
|
||||
{
|
||||
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
|
||||
settings.accounts = accounts;
|
||||
}
|
||||
self.settings.save(JsonSettings::write);
|
||||
}
|
||||
|
||||
/// Sets a default account for specific dapp.
|
||||
pub fn set_default(&mut self, id: DappId, default: Address) {
|
||||
{
|
||||
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
|
||||
settings.default = Some(default);
|
||||
}
|
||||
self.settings.save(JsonSettings::write);
|
||||
}
|
||||
}
|
||||
|
||||
/// Disk-serializable HashMap
|
||||
#[derive(Debug)]
|
||||
struct DiskMap<K: hash::Hash + Eq, V> {
|
||||
@ -366,8 +151,7 @@ impl<K: hash::Hash + Eq, V> DiskMap<K, V> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{AddressBook, DappsSettingsStore, DappsSettings, NewDappsPolicy};
|
||||
use account_provider::DappId;
|
||||
use super::AddressBook;
|
||||
use std::collections::HashMap;
|
||||
use ethjson::misc::AccountMeta;
|
||||
use tempdir::TempDir;
|
||||
@ -398,63 +182,4 @@ mod tests {
|
||||
3.into() => AccountMeta{name: "Three".to_owned(), meta: "{}".to_owned(), uuid: None}
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_save_and_reload_dapps_settings() {
|
||||
// given
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let mut b = DappsSettingsStore::new(tempdir.path());
|
||||
|
||||
// when
|
||||
b.set_accounts("dappOne".into(), Some(vec![1.into(), 2.into()]));
|
||||
|
||||
// then
|
||||
let b = DappsSettingsStore::new(tempdir.path());
|
||||
assert_eq!(b.settings(), hash_map![
|
||||
"dappOne".into() => DappsSettings {
|
||||
accounts: Some(vec![1.into(), 2.into()]),
|
||||
default: None,
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_maintain_a_map_of_recent_dapps() {
|
||||
let mut store = DappsSettingsStore::transient();
|
||||
assert!(store.recent_dapps().is_empty(), "Initially recent dapps should be empty.");
|
||||
|
||||
let dapp1: DappId = "dapp1".into();
|
||||
let dapp2: DappId = "dapp2".into();
|
||||
store.mark_dapp_used(dapp1.clone());
|
||||
let recent = store.recent_dapps();
|
||||
assert_eq!(recent.len(), 1);
|
||||
assert_eq!(recent.get(&dapp1), Some(&1));
|
||||
|
||||
store.mark_dapp_used(dapp2.clone());
|
||||
let recent = store.recent_dapps();
|
||||
assert_eq!(recent.len(), 2);
|
||||
assert_eq!(recent.get(&dapp1), Some(&1));
|
||||
assert_eq!(recent.get(&dapp2), Some(&2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_store_dapps_policy() {
|
||||
// given
|
||||
let tempdir = TempDir::new("").unwrap();
|
||||
let mut store = DappsSettingsStore::new(tempdir.path());
|
||||
|
||||
// Test default policy
|
||||
assert_eq!(store.policy(), NewDappsPolicy::AllAccounts {
|
||||
default: 0.into(),
|
||||
});
|
||||
|
||||
// when
|
||||
store.set_policy(NewDappsPolicy::Whitelist(vec![1.into(), 2.into()]));
|
||||
|
||||
// then
|
||||
let store = DappsSettingsStore::new(tempdir.path());
|
||||
assert_eq!(store.policy.clone(), hash_map![
|
||||
"default".into() => NewDappsPolicy::Whitelist(vec![1.into(), 2.into()])
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ fn enact(
|
||||
ancestry: &mut Iterator<Item=ExtendedHeader>,
|
||||
) -> Result<LockedBlock, Error> {
|
||||
{
|
||||
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
||||
if ::log::max_level() >= ::log::Level::Trace {
|
||||
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?;
|
||||
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
|
||||
header.number(), s.root(), header.author(), s.balance(&header.author())?);
|
||||
@ -637,10 +637,11 @@ mod tests {
|
||||
use ethereum_types::Address;
|
||||
use std::sync::Arc;
|
||||
use transaction::SignedTransaction;
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
fn enact_bytes(
|
||||
block_bytes: &[u8],
|
||||
block_bytes: Vec<u8>,
|
||||
engine: &EthEngine,
|
||||
tracing: bool,
|
||||
db: StateDB,
|
||||
@ -648,10 +649,10 @@ mod tests {
|
||||
last_hashes: Arc<LastHashes>,
|
||||
factories: Factories,
|
||||
) -> Result<LockedBlock, Error> {
|
||||
let block = view!(BlockView, block_bytes);
|
||||
let header = block.header();
|
||||
let block = Unverified::from_rlp(block_bytes)?;
|
||||
let header = block.header;
|
||||
let transactions: Result<Vec<_>, Error> = block
|
||||
.transactions()
|
||||
.transactions
|
||||
.into_iter()
|
||||
.map(SignedTransaction::new)
|
||||
.map(|r| r.map_err(Into::into))
|
||||
@ -659,7 +660,7 @@ mod tests {
|
||||
let transactions = transactions?;
|
||||
|
||||
{
|
||||
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
||||
if ::log::max_level() >= ::log::Level::Trace {
|
||||
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?;
|
||||
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
|
||||
header.number(), s.root(), header.author(), s.balance(&header.author())?);
|
||||
@ -683,8 +684,8 @@ mod tests {
|
||||
b.populate_from(&header);
|
||||
b.push_transactions(transactions)?;
|
||||
|
||||
for u in &block.uncles() {
|
||||
b.push_uncle(u.clone())?;
|
||||
for u in block.uncles {
|
||||
b.push_uncle(u)?;
|
||||
}
|
||||
|
||||
b.close_and_lock()
|
||||
@ -692,7 +693,7 @@ mod tests {
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
|
||||
fn enact_and_seal(
|
||||
block_bytes: &[u8],
|
||||
block_bytes: Vec<u8>,
|
||||
engine: &EthEngine,
|
||||
tracing: bool,
|
||||
db: StateDB,
|
||||
@ -700,8 +701,9 @@ mod tests {
|
||||
last_hashes: Arc<LastHashes>,
|
||||
factories: Factories,
|
||||
) -> Result<SealedBlock, Error> {
|
||||
let header = view!(BlockView, block_bytes).header_view();
|
||||
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?.seal(engine, header.seal())?)
|
||||
let header = Unverified::from_rlp(block_bytes.clone())?.header;
|
||||
Ok(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes, factories)?
|
||||
.seal(engine, header.seal().to_vec())?)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -731,7 +733,7 @@ mod tests {
|
||||
let orig_db = b.drain().state.drop().1;
|
||||
|
||||
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
|
||||
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
|
||||
let e = enact_and_seal(orig_bytes.clone(), engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
|
||||
|
||||
assert_eq!(e.rlp_bytes(), orig_bytes);
|
||||
|
||||
@ -762,7 +764,7 @@ mod tests {
|
||||
let orig_db = b.drain().state.drop().1;
|
||||
|
||||
let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
|
||||
let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
|
||||
let e = enact_and_seal(orig_bytes.clone(), engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap();
|
||||
|
||||
let bytes = e.rlp_bytes();
|
||||
assert_eq!(bytes, orig_bytes);
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
use std::collections::{HashSet, BTreeMap, VecDeque};
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
||||
use std::sync::{Arc, Weak};
|
||||
@ -50,13 +49,16 @@ use client::{
|
||||
};
|
||||
use encoded;
|
||||
use engines::{EthEngine, EpochTransition, ForkChoice};
|
||||
use error::{ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
||||
use error::{
|
||||
ImportErrorKind, BlockImportErrorKind, ExecutionError, CallError, BlockError, ImportResult,
|
||||
QueueError, QueueErrorKind, Error as EthcoreError
|
||||
};
|
||||
use vm::{EnvInfo, LastHashes};
|
||||
use evm::Schedule;
|
||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||
use factory::{Factories, VmFactory};
|
||||
use header::{BlockNumber, Header, ExtendedHeader};
|
||||
use io::{IoChannel, IoError};
|
||||
use io::IoChannel;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use miner::{Miner, MinerService};
|
||||
use ethcore_miner::pool::VerifiedTransaction;
|
||||
@ -1813,9 +1815,7 @@ impl BlockChainClient for Client {
|
||||
self.engine.additional_params().into_iter().collect()
|
||||
}
|
||||
|
||||
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
|
||||
// Wrap the logic inside a closure so that we can take advantage of question mark syntax.
|
||||
let fetch_logs = || {
|
||||
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
|
||||
let chain = self.chain.read();
|
||||
|
||||
// First, check whether `filter.from_block` and `filter.to_block` is on the canon chain. If so, we can use the
|
||||
@ -1832,8 +1832,24 @@ impl BlockChainClient for Client {
|
||||
|
||||
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)?;
|
||||
//
|
||||
// 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()
|
||||
@ -1841,9 +1857,18 @@ impl BlockChainClient for Client {
|
||||
.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 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| {
|
||||
@ -1855,7 +1880,10 @@ impl BlockChainClient for Client {
|
||||
let mut current_hash = to_hash;
|
||||
|
||||
loop {
|
||||
let header = chain.block_header_data(¤t_hash)?;
|
||||
let header = match chain.block_header_data(¤t_hash) {
|
||||
Some(val) => val,
|
||||
None => return Err(BlockId::Hash(current_hash)),
|
||||
};
|
||||
if bloom_match(&header) {
|
||||
blocks.push(current_hash);
|
||||
}
|
||||
@ -1873,16 +1901,14 @@ impl BlockChainClient for Client {
|
||||
|
||||
// Check if we've actually reached the expected `from` block.
|
||||
if last_hash != from_hash || blocks.is_empty() {
|
||||
return None;
|
||||
// In this case, from_hash is the cause (for not matching last_hash).
|
||||
return Err(BlockId::Hash(from_hash));
|
||||
}
|
||||
|
||||
blocks
|
||||
};
|
||||
|
||||
Some(self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit))
|
||||
};
|
||||
|
||||
fetch_logs().unwrap_or_default()
|
||||
Ok(self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit))
|
||||
}
|
||||
|
||||
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
|
||||
@ -2071,7 +2097,7 @@ impl IoClient for Client {
|
||||
|
||||
let queued = self.queued_ancient_blocks.clone();
|
||||
let lock = self.ancient_blocks_import_lock.clone();
|
||||
match self.queue_ancient_blocks.queue(&self.io_channel.read(), 1, move |client| {
|
||||
self.queue_ancient_blocks.queue(&self.io_channel.read(), 1, move |client| {
|
||||
trace_time!("import_ancient_block");
|
||||
// Make sure to hold the lock here to prevent importing out of order.
|
||||
// We use separate lock, cause we don't want to block queueing.
|
||||
@ -2095,10 +2121,9 @@ impl IoClient for Client {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Ok(_) => Ok(hash),
|
||||
Err(e) => bail!(BlockImportErrorKind::Other(format!("{}", e))),
|
||||
}
|
||||
})?;
|
||||
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
fn queue_consensus_message(&self, message: Bytes) {
|
||||
@ -2514,21 +2539,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum QueueError {
|
||||
Channel(IoError),
|
||||
Full(usize),
|
||||
}
|
||||
|
||||
impl fmt::Display for QueueError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
QueueError::Channel(ref c) => fmt::Display::fmt(c, fmt),
|
||||
QueueError::Full(limit) => write!(fmt, "The queue is full ({})", limit),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Queue some items to be processed by IO client.
|
||||
struct IoChannelQueue {
|
||||
currently_queued: Arc<AtomicUsize>,
|
||||
@ -2547,7 +2557,7 @@ impl IoChannelQueue {
|
||||
F: Fn(&Client) + Send + Sync + 'static,
|
||||
{
|
||||
let queue_size = self.currently_queued.load(AtomicOrdering::Relaxed);
|
||||
ensure!(queue_size < self.limit, QueueError::Full(self.limit));
|
||||
ensure!(queue_size < self.limit, QueueErrorKind::Full(self.limit));
|
||||
|
||||
let currently_queued = self.currently_queued.clone();
|
||||
let result = channel.send(ClientIoMessage::execute(move |client| {
|
||||
@ -2560,7 +2570,7 @@ impl IoChannelQueue {
|
||||
self.currently_queued.fetch_add(count, AtomicOrdering::SeqCst);
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => Err(QueueError::Channel(e)),
|
||||
Err(e) => bail!(QueueErrorKind::Channel(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use ethereum_types::{H256, U256, H160};
|
||||
use {factory, journaldb, trie, kvdb_memorydb, bytes};
|
||||
use {factory, journaldb, trie, kvdb_memorydb};
|
||||
use kvdb::{self, KeyValueDB};
|
||||
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state, log_entry, receipt};
|
||||
use factory::Factories;
|
||||
@ -183,14 +183,12 @@ impl<'a> EvmTestClient<'a> {
|
||||
gas_limit: *genesis.gas_limit(),
|
||||
};
|
||||
let mut substate = state::Substate::new();
|
||||
let mut output = vec![];
|
||||
let machine = self.spec.engine.machine();
|
||||
let schedule = machine.schedule(info.number);
|
||||
let mut executive = executive::Executive::new(&mut self.state, &info, &machine, &schedule);
|
||||
executive.call(
|
||||
params,
|
||||
&mut substate,
|
||||
bytes::BytesRef::Flexible(&mut output),
|
||||
tracer,
|
||||
vm_tracer,
|
||||
).map_err(EvmTestError::Evm)
|
||||
|
@ -94,6 +94,8 @@ pub struct TestBlockChainClient {
|
||||
pub receipts: RwLock<HashMap<TransactionId, LocalizedReceipt>>,
|
||||
/// Logs
|
||||
pub logs: RwLock<Vec<LocalizedLogEntry>>,
|
||||
/// Should return errors on logs.
|
||||
pub error_on_logs: RwLock<Option<BlockId>>,
|
||||
/// Block queue size.
|
||||
pub queue_size: AtomicUsize,
|
||||
/// Miner
|
||||
@ -178,6 +180,7 @@ impl TestBlockChainClient {
|
||||
traces: RwLock::new(None),
|
||||
history: RwLock::new(None),
|
||||
disabled: AtomicBool::new(false),
|
||||
error_on_logs: RwLock::new(None),
|
||||
};
|
||||
|
||||
// insert genesis hash.
|
||||
@ -233,6 +236,11 @@ impl TestBlockChainClient {
|
||||
*self.logs.write() = logs;
|
||||
}
|
||||
|
||||
/// Set return errors on logs.
|
||||
pub fn set_error_on_logs(&self, val: Option<BlockId>) {
|
||||
*self.error_on_logs.write() = val;
|
||||
}
|
||||
|
||||
/// Add blocks to test client.
|
||||
pub fn add_blocks(&self, count: usize, with: EachBlockWith) {
|
||||
let len = self.numbers.read().len();
|
||||
@ -665,13 +673,18 @@ impl BlockChainClient for TestBlockChainClient {
|
||||
self.receipts.read().get(&id).cloned()
|
||||
}
|
||||
|
||||
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
|
||||
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId> {
|
||||
match self.error_on_logs.read().as_ref() {
|
||||
Some(id) => return Err(id.clone()),
|
||||
None => (),
|
||||
}
|
||||
|
||||
let mut logs = self.logs.read().clone();
|
||||
let len = logs.len();
|
||||
match filter.limit {
|
||||
Ok(match filter.limit {
|
||||
Some(limit) if limit <= len => logs.split_off(len - limit),
|
||||
_ => logs,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn last_hashes(&self) -> LastHashes {
|
||||
|
@ -297,8 +297,8 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra
|
||||
/// Get the registrar address, if it exists.
|
||||
fn additional_params(&self) -> BTreeMap<String, String>;
|
||||
|
||||
/// Returns logs matching given filter.
|
||||
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry>;
|
||||
/// Returns logs matching given filter. If one of the filtering block cannot be found, returns the block id that caused the error.
|
||||
fn logs(&self, filter: Filter) -> Result<Vec<LocalizedLogEntry>, BlockId>;
|
||||
|
||||
/// Replays a given transaction for inspection.
|
||||
fn replay(&self, t: TransactionId, analytics: CallAnalytics) -> Result<Executed, CallError>;
|
||||
|
@ -150,6 +150,24 @@ impl error::Error for BlockError {
|
||||
}
|
||||
}
|
||||
|
||||
error_chain! {
|
||||
types {
|
||||
QueueError, QueueErrorKind, QueueErrorResultExt, QueueErrorResult;
|
||||
}
|
||||
|
||||
errors {
|
||||
#[doc = "Queue is full"]
|
||||
Full(limit: usize) {
|
||||
description("Queue is full")
|
||||
display("The queue is full ({})", limit)
|
||||
}
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
Channel(IoError) #[doc = "Io channel error"];
|
||||
}
|
||||
}
|
||||
|
||||
error_chain! {
|
||||
types {
|
||||
ImportError, ImportErrorKind, ImportErrorResultExt, ImportErrorResult;
|
||||
@ -183,6 +201,7 @@ error_chain! {
|
||||
|
||||
links {
|
||||
Import(ImportError, ImportErrorKind) #[doc = "Import error"];
|
||||
Queue(QueueError, QueueErrorKind) #[doc = "Io channel queue error"];
|
||||
}
|
||||
|
||||
foreign_links {
|
||||
|
@ -20,7 +20,7 @@ use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
use hash::{KECCAK_EMPTY_LIST_RLP};
|
||||
use engines::block_reward::{self, RewardKind};
|
||||
use ethash::{quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
|
||||
use ethash::{self, quick_get_difficulty, slow_hash_block_number, EthashManager, OptimizeFor};
|
||||
use ethereum_types::{H256, H64, U256, Address};
|
||||
use unexpected::{OutOfBounds, Mismatch};
|
||||
use block::*;
|
||||
@ -302,7 +302,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
return Err(From::from(BlockError::DifficultyOutOfBounds(OutOfBounds { min: Some(min_difficulty), max: None, found: header.difficulty().clone() })))
|
||||
}
|
||||
|
||||
let difficulty = Ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
|
||||
let difficulty = ethash::boundary_to_difficulty(&H256(quick_get_difficulty(
|
||||
&header.bare_hash().0,
|
||||
seal.nonce.low_u64(),
|
||||
&seal.mix_hash.0
|
||||
@ -324,7 +324,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
|
||||
let result = self.pow.compute_light(header.number() as u64, &header.bare_hash().0, seal.nonce.low_u64());
|
||||
let mix = H256(result.mix_hash);
|
||||
let difficulty = Ethash::boundary_to_difficulty(&H256(result.value));
|
||||
let difficulty = ethash::boundary_to_difficulty(&H256(result.value));
|
||||
trace!(target: "miner", "num: {num}, seed: {seed}, h: {h}, non: {non}, mix: {mix}, res: {res}",
|
||||
num = header.number() as u64,
|
||||
seed = H256(slow_hash_block_number(header.number() as u64)),
|
||||
@ -447,25 +447,6 @@ impl Ethash {
|
||||
}
|
||||
target
|
||||
}
|
||||
|
||||
/// Convert an Ethash boundary to its original difficulty. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn boundary_to_difficulty(boundary: &H256) -> U256 {
|
||||
let d = U256::from(*boundary);
|
||||
if d <= U256::one() {
|
||||
U256::max_value()
|
||||
} else {
|
||||
((U256::one() << 255) / d) << 1
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an Ethash difficulty to the target boundary. Basically just `f(x) = 2^256 / x`.
|
||||
pub fn difficulty_to_boundary(difficulty: &U256) -> H256 {
|
||||
if *difficulty <= U256::one() {
|
||||
U256::max_value().into()
|
||||
} else {
|
||||
(((U256::one() << 255) / *difficulty) << 1).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256) {
|
||||
@ -766,16 +747,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_difficulty_to_boundary() {
|
||||
// result of f(0) is undefined, so do not assert the result
|
||||
let _ = Ethash::difficulty_to_boundary(&U256::from(0));
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(1)), H256::from(U256::max_value()));
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(2)), H256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(4)), H256::from_str("4000000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
assert_eq!(Ethash::difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn difficulty_frontier() {
|
||||
let machine = new_homestead_test_machine();
|
||||
|
@ -30,7 +30,8 @@ pub use self::denominations::*;
|
||||
use machine::EthereumMachine;
|
||||
use super::spec::*;
|
||||
|
||||
fn load<'a, T: Into<Option<SpecParams<'a>>>>(params: T, b: &[u8]) -> Spec {
|
||||
/// Load chain spec from `SpecParams` and JSON.
|
||||
pub fn load<'a, T: Into<Option<SpecParams<'a>>>>(params: T, b: &[u8]) -> Spec {
|
||||
match params.into() {
|
||||
Some(params) => Spec::load(params, b),
|
||||
None => Spec::load(&::std::env::temp_dir(), b)
|
||||
|
@ -204,7 +204,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
&'any mut self,
|
||||
origin_info: OriginInfo,
|
||||
substate: &'any mut Substate,
|
||||
output: OutputPolicy<'any, 'any>,
|
||||
output: OutputPolicy,
|
||||
tracer: &'any mut T,
|
||||
vm_tracer: &'any mut V,
|
||||
static_call: bool,
|
||||
@ -312,8 +312,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
call_type: CallType::None,
|
||||
params_type: vm::ParamsType::Embedded,
|
||||
};
|
||||
let mut out = if output_from_create { Some(vec![]) } else { None };
|
||||
(self.create(params, &mut substate, &mut out, &mut tracer, &mut vm_tracer), out.unwrap_or_else(Vec::new))
|
||||
let res = self.create(params, &mut substate, &mut tracer, &mut vm_tracer);
|
||||
let out = match &res {
|
||||
Ok(res) if output_from_create => res.return_data.to_vec(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
(res, out)
|
||||
},
|
||||
Action::Call(ref address) => {
|
||||
let params = ActionParams {
|
||||
@ -330,8 +334,12 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
call_type: CallType::Call,
|
||||
params_type: vm::ParamsType::Separate,
|
||||
};
|
||||
let mut out = vec![];
|
||||
(self.call(params, &mut substate, BytesRef::Flexible(&mut out), &mut tracer, &mut vm_tracer), out)
|
||||
let res = self.call(params, &mut substate, &mut tracer, &mut vm_tracer);
|
||||
let out = match &res {
|
||||
Ok(res) => res.return_data.to_vec(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
(res, out)
|
||||
}
|
||||
};
|
||||
|
||||
@ -354,23 +362,22 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
// Ordinary execution - keep VM in same thread
|
||||
if self.depth != depth_threshold {
|
||||
let vm_factory = self.state.vm_factory();
|
||||
let wasm = self.schedule.wasm.is_some();
|
||||
let origin_info = OriginInfo::from(¶ms);
|
||||
trace!(target: "executive", "ext.schedule.have_delegate_call: {}", self.schedule.have_delegate_call);
|
||||
let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
||||
let mut vm = vm_factory.create(¶ms, wasm);
|
||||
return vm.exec(params, &mut ext).finalize(ext);
|
||||
let mut vm = vm_factory.create(params, self.schedule, self.depth);
|
||||
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
||||
return vm.exec(&mut ext).finalize(ext);
|
||||
}
|
||||
|
||||
// Start in new thread with stack size needed up to max depth
|
||||
crossbeam::scope(|scope| {
|
||||
let vm_factory = self.state.vm_factory();
|
||||
let max_depth = self.schedule.max_depth;
|
||||
let wasm = self.schedule.wasm.is_some();
|
||||
let mut ext = self.as_externalities(OriginInfo::from(¶ms), unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
||||
let origin_info = OriginInfo::from(¶ms);
|
||||
|
||||
scope.builder().stack_size(::std::cmp::max(max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
|
||||
let mut vm = vm_factory.create(¶ms, wasm);
|
||||
vm.exec(params, &mut ext).finalize(ext)
|
||||
scope.builder().stack_size(::std::cmp::max(self.schedule.max_depth.saturating_sub(depth_threshold) * STACK_SIZE_PER_DEPTH, local_stack_size)).spawn(move || {
|
||||
let mut vm = vm_factory.create(params, self.schedule, self.depth);
|
||||
let mut ext = self.as_externalities(origin_info, unconfirmed_substate, output_policy, tracer, vm_tracer, static_call);
|
||||
vm.exec(&mut ext).finalize(ext)
|
||||
}).expect("Sub-thread creation cannot fail; the host might run out of resources; qed")
|
||||
}).join()
|
||||
}
|
||||
@ -383,7 +390,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
&mut self,
|
||||
params: ActionParams,
|
||||
substate: &mut Substate,
|
||||
mut output: BytesRef,
|
||||
tracer: &mut T,
|
||||
vm_tracer: &mut V
|
||||
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
||||
@ -417,8 +423,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
let default = [];
|
||||
let data = if let Some(ref d) = params.data { d as &[u8] } else { &default as &[u8] };
|
||||
|
||||
let trace_info = tracer.prepare_trace_call(¶ms);
|
||||
|
||||
let cost = builtin.cost(data);
|
||||
if cost <= params.gas {
|
||||
let mut builtin_out_buffer = Vec::new();
|
||||
@ -429,11 +433,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
if let Err(e) = result {
|
||||
self.state.revert_to_checkpoint();
|
||||
let evm_err: vm::Error = e.into();
|
||||
tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into());
|
||||
let trace_info = tracer.prepare_trace_call(¶ms);
|
||||
tracer.trace_failed_call(
|
||||
trace_info,
|
||||
vec![],
|
||||
evm_err.clone().into()
|
||||
);
|
||||
Err(evm_err)
|
||||
} else {
|
||||
self.state.discard_checkpoint();
|
||||
output.write(0, &builtin_out_buffer);
|
||||
|
||||
// Trace only top level calls and calls with balance transfer to builtins. The reason why we don't
|
||||
// trace all internal calls to builtin contracts is that memcpy (IDENTITY) is a heavily used
|
||||
@ -443,15 +451,11 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
ActionValue::Apparent(_) => false,
|
||||
};
|
||||
if self.depth == 0 || is_transferred {
|
||||
let mut trace_output = tracer.prepare_trace_output();
|
||||
if let Some(out) = trace_output.as_mut() {
|
||||
*out = output.to_owned();
|
||||
}
|
||||
|
||||
let trace_info = tracer.prepare_trace_call(¶ms);
|
||||
tracer.trace_call(
|
||||
trace_info,
|
||||
cost,
|
||||
trace_output,
|
||||
&builtin_out_buffer,
|
||||
vec![]
|
||||
);
|
||||
}
|
||||
@ -467,13 +471,17 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
// just drain the whole gas
|
||||
self.state.revert_to_checkpoint();
|
||||
|
||||
tracer.trace_failed_call(trace_info, vec![], vm::Error::OutOfGas.into());
|
||||
let trace_info = tracer.prepare_trace_call(¶ms);
|
||||
tracer.trace_failed_call(
|
||||
trace_info,
|
||||
vec![],
|
||||
vm::Error::OutOfGas.into()
|
||||
);
|
||||
|
||||
Err(vm::Error::OutOfGas)
|
||||
}
|
||||
} else {
|
||||
let trace_info = tracer.prepare_trace_call(¶ms);
|
||||
let mut trace_output = tracer.prepare_trace_output();
|
||||
let mut subtracer = tracer.subtracer();
|
||||
|
||||
let gas = params.gas;
|
||||
@ -486,7 +494,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
let mut subvmtracer = vm_tracer.prepare_subtrace(params.code.as_ref().expect("scope is conditional on params.code.is_some(); qed"));
|
||||
|
||||
let res = {
|
||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()), &mut subtracer, &mut subvmtracer)
|
||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return, &mut subtracer, &mut subvmtracer)
|
||||
};
|
||||
|
||||
vm_tracer.done_subtrace(subvmtracer);
|
||||
@ -495,12 +503,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
|
||||
let traces = subtracer.drain();
|
||||
match res {
|
||||
Ok(ref res) if res.apply_state => tracer.trace_call(
|
||||
Ok(ref res) if res.apply_state => {
|
||||
tracer.trace_call(
|
||||
trace_info,
|
||||
gas - res.gas_left,
|
||||
trace_output,
|
||||
&res.return_data,
|
||||
traces
|
||||
),
|
||||
);
|
||||
},
|
||||
Ok(_) => tracer.trace_failed_call(trace_info, traces, vm::Error::Reverted.into()),
|
||||
Err(ref e) => tracer.trace_failed_call(trace_info, traces, e.into()),
|
||||
};
|
||||
@ -514,7 +524,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
// otherwise it's just a basic transaction, only do tracing, if necessary.
|
||||
self.state.discard_checkpoint();
|
||||
|
||||
tracer.trace_call(trace_info, U256::zero(), trace_output, vec![]);
|
||||
tracer.trace_call(trace_info, U256::zero(), &[], vec![]);
|
||||
Ok(FinalizationResult {
|
||||
gas_left: params.gas,
|
||||
return_data: ReturnData::empty(),
|
||||
@ -531,7 +541,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
&mut self,
|
||||
params: ActionParams,
|
||||
substate: &mut Substate,
|
||||
output: &mut Option<Bytes>,
|
||||
tracer: &mut T,
|
||||
vm_tracer: &mut V,
|
||||
) -> vm::Result<FinalizationResult> where T: Tracer, V: VMTracer {
|
||||
@ -570,7 +579,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
}
|
||||
|
||||
let trace_info = tracer.prepare_trace_create(¶ms);
|
||||
let mut trace_output = tracer.prepare_trace_output();
|
||||
let mut subtracer = tracer.subtracer();
|
||||
let gas = params.gas;
|
||||
let created = params.address.clone();
|
||||
@ -580,7 +588,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
let res = self.exec_vm(
|
||||
params,
|
||||
&mut unconfirmed_substate,
|
||||
OutputPolicy::InitContract(output.as_mut().or(trace_output.as_mut())),
|
||||
OutputPolicy::InitContract,
|
||||
&mut subtracer,
|
||||
&mut subvmtracer
|
||||
);
|
||||
@ -588,13 +596,15 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
|
||||
vm_tracer.done_subtrace(subvmtracer);
|
||||
|
||||
match res {
|
||||
Ok(ref res) if res.apply_state => tracer.trace_create(
|
||||
Ok(ref res) if res.apply_state => {
|
||||
tracer.trace_create(
|
||||
trace_info,
|
||||
gas - res.gas_left,
|
||||
trace_output.map(|data| output.as_ref().map(|out| out.to_vec()).unwrap_or(data)),
|
||||
&res.return_data,
|
||||
created,
|
||||
subtracer.drain()
|
||||
),
|
||||
);
|
||||
}
|
||||
Ok(_) => tracer.trace_failed_create(trace_info, subtracer.drain(), vm::Error::Reverted.into()),
|
||||
Err(ref e) => tracer.trace_failed_create(trace_info, subtracer.drain(), e.into())
|
||||
};
|
||||
@ -716,7 +726,6 @@ mod tests {
|
||||
use ethkey::{Generator, Random};
|
||||
use super::*;
|
||||
use ethereum_types::{H256, U256, U512, Address};
|
||||
use bytes::BytesRef;
|
||||
use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress};
|
||||
use evm::{Factory, VMType};
|
||||
use error::ExecutionError;
|
||||
@ -767,7 +776,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(79_975));
|
||||
@ -825,7 +834,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(62_976));
|
||||
@ -869,8 +878,7 @@ mod tests {
|
||||
let mut vm_tracer = ExecutiveVMTracer::toplevel();
|
||||
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
let output = BytesRef::Fixed(&mut[0u8;0]);
|
||||
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap();
|
||||
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap();
|
||||
|
||||
assert_eq!(tracer.drain(), vec![FlatTrace {
|
||||
action: trace::Action::Call(trace::Call {
|
||||
@ -897,7 +905,7 @@ mod tests {
|
||||
call_type: CallType::Call
|
||||
}), result: trace::Res::Call(trace::CallResult {
|
||||
gas_used: 600.into(),
|
||||
output: vec![]
|
||||
output: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 17, 133, 165, 197, 233, 252, 84, 97, 40, 8, 151, 126, 232, 245, 72, 178, 37, 141, 49]
|
||||
}),
|
||||
subtraces: 0,
|
||||
trace_address: vec![0].into_iter().collect(),
|
||||
@ -955,8 +963,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
let output = BytesRef::Fixed(&mut[0u8;0]);
|
||||
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
|
||||
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(44_752));
|
||||
@ -1072,8 +1079,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
let output = BytesRef::Fixed(&mut[0u8;0]);
|
||||
ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap()
|
||||
ex.call(params, &mut substate, &mut tracer, &mut vm_tracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(62967));
|
||||
@ -1145,7 +1151,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap()
|
||||
ex.create(params.clone(), &mut substate, &mut tracer, &mut vm_tracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(96_776));
|
||||
@ -1231,7 +1237,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(62_976));
|
||||
@ -1283,7 +1289,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap();
|
||||
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(substate.contracts_created.len(), 1);
|
||||
@ -1344,7 +1350,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(73_237));
|
||||
@ -1389,7 +1395,7 @@ mod tests {
|
||||
|
||||
let FinalizationResult { gas_left, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(59_870));
|
||||
@ -1563,7 +1569,7 @@ mod tests {
|
||||
|
||||
let result = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer)
|
||||
ex.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer)
|
||||
};
|
||||
|
||||
match result {
|
||||
@ -1596,10 +1602,11 @@ mod tests {
|
||||
let mut substate = Substate::new();
|
||||
|
||||
let mut output = [0u8; 14];
|
||||
let FinalizationResult { gas_left: result, .. } = {
|
||||
let FinalizationResult { gas_left: result, return_data, .. } = {
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
(&mut output).copy_from_slice(&return_data[..(cmp::min(14, return_data.len()))]);
|
||||
|
||||
assert_eq!(result, U256::from(1));
|
||||
assert_eq!(output[..], returns[..]);
|
||||
@ -1639,11 +1646,12 @@ mod tests {
|
||||
let machine = ::ethereum::new_kovan_wasm_test_machine();
|
||||
|
||||
let mut output = [0u8; 20];
|
||||
let FinalizationResult { gas_left: result, .. } = {
|
||||
let FinalizationResult { gas_left: result, return_data, .. } = {
|
||||
let schedule = machine.schedule(info.number);
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.call(params.clone(), &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.call(params.clone(), &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
(&mut output).copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]);
|
||||
|
||||
assert_eq!(result, U256::from(18433));
|
||||
// Transaction successfully returned sender
|
||||
@ -1653,11 +1661,12 @@ mod tests {
|
||||
info.number = 1;
|
||||
|
||||
let mut output = [0u8; 20];
|
||||
let FinalizationResult { gas_left: result, .. } = {
|
||||
let FinalizationResult { gas_left: result, return_data, .. } = {
|
||||
let schedule = machine.schedule(info.number);
|
||||
let mut ex = Executive::new(&mut state, &info, &machine, &schedule);
|
||||
ex.call(params, &mut Substate::new(), BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
ex.call(params, &mut Substate::new(), &mut NoopTracer, &mut NoopVMTracer).unwrap()
|
||||
};
|
||||
(&mut output[..((cmp::min(20, return_data.len())))]).copy_from_slice(&return_data[..(cmp::min(20, return_data.len()))]);
|
||||
|
||||
assert_eq!(result, U256::from(20025));
|
||||
// Since transaction errored due to wasm was not activated, result is just empty
|
||||
|
@ -18,7 +18,7 @@
|
||||
use std::cmp;
|
||||
use std::sync::Arc;
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use bytes::{Bytes, BytesRef};
|
||||
use bytes::Bytes;
|
||||
use state::{Backend as StateBackend, State, Substate, CleanupMode};
|
||||
use machine::EthereumMachine as Machine;
|
||||
use executive::*;
|
||||
@ -32,12 +32,12 @@ use transaction::UNSIGNED_SENDER;
|
||||
use trace::{Tracer, VMTracer};
|
||||
|
||||
/// Policy for handling output data on `RETURN` opcode.
|
||||
pub enum OutputPolicy<'a, 'b> {
|
||||
pub enum OutputPolicy {
|
||||
/// Return reference to fixed sized output.
|
||||
/// Used for message calls.
|
||||
Return(BytesRef<'a>, Option<&'b mut Bytes>),
|
||||
Return,
|
||||
/// Init new contract as soon as `RETURN` is called.
|
||||
InitContract(Option<&'b mut Bytes>),
|
||||
InitContract,
|
||||
}
|
||||
|
||||
/// Transaction properties that externalities need to know about.
|
||||
@ -71,7 +71,7 @@ pub struct Externalities<'a, T: 'a, V: 'a, B: 'a> {
|
||||
substate: &'a mut Substate,
|
||||
machine: &'a Machine,
|
||||
schedule: &'a Schedule,
|
||||
output: OutputPolicy<'a, 'a>,
|
||||
output: OutputPolicy,
|
||||
tracer: &'a mut T,
|
||||
vm_tracer: &'a mut V,
|
||||
static_flag: bool,
|
||||
@ -89,7 +89,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
||||
depth: usize,
|
||||
origin_info: OriginInfo,
|
||||
substate: &'a mut Substate,
|
||||
output: OutputPolicy<'a, 'a>,
|
||||
output: OutputPolicy,
|
||||
tracer: &'a mut T,
|
||||
vm_tracer: &'a mut V,
|
||||
static_flag: bool,
|
||||
@ -171,9 +171,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
params_type: vm::ParamsType::Separate,
|
||||
};
|
||||
|
||||
let mut output = H256::new();
|
||||
let mut ex = Executive::new(self.state, self.env_info, self.machine, self.schedule);
|
||||
let r = ex.call(params, self.substate, BytesRef::Fixed(&mut output), self.tracer, self.vm_tracer);
|
||||
let r = ex.call(params, self.substate, self.tracer, self.vm_tracer);
|
||||
let output = match &r {
|
||||
Ok(ref r) => H256::from(&r.return_data[..32]),
|
||||
_ => H256::new(),
|
||||
};
|
||||
trace!("ext: blockhash contract({}) -> {:?}({}) self.env_info.number={}\n", number, r, output, self.env_info.number);
|
||||
output
|
||||
} else {
|
||||
@ -194,7 +197,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
}
|
||||
}
|
||||
|
||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address_scheme: CreateContractAddress) -> ContractCreateResult {
|
||||
fn create(
|
||||
&mut self,
|
||||
gas: &U256,
|
||||
value: &U256,
|
||||
code: &[u8],
|
||||
address_scheme: CreateContractAddress
|
||||
) -> ContractCreateResult {
|
||||
// create new contract address
|
||||
let (address, code_hash) = match self.state.nonce(&self.origin_info.address) {
|
||||
Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code),
|
||||
@ -231,7 +240,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
|
||||
|
||||
// TODO: handle internal error separately
|
||||
match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) {
|
||||
match ex.create(params, self.substate, self.tracer, self.vm_tracer) {
|
||||
Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => {
|
||||
self.substate.contracts_created.push(address.clone());
|
||||
ContractCreateResult::Created(address, gas_left)
|
||||
@ -243,14 +252,14 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
}
|
||||
}
|
||||
|
||||
fn call(&mut self,
|
||||
fn call(
|
||||
&mut self,
|
||||
gas: &U256,
|
||||
sender_address: &Address,
|
||||
receive_address: &Address,
|
||||
value: Option<U256>,
|
||||
data: &[u8],
|
||||
code_address: &Address,
|
||||
output: &mut [u8],
|
||||
call_type: CallType
|
||||
) -> MessageCallResult {
|
||||
trace!(target: "externalities", "call");
|
||||
@ -284,7 +293,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
|
||||
let mut ex = Executive::from_parent(self.state, self.env_info, self.machine, self.schedule, self.depth, self.static_flag);
|
||||
|
||||
match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) {
|
||||
match ex.call(params, self.substate, self.tracer, self.vm_tracer) {
|
||||
Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data),
|
||||
Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data),
|
||||
_ => MessageCallResult::Failed
|
||||
@ -303,27 +312,13 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
Ok(self.state.code_size(address)?)
|
||||
}
|
||||
|
||||
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
||||
fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
||||
where Self: Sized {
|
||||
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
||||
to.as_mut().map(|b| **b = data.to_vec());
|
||||
};
|
||||
match self.output {
|
||||
OutputPolicy::Return(BytesRef::Fixed(ref mut slice), ref mut copy) => {
|
||||
handle_copy(copy);
|
||||
|
||||
let len = cmp::min(slice.len(), data.len());
|
||||
(&mut slice[..len]).copy_from_slice(&data[..len]);
|
||||
OutputPolicy::Return => {
|
||||
Ok(*gas)
|
||||
},
|
||||
OutputPolicy::Return(BytesRef::Flexible(ref mut vec), ref mut copy) => {
|
||||
handle_copy(copy);
|
||||
|
||||
vec.clear();
|
||||
vec.extend_from_slice(&*data);
|
||||
Ok(*gas)
|
||||
},
|
||||
OutputPolicy::InitContract(ref mut copy) if apply_state => {
|
||||
OutputPolicy::InitContract if apply_state => {
|
||||
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
||||
if return_cost > *gas || data.len() > self.schedule.create_data_limit {
|
||||
return match self.schedule.exceptional_failed_code_deposit {
|
||||
@ -331,11 +326,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
false => Ok(*gas)
|
||||
}
|
||||
}
|
||||
handle_copy(copy);
|
||||
self.state.init_code(&self.origin_info.address, data.to_vec())?;
|
||||
Ok(*gas - return_cost)
|
||||
},
|
||||
OutputPolicy::InitContract(_) => {
|
||||
OutputPolicy::InitContract => {
|
||||
Ok(*gas)
|
||||
},
|
||||
}
|
||||
@ -479,7 +473,7 @@ mod tests {
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
assert_eq!(ext.env_info().number, 100);
|
||||
}
|
||||
@ -491,7 +485,7 @@ mod tests {
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
||||
|
||||
@ -515,7 +509,7 @@ mod tests {
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
let hash = ext.blockhash(&"0000000000000000000000000000000000000000000000000000000000120000".parse::<U256>().unwrap());
|
||||
|
||||
@ -530,9 +524,7 @@ mod tests {
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
let mut output = vec![];
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
// this should panic because we have no balance on any account
|
||||
ext.call(
|
||||
@ -542,7 +534,6 @@ mod tests {
|
||||
Some("0000000000000000000000000000000000000000000000000000000000150000".parse::<U256>().unwrap()),
|
||||
&[],
|
||||
&Address::new(),
|
||||
&mut output,
|
||||
CallType::Call
|
||||
);
|
||||
}
|
||||
@ -558,7 +549,7 @@ mod tests {
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
{
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
ext.log(log_topics, &log_data).unwrap();
|
||||
}
|
||||
|
||||
@ -575,7 +566,7 @@ mod tests {
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
{
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
ext.suicide(refund_account).unwrap();
|
||||
}
|
||||
|
||||
@ -592,7 +583,7 @@ mod tests {
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let address = {
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) {
|
||||
ContractCreateResult::Created(address, _) => address,
|
||||
_ => panic!("Test create failed; expected Created, got Failed/Reverted."),
|
||||
@ -612,7 +603,7 @@ mod tests {
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
|
||||
let address = {
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false);
|
||||
let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, &setup.schedule, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract, &mut tracer, &mut vm_tracer, false);
|
||||
|
||||
match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) {
|
||||
ContractCreateResult::Created(address, _) => address,
|
||||
|
@ -18,7 +18,7 @@ use trie::TrieFactory;
|
||||
use ethtrie::RlpCodec;
|
||||
use account_db::Factory as AccountFactory;
|
||||
use evm::{Factory as EvmFactory, VMType};
|
||||
use vm::{Vm, ActionParams};
|
||||
use vm::{Vm, ActionParams, Schedule};
|
||||
use wasm::WasmInterpreter;
|
||||
use keccak_hasher::KeccakHasher;
|
||||
|
||||
@ -31,11 +31,11 @@ pub struct VmFactory {
|
||||
}
|
||||
|
||||
impl VmFactory {
|
||||
pub fn create(&self, params: &ActionParams, wasm: bool) -> Box<Vm> {
|
||||
if wasm && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
|
||||
Box::new(WasmInterpreter)
|
||||
pub fn create(&self, params: ActionParams, schedule: &Schedule, depth: usize) -> Box<Vm> {
|
||||
if schedule.wasm.is_some() && params.code.as_ref().map_or(false, |code| code.len() > 4 && &code[0..4] == WASM_MAGIC_NUMBER) {
|
||||
Box::new(WasmInterpreter::new(params))
|
||||
} else {
|
||||
self.evm.create(¶ms.gas)
|
||||
self.evm.create(params, schedule, depth)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ use test_helpers::get_temp_state;
|
||||
use ethjson;
|
||||
use trace::{Tracer, NoopTracer};
|
||||
use trace::{VMTracer, NoopVMTracer};
|
||||
use bytes::{Bytes, BytesRef};
|
||||
use bytes::Bytes;
|
||||
use ethtrie;
|
||||
use rlp::RlpStream;
|
||||
use hash::keccak;
|
||||
@ -90,7 +90,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
|
||||
depth: usize,
|
||||
origin_info: OriginInfo,
|
||||
substate: &'a mut Substate,
|
||||
output: OutputPolicy<'a, 'a>,
|
||||
output: OutputPolicy,
|
||||
address: Address,
|
||||
tracer: &'a mut T,
|
||||
vm_tracer: &'a mut V,
|
||||
@ -154,7 +154,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
|
||||
value: Option<U256>,
|
||||
data: &[u8],
|
||||
_code_address: &Address,
|
||||
_output: &mut [u8],
|
||||
_call_type: CallType
|
||||
) -> MessageCallResult {
|
||||
self.callcreates.push(CallCreate {
|
||||
@ -262,7 +261,6 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
||||
let mut substate = Substate::new();
|
||||
let mut tracer = NoopTracer;
|
||||
let mut vm_tracer = NoopVMTracer;
|
||||
let mut output = vec![];
|
||||
let vm_factory = state.vm_factory();
|
||||
|
||||
// execute
|
||||
@ -276,18 +274,23 @@ fn do_json_test_for<H: FnMut(&str, HookType)>(vm_type: &VMType, json_data: &[u8]
|
||||
0,
|
||||
OriginInfo::from(¶ms),
|
||||
&mut substate,
|
||||
OutputPolicy::Return(BytesRef::Flexible(&mut output), None),
|
||||
OutputPolicy::Return,
|
||||
params.address.clone(),
|
||||
&mut tracer,
|
||||
&mut vm_tracer,
|
||||
));
|
||||
let mut evm = vm_factory.create(¶ms, schedule.wasm.is_some());
|
||||
let res = evm.exec(params, &mut ex);
|
||||
let mut evm = vm_factory.create(params, &schedule, 0);
|
||||
let res = evm.exec(&mut ex);
|
||||
// a return in finalize will not alter callcreates
|
||||
let callcreates = ex.callcreates.clone();
|
||||
(res.finalize(ex), callcreates)
|
||||
};
|
||||
|
||||
let output = match &res {
|
||||
Ok(res) => res.return_data.to_vec(),
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
|
||||
let log_hash = {
|
||||
let mut rlp = RlpStream::new_list(substate.logs.len());
|
||||
for l in &substate.logs {
|
||||
|
@ -33,7 +33,6 @@ use transaction::{self, SYSTEM_ADDRESS, UnverifiedTransaction, SignedTransaction
|
||||
use tx_filter::TransactionFilter;
|
||||
|
||||
use ethereum_types::{U256, Address};
|
||||
use bytes::BytesRef;
|
||||
use rlp::Rlp;
|
||||
use vm::{CallType, ActionParams, ActionValue, ParamsType};
|
||||
use vm::{EnvInfo, Schedule, CreateContractAddress};
|
||||
@ -148,10 +147,14 @@ impl EthereumMachine {
|
||||
let schedule = self.schedule(env_info.number);
|
||||
let mut ex = Executive::new(&mut state, &env_info, self, &schedule);
|
||||
let mut substate = Substate::new();
|
||||
let mut output = Vec::new();
|
||||
if let Err(e) = ex.call(params, &mut substate, BytesRef::Flexible(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
|
||||
let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
|
||||
let output = match res {
|
||||
Ok(res) => res.return_data.to_vec(),
|
||||
Err(e) => {
|
||||
warn!("Encountered error on making system call: {}", e);
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
@ -343,7 +346,7 @@ impl EthereumMachine {
|
||||
-> Result<(), transaction::Error>
|
||||
{
|
||||
if let Some(ref filter) = self.tx_filter.as_ref() {
|
||||
if !filter.transaction_allowed(header.parent_hash(), t, client) {
|
||||
if !filter.transaction_allowed(header.parent_hash(), header.number(), t, client) {
|
||||
return Err(transaction::Error::NotAllowed.into())
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ use using_queue::{UsingQueue, GetAction};
|
||||
use account_provider::{AccountProvider, SignError as AccountError};
|
||||
use block::{ClosedBlock, IsBlock, Block, SealedBlock};
|
||||
use client::{
|
||||
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce
|
||||
BlockChain, ChainInfo, CallContract, BlockProducer, SealedBlockImporter, Nonce, TransactionInfo, TransactionId
|
||||
};
|
||||
use client::{BlockId, ClientIoMessage};
|
||||
use executive::contract_address;
|
||||
@ -296,6 +296,19 @@ impl Miner {
|
||||
*self.io_channel.write() = Some(io_channel);
|
||||
}
|
||||
|
||||
/// Sets in-blockchain checker for transactions.
|
||||
pub fn set_in_chain_checker<C>(&self, chain: &Arc<C>) where
|
||||
C: TransactionInfo + Send + Sync + 'static,
|
||||
{
|
||||
let client = Arc::downgrade(chain);
|
||||
self.transaction_queue.set_in_chain_checker(move |hash| {
|
||||
match client.upgrade() {
|
||||
Some(info) => info.transaction_block(TransactionId::Hash(*hash)).is_some(),
|
||||
None => false,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Clear all pending block states
|
||||
pub fn clear(&self) {
|
||||
self.sealing.lock().queue.reset();
|
||||
@ -319,14 +332,15 @@ impl Miner {
|
||||
/// Retrieves an existing pending block iff it's not older than given block number.
|
||||
///
|
||||
/// NOTE: This will not prepare a new pending block if it's not existing.
|
||||
/// See `map_pending_block` for alternative behaviour.
|
||||
fn map_existing_pending_block<F, T>(&self, f: F, latest_block_number: BlockNumber) -> Option<T> where
|
||||
F: FnOnce(&ClosedBlock) -> T,
|
||||
{
|
||||
self.sealing.lock().queue
|
||||
.peek_last_ref()
|
||||
.and_then(|b| {
|
||||
if b.block().header().number() > latest_block_number {
|
||||
// to prevent a data race between block import and updating pending block
|
||||
// we allow the number to be equal.
|
||||
if b.block().header().number() >= latest_block_number {
|
||||
Some(f(b))
|
||||
} else {
|
||||
None
|
||||
@ -365,7 +379,7 @@ impl Miner {
|
||||
// if at least one was pushed successfully, close and enqueue new ClosedBlock;
|
||||
// otherwise, leave everything alone.
|
||||
// otherwise, author a fresh block.
|
||||
let mut open_block = match sealing.queue.pop_if(|b| b.block().header().parent_hash() == &best_hash) {
|
||||
let mut open_block = match sealing.queue.get_pending_if(|b| b.block().header().parent_hash() == &best_hash) {
|
||||
Some(old_block) => {
|
||||
trace!(target: "miner", "prepare_block: Already have previous work; updating and returning");
|
||||
// add transactions to old_block
|
||||
@ -628,7 +642,7 @@ impl Miner {
|
||||
{
|
||||
let mut sealing = self.sealing.lock();
|
||||
sealing.next_mandatory_reseal = Instant::now() + self.options.reseal_max_period;
|
||||
sealing.queue.push(block.clone());
|
||||
sealing.queue.set_pending(block.clone());
|
||||
sealing.queue.use_last_ref();
|
||||
}
|
||||
|
||||
@ -690,7 +704,7 @@ impl Miner {
|
||||
);
|
||||
let is_new = original_work_hash.map_or(true, |h| h != block_hash);
|
||||
|
||||
sealing.queue.push(block);
|
||||
sealing.queue.set_pending(block);
|
||||
|
||||
#[cfg(feature = "work-notify")]
|
||||
{
|
||||
@ -1108,7 +1122,7 @@ impl miner::MinerService for Miner {
|
||||
Some(false) => {
|
||||
trace!(target: "miner", "update_sealing: engine is not keen to seal internally right now");
|
||||
// anyway, save the block for later use
|
||||
self.sealing.lock().queue.push(block);
|
||||
self.sealing.lock().queue.set_pending(block);
|
||||
},
|
||||
None => {
|
||||
trace!(target: "miner", "update_sealing: engine does not seal internally, preparing work");
|
||||
|
@ -22,8 +22,7 @@ use std::fmt;
|
||||
|
||||
use client::{Client, ImportSealedBlock};
|
||||
use ethereum_types::{H64, H256, clean_0x, U256};
|
||||
use ethereum::ethash::Ethash;
|
||||
use ethash::SeedHashCompute;
|
||||
use ethash::{self, SeedHashCompute};
|
||||
#[cfg(feature = "work-notify")]
|
||||
use ethcore_miner::work_notify::NotifyWork;
|
||||
#[cfg(feature = "work-notify")]
|
||||
@ -167,7 +166,7 @@ impl StratumJobDispatcher {
|
||||
/// Serializes payload for stratum service
|
||||
fn payload(&self, pow_hash: H256, difficulty: U256, number: u64) -> String {
|
||||
// TODO: move this to engine
|
||||
let target = Ethash::difficulty_to_boundary(&difficulty);
|
||||
let target = ethash::difficulty_to_boundary(&difficulty);
|
||||
let seed_hash = &self.seed_compute.lock().hash_block_number(number);
|
||||
let seed_hash = H256::from_slice(&seed_hash[..]);
|
||||
format!(
|
||||
|
@ -125,6 +125,10 @@ pub struct CommonParams {
|
||||
pub remove_dust_contracts: bool,
|
||||
/// Wasm activation blocknumber, if any disabled initially.
|
||||
pub wasm_activation_transition: BlockNumber,
|
||||
/// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated.
|
||||
pub kip4_transition: BlockNumber,
|
||||
/// Number of first block where KIP-6 rules begin. Only has effect if Wasm is activated.
|
||||
pub kip6_transition: BlockNumber,
|
||||
/// Gas limit bound divisor (how much gas limit can change per block)
|
||||
pub gas_limit_bound_divisor: U256,
|
||||
/// Registrar contract address.
|
||||
@ -137,6 +141,8 @@ pub struct CommonParams {
|
||||
pub max_code_size_transition: BlockNumber,
|
||||
/// Transaction permission managing contract address.
|
||||
pub transaction_permission_contract: Option<Address>,
|
||||
/// Block at which the transaction permission contract should start being used.
|
||||
pub transaction_permission_contract_transition: BlockNumber,
|
||||
/// Maximum size of transaction's RLP payload
|
||||
pub max_transaction_size: usize,
|
||||
}
|
||||
@ -187,7 +193,14 @@ impl CommonParams {
|
||||
};
|
||||
}
|
||||
if block_number >= self.wasm_activation_transition {
|
||||
schedule.wasm = Some(Default::default());
|
||||
let mut wasm = ::vm::WasmCosts::default();
|
||||
if block_number >= self.kip4_transition {
|
||||
wasm.have_create2 = true;
|
||||
}
|
||||
if block_number >= self.kip6_transition {
|
||||
wasm.have_gasleft = true;
|
||||
}
|
||||
schedule.wasm = Some(wasm);
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,10 +303,20 @@ impl From<ethjson::spec::Params> for CommonParams {
|
||||
max_transaction_size: p.max_transaction_size.map_or(MAX_TRANSACTION_SIZE, Into::into),
|
||||
max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into),
|
||||
transaction_permission_contract: p.transaction_permission_contract.map(Into::into),
|
||||
transaction_permission_contract_transition:
|
||||
p.transaction_permission_contract_transition.map_or(0, Into::into),
|
||||
wasm_activation_transition: p.wasm_activation_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into
|
||||
),
|
||||
kip4_transition: p.kip4_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into
|
||||
),
|
||||
kip6_transition: p.kip6_transition.map_or_else(
|
||||
BlockNumber::max_value,
|
||||
Into::into
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -641,7 +664,7 @@ impl Spec {
|
||||
let machine = self.engine.machine();
|
||||
let schedule = machine.schedule(env_info.number);
|
||||
let mut exec = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||
if let Err(e) = exec.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer) {
|
||||
if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
|
||||
warn!(target: "spec", "Genesis constructor execution at {} failed: {}.", address, e);
|
||||
}
|
||||
}
|
||||
@ -756,6 +779,11 @@ impl Spec {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return genesis state as Plain old data.
|
||||
pub fn genesis_state(&self) -> &PodState {
|
||||
&self.genesis_state
|
||||
}
|
||||
|
||||
/// Returns `false` if the memoized state root is invalid. `true` otherwise.
|
||||
pub fn is_state_root_valid(&self) -> bool {
|
||||
// TODO: get rid of this function and ensure state root always is valid.
|
||||
|
@ -150,7 +150,7 @@ fn returns_logs() {
|
||||
address: None,
|
||||
topics: vec![],
|
||||
limit: None,
|
||||
});
|
||||
}).unwrap();
|
||||
assert_eq!(logs.len(), 0);
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ fn returns_logs_with_limit() {
|
||||
address: None,
|
||||
topics: vec![],
|
||||
limit: None,
|
||||
});
|
||||
}).unwrap();
|
||||
assert_eq!(logs.len(), 0);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ use transaction::SYSTEM_ADDRESS;
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
use ethereum_types::{H256, Address};
|
||||
use bytes::BytesRef;
|
||||
|
||||
evm_test!{test_blockhash_eip210: test_blockhash_eip210_int}
|
||||
fn test_blockhash_eip210(factory: Factory) {
|
||||
@ -65,8 +64,7 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
let schedule = machine.schedule(env_info.number);
|
||||
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||
let mut substate = Substate::new();
|
||||
let mut output = [];
|
||||
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
|
||||
if let Err(e) = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
|
||||
panic!("Encountered error on updating last hashes: {}", e);
|
||||
}
|
||||
}
|
||||
@ -89,9 +87,12 @@ fn test_blockhash_eip210(factory: Factory) {
|
||||
let schedule = machine.schedule(env_info.number);
|
||||
let mut ex = Executive::new(&mut state, &env_info, &machine, &schedule);
|
||||
let mut substate = Substate::new();
|
||||
let mut output = H256::new();
|
||||
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
|
||||
let res = ex.call(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer);
|
||||
let output = match res {
|
||||
Ok(res) => H256::from(&res.return_data[..32]),
|
||||
Err(e) => {
|
||||
panic!("Encountered error on getting last hash: {}", e);
|
||||
}
|
||||
},
|
||||
};
|
||||
assert_eq!(output, 255.into());
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
//! Simple executive tracer.
|
||||
|
||||
use ethereum_types::{U256, Address};
|
||||
use bytes::Bytes;
|
||||
use vm::ActionParams;
|
||||
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType};
|
||||
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
||||
@ -92,18 +91,14 @@ impl Tracer for ExecutiveTracer {
|
||||
Some(Create::from(params.clone()))
|
||||
}
|
||||
|
||||
fn prepare_trace_output(&self) -> Option<Bytes> {
|
||||
Some(vec![])
|
||||
}
|
||||
|
||||
fn trace_call(&mut self, call: Option<Call>, gas_used: U256, output: Option<Bytes>, subs: Vec<FlatTrace>) {
|
||||
fn trace_call(&mut self, call: Option<Call>, gas_used: U256, output: &[u8], subs: Vec<FlatTrace>) {
|
||||
let trace = FlatTrace {
|
||||
trace_address: Default::default(),
|
||||
subtraces: top_level_subtraces(&subs),
|
||||
action: Action::Call(call.expect("self.prepare_trace_call().is_some(): so we must be tracing: qed")),
|
||||
result: Res::Call(CallResult {
|
||||
gas_used: gas_used,
|
||||
output: output.expect("self.prepare_trace_output().is_some(): so we must be tracing: qed")
|
||||
output: output.into()
|
||||
}),
|
||||
};
|
||||
debug!(target: "trace", "Traced call {:?}", trace);
|
||||
@ -111,13 +106,13 @@ impl Tracer for ExecutiveTracer {
|
||||
self.traces.extend(prefix_subtrace_addresses(subs));
|
||||
}
|
||||
|
||||
fn trace_create(&mut self, create: Option<Create>, gas_used: U256, code: Option<Bytes>, address: Address, subs: Vec<FlatTrace>) {
|
||||
fn trace_create(&mut self, create: Option<Create>, gas_used: U256, code: &[u8], address: Address, subs: Vec<FlatTrace>) {
|
||||
let trace = FlatTrace {
|
||||
subtraces: top_level_subtraces(&subs),
|
||||
action: Action::Create(create.expect("self.prepare_trace_create().is_some(): so we must be tracing: qed")),
|
||||
result: Res::Create(CreateResult {
|
||||
gas_used: gas_used,
|
||||
code: code.expect("self.prepare_trace_output.is_some(): so we must be tracing: qed"),
|
||||
code: code.into(),
|
||||
address: address
|
||||
}),
|
||||
trace_address: Default::default(),
|
||||
|
@ -38,7 +38,6 @@ pub use self::types::filter::{Filter, AddressesFilter};
|
||||
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
use kvdb::DBTransaction;
|
||||
use bytes::Bytes;
|
||||
use self::trace::{Call, Create};
|
||||
use vm::ActionParams;
|
||||
use header::BlockNumber;
|
||||
@ -58,9 +57,6 @@ pub trait Tracer: Send {
|
||||
/// This is called before a create has been executed.
|
||||
fn prepare_trace_create(&self, params: &ActionParams) -> Option<Create>;
|
||||
|
||||
/// Prepare trace output. Noop tracer should return None.
|
||||
fn prepare_trace_output(&self) -> Option<Bytes>;
|
||||
|
||||
/// Stores trace call info.
|
||||
///
|
||||
/// This is called after a call has completed successfully.
|
||||
@ -68,7 +64,7 @@ pub trait Tracer: Send {
|
||||
&mut self,
|
||||
call: Option<Call>,
|
||||
gas_used: U256,
|
||||
output: Option<Bytes>,
|
||||
output: &[u8],
|
||||
subs: Vec<Self::Output>,
|
||||
);
|
||||
|
||||
@ -79,7 +75,7 @@ pub trait Tracer: Send {
|
||||
&mut self,
|
||||
create: Option<Create>,
|
||||
gas_used: U256,
|
||||
code: Option<Bytes>,
|
||||
code: &[u8],
|
||||
address: Address,
|
||||
subs: Vec<Self::Output>
|
||||
);
|
||||
|
@ -17,7 +17,6 @@
|
||||
//! Nonoperative tracer.
|
||||
|
||||
use ethereum_types::{U256, Address};
|
||||
use bytes::Bytes;
|
||||
use vm::ActionParams;
|
||||
use trace::{Tracer, VMTracer, FlatTrace, TraceError};
|
||||
use trace::trace::{Call, Create, VMTrace, RewardType};
|
||||
@ -36,18 +35,12 @@ impl Tracer for NoopTracer {
|
||||
None
|
||||
}
|
||||
|
||||
fn prepare_trace_output(&self) -> Option<Bytes> {
|
||||
None
|
||||
}
|
||||
|
||||
fn trace_call(&mut self, call: Option<Call>, _: U256, output: Option<Bytes>, _: Vec<FlatTrace>) {
|
||||
fn trace_call(&mut self, call: Option<Call>, _: U256, _: &[u8], _: Vec<FlatTrace>) {
|
||||
assert!(call.is_none(), "self.prepare_trace_call().is_none(): so we can't be tracing: qed");
|
||||
assert!(output.is_none(), "self.prepare_trace_output().is_none(): so we can't be tracing: qed");
|
||||
}
|
||||
|
||||
fn trace_create(&mut self, create: Option<Create>, _: U256, code: Option<Bytes>, _: Address, _: Vec<FlatTrace>) {
|
||||
fn trace_create(&mut self, create: Option<Create>, _: U256, _: &[u8], _: Address, _: Vec<FlatTrace>) {
|
||||
assert!(create.is_none(), "self.prepare_trace_create().is_none(): so we can't be tracing: qed");
|
||||
assert!(code.is_none(), "self.prepare_trace_output().is_none(): so we can't be tracing: qed");
|
||||
}
|
||||
|
||||
fn trace_failed_call(&mut self, call: Option<Call>, _: Vec<FlatTrace>, _: TraceError) {
|
||||
|
@ -23,6 +23,7 @@ use client::{BlockInfo, CallContract, BlockId};
|
||||
use parking_lot::Mutex;
|
||||
use spec::CommonParams;
|
||||
use transaction::{Action, SignedTransaction};
|
||||
use types::BlockNumber;
|
||||
use hash::KECCAK_EMPTY;
|
||||
|
||||
use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json");
|
||||
@ -44,6 +45,7 @@ pub struct TransactionFilter {
|
||||
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated,
|
||||
contract: transact_acl::TransactAcl,
|
||||
contract_address: Address,
|
||||
transition_block: BlockNumber,
|
||||
permission_cache: Mutex<LruCache<(H256, Address), u32>>,
|
||||
contract_version_cache: Mutex<LruCache<(H256), Option<U256>>>
|
||||
}
|
||||
@ -56,6 +58,7 @@ impl TransactionFilter {
|
||||
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(),
|
||||
contract: transact_acl::TransactAcl::default(),
|
||||
contract_address: address,
|
||||
transition_block: params.transaction_permission_contract_transition,
|
||||
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
|
||||
contract_version_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
|
||||
}
|
||||
@ -63,7 +66,9 @@ impl TransactionFilter {
|
||||
}
|
||||
|
||||
/// Check if transaction is allowed at given block.
|
||||
pub fn transaction_allowed<C: BlockInfo + CallContract>(&self, parent_hash: &H256, transaction: &SignedTransaction, client: &C) -> bool {
|
||||
pub fn transaction_allowed<C: BlockInfo + CallContract>(&self, parent_hash: &H256, block_number: BlockNumber, transaction: &SignedTransaction, client: &C) -> bool {
|
||||
if block_number < self.transition_block { return true; }
|
||||
|
||||
let mut permission_cache = self.permission_cache.lock();
|
||||
let mut contract_version_cache = self.contract_version_cache.lock();
|
||||
|
||||
@ -196,33 +201,38 @@ mod test {
|
||||
basic_tx_with_ether_and_to_key6.value = U256::from(123123);
|
||||
|
||||
let genesis = client.block_hash(BlockId::Latest).unwrap();
|
||||
let block_number = 1;
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
// same tx but request is allowed because the contract only enables at block #1
|
||||
assert!(filter.transaction_allowed(&genesis, 0, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key2.secret(), None), &*client));
|
||||
|
||||
assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key3.secret(), None), &*client));
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key4.secret(), None), &*client));
|
||||
|
||||
assert!(!filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key7.clone().sign(key5.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key6.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key7.clone().sign(key6.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx_to_key6.clone().sign(key7.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
|
||||
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key5.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key6.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key6.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx_to_key6.clone().sign(key7.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
|
||||
}
|
||||
|
||||
/// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a
|
||||
@ -254,21 +264,26 @@ mod test {
|
||||
call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005"));
|
||||
|
||||
let genesis = client.block_hash(BlockId::Latest).unwrap();
|
||||
let block_number = 1;
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
// same tx but request is allowed because the contract only enables at block #1
|
||||
assert!(filter.transaction_allowed(&genesis, 0, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
|
||||
|
||||
assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key2.secret(), None), &*client));
|
||||
|
||||
assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key3.secret(), None), &*client));
|
||||
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
|
||||
assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key4.secret(), None), &*client));
|
||||
}
|
||||
}
|
||||
|
@ -113,6 +113,7 @@ pub mod blocks {
|
||||
}
|
||||
|
||||
/// An unverified block.
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub struct Unverified {
|
||||
/// Unverified block header.
|
||||
pub header: Header,
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering as AtomicOrdering};
|
||||
use std::sync::{Condvar as SCondvar, Mutex as SMutex, Arc};
|
||||
use std::sync::Arc;
|
||||
use std::cmp;
|
||||
use std::collections::{VecDeque, HashSet, HashMap};
|
||||
use heapsize::HeapSizeOf;
|
||||
@ -141,11 +141,11 @@ struct Sizes {
|
||||
/// Keeps them in the same order as inserted, minus invalid items.
|
||||
pub struct VerificationQueue<K: Kind> {
|
||||
engine: Arc<EthEngine>,
|
||||
more_to_verify: Arc<SCondvar>,
|
||||
more_to_verify: Arc<Condvar>,
|
||||
verification: Arc<Verification<K>>,
|
||||
deleting: Arc<AtomicBool>,
|
||||
ready_signal: Arc<QueueSignal>,
|
||||
empty: Arc<SCondvar>,
|
||||
empty: Arc<Condvar>,
|
||||
processing: RwLock<HashMap<H256, U256>>, // hash to difficulty
|
||||
ticks_since_adjustment: AtomicUsize,
|
||||
max_queue_size: usize,
|
||||
@ -202,8 +202,6 @@ struct Verification<K: Kind> {
|
||||
verifying: Mutex<VecDeque<Verifying<K>>>,
|
||||
verified: Mutex<VecDeque<K::Verified>>,
|
||||
bad: Mutex<HashSet<H256>>,
|
||||
more_to_verify: SMutex<()>,
|
||||
empty: SMutex<()>,
|
||||
sizes: Sizes,
|
||||
check_seal: bool,
|
||||
}
|
||||
@ -216,8 +214,6 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
verifying: Mutex::new(VecDeque::new()),
|
||||
verified: Mutex::new(VecDeque::new()),
|
||||
bad: Mutex::new(HashSet::new()),
|
||||
more_to_verify: SMutex::new(()),
|
||||
empty: SMutex::new(()),
|
||||
sizes: Sizes {
|
||||
unverified: AtomicUsize::new(0),
|
||||
verifying: AtomicUsize::new(0),
|
||||
@ -225,14 +221,14 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
},
|
||||
check_seal: check_seal,
|
||||
});
|
||||
let more_to_verify = Arc::new(SCondvar::new());
|
||||
let more_to_verify = Arc::new(Condvar::new());
|
||||
let deleting = Arc::new(AtomicBool::new(false));
|
||||
let ready_signal = Arc::new(QueueSignal {
|
||||
deleting: deleting.clone(),
|
||||
signalled: AtomicBool::new(false),
|
||||
message_channel: Mutex::new(message_channel),
|
||||
});
|
||||
let empty = Arc::new(SCondvar::new());
|
||||
let empty = Arc::new(Condvar::new());
|
||||
let scale_verifiers = config.verifier_settings.scale_verifiers;
|
||||
|
||||
let num_cpus = ::num_cpus::get();
|
||||
@ -292,9 +288,9 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
fn verify(
|
||||
verification: Arc<Verification<K>>,
|
||||
engine: Arc<EthEngine>,
|
||||
wait: Arc<SCondvar>,
|
||||
wait: Arc<Condvar>,
|
||||
ready: Arc<QueueSignal>,
|
||||
empty: Arc<SCondvar>,
|
||||
empty: Arc<Condvar>,
|
||||
state: Arc<(Mutex<State>, Condvar)>,
|
||||
id: usize,
|
||||
) {
|
||||
@ -319,19 +315,19 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
|
||||
// wait for work if empty.
|
||||
{
|
||||
let mut more_to_verify = verification.more_to_verify.lock().unwrap();
|
||||
let mut unverified = verification.unverified.lock();
|
||||
|
||||
if verification.unverified.lock().is_empty() && verification.verifying.lock().is_empty() {
|
||||
if unverified.is_empty() && verification.verifying.lock().is_empty() {
|
||||
empty.notify_all();
|
||||
}
|
||||
|
||||
while verification.unverified.lock().is_empty() {
|
||||
while unverified.is_empty() {
|
||||
if let State::Exit = *state.0.lock() {
|
||||
debug!(target: "verification", "verifier {} exiting", id);
|
||||
return;
|
||||
}
|
||||
|
||||
more_to_verify = wait.wait(more_to_verify).unwrap();
|
||||
wait.wait(&mut unverified);
|
||||
}
|
||||
|
||||
if let State::Exit = *state.0.lock() {
|
||||
@ -450,9 +446,9 @@ impl<K: Kind> VerificationQueue<K> {
|
||||
|
||||
/// Wait for unverified queue to be empty
|
||||
pub fn flush(&self) {
|
||||
let mut lock = self.verification.empty.lock().unwrap();
|
||||
while !self.verification.unverified.lock().is_empty() || !self.verification.verifying.lock().is_empty() {
|
||||
lock = self.empty.wait(lock).unwrap();
|
||||
let mut unverified = self.verification.unverified.lock();
|
||||
while !unverified.is_empty() || !self.verification.verifying.lock().is_empty() {
|
||||
self.empty.wait(&mut unverified);
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,7 +708,7 @@ impl<K: Kind> Drop for VerificationQueue<K> {
|
||||
// acquire this lock to force threads to reach the waiting point
|
||||
// if they're in-between the exit check and the more_to_verify wait.
|
||||
{
|
||||
let _more = self.verification.more_to_verify.lock().unwrap();
|
||||
let _unverified = self.verification.unverified.lock();
|
||||
self.more_to_verify.notify_all();
|
||||
}
|
||||
|
||||
|
@ -376,7 +376,6 @@ mod tests {
|
||||
use types::log_entry::{LogEntry, LocalizedLogEntry};
|
||||
use rlp;
|
||||
use triehash::ordered_trie_root;
|
||||
use views::BlockView;
|
||||
|
||||
fn check_ok(result: Result<(), Error>) {
|
||||
result.unwrap_or_else(|e| panic!("Block verification failed: {:?}", e));
|
||||
@ -420,10 +419,10 @@ mod tests {
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, bytes: Bytes) {
|
||||
let number = view!(BlockView, &bytes).header_view().number();
|
||||
let hash = view!(BlockView, &bytes).header_view().hash();
|
||||
self.blocks.insert(hash.clone(), bytes);
|
||||
self.numbers.insert(number, hash.clone());
|
||||
let header = Unverified::from_rlp(bytes.clone()).unwrap().header;
|
||||
let hash = header.hash();
|
||||
self.blocks.insert(hash, bytes);
|
||||
self.numbers.insert(header.number(), hash);
|
||||
}
|
||||
}
|
||||
|
||||
@ -460,11 +459,11 @@ mod tests {
|
||||
/// Get the familial details concerning a block.
|
||||
fn block_details(&self, hash: &H256) -> Option<BlockDetails> {
|
||||
self.blocks.get(hash).map(|bytes| {
|
||||
let header = view!(BlockView, bytes).header();
|
||||
let header = Unverified::from_rlp(bytes.to_vec()).unwrap().header;
|
||||
BlockDetails {
|
||||
number: header.number(),
|
||||
total_difficulty: header.difficulty().clone(),
|
||||
parent: header.parent_hash().clone(),
|
||||
total_difficulty: *header.difficulty(),
|
||||
parent: *header.parent_hash(),
|
||||
children: Vec::new(),
|
||||
is_finalized: false,
|
||||
}
|
||||
@ -501,9 +500,9 @@ mod tests {
|
||||
}
|
||||
|
||||
fn family_test<BC>(bytes: &[u8], engine: &EthEngine, bc: &BC) -> Result<(), Error> where BC: BlockProvider {
|
||||
let view = view!(BlockView, bytes);
|
||||
let header = view.header();
|
||||
let transactions: Vec<_> = view.transactions()
|
||||
let block = Unverified::from_rlp(bytes.to_vec()).unwrap();
|
||||
let header = block.header;
|
||||
let transactions: Vec<_> = block.transactions
|
||||
.into_iter()
|
||||
.map(SignedTransaction::new)
|
||||
.collect::<Result<_,_>>()?;
|
||||
@ -520,7 +519,7 @@ mod tests {
|
||||
let block = PreverifiedBlock {
|
||||
header,
|
||||
transactions,
|
||||
uncles: view.uncles(),
|
||||
uncles: block.uncles,
|
||||
bytes: bytes.to_vec(),
|
||||
};
|
||||
|
||||
@ -533,7 +532,6 @@ mod tests {
|
||||
}
|
||||
|
||||
fn unordered_test(bytes: &[u8], engine: &EthEngine) -> Result<(), Error> {
|
||||
use verification::queue::kind::blocks::Unverified;
|
||||
let un = Unverified::from_rlp(bytes.to_vec())?;
|
||||
verify_block_unordered(un, engine, false)?;
|
||||
Ok(())
|
||||
|
@ -11,11 +11,11 @@ keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
|
||||
jsonrpc-macros = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
|
||||
jsonrpc-tcp-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.11" }
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
parking_lot = "0.6"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.4"
|
||||
env_logger = "0.5"
|
||||
tokio-core = "0.1"
|
||||
tokio-io = "0.1"
|
||||
ethcore-logger = { path = "../../logger" }
|
||||
|
@ -8,6 +8,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[lib]
|
||||
|
||||
[dependencies]
|
||||
common-types = { path = "../types" }
|
||||
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
ethcore-network = { path = "../../util/network" }
|
||||
ethcore-network-devp2p = { path = "../../util/network-devp2p" }
|
||||
@ -17,7 +18,7 @@ ethcore-transaction = { path = "../transaction" }
|
||||
ethcore = { path = ".." }
|
||||
ethereum-types = "0.3"
|
||||
hashdb = { git = "https://github.com/paritytech/parity-common" }
|
||||
plain_hasher = { git = "https://github.com/paritytech/parity-common" }
|
||||
fastmap = { path = "../../util/fastmap" }
|
||||
rlp = { git = "https://github.com/paritytech/parity-common" }
|
||||
rustc-hex = "1.0"
|
||||
keccak-hash = { git = "https://github.com/paritytech/parity-common" }
|
||||
@ -25,8 +26,8 @@ keccak-hasher = { path = "../../util/keccak-hasher" }
|
||||
triehash-ethereum = {version = "0.2", path = "../../util/triehash-ethereum" }
|
||||
kvdb = { git = "https://github.com/paritytech/parity-common" }
|
||||
macros = { path = "../../util/macros" }
|
||||
log = "0.3"
|
||||
env_logger = "0.4"
|
||||
log = "0.4"
|
||||
env_logger = "0.5"
|
||||
rand = "0.4"
|
||||
heapsize = "0.4"
|
||||
semver = "0.9"
|
||||
|
@ -24,6 +24,8 @@ use devp2p::NetworkService;
|
||||
use network::{NetworkProtocolHandler, NetworkContext, PeerId, ProtocolId,
|
||||
NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, Error, ErrorKind,
|
||||
ConnectionFilter};
|
||||
|
||||
use types::pruning_info::PruningInfo;
|
||||
use ethereum_types::{H256, H512, U256};
|
||||
use io::{TimerToken};
|
||||
use ethcore::ethstore::ethkey::Secret;
|
||||
@ -39,7 +41,10 @@ use chain::{ETH_PROTOCOL_VERSION_63, ETH_PROTOCOL_VERSION_62,
|
||||
PAR_PROTOCOL_VERSION_1, PAR_PROTOCOL_VERSION_2, PAR_PROTOCOL_VERSION_3};
|
||||
use light::client::AsLightClient;
|
||||
use light::Provider;
|
||||
use light::net::{self as light_net, LightProtocol, Params as LightParams, Capabilities, Handler as LightHandler, EventContext};
|
||||
use light::net::{
|
||||
self as light_net, LightProtocol, Params as LightParams,
|
||||
Capabilities, Handler as LightHandler, EventContext, SampleStore,
|
||||
};
|
||||
use network::IpFilter;
|
||||
use private_tx::PrivateTxHandler;
|
||||
use transaction::UnverifiedTransaction;
|
||||
@ -256,23 +261,16 @@ pub struct EthSync {
|
||||
light_subprotocol_name: [u8; 3],
|
||||
}
|
||||
|
||||
impl EthSync {
|
||||
/// Creates and register protocol with the network service
|
||||
pub fn new(params: Params, connection_filter: Option<Arc<ConnectionFilter>>) -> Result<Arc<EthSync>, Error> {
|
||||
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 pruning_info = params.chain.pruning_info();
|
||||
let light_proto = match params.config.serve_light {
|
||||
false => None,
|
||||
true => Some({
|
||||
let sample_store = params.network_config.net_config_path
|
||||
.clone()
|
||||
.map(::std::path::PathBuf::from)
|
||||
.map(|mut p| { p.push("request_timings"); light_net::FileStore(p) })
|
||||
.map(|store| Box::new(store) as Box<_>);
|
||||
|
||||
let mut light_params = LightParams {
|
||||
network_id: params.config.network_id,
|
||||
network_id: network_id,
|
||||
config: Default::default(),
|
||||
capabilities: Capabilities {
|
||||
serve_headers: true,
|
||||
@ -283,9 +281,32 @@ impl EthSync {
|
||||
sample_store: sample_store,
|
||||
};
|
||||
|
||||
let max_peers = ::std::cmp::min(params.network_config.max_peers, 1);
|
||||
let max_peers = ::std::cmp::max(max_peers, 1);
|
||||
light_params.config.load_share = MAX_LIGHTSERV_LOAD / max_peers as f64;
|
||||
|
||||
light_params
|
||||
}
|
||||
|
||||
impl EthSync {
|
||||
/// Creates and register protocol with the network service
|
||||
pub fn new(params: Params, connection_filter: Option<Arc<ConnectionFilter>>) -> Result<Arc<EthSync>, Error> {
|
||||
let pruning_info = params.chain.pruning_info();
|
||||
let light_proto = match params.config.serve_light {
|
||||
false => None,
|
||||
true => Some({
|
||||
let sample_store = params.network_config.net_config_path
|
||||
.clone()
|
||||
.map(::std::path::PathBuf::from)
|
||||
.map(|mut p| { p.push("request_timings"); light_net::FileStore(p) })
|
||||
.map(|store| Box::new(store) as Box<_>);
|
||||
|
||||
let light_params = light_params(
|
||||
params.config.network_id,
|
||||
params.network_config.max_peers,
|
||||
pruning_info,
|
||||
sample_store,
|
||||
);
|
||||
|
||||
let mut light_proto = LightProtocol::new(params.provider, light_params);
|
||||
light_proto.add_handler(Arc::new(TxRelay(params.chain.clone())));
|
||||
|
||||
@ -916,3 +937,19 @@ impl LightSyncProvider for LightSync {
|
||||
Default::default() // TODO
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn light_params_load_share_depends_on_max_peers() {
|
||||
let pruning_info = PruningInfo {
|
||||
earliest_chain: 0,
|
||||
earliest_state: 0,
|
||||
};
|
||||
let params1 = light_params(0, 10, pruning_info.clone(), None);
|
||||
let params2 = light_params(0, 20, pruning_info, None);
|
||||
assert!(params1.config.load_share > params2.config.load_share)
|
||||
}
|
||||
}
|
||||
|
@ -23,12 +23,11 @@ use std::cmp;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::H256;
|
||||
use rlp::{self, Rlp};
|
||||
use ethcore::header::{BlockNumber, Header as BlockHeader};
|
||||
use ethcore::header::BlockNumber;
|
||||
use ethcore::client::{BlockStatus, BlockId, BlockImportError, BlockImportErrorKind};
|
||||
use ethcore::error::{ImportErrorKind, BlockError};
|
||||
use ethcore::verification::queue::kind::blocks::Unverified;
|
||||
use ethcore::error::{ImportErrorKind, QueueErrorKind, BlockError};
|
||||
use sync_io::SyncIo;
|
||||
use blocks::BlockCollection;
|
||||
use blocks::{BlockCollection, SyncBody, SyncHeader};
|
||||
|
||||
const MAX_HEADERS_TO_REQUEST: usize = 128;
|
||||
const MAX_BODIES_TO_REQUEST: usize = 32;
|
||||
@ -236,45 +235,39 @@ impl BlockDownloader {
|
||||
let mut valid_response = item_count == 0; //empty response is valid
|
||||
let mut any_known = false;
|
||||
for i in 0..item_count {
|
||||
let info: BlockHeader = r.val_at(i).map_err(|e| {
|
||||
trace!(target: "sync", "Error decoding block header RLP: {:?}", e);
|
||||
BlockDownloaderImportError::Invalid
|
||||
})?;
|
||||
let number = BlockNumber::from(info.number());
|
||||
let info = SyncHeader::from_rlp(r.at(i)?.as_raw().to_vec())?;
|
||||
let number = BlockNumber::from(info.header.number());
|
||||
let hash = info.header.hash();
|
||||
// Check if any of the headers matches the hash we requested
|
||||
if !valid_response {
|
||||
if let Some(expected) = expected_hash {
|
||||
valid_response = expected == info.hash()
|
||||
valid_response = expected == hash;
|
||||
}
|
||||
}
|
||||
any_known = any_known || self.blocks.contains_head(&info.hash());
|
||||
if self.blocks.contains(&info.hash()) {
|
||||
trace!(target: "sync", "Skipping existing block header {} ({:?})", number, info.hash());
|
||||
any_known = any_known || self.blocks.contains_head(&hash);
|
||||
if self.blocks.contains(&hash) {
|
||||
trace!(target: "sync", "Skipping existing block header {} ({:?})", number, hash);
|
||||
continue;
|
||||
}
|
||||
|
||||
if self.highest_block.as_ref().map_or(true, |n| number > *n) {
|
||||
self.highest_block = Some(number);
|
||||
}
|
||||
let hash = info.hash();
|
||||
let hdr = r.at(i).map_err(|e| {
|
||||
trace!(target: "sync", "Error decoding block header RLP: {:?}", e);
|
||||
BlockDownloaderImportError::Invalid
|
||||
})?;
|
||||
|
||||
match io.chain().block_status(BlockId::Hash(hash.clone())) {
|
||||
BlockStatus::InChain | BlockStatus::Queued => {
|
||||
match self.state {
|
||||
State::Blocks => trace!(target: "sync", "Header already in chain {} ({})", number, hash),
|
||||
_ => trace!(target: "sync", "Header already in chain {} ({}), state = {:?}", number, hash, self.state),
|
||||
}
|
||||
headers.push(hdr.as_raw().to_vec());
|
||||
headers.push(info);
|
||||
hashes.push(hash);
|
||||
},
|
||||
BlockStatus::Bad => {
|
||||
return Err(BlockDownloaderImportError::Invalid);
|
||||
},
|
||||
BlockStatus::Unknown | BlockStatus::Pending => {
|
||||
headers.push(hdr.as_raw().to_vec());
|
||||
headers.push(info);
|
||||
hashes.push(hash);
|
||||
}
|
||||
}
|
||||
@ -325,19 +318,15 @@ impl BlockDownloader {
|
||||
let item_count = r.item_count().unwrap_or(0);
|
||||
if item_count == 0 {
|
||||
return Err(BlockDownloaderImportError::Useless);
|
||||
}
|
||||
else if self.state != State::Blocks {
|
||||
} else if self.state != State::Blocks {
|
||||
trace!(target: "sync", "Ignored unexpected block bodies");
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let mut bodies = Vec::with_capacity(item_count);
|
||||
for i in 0..item_count {
|
||||
let body = r.at(i).map_err(|e| {
|
||||
trace!(target: "sync", "Error decoding block boides RLP: {:?}", e);
|
||||
BlockDownloaderImportError::Invalid
|
||||
})?;
|
||||
bodies.push(body.as_raw().to_vec());
|
||||
let body = SyncBody::from_rlp(r.at(i)?.as_raw())?;
|
||||
bodies.push(body);
|
||||
}
|
||||
|
||||
if self.blocks.insert_bodies(bodies) != item_count {
|
||||
trace!(target: "sync", "Deactivating peer for giving invalid block bodies");
|
||||
return Err(BlockDownloaderImportError::Invalid);
|
||||
@ -483,15 +472,6 @@ impl BlockDownloader {
|
||||
let block = block_and_receipts.block;
|
||||
let receipts = block_and_receipts.receipts;
|
||||
|
||||
let block = match Unverified::from_rlp(block) {
|
||||
Ok(block) => block,
|
||||
Err(_) => {
|
||||
debug!(target: "sync", "Bad block rlp");
|
||||
bad = true;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let h = block.header.hash();
|
||||
let number = block.header.number();
|
||||
let parent = *block.header.parent_hash();
|
||||
@ -533,6 +513,10 @@ impl BlockDownloader {
|
||||
debug!(target: "sync", "Block temporarily invalid, restarting sync");
|
||||
break;
|
||||
},
|
||||
Err(BlockImportError(BlockImportErrorKind::Queue(QueueErrorKind::Full(limit)), _)) => {
|
||||
debug!(target: "sync", "Block import queue full ({}), restarting sync", limit);
|
||||
break;
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(target: "sync", "Bad block {:?} : {:?}", h, e);
|
||||
bad = true;
|
||||
|
@ -23,28 +23,86 @@ use triehash_ethereum::ordered_trie_root;
|
||||
use bytes::Bytes;
|
||||
use rlp::{Rlp, RlpStream, DecoderError};
|
||||
use network;
|
||||
use ethcore::encoded::Block;
|
||||
use ethcore::views::{HeaderView, BodyView};
|
||||
use ethcore::header::Header as BlockHeader;
|
||||
use ethcore::verification::queue::kind::blocks::Unverified;
|
||||
use transaction::UnverifiedTransaction;
|
||||
|
||||
known_heap_size!(0, HeaderId);
|
||||
|
||||
type SmallHashVec = SmallVec<[H256; 1]>;
|
||||
|
||||
/// Block data with optional body.
|
||||
struct SyncBlock {
|
||||
header: Bytes,
|
||||
body: Option<Bytes>,
|
||||
receipts: Option<Bytes>,
|
||||
receipts_root: H256,
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub struct SyncHeader {
|
||||
pub bytes: Bytes,
|
||||
pub header: BlockHeader,
|
||||
}
|
||||
|
||||
/// Block with optional receipt
|
||||
pub struct BlockAndReceipts {
|
||||
/// Block data.
|
||||
pub block: Bytes,
|
||||
/// Block receipts RLP list.
|
||||
pub receipts: Option<Bytes>,
|
||||
impl HeapSizeOf for SyncHeader {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.bytes.heap_size_of_children()
|
||||
+ self.header.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
impl SyncHeader {
|
||||
pub fn from_rlp(bytes: Bytes) -> Result<Self, DecoderError> {
|
||||
let result = SyncHeader {
|
||||
header: ::rlp::decode(&bytes)?,
|
||||
bytes,
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SyncBody {
|
||||
pub transactions_bytes: Bytes,
|
||||
pub transactions: Vec<UnverifiedTransaction>,
|
||||
pub uncles_bytes: Bytes,
|
||||
pub uncles: Vec<BlockHeader>,
|
||||
}
|
||||
|
||||
impl SyncBody {
|
||||
pub fn from_rlp(bytes: &[u8]) -> Result<Self, DecoderError> {
|
||||
let rlp = Rlp::new(bytes);
|
||||
let transactions_rlp = rlp.at(0)?;
|
||||
let uncles_rlp = rlp.at(1)?;
|
||||
|
||||
let result = SyncBody {
|
||||
transactions_bytes: transactions_rlp.as_raw().to_vec(),
|
||||
transactions: transactions_rlp.as_list()?,
|
||||
uncles_bytes: uncles_rlp.as_raw().to_vec(),
|
||||
uncles: uncles_rlp.as_list()?,
|
||||
};
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn empty_body() -> Self {
|
||||
SyncBody {
|
||||
transactions_bytes: ::rlp::EMPTY_LIST_RLP.to_vec(),
|
||||
transactions: Vec::with_capacity(0),
|
||||
uncles_bytes: ::rlp::EMPTY_LIST_RLP.to_vec(),
|
||||
uncles: Vec::with_capacity(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HeapSizeOf for SyncBody {
|
||||
fn heap_size_of_children(&self) -> usize {
|
||||
self.transactions_bytes.heap_size_of_children()
|
||||
+ self.transactions.heap_size_of_children()
|
||||
+ self.uncles_bytes.heap_size_of_children()
|
||||
+ self.uncles.heap_size_of_children()
|
||||
}
|
||||
}
|
||||
|
||||
/// Block data with optional body.
|
||||
struct SyncBlock {
|
||||
header: SyncHeader,
|
||||
body: Option<SyncBody>,
|
||||
receipts: Option<Bytes>,
|
||||
receipts_root: H256,
|
||||
}
|
||||
|
||||
impl HeapSizeOf for SyncBlock {
|
||||
@ -53,6 +111,29 @@ impl HeapSizeOf for SyncBlock {
|
||||
}
|
||||
}
|
||||
|
||||
fn unverified_from_sync(header: SyncHeader, body: Option<SyncBody>) -> Unverified {
|
||||
let mut stream = RlpStream::new_list(3);
|
||||
stream.append_raw(&header.bytes, 1);
|
||||
let body = body.unwrap_or_else(SyncBody::empty_body);
|
||||
stream.append_raw(&body.transactions_bytes, 1);
|
||||
stream.append_raw(&body.uncles_bytes, 1);
|
||||
|
||||
Unverified {
|
||||
header: header.header,
|
||||
transactions: body.transactions,
|
||||
uncles: body.uncles,
|
||||
bytes: stream.out().to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Block with optional receipt
|
||||
pub struct BlockAndReceipts {
|
||||
/// Block data.
|
||||
pub block: Unverified,
|
||||
/// Block receipts RLP list.
|
||||
pub receipts: Option<Bytes>,
|
||||
}
|
||||
|
||||
/// Used to identify header by transactions and uncles hashes
|
||||
#[derive(Eq, PartialEq, Hash)]
|
||||
struct HeaderId {
|
||||
@ -124,7 +205,7 @@ impl BlockCollection {
|
||||
}
|
||||
|
||||
/// Insert a set of headers into collection and advance subchain head pointers.
|
||||
pub fn insert_headers(&mut self, headers: Vec<Bytes>) {
|
||||
pub fn insert_headers(&mut self, headers: Vec<SyncHeader>) {
|
||||
for h in headers {
|
||||
if let Err(e) = self.insert_header(h) {
|
||||
trace!(target: "sync", "Ignored invalid header: {:?}", e);
|
||||
@ -134,7 +215,7 @@ impl BlockCollection {
|
||||
}
|
||||
|
||||
/// Insert a collection of block bodies for previously downloaded headers.
|
||||
pub fn insert_bodies(&mut self, bodies: Vec<Bytes>) -> usize {
|
||||
pub fn insert_bodies(&mut self, bodies: Vec<SyncBody>) -> usize {
|
||||
let mut inserted = 0;
|
||||
for b in bodies {
|
||||
if let Err(e) = self.insert_body(b) {
|
||||
@ -278,30 +359,33 @@ impl BlockCollection {
|
||||
while let Some(h) = head {
|
||||
head = self.parents.get(&h).cloned();
|
||||
if let Some(head) = head {
|
||||
match self.blocks.get(&head) {
|
||||
Some(block) if block.body.is_some() && (!self.need_receipts || block.receipts.is_some()) => {
|
||||
match self.blocks.remove(&head) {
|
||||
Some(block) => {
|
||||
if block.body.is_some() && (!self.need_receipts || block.receipts.is_some()) {
|
||||
blocks.push(block);
|
||||
hashes.push(head);
|
||||
self.head = Some(head);
|
||||
} else {
|
||||
self.blocks.insert(head, block);
|
||||
break;
|
||||
}
|
||||
_ => break,
|
||||
},
|
||||
_ => {
|
||||
break;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for block in blocks {
|
||||
let body = view!(BodyView, block.body.as_ref().expect("blocks contains only full blocks; qed"));
|
||||
let header = view!(HeaderView, &block.header);
|
||||
let block_view = Block::new_from_header_and_body(&header, &body);
|
||||
for block in blocks.into_iter() {
|
||||
let unverified = unverified_from_sync(block.header, block.body);
|
||||
drained.push(BlockAndReceipts {
|
||||
block: block_view.into_inner(),
|
||||
block: unverified,
|
||||
receipts: block.receipts.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
for h in hashes {
|
||||
self.blocks.remove(&h);
|
||||
}
|
||||
|
||||
trace!(target: "sync", "Drained {} blocks, new head :{:?}", drained.len(), self.head);
|
||||
drained
|
||||
}
|
||||
@ -337,26 +421,23 @@ impl BlockCollection {
|
||||
self.downloading_headers.contains(hash) || self.downloading_bodies.contains(hash)
|
||||
}
|
||||
|
||||
fn insert_body(&mut self, b: Bytes) -> Result<(), network::Error> {
|
||||
fn insert_body(&mut self, body: SyncBody) -> Result<(), network::Error> {
|
||||
let header_id = {
|
||||
let body = Rlp::new(&b);
|
||||
let tx = body.at(0)?;
|
||||
let tx_root = ordered_trie_root(tx.iter().map(|r| r.as_raw()));
|
||||
let uncles = keccak(body.at(1)?.as_raw());
|
||||
let tx_root = ordered_trie_root(Rlp::new(&body.transactions_bytes).iter().map(|r| r.as_raw()));
|
||||
let uncles = keccak(&body.uncles_bytes);
|
||||
HeaderId {
|
||||
transactions_root: tx_root,
|
||||
uncles: uncles
|
||||
}
|
||||
};
|
||||
|
||||
match self.header_ids.get(&header_id).cloned() {
|
||||
match self.header_ids.remove(&header_id) {
|
||||
Some(h) => {
|
||||
self.header_ids.remove(&header_id);
|
||||
self.downloading_bodies.remove(&h);
|
||||
match self.blocks.get_mut(&h) {
|
||||
Some(ref mut block) => {
|
||||
trace!(target: "sync", "Got body {}", h);
|
||||
block.body = Some(b);
|
||||
block.body = Some(body);
|
||||
Ok(())
|
||||
},
|
||||
None => {
|
||||
@ -401,54 +482,63 @@ impl BlockCollection {
|
||||
}
|
||||
}
|
||||
|
||||
fn insert_header(&mut self, header: Bytes) -> Result<H256, DecoderError> {
|
||||
let info: BlockHeader = Rlp::new(&header).as_val()?;
|
||||
let hash = info.hash();
|
||||
fn insert_header(&mut self, info: SyncHeader) -> Result<H256, DecoderError> {
|
||||
let hash = info.header.hash();
|
||||
if self.blocks.contains_key(&hash) {
|
||||
return Ok(hash);
|
||||
}
|
||||
|
||||
match self.head {
|
||||
None if hash == self.heads[0] => {
|
||||
trace!(target: "sync", "New head {}", hash);
|
||||
self.head = Some(info.parent_hash().clone());
|
||||
self.head = Some(info.header.parent_hash().clone());
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
|
||||
let mut block = SyncBlock {
|
||||
header: header,
|
||||
body: None,
|
||||
receipts: None,
|
||||
receipts_root: H256::new(),
|
||||
};
|
||||
let header_id = HeaderId {
|
||||
transactions_root: info.transactions_root().clone(),
|
||||
uncles: info.uncles_hash().clone(),
|
||||
transactions_root: *info.header.transactions_root(),
|
||||
uncles: *info.header.uncles_hash(),
|
||||
};
|
||||
if header_id.transactions_root == KECCAK_NULL_RLP && header_id.uncles == KECCAK_EMPTY_LIST_RLP {
|
||||
|
||||
let body = if header_id.transactions_root == KECCAK_NULL_RLP && header_id.uncles == KECCAK_EMPTY_LIST_RLP {
|
||||
// empty body, just mark as downloaded
|
||||
let mut body_stream = RlpStream::new_list(2);
|
||||
body_stream.append_raw(&::rlp::EMPTY_LIST_RLP, 1);
|
||||
body_stream.append_raw(&::rlp::EMPTY_LIST_RLP, 1);
|
||||
block.body = Some(body_stream.out());
|
||||
}
|
||||
else {
|
||||
trace!("Queueing body tx_root = {:?}, uncles = {:?}, block = {:?}, number = {}", header_id.transactions_root, header_id.uncles, hash, info.number());
|
||||
self.header_ids.insert(header_id, hash.clone());
|
||||
}
|
||||
if self.need_receipts {
|
||||
let receipt_root = info.receipts_root().clone();
|
||||
Some(SyncBody::empty_body())
|
||||
} else {
|
||||
trace!(
|
||||
"Queueing body tx_root = {:?}, uncles = {:?}, block = {:?}, number = {}",
|
||||
header_id.transactions_root,
|
||||
header_id.uncles,
|
||||
hash,
|
||||
info.header.number()
|
||||
);
|
||||
self.header_ids.insert(header_id, hash);
|
||||
None
|
||||
};
|
||||
|
||||
let (receipts, receipts_root) = if self.need_receipts {
|
||||
let receipt_root = *info.header.receipts_root();
|
||||
if receipt_root == KECCAK_NULL_RLP {
|
||||
let receipts_stream = RlpStream::new_list(0);
|
||||
block.receipts = Some(receipts_stream.out());
|
||||
(Some(receipts_stream.out()), receipt_root)
|
||||
} else {
|
||||
self.receipt_ids.entry(receipt_root).or_insert_with(|| SmallHashVec::new()).push(hash.clone());
|
||||
}
|
||||
block.receipts_root = receipt_root;
|
||||
self.receipt_ids.entry(receipt_root).or_insert_with(|| SmallHashVec::new()).push(hash);
|
||||
(None, receipt_root)
|
||||
}
|
||||
} else {
|
||||
(None, H256::new())
|
||||
};
|
||||
|
||||
self.parents.insert(info.parent_hash().clone(), hash.clone());
|
||||
self.blocks.insert(hash.clone(), block);
|
||||
self.parents.insert(*info.header.parent_hash(), hash);
|
||||
|
||||
let block = SyncBlock {
|
||||
header: info,
|
||||
body,
|
||||
receipts,
|
||||
receipts_root,
|
||||
};
|
||||
|
||||
self.blocks.insert(hash, block);
|
||||
trace!(target: "sync", "New header: {:x}", hash);
|
||||
Ok(hash)
|
||||
}
|
||||
@ -485,10 +575,10 @@ impl BlockCollection {
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::BlockCollection;
|
||||
use super::{BlockCollection, SyncHeader};
|
||||
use ethcore::client::{TestBlockChainClient, EachBlockWith, BlockId, BlockChainClient};
|
||||
use ethcore::views::HeaderView;
|
||||
use ethcore::header::BlockNumber;
|
||||
use ethcore::verification::queue::kind::blocks::Unverified;
|
||||
use rlp::*;
|
||||
|
||||
fn is_empty(bc: &BlockCollection) -> bool {
|
||||
@ -524,9 +614,9 @@ mod test {
|
||||
let blocks: Vec<_> = (0..nblocks)
|
||||
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).unwrap().into_inner())
|
||||
.collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
|
||||
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
|
||||
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(*h) } else { None }).collect();
|
||||
bc.reset_to(heads);
|
||||
assert!(!bc.is_empty());
|
||||
assert_eq!(hashes[0], bc.heads[0]);
|
||||
@ -541,7 +631,7 @@ mod test {
|
||||
assert_eq!(bc.downloading_headers.len(), 1);
|
||||
assert!(bc.drain().is_empty());
|
||||
|
||||
bc.insert_headers(headers[0..6].to_vec());
|
||||
bc.insert_headers(headers[0..6].into_iter().map(Clone::clone).collect());
|
||||
assert_eq!(hashes[5], bc.heads[0]);
|
||||
for h in &hashes[0..6] {
|
||||
bc.clear_header_download(h)
|
||||
@ -550,7 +640,10 @@ mod test {
|
||||
assert!(!bc.is_downloading(&hashes[0]));
|
||||
assert!(bc.contains(&hashes[0]));
|
||||
|
||||
assert_eq!(&bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>()[..], &blocks[0..6]);
|
||||
assert_eq!(
|
||||
bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>(),
|
||||
blocks[0..6].iter().map(|b| Unverified::from_rlp(b.to_vec()).unwrap()).collect::<Vec<_>>()
|
||||
);
|
||||
assert!(!bc.contains(&hashes[0]));
|
||||
assert_eq!(hashes[5], bc.head.unwrap());
|
||||
|
||||
@ -558,13 +651,17 @@ mod test {
|
||||
assert_eq!(hashes[5], h);
|
||||
let (h, _) = bc.needed_headers(6, false).unwrap();
|
||||
assert_eq!(hashes[20], h);
|
||||
bc.insert_headers(headers[10..16].to_vec());
|
||||
bc.insert_headers(headers[10..16].into_iter().map(Clone::clone).collect());
|
||||
assert!(bc.drain().is_empty());
|
||||
bc.insert_headers(headers[5..10].to_vec());
|
||||
assert_eq!(&bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>()[..], &blocks[6..16]);
|
||||
bc.insert_headers(headers[5..10].into_iter().map(Clone::clone).collect());
|
||||
assert_eq!(
|
||||
bc.drain().into_iter().map(|b| b.block).collect::<Vec<_>>(),
|
||||
blocks[6..16].iter().map(|b| Unverified::from_rlp(b.to_vec()).unwrap()).collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
assert_eq!(hashes[15], bc.heads[0]);
|
||||
|
||||
bc.insert_headers(headers[15..].to_vec());
|
||||
bc.insert_headers(headers[15..].into_iter().map(Clone::clone).collect());
|
||||
bc.drain();
|
||||
assert!(bc.is_empty());
|
||||
}
|
||||
@ -579,16 +676,16 @@ mod test {
|
||||
let blocks: Vec<_> = (0..nblocks)
|
||||
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).unwrap().into_inner())
|
||||
.collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
|
||||
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
|
||||
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(*h) } else { None }).collect();
|
||||
bc.reset_to(heads);
|
||||
|
||||
bc.insert_headers(headers[2..22].to_vec());
|
||||
bc.insert_headers(headers[2..22].into_iter().map(Clone::clone).collect());
|
||||
assert_eq!(hashes[0], bc.heads[0]);
|
||||
assert_eq!(hashes[21], bc.heads[1]);
|
||||
assert!(bc.head.is_none());
|
||||
bc.insert_headers(headers[0..2].to_vec());
|
||||
bc.insert_headers(headers[0..2].into_iter().map(Clone::clone).collect());
|
||||
assert!(bc.head.is_some());
|
||||
assert_eq!(hashes[21], bc.heads[0]);
|
||||
}
|
||||
@ -603,14 +700,14 @@ mod test {
|
||||
let blocks: Vec<_> = (0..nblocks)
|
||||
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).unwrap().into_inner())
|
||||
.collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
|
||||
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(h.clone()) } else { None }).collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
|
||||
let heads: Vec<_> = hashes.iter().enumerate().filter_map(|(i, h)| if i % 20 == 0 { Some(*h) } else { None }).collect();
|
||||
bc.reset_to(heads);
|
||||
|
||||
bc.insert_headers(headers[1..2].to_vec());
|
||||
bc.insert_headers(headers[1..2].into_iter().map(Clone::clone).collect());
|
||||
assert!(bc.drain().is_empty());
|
||||
bc.insert_headers(headers[0..1].to_vec());
|
||||
bc.insert_headers(headers[0..1].into_iter().map(Clone::clone).collect());
|
||||
assert_eq!(bc.drain().len(), 2);
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ use std::time::{Duration, Instant};
|
||||
use hash::keccak;
|
||||
use heapsize::HeapSizeOf;
|
||||
use ethereum_types::{H256, U256};
|
||||
use plain_hasher::H256FastMap;
|
||||
use fastmap::H256FastMap;
|
||||
use parking_lot::RwLock;
|
||||
use bytes::Bytes;
|
||||
use rlp::{Rlp, RlpStream, DecoderError};
|
||||
@ -148,7 +148,8 @@ const MAX_PEER_LAG_PROPAGATION: BlockNumber = 20;
|
||||
const MAX_NEW_HASHES: usize = 64;
|
||||
const MAX_NEW_BLOCK_AGE: BlockNumber = 20;
|
||||
// maximal packet size with transactions (cannot be greater than 16MB - protocol limitation).
|
||||
const MAX_TRANSACTION_PACKET_SIZE: usize = 8 * 1024 * 1024;
|
||||
// keep it under 8MB as well, cause it seems that it may result oversized after compression.
|
||||
const MAX_TRANSACTION_PACKET_SIZE: usize = 5 * 1024 * 1024;
|
||||
// Min number of blocks to be behind for a snapshot sync
|
||||
const SNAPSHOT_RESTORE_THRESHOLD: BlockNumber = 30000;
|
||||
const SNAPSHOT_MIN_PEERS: usize = 3;
|
||||
|
@ -237,8 +237,9 @@ impl SyncPropagator {
|
||||
let lucky_peers_len = lucky_peers.len();
|
||||
for (peer_id, sent, rlp) in lucky_peers {
|
||||
peers.insert(peer_id);
|
||||
let size = rlp.len();
|
||||
SyncPropagator::send_packet(io, peer_id, TRANSACTIONS_PACKET, rlp);
|
||||
trace!(target: "sync", "{:02} <- Transactions ({} entries)", peer_id, sent);
|
||||
trace!(target: "sync", "{:02} <- Transactions ({} entries; {} bytes)", peer_id, sent, size);
|
||||
max_sent = cmp::max(max_sent, sent);
|
||||
}
|
||||
debug!(target: "sync", "Sent up to {} transactions to {} peers.", max_sent, lucky_peers_len);
|
||||
|
@ -307,11 +307,11 @@ mod test {
|
||||
use bytes::Bytes;
|
||||
use rlp::{Rlp, RlpStream};
|
||||
use super::{*, super::tests::*};
|
||||
use blocks::SyncHeader;
|
||||
use ethcore::client::{BlockChainClient, EachBlockWith, TestBlockChainClient};
|
||||
|
||||
#[test]
|
||||
fn return_block_headers() {
|
||||
use ethcore::views::HeaderView;
|
||||
fn make_hash_req(h: &H256, count: usize, skip: usize, reverse: bool) -> Bytes {
|
||||
let mut rlp = RlpStream::new_list(4);
|
||||
rlp.append(h);
|
||||
@ -329,16 +329,16 @@ mod test {
|
||||
rlp.append(&if reverse {1u32} else {0u32});
|
||||
rlp.out()
|
||||
}
|
||||
fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<Bytes> {
|
||||
Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| r.as_raw().to_vec()).collect()
|
||||
fn to_header_vec(rlp: ::chain::RlpResponseResult) -> Vec<SyncHeader> {
|
||||
Rlp::new(&rlp.unwrap().unwrap().1.out()).iter().map(|r| SyncHeader::from_rlp(r.as_raw().to_vec()).unwrap()).collect()
|
||||
}
|
||||
|
||||
let mut client = TestBlockChainClient::new();
|
||||
client.add_blocks(100, EachBlockWith::Nothing);
|
||||
let blocks: Vec<_> = (0 .. 100)
|
||||
.map(|i| (&client as &BlockChainClient).block(BlockId::Number(i as BlockNumber)).map(|b| b.into_inner()).unwrap()).collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| Rlp::new(b).at(0).unwrap().as_raw().to_vec()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| view!(HeaderView, h).hash()).collect();
|
||||
let headers: Vec<_> = blocks.iter().map(|b| SyncHeader::from_rlp(Rlp::new(b).at(0).unwrap().as_raw().to_vec()).unwrap()).collect();
|
||||
let hashes: Vec<_> = headers.iter().map(|h| h.header.hash()).collect();
|
||||
|
||||
let queue = RwLock::new(VecDeque::new());
|
||||
let ss = TestSnapshotService::new();
|
||||
|
@ -21,17 +21,17 @@
|
||||
//! https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol
|
||||
//!
|
||||
|
||||
extern crate common_types as types;
|
||||
extern crate ethcore_network as network;
|
||||
extern crate ethcore_network_devp2p as devp2p;
|
||||
extern crate parity_bytes as bytes;
|
||||
extern crate ethcore_io as io;
|
||||
extern crate ethcore_transaction as transaction;
|
||||
#[macro_use]
|
||||
extern crate ethcore;
|
||||
extern crate ethereum_types;
|
||||
extern crate env_logger;
|
||||
extern crate hashdb;
|
||||
extern crate plain_hasher;
|
||||
extern crate fastmap;
|
||||
extern crate rand;
|
||||
extern crate semver;
|
||||
extern crate parking_lot;
|
||||
|
@ -22,7 +22,7 @@ use {SyncConfig, WarpSync};
|
||||
|
||||
#[test]
|
||||
fn two_peers() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle);
|
||||
net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle);
|
||||
@ -33,7 +33,7 @@ fn two_peers() {
|
||||
|
||||
#[test]
|
||||
fn long_chain() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(2);
|
||||
net.peer(1).chain.add_blocks(50000, EachBlockWith::Nothing);
|
||||
net.sync();
|
||||
@ -43,7 +43,7 @@ fn long_chain() {
|
||||
|
||||
#[test]
|
||||
fn status_after_sync() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle);
|
||||
net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle);
|
||||
@ -63,7 +63,7 @@ fn takes_few_steps() {
|
||||
|
||||
#[test]
|
||||
fn empty_blocks() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
for n in 0..200 {
|
||||
let with = if n % 2 == 0 { EachBlockWith::Nothing } else { EachBlockWith::Uncle };
|
||||
@ -77,7 +77,7 @@ fn empty_blocks() {
|
||||
|
||||
#[test]
|
||||
fn forked() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
net.peer(0).chain.add_blocks(30, EachBlockWith::Uncle);
|
||||
net.peer(1).chain.add_blocks(30, EachBlockWith::Uncle);
|
||||
@ -98,7 +98,7 @@ fn forked() {
|
||||
|
||||
#[test]
|
||||
fn forked_with_misbehaving_peer() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
|
||||
let mut alt_spec = ::ethcore::spec::Spec::new_test();
|
||||
@ -122,7 +122,7 @@ fn forked_with_misbehaving_peer() {
|
||||
|
||||
#[test]
|
||||
fn net_hard_fork() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let ref_client = TestBlockChainClient::new();
|
||||
ref_client.add_blocks(50, EachBlockWith::Uncle);
|
||||
{
|
||||
@ -141,7 +141,7 @@ fn net_hard_fork() {
|
||||
|
||||
#[test]
|
||||
fn restart() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(3);
|
||||
net.peer(1).chain.add_blocks(1000, EachBlockWith::Uncle);
|
||||
net.peer(2).chain.add_blocks(1000, EachBlockWith::Uncle);
|
||||
@ -255,7 +255,7 @@ fn high_td_attach() {
|
||||
|
||||
#[test]
|
||||
fn disconnect_on_unrelated_chain() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut net = TestNet::new(2);
|
||||
net.peer(0).chain.set_history(Some(20));
|
||||
net.peer(1).chain.set_history(Some(20));
|
||||
|
@ -141,7 +141,7 @@ impl SnapshotService for TestSnapshotService {
|
||||
|
||||
#[test]
|
||||
fn snapshot_sync() {
|
||||
::env_logger::init().ok();
|
||||
::env_logger::try_init().ok();
|
||||
let mut config = SyncConfig::default();
|
||||
config.warp_sync = WarpSync::Enabled;
|
||||
let mut net = TestNet::new_with_config(5, config);
|
||||
|
@ -17,7 +17,7 @@
|
||||
use api::TransactionStats;
|
||||
use std::collections::{HashSet, HashMap};
|
||||
use ethereum_types::{H256, H512};
|
||||
use plain_hasher::H256FastMap;
|
||||
use fastmap::H256FastMap;
|
||||
|
||||
type NodeId = H512;
|
||||
type BlockNumber = u64;
|
||||
|
@ -9,7 +9,7 @@ parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
ethereum-types = "0.3"
|
||||
patricia-trie = { git = "https://github.com/paritytech/parity-common" }
|
||||
patricia-trie-ethereum = { path = "../../util/patricia-trie-ethereum" }
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
common-types = { path = "../types" }
|
||||
ethjson = { path = "../../json" }
|
||||
rlp = { git = "https://github.com/paritytech/parity-common" }
|
||||
|
@ -51,7 +51,7 @@ pub enum MessageCallResult {
|
||||
}
|
||||
|
||||
/// Specifies how an address is calculated for a new contract.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum CreateContractAddress {
|
||||
/// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis)
|
||||
FromSenderAndNonce,
|
||||
@ -101,7 +101,6 @@ pub trait Ext {
|
||||
value: Option<U256>,
|
||||
data: &[u8],
|
||||
code_address: &Address,
|
||||
output: &mut [u8],
|
||||
call_type: CallType
|
||||
) -> MessageCallResult;
|
||||
|
||||
|
@ -48,5 +48,5 @@ pub trait Vm {
|
||||
/// This function should be used to execute transaction.
|
||||
/// It returns either an error, a known amount of gas left, or parameters to be used
|
||||
/// to compute the final gas left.
|
||||
fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result<GasLeft>;
|
||||
fn exec(&mut self, ext: &mut Ext) -> Result<GasLeft>;
|
||||
}
|
||||
|
@ -149,6 +149,10 @@ pub struct WasmCosts {
|
||||
pub opcodes_mul: u32,
|
||||
/// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div`
|
||||
pub opcodes_div: u32,
|
||||
/// Whether create2 extern function is activated.
|
||||
pub have_create2: bool,
|
||||
/// Whether gasleft extern function is activated.
|
||||
pub have_gasleft: bool,
|
||||
}
|
||||
|
||||
impl Default for WasmCosts {
|
||||
@ -166,6 +170,8 @@ impl Default for WasmCosts {
|
||||
max_stack_height: 64*1024,
|
||||
opcodes_mul: 3,
|
||||
opcodes_div: 8,
|
||||
have_create2: false,
|
||||
have_gasleft: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ pub enum FakeCallType {
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub struct FakeCall {
|
||||
pub call_type: FakeCallType,
|
||||
pub create_scheme: Option<CreateContractAddress>,
|
||||
pub gas: U256,
|
||||
pub sender_address: Option<Address>,
|
||||
pub receive_address: Option<Address>,
|
||||
@ -133,9 +134,10 @@ impl Ext for FakeExt {
|
||||
self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
|
||||
}
|
||||
|
||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
|
||||
fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult {
|
||||
self.calls.insert(FakeCall {
|
||||
call_type: FakeCallType::Create,
|
||||
create_scheme: Some(address),
|
||||
gas: *gas,
|
||||
sender_address: None,
|
||||
receive_address: None,
|
||||
@ -153,12 +155,12 @@ impl Ext for FakeExt {
|
||||
value: Option<U256>,
|
||||
data: &[u8],
|
||||
code_address: &Address,
|
||||
_output: &mut [u8],
|
||||
_call_type: CallType
|
||||
) -> MessageCallResult {
|
||||
|
||||
self.calls.insert(FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: *gas,
|
||||
sender_address: Some(sender_address.clone()),
|
||||
receive_address: Some(receive_address.clone()),
|
||||
|
@ -6,7 +6,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
byteorder = "1.0"
|
||||
ethereum-types = "0.3"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
parity-wasm = "0.31"
|
||||
libc = "0.2"
|
||||
pwasm-utils = "0.2.2"
|
||||
|
@ -31,8 +31,8 @@ fn load_code<P: AsRef<path::Path>>(p: P) -> io::Result<Vec<u8>> {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn wasm_interpreter() -> WasmInterpreter {
|
||||
WasmInterpreter
|
||||
fn wasm_interpreter(params: ActionParams) -> WasmInterpreter {
|
||||
WasmInterpreter::new(params)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -131,7 +131,7 @@ pub fn construct(
|
||||
params.params_type = ParamsType::Separate;
|
||||
|
||||
Ok(
|
||||
match wasm_interpreter().exec(params, ext)? {
|
||||
match wasm_interpreter(params).exec(ext)? {
|
||||
GasLeft::Known(_) => Vec::new(),
|
||||
GasLeft::NeedsReturn { data, .. } => data.to_vec(),
|
||||
}
|
||||
@ -192,9 +192,9 @@ pub fn run_fixture(fixture: &Fixture) -> Vec<Fail> {
|
||||
}
|
||||
}
|
||||
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
|
||||
let interpreter_return = match interpreter.exec(params, &mut ext) {
|
||||
let interpreter_return = match interpreter.exec(&mut ext) {
|
||||
Ok(ret) => ret,
|
||||
Err(e) => { return Fail::runtime(e); }
|
||||
};
|
||||
|
@ -17,6 +17,7 @@
|
||||
//! Env module glue for wasmi interpreter
|
||||
|
||||
use std::cell::RefCell;
|
||||
use vm::WasmCosts;
|
||||
use wasmi::{
|
||||
self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor,
|
||||
MemoryRef, MemoryInstance, memory_units,
|
||||
@ -47,6 +48,8 @@ pub mod ids {
|
||||
pub const SENDER_FUNC: usize = 190;
|
||||
pub const ORIGIN_FUNC: usize = 200;
|
||||
pub const ELOG_FUNC: usize = 210;
|
||||
pub const CREATE2_FUNC: usize = 220;
|
||||
pub const GASLEFT_FUNC: usize = 230;
|
||||
|
||||
pub const PANIC_FUNC: usize = 1000;
|
||||
pub const DEBUG_FUNC: usize = 1010;
|
||||
@ -125,6 +128,11 @@ pub mod signatures {
|
||||
Some(I32),
|
||||
);
|
||||
|
||||
pub const CREATE2: StaticSignature = StaticSignature(
|
||||
&[I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
);
|
||||
|
||||
pub const SUICIDE: StaticSignature = StaticSignature(
|
||||
&[I32],
|
||||
None,
|
||||
@ -150,6 +158,11 @@ pub mod signatures {
|
||||
None,
|
||||
);
|
||||
|
||||
pub const GASLEFT: StaticSignature = StaticSignature(
|
||||
&[],
|
||||
Some(I64),
|
||||
);
|
||||
|
||||
pub const GASLIMIT: StaticSignature = StaticSignature(
|
||||
&[I32],
|
||||
None,
|
||||
@ -195,18 +208,23 @@ fn host(signature: signatures::StaticSignature, idx: usize) -> FuncRef {
|
||||
/// Maps all functions that runtime support to the corresponding contract import
|
||||
/// entries.
|
||||
/// Also manages initial memory request from the runtime.
|
||||
#[derive(Default)]
|
||||
pub struct ImportResolver {
|
||||
max_memory: u32,
|
||||
memory: RefCell<Option<MemoryRef>>,
|
||||
|
||||
have_create2: bool,
|
||||
have_gasleft: bool,
|
||||
}
|
||||
|
||||
impl ImportResolver {
|
||||
/// New import resolver with specifed maximum amount of inital memory (in wasm pages = 64kb)
|
||||
pub fn with_limit(max_memory: u32) -> ImportResolver {
|
||||
pub fn with_limit(max_memory: u32, schedule: &WasmCosts) -> ImportResolver {
|
||||
ImportResolver {
|
||||
max_memory: max_memory,
|
||||
memory: RefCell::new(None),
|
||||
|
||||
have_create2: schedule.have_create2,
|
||||
have_gasleft: schedule.have_gasleft,
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,6 +281,8 @@ impl wasmi::ModuleImportResolver for ImportResolver {
|
||||
"sender" => host(signatures::SENDER, ids::SENDER_FUNC),
|
||||
"origin" => host(signatures::ORIGIN, ids::ORIGIN_FUNC),
|
||||
"elog" => host(signatures::ELOG, ids::ELOG_FUNC),
|
||||
"create2" if self.have_create2 => host(signatures::CREATE2, ids::CREATE2_FUNC),
|
||||
"gasleft" if self.have_gasleft => host(signatures::GASLEFT, ids::GASLEFT_FUNC),
|
||||
_ => {
|
||||
return Err(wasmi::Error::Instantiation(
|
||||
format!("Export {} not found", field_name),
|
||||
|
@ -69,7 +69,15 @@ impl From<Error> for vm::Error {
|
||||
}
|
||||
|
||||
/// Wasm interpreter instance
|
||||
pub struct WasmInterpreter;
|
||||
pub struct WasmInterpreter {
|
||||
params: ActionParams,
|
||||
}
|
||||
|
||||
impl WasmInterpreter {
|
||||
pub fn new(params: ActionParams) -> Self {
|
||||
WasmInterpreter { params }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<runtime::Error> for vm::Error {
|
||||
fn from(e: runtime::Error) -> Self {
|
||||
@ -85,19 +93,19 @@ enum ExecutionOutcome {
|
||||
|
||||
impl vm::Vm for WasmInterpreter {
|
||||
|
||||
fn exec(&mut self, params: ActionParams, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||
let (module, data) = parser::payload(¶ms, ext.schedule().wasm())?;
|
||||
fn exec(&mut self, ext: &mut vm::Ext) -> vm::Result<GasLeft> {
|
||||
let (module, data) = parser::payload(&self.params, ext.schedule().wasm())?;
|
||||
|
||||
let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?;
|
||||
|
||||
let instantiation_resolver = env::ImportResolver::with_limit(16);
|
||||
let instantiation_resolver = env::ImportResolver::with_limit(16, ext.schedule().wasm());
|
||||
|
||||
let module_instance = wasmi::ModuleInstance::new(
|
||||
&loaded_module,
|
||||
&wasmi::ImportsBuilder::new().with_resolver("env", &instantiation_resolver)
|
||||
).map_err(Error::Interpreter)?;
|
||||
|
||||
let adjusted_gas = params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
|
||||
let adjusted_gas = self.params.gas * U256::from(ext.schedule().wasm().opcodes_div) /
|
||||
U256::from(ext.schedule().wasm().opcodes_mul);
|
||||
|
||||
if adjusted_gas > ::std::u64::MAX.into()
|
||||
@ -116,11 +124,11 @@ impl vm::Vm for WasmInterpreter {
|
||||
adjusted_gas.low_u64(),
|
||||
data.to_vec(),
|
||||
RuntimeContext {
|
||||
address: params.address,
|
||||
sender: params.sender,
|
||||
origin: params.origin,
|
||||
code_address: params.code_address,
|
||||
value: params.value.value(),
|
||||
address: self.params.address,
|
||||
sender: self.params.sender,
|
||||
origin: self.params.origin,
|
||||
code_address: self.params.code_address,
|
||||
value: self.params.value.value(),
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::cmp;
|
||||
use ethereum_types::{U256, H256, Address};
|
||||
use vm::{self, CallType};
|
||||
use wasmi::{self, MemoryRef, RuntimeArgs, RuntimeValue, Error as InterpreterError, Trap, TrapKind};
|
||||
@ -447,12 +448,14 @@ impl<'a> Runtime<'a> {
|
||||
val,
|
||||
&payload,
|
||||
&address,
|
||||
&mut result[..],
|
||||
call_type,
|
||||
);
|
||||
|
||||
match call_result {
|
||||
vm::MessageCallResult::Success(gas_left, _) => {
|
||||
vm::MessageCallResult::Success(gas_left, data) => {
|
||||
let len = cmp::min(result.len(), data.len());
|
||||
(&mut result[..len]).copy_from_slice(&data[..len]);
|
||||
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter -
|
||||
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
|
||||
@ -461,7 +464,10 @@ impl<'a> Runtime<'a> {
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(0i32.into())
|
||||
},
|
||||
vm::MessageCallResult::Reverted(gas_left, _) => {
|
||||
vm::MessageCallResult::Reverted(gas_left, data) => {
|
||||
let len = cmp::min(result.len(), data.len());
|
||||
(&mut result[..len]).copy_from_slice(&data[..len]);
|
||||
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter -
|
||||
gas_left.low_u64() * self.ext.schedule().wasm().opcodes_div as u64
|
||||
@ -511,29 +517,7 @@ impl<'a> Runtime<'a> {
|
||||
self.return_u256_ptr(args.nth_checked(0)?, val)
|
||||
}
|
||||
|
||||
/// Creates a new contract
|
||||
///
|
||||
/// Arguments:
|
||||
/// * endowment - how much value (in Wei) transfer to the newly created contract
|
||||
/// * code_ptr - pointer to the code data
|
||||
/// * code_len - lenght of the code data
|
||||
/// * result_ptr - pointer to write an address of the newly created contract
|
||||
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue>
|
||||
{
|
||||
//
|
||||
// method signature:
|
||||
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||
//
|
||||
trace!(target: "wasm", "runtime: CREATE");
|
||||
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||
trace!(target: "wasm", " val: {:?}", endowment);
|
||||
let code_ptr: u32 = args.nth_checked(1)?;
|
||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||
let code_len: u32 = args.nth_checked(2)?;
|
||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||
let result_ptr: u32 = args.nth_checked(3)?;
|
||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||
|
||||
fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result<RuntimeValue> {
|
||||
let code = self.memory.get(code_ptr, code_len as usize)?;
|
||||
|
||||
self.adjusted_charge(|schedule| schedule.create_gas as u64)?;
|
||||
@ -543,7 +527,7 @@ impl<'a> Runtime<'a> {
|
||||
* U256::from(self.ext.schedule().wasm().opcodes_mul)
|
||||
/ U256::from(self.ext.schedule().wasm().opcodes_div);
|
||||
|
||||
match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) {
|
||||
match self.ext.create(&gas_left, &endowment, &code, scheme) {
|
||||
vm::ContractCreateResult::Created(address, gas_left) => {
|
||||
self.memory.set(result_ptr, &*address)?;
|
||||
self.gas_counter = self.gas_limit -
|
||||
@ -571,6 +555,59 @@ impl<'a> Runtime<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new contract
|
||||
///
|
||||
/// Arguments:
|
||||
/// * endowment - how much value (in Wei) transfer to the newly created contract
|
||||
/// * code_ptr - pointer to the code data
|
||||
/// * code_len - lenght of the code data
|
||||
/// * result_ptr - pointer to write an address of the newly created contract
|
||||
pub fn create(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
|
||||
//
|
||||
// method signature:
|
||||
// fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||
//
|
||||
trace!(target: "wasm", "runtime: CREATE");
|
||||
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||
trace!(target: "wasm", " val: {:?}", endowment);
|
||||
let code_ptr: u32 = args.nth_checked(1)?;
|
||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||
let code_len: u32 = args.nth_checked(2)?;
|
||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||
let result_ptr: u32 = args.nth_checked(3)?;
|
||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||
|
||||
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderAndCodeHash)
|
||||
}
|
||||
|
||||
/// Creates a new contract using FromSenderSaltAndCodeHash scheme
|
||||
///
|
||||
/// Arguments:
|
||||
/// * endowment - how much value (in Wei) transfer to the newly created contract
|
||||
/// * salt - salt to be used in contract creation address
|
||||
/// * code_ptr - pointer to the code data
|
||||
/// * code_len - lenght of the code data
|
||||
/// * result_ptr - pointer to write an address of the newly created contract
|
||||
pub fn create2(&mut self, args: RuntimeArgs) -> Result<RuntimeValue> {
|
||||
//
|
||||
// method signature:
|
||||
// fn create2(endowment: *const u8, salt: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32;
|
||||
//
|
||||
trace!(target: "wasm", "runtime: CREATE2");
|
||||
let endowment = self.u256_at(args.nth_checked(0)?)?;
|
||||
trace!(target: "wasm", " val: {:?}", endowment);
|
||||
let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into();
|
||||
trace!(target: "wasm", " salt: {:?}", salt);
|
||||
let code_ptr: u32 = args.nth_checked(2)?;
|
||||
trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
|
||||
let code_len: u32 = args.nth_checked(3)?;
|
||||
trace!(target: "wasm", " code_len: {:?}", code_len);
|
||||
let result_ptr: u32 = args.nth_checked(4)?;
|
||||
trace!(target: "wasm", "result_ptr: {:?}", result_ptr);
|
||||
|
||||
self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderSaltAndCodeHash(salt))
|
||||
}
|
||||
|
||||
fn debug(&mut self, args: RuntimeArgs) -> Result<()>
|
||||
{
|
||||
trace!(target: "wasm", "Contract debug message: {}", {
|
||||
@ -629,6 +666,15 @@ impl<'a> Runtime<'a> {
|
||||
self.return_u256_ptr(args.nth_checked(0)?, difficulty)
|
||||
}
|
||||
|
||||
/// Signature: `fn gasleft() -> i64`
|
||||
pub fn gasleft(&mut self) -> Result<RuntimeValue> {
|
||||
Ok(RuntimeValue::from(
|
||||
self.gas_left()? * self.ext.schedule().wasm().opcodes_mul as u64
|
||||
/ self.ext.schedule().wasm().opcodes_div as u64
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// Signature: `fn gaslimit(dest: *mut u8)`
|
||||
pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> {
|
||||
let gas_limit = self.ext.env_info().gas_limit;
|
||||
@ -744,6 +790,8 @@ mod ext_impl {
|
||||
SENDER_FUNC => void!(self.sender(args)),
|
||||
ORIGIN_FUNC => void!(self.origin(args)),
|
||||
ELOG_FUNC => void!(self.elog(args)),
|
||||
CREATE2_FUNC => some!(self.create2(args)),
|
||||
GASLEFT_FUNC => some!(self.gasleft()),
|
||||
_ => panic!("env module doesn't provide function at index {}", index),
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ use byteorder::{LittleEndian, ByteOrder};
|
||||
use ethereum_types::{H256, U256, Address};
|
||||
|
||||
use super::WasmInterpreter;
|
||||
use vm::{self, Vm, GasLeft, ActionParams, ActionValue};
|
||||
use vm::{self, Vm, GasLeft, ActionParams, ActionValue, CreateContractAddress};
|
||||
use vm::tests::{FakeCall, FakeExt, FakeCallType};
|
||||
|
||||
macro_rules! load_sample {
|
||||
@ -47,8 +47,8 @@ macro_rules! reqrep_test {
|
||||
fake_ext.info = $info;
|
||||
fake_ext.blockhashes = $block_hashes;
|
||||
|
||||
let mut interpreter = wasm_interpreter();
|
||||
interpreter.exec(params, &mut fake_ext)
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
interpreter.exec(&mut fake_ext)
|
||||
.map(|result| match result {
|
||||
GasLeft::Known(_) => { panic!("Test is expected to return payload to check"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -65,8 +65,8 @@ fn test_finalize(res: Result<GasLeft, vm::Error>) -> Result<U256, vm::Error> {
|
||||
}
|
||||
}
|
||||
|
||||
fn wasm_interpreter() -> WasmInterpreter {
|
||||
WasmInterpreter
|
||||
fn wasm_interpreter(params: ActionParams) -> WasmInterpreter {
|
||||
WasmInterpreter::new(params)
|
||||
}
|
||||
|
||||
/// Empty contract does almost nothing except producing 1 (one) local node debug log message
|
||||
@ -82,8 +82,8 @@ fn empty() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
test_finalize(interpreter.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(96_926));
|
||||
@ -111,8 +111,8 @@ fn logger() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
test_finalize(interpreter.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
let address_val: H256 = address.into();
|
||||
@ -138,7 +138,7 @@ fn logger() {
|
||||
U256::from(1_000_000_000),
|
||||
"Logger sets 0x04 key to the trasferred value"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(16_181));
|
||||
assert_eq!(gas_left, U256::from(17_716));
|
||||
}
|
||||
|
||||
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
|
||||
@ -160,8 +160,8 @@ fn identity() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("Identity contract should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -173,7 +173,7 @@ fn identity() {
|
||||
sender,
|
||||
"Idenity test contract does not return the sender passed"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_883));
|
||||
assert_eq!(gas_left, U256::from(98_419));
|
||||
}
|
||||
|
||||
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
|
||||
@ -195,8 +195,8 @@ fn dispersion() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("Dispersion routine should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -207,7 +207,7 @@ fn dispersion() {
|
||||
result,
|
||||
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(92_371));
|
||||
assert_eq!(gas_left, U256::from(92_377));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -223,8 +223,8 @@ fn suicide_not() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("Suicidal contract should return payload when had not actualy killed himself"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -256,8 +256,8 @@ fn suicide() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas) => gas,
|
||||
GasLeft::NeedsReturn { .. } => {
|
||||
@ -267,7 +267,7 @@ fn suicide() {
|
||||
};
|
||||
|
||||
assert!(ext.suicides.contains(&refund));
|
||||
assert_eq!(gas_left, U256::from(93_348));
|
||||
assert_eq!(gas_left, U256::from(93_346));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -281,14 +281,19 @@ fn create() {
|
||||
params.value = ActionValue::transfer(1_000_000_000);
|
||||
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
ext.schedule.wasm.as_mut().unwrap().have_create2 = true;
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas) => gas,
|
||||
GasLeft::NeedsReturn { .. } => {
|
||||
panic!("Create contract should not return anthing because ext always fails on creation");
|
||||
GasLeft::Known(_) => {
|
||||
panic!("Create contract always return 40 bytes of the creation address, or in the case where it fails, return 40 bytes of zero.");
|
||||
},
|
||||
GasLeft::NeedsReturn { gas_left, data, apply_state } => {
|
||||
assert!(apply_state);
|
||||
assert_eq!(data.as_ref(), [0u8; 40].as_ref()); // FakeExt never succeeds in create.
|
||||
gas_left
|
||||
},
|
||||
}
|
||||
};
|
||||
@ -297,15 +302,28 @@ fn create() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Create,
|
||||
gas: U256::from(59_269),
|
||||
create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash),
|
||||
gas: U256::from(49_674),
|
||||
sender_address: None,
|
||||
receive_address: None,
|
||||
value: Some(1_000_000_000.into()),
|
||||
value: Some((1_000_000_000 / 2).into()),
|
||||
data: vec![0u8, 2, 4, 8, 16, 32, 64, 128],
|
||||
code_address: None,
|
||||
}
|
||||
));
|
||||
assert_eq!(gas_left, U256::from(59_212));
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Create,
|
||||
create_scheme: Some(CreateContractAddress::FromSenderSaltAndCodeHash(H256::from([5u8].as_ref()))),
|
||||
gas: U256::from(6039),
|
||||
sender_address: None,
|
||||
receive_address: None,
|
||||
value: Some((1_000_000_000 / 2).into()),
|
||||
data: vec![0u8, 2, 4, 8, 16, 32, 64, 128],
|
||||
code_address: None,
|
||||
}
|
||||
));
|
||||
assert_eq!(gas_left, U256::from(5974));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -328,8 +346,8 @@ fn call_msg() {
|
||||
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas_left) => gas_left,
|
||||
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
|
||||
@ -340,6 +358,7 @@ fn call_msg() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(33_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
@ -352,6 +371,54 @@ fn call_msg() {
|
||||
assert_eq!(gas_left, U256::from(91_672));
|
||||
}
|
||||
|
||||
// The same as `call_msg`, but send a `pwasm_ethereum::gasleft`
|
||||
// value as `gas` argument to the inner pwasm_ethereum::call
|
||||
#[test]
|
||||
fn call_msg_gasleft() {
|
||||
::ethcore_logger::init_log();
|
||||
|
||||
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
params.address = receiver.clone();
|
||||
params.code_address = contract_address.clone();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(load_sample!("call_gasleft.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
ext.schedule.wasm.as_mut().unwrap().have_gasleft = true;
|
||||
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas_left) => gas_left,
|
||||
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
|
||||
}
|
||||
};
|
||||
|
||||
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(91_165),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
value: Some(1000000000.into()),
|
||||
data: vec![129u8, 123, 113, 107, 101, 97],
|
||||
code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
}
|
||||
));
|
||||
|
||||
assert_eq!(gas_left, U256::from(91_671));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_code() {
|
||||
::ethcore_logger::init_log();
|
||||
@ -370,8 +437,8 @@ fn call_code() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("Call test should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -382,6 +449,7 @@ fn call_code() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
@ -394,7 +462,7 @@ fn call_code() {
|
||||
// siphash result
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 4198595614);
|
||||
assert_eq!(gas_left, U256::from(90_038));
|
||||
assert_eq!(gas_left, U256::from(90_037));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -417,8 +485,8 @@ fn call_static() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("Static call test should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -429,6 +497,7 @@ fn call_static() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
create_scheme: None,
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
@ -442,7 +511,7 @@ fn call_static() {
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 317632590);
|
||||
|
||||
assert_eq!(gas_left, U256::from(90_043));
|
||||
assert_eq!(gas_left, U256::from(90_042));
|
||||
}
|
||||
|
||||
// Realloc test
|
||||
@ -457,15 +526,15 @@ fn realloc() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("Realloc should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
}
|
||||
};
|
||||
assert_eq!(result, vec![0u8; 2]);
|
||||
assert_eq!(gas_left, U256::from(92_842));
|
||||
assert_eq!(gas_left, U256::from(92_848));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -479,15 +548,15 @@ fn alloc() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("alloc test should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
}
|
||||
};
|
||||
assert_eq!(result, vec![5u8; 1024*400]);
|
||||
assert_eq!(gas_left, U256::from(6_893_883));
|
||||
assert_eq!(gas_left, U256::from(6_893_881));
|
||||
}
|
||||
|
||||
// Tests that contract's ability to read from a storage
|
||||
@ -506,8 +575,8 @@ fn storage_read() {
|
||||
ext.store.insert("0100000000000000000000000000000000000000000000000000000000000000".into(), address.into());
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("storage_read should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -515,7 +584,7 @@ fn storage_read() {
|
||||
};
|
||||
|
||||
assert_eq!(Address::from(&result[12..32]), address);
|
||||
assert_eq!(gas_left, U256::from(96_833));
|
||||
assert_eq!(gas_left, U256::from(98_369));
|
||||
}
|
||||
|
||||
// Tests keccak calculation
|
||||
@ -532,8 +601,8 @@ fn keccak() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("keccak should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -541,7 +610,7 @@ fn keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(84_134));
|
||||
assert_eq!(gas_left, U256::from(85_949));
|
||||
}
|
||||
|
||||
// math_* tests check the ability of wasm contract to perform big integer operations
|
||||
@ -570,7 +639,7 @@ fn math_add() {
|
||||
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(92_086));
|
||||
assert_eq!(gas_left, U256::from(92_072));
|
||||
}
|
||||
|
||||
// multiplication
|
||||
@ -592,7 +661,7 @@ fn math_mul() {
|
||||
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(91_414));
|
||||
assert_eq!(gas_left, U256::from(91_400));
|
||||
}
|
||||
|
||||
// subtraction
|
||||
@ -614,7 +683,7 @@ fn math_sub() {
|
||||
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(92_086));
|
||||
assert_eq!(gas_left, U256::from(92_072));
|
||||
}
|
||||
|
||||
// subtraction with overflow
|
||||
@ -656,7 +725,7 @@ fn math_div() {
|
||||
U256::from_dec_str("1125000").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(87_376));
|
||||
assert_eq!(gas_left, U256::from(85_700));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -679,12 +748,12 @@ fn storage_metering() {
|
||||
]);
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
test_finalize(interpreter.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
// 0 -> not 0
|
||||
assert_eq!(gas_left, U256::from(72_399));
|
||||
assert_eq!(gas_left, U256::from(72_164));
|
||||
|
||||
// #2
|
||||
|
||||
@ -698,12 +767,12 @@ fn storage_metering() {
|
||||
]);
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
test_finalize(interpreter.exec(&mut ext)).unwrap()
|
||||
};
|
||||
|
||||
// not 0 -> not 0
|
||||
assert_eq!(gas_left, U256::from(87_399));
|
||||
assert_eq!(gas_left, U256::from(87_164));
|
||||
}
|
||||
|
||||
// This test checks the ability of wasm contract to invoke
|
||||
@ -791,7 +860,48 @@ fn externs() {
|
||||
"Gas limit requested and returned does not match"
|
||||
);
|
||||
|
||||
assert_eq!(gas_left, U256::from(90_435));
|
||||
assert_eq!(gas_left, U256::from(90_428));
|
||||
}
|
||||
|
||||
// This test checks the ability of wasm contract to invoke gasleft
|
||||
#[test]
|
||||
fn gasleft() {
|
||||
::ethcore_logger::init_log();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(load_sample!("gasleft.wasm")));
|
||||
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
ext.schedule.wasm.as_mut().unwrap().have_gasleft = true;
|
||||
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => {},
|
||||
GasLeft::NeedsReturn { gas_left, data, .. } => {
|
||||
let gas = LittleEndian::read_u64(data.as_ref());
|
||||
assert_eq!(gas, 93_423);
|
||||
assert_eq!(gas_left, U256::from(93_349));
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// This test should fail because
|
||||
// ext.schedule.wasm.as_mut().unwrap().have_gasleft = false;
|
||||
#[test]
|
||||
fn gasleft_fail() {
|
||||
::ethcore_logger::init_log();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(load_sample!("gasleft.wasm")));
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
match interpreter.exec(&mut ext) {
|
||||
Err(_) => {},
|
||||
Ok(_) => panic!("interpreter.exec should return Err if ext.schedule.wasm.have_gasleft = false")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -808,8 +918,8 @@ fn embedded_keccak() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("keccak should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -817,7 +927,7 @@ fn embedded_keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(84_134));
|
||||
assert_eq!(gas_left, U256::from(85_949));
|
||||
}
|
||||
|
||||
/// This test checks the correctness of log extern
|
||||
@ -836,8 +946,8 @@ fn events() {
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let (gas_left, result) = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(_) => { panic!("events should return payload"); },
|
||||
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
|
||||
@ -852,7 +962,7 @@ fn events() {
|
||||
assert_eq!(&log_entry.data, b"gnihtemos");
|
||||
|
||||
assert_eq!(&result, b"gnihtemos");
|
||||
assert_eq!(gas_left, U256::from(81_351));
|
||||
assert_eq!(gas_left, U256::from(83_161));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -876,8 +986,8 @@ fn recursive() {
|
||||
|
||||
let mut ext = FakeExt::new().with_wasm();
|
||||
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext);
|
||||
let mut interpreter = wasm_interpreter(params);
|
||||
let result = interpreter.exec(&mut ext);
|
||||
|
||||
// We expect that stack overflow will occur and it should be generated by
|
||||
// deterministic stack metering. Exceeding deterministic stack height limit
|
||||
|
@ -10,7 +10,7 @@ parity-crypto = { git = "https://github.com/paritytech/parity-common" }
|
||||
eth-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1" }
|
||||
ethereum-types = "0.3"
|
||||
lazy_static = "1.0"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
mem = { path = "../util/mem" }
|
||||
parity-wordlist = "1.2"
|
||||
quick-error = "1.2.2"
|
||||
|
@ -5,7 +5,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
docopt = "0.8"
|
||||
env_logger = "0.4"
|
||||
env_logger = "0.5"
|
||||
ethkey = { path = "../" }
|
||||
panic_hook = { path = "../../util/panic_hook" }
|
||||
parity-wordlist="1.2"
|
||||
|
@ -162,7 +162,7 @@ impl DisplayMode {
|
||||
|
||||
fn main() {
|
||||
panic_hook::set_abort();
|
||||
env_logger::init().expect("Logger initialized only once.");
|
||||
env_logger::try_init().expect("Logger initialized only once.");
|
||||
|
||||
match execute(env::args()) {
|
||||
Ok(ok) => println!("{}", ok),
|
||||
|
@ -4,7 +4,7 @@ version = "0.2.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
libc = "0.2"
|
||||
rand = "0.4"
|
||||
ethkey = { path = "../ethkey" }
|
||||
|
@ -10,6 +10,7 @@ path = "./src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
docopt = "0.8"
|
||||
env_logger = "0.5"
|
||||
ethcore = { path = "../ethcore", features = ["test-helpers", "json-tests"] }
|
||||
ethjson = { path = "../json" }
|
||||
parity-bytes = { git = "https://github.com/paritytech/parity-common" }
|
||||
|
38
evmbin/res/testchain.json
Normal file
38
evmbin/res/testchain.json
Normal 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"
|
||||
}
|
||||
}
|
@ -167,13 +167,13 @@ impl<T: Writer> trace::VMTracer for Informant<T> {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub mod tests {
|
||||
use std::sync::{Arc, Mutex};
|
||||
use super::*;
|
||||
use info::tests::run_test;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
|
||||
pub struct TestWriter(pub Arc<Mutex<Vec<u8>>>);
|
||||
|
||||
impl Writer for TestWriter {
|
||||
fn clone(&self) -> Self { Clone::clone(self) }
|
||||
@ -189,7 +189,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn informant() -> (Informant<TestWriter>, Arc<Mutex<Vec<u8>>>) {
|
||||
pub fn informant() -> (Informant<TestWriter>, Arc<Mutex<Vec<u8>>>) {
|
||||
let writer = TestWriter::default();
|
||||
let res = writer.0.clone();
|
||||
(Informant::new(writer), res)
|
||||
|
@ -68,11 +68,19 @@ pub type RunResult<T> = Result<Success<T>, Failure<T>>;
|
||||
/// Execute given `ActionParams` and return the result.
|
||||
pub fn run_action<T: Informant>(
|
||||
spec: &spec::Spec,
|
||||
params: ActionParams,
|
||||
mut params: ActionParams,
|
||||
mut informant: T,
|
||||
) -> RunResult<T::Output> {
|
||||
informant.set_gas(params.gas);
|
||||
run(spec, params.gas, None, |mut client| {
|
||||
|
||||
// if the code is not overwritten from CLI, use code from spec file.
|
||||
if params.code.is_none() {
|
||||
if let Some(acc) = spec.genesis_state().get().get(¶ms.code_address) {
|
||||
params.code = acc.code.clone().map(::std::sync::Arc::new);
|
||||
params.code_hash = None;
|
||||
}
|
||||
}
|
||||
run(spec, params.gas, spec.genesis_state(), |mut client| {
|
||||
let result = client
|
||||
.call(params, &mut trace::NoopTracer, &mut informant)
|
||||
.map(|r| (0.into(), r.gas_left, r.return_data.to_vec()));
|
||||
@ -130,19 +138,16 @@ pub fn run_transaction<T: Informant>(
|
||||
}
|
||||
|
||||
/// Execute VM with given `ActionParams`
|
||||
pub fn run<'a, F, T, X>(
|
||||
pub fn run<'a, F, X>(
|
||||
spec: &'a spec::Spec,
|
||||
initial_gas: U256,
|
||||
pre_state: T,
|
||||
pre_state: &'a pod_state::PodState,
|
||||
run: F,
|
||||
) -> RunResult<X> where
|
||||
F: FnOnce(EvmTestClient) -> (Result<(H256, U256, Vec<u8>), EvmTestError>, Option<X>),
|
||||
T: Into<Option<&'a pod_state::PodState>>,
|
||||
{
|
||||
let test_client = match pre_state.into() {
|
||||
Some(pre_state) => EvmTestClient::from_pod_state(spec, pre_state.clone()),
|
||||
None => EvmTestClient::new(spec),
|
||||
}.map_err(|error| Failure {
|
||||
let test_client = EvmTestClient::from_pod_state(spec, pre_state.clone())
|
||||
.map_err(|error| Failure {
|
||||
gas_used: 0.into(),
|
||||
error,
|
||||
time: Duration::from_secs(0),
|
||||
@ -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}
|
||||
"#);
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ extern crate ethereum_types;
|
||||
extern crate vm;
|
||||
extern crate evm;
|
||||
extern crate panic_hook;
|
||||
extern crate env_logger;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
@ -92,6 +93,7 @@ General options:
|
||||
|
||||
fn main() {
|
||||
panic_hook::set_abort();
|
||||
env_logger::init();
|
||||
|
||||
let args: Args = Docopt::new(USAGE).and_then(|d| d.deserialize()).unwrap_or_else(|e| e.exit());
|
||||
|
||||
|
@ -9,7 +9,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
[dependencies]
|
||||
futures = "0.1"
|
||||
futures-cpupool = "0.1"
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
mime = "0.3"
|
||||
mime_guess = "2.0.0-alpha.2"
|
||||
rand = "0.4"
|
||||
|
@ -7,7 +7,7 @@ version = "1.12.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
log = "0.4"
|
||||
parking_lot = "0.6"
|
||||
protobuf = "1.4"
|
||||
hidapi = { git = "https://github.com/paritytech/hidapi-rs" }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user