diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5d90c5d4e..1c2ad13d6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -541,7 +541,7 @@ test-windows: - git submodule update --init --recursive script: - set RUST_BACKTRACE=1 - - echo cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p ethcore-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release + - echo cargo test --features json-tests -p rlp -p ethash -p ethcore -p ethcore-bigint -p ethcore-dapps -p parity-rpc -p ethcore-signer -p ethcore-util -p ethcore-network -p ethcore-io -p ethkey -p ethstore -p ethsync -p ethcore-ipc -p ethcore-ipc-tests -p ethcore-ipc-nano -p parity %CARGOFLAGS% --verbose --release tags: - rust-windows allow_failure: true diff --git a/Cargo.lock b/Cargo.lock index 3298887d5..f8fabc342 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,6 @@ dependencies = [ "ethcore-ipc-tests 0.1.0", "ethcore-light 1.7.0", "ethcore-logger 1.7.0", - "ethcore-rpc 1.7.0", "ethcore-secretstore 1.0.0", "ethcore-signer 1.7.0", "ethcore-stratum 1.7.0", @@ -38,6 +37,7 @@ dependencies = [ "parity-ipfs-api 1.7.0", "parity-local-store 0.1.0", "parity-reactor 0.1.0", + "parity-rpc 1.7.0", "parity-rpc-client 1.4.0", "parity-updater 1.7.0", "path 0.1.0", @@ -592,49 +592,6 @@ dependencies = [ "tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ethcore-rpc" -version = "1.7.0" -dependencies = [ - "cid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "ethash 1.7.0", - "ethcore 1.7.0", - "ethcore-devtools 1.7.0", - "ethcore-io 1.7.0", - "ethcore-ipc 1.7.0", - "ethcore-light 1.7.0", - "ethcore-logger 1.7.0", - "ethcore-util 1.7.0", - "ethcrypto 0.1.0", - "ethjson 0.1.0", - "ethkey 0.2.0", - "ethstore 0.1.0", - "ethsync 1.7.0", - "fetch 0.1.0", - "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-reactor 0.1.0", - "parity-updater 1.7.0", - "rlp 0.1.0", - "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", - "stats 0.1.0", - "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ethcore-secretstore" version = "1.0.0" @@ -674,12 +631,12 @@ dependencies = [ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-devtools 1.7.0", "ethcore-io 1.7.0", - "ethcore-rpc 1.7.0", "ethcore-util 1.7.0", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-rpc 1.7.0", "parity-ui 1.7.0", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1080,7 +1037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jsonrpc-core" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1092,7 +1049,7 @@ dependencies = [ [[package]] name = "jsonrpc-http-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1105,7 +1062,7 @@ dependencies = [ [[package]] name = "jsonrpc-ipc-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1117,7 +1074,7 @@ dependencies = [ [[package]] name = "jsonrpc-macros" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1127,7 +1084,7 @@ dependencies = [ [[package]] name = "jsonrpc-minihttp-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1141,7 +1098,7 @@ dependencies = [ [[package]] name = "jsonrpc-pubsub" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1151,7 +1108,7 @@ dependencies = [ [[package]] name = "jsonrpc-server-utils" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1162,7 +1119,7 @@ dependencies = [ [[package]] name = "jsonrpc-tcp-server" version = "7.0.0" -source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#32c1c083139db50db6a5d532ccfc2004236dbfc3" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" dependencies = [ "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1172,6 +1129,17 @@ dependencies = [ "tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "jsonrpc-ws-server" +version = "7.0.0" +source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#ad0682785a693eba3069e48b57ec89abb62c3b60" +dependencies = [ + "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ws 0.6.0 (git+https://github.com/tomusdrw/ws-rs)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1708,16 +1676,60 @@ dependencies = [ "tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parity-rpc" +version = "1.7.0" +dependencies = [ + "cid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "ethash 1.7.0", + "ethcore 1.7.0", + "ethcore-devtools 1.7.0", + "ethcore-io 1.7.0", + "ethcore-ipc 1.7.0", + "ethcore-light 1.7.0", + "ethcore-logger 1.7.0", + "ethcore-util 1.7.0", + "ethcrypto 0.1.0", + "ethjson 0.1.0", + "ethkey 0.2.0", + "ethstore 0.1.0", + "ethsync 1.7.0", + "fetch 0.1.0", + "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-minihttp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "multihash 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-reactor 0.1.0", + "parity-updater 1.7.0", + "rlp 0.1.0", + "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", + "stats 0.1.0", + "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parity-rpc-client" version = "1.4.0" dependencies = [ - "ethcore-rpc 1.7.0", "ethcore-signer 1.7.0", "ethcore-util 1.7.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-rpc 1.7.0", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1761,7 +1773,7 @@ dependencies = [ [[package]] name = "parity-ui-precompiled" version = "1.4.0" -source = "git+https://github.com/paritytech/js-precompiled.git#b4c41885c6e02c64fb773546b2f135f56ea7022f" +source = "git+https://github.com/paritytech/js-precompiled.git#bceb0caa1eae7d78ad3386338a76b7ca92bf033a" dependencies = [ "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2081,9 +2093,9 @@ name = "rpc-cli" version = "1.4.0" dependencies = [ "ethcore-bigint 0.1.2", - "ethcore-rpc 1.7.0", "ethcore-util 1.7.0", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-rpc 1.7.0", "parity-rpc-client 1.4.0", "rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2710,6 +2722,21 @@ dependencies = [ "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ws" +version = "0.6.0" +source = "git+https://github.com/tomusdrw/ws-rs#3259e7ca906c848beae109eb32e492871f8f397d" +dependencies = [ + "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2824,6 +2851,7 @@ dependencies = [ "checksum jsonrpc-pubsub 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" "checksum jsonrpc-server-utils 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" "checksum jsonrpc-tcp-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" +"checksum jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" @@ -2981,6 +3009,7 @@ dependencies = [ "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum ws 0.5.3 (git+https://github.com/paritytech/ws-rs.git?branch=parity-1.7)" = "" +"checksum ws 0.6.0 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453" "checksum xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65e74b96bd3179209dc70a980da6df843dff09e46eee103a0376c0949257e3ef" diff --git a/Cargo.toml b/Cargo.toml index 09af66e09..37effabb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,6 @@ ethcore = { path = "ethcore" } ethcore-util = { path = "util" } ethcore-io = { path = "util/io" } ethcore-devtools = { path = "devtools" } -ethcore-rpc = { path = "rpc" } ethcore-signer = { path = "signer" } ethcore-ipc = { path = "ipc/rpc" } ethcore-ipc-nano = { path = "ipc/nano" } @@ -45,12 +44,13 @@ ethkey = { path = "ethkey" } evmbin = { path = "evmbin" } rlp = { path = "util/rlp" } rpc-cli = { path = "rpc_cli" } -parity-rpc-client = { path = "rpc_client" } parity-hash-fetch = { path = "hash-fetch" } parity-ipfs-api = { path = "ipfs" } -parity-updater = { path = "updater" } -parity-reactor = { path = "util/reactor" } parity-local-store = { path = "local-store" } +parity-reactor = { path = "util/reactor" } +parity-rpc = { path = "rpc" } +parity-rpc-client = { path = "rpc_client" } +parity-updater = { path = "updater" } path = { path = "util/path" } parity-dapps = { path = "dapps", optional = true } @@ -85,7 +85,7 @@ ui-precompiled = [ dapps = ["parity-dapps"] ipc = ["ethcore/ipc", "ethsync/ipc"] jit = ["ethcore/jit"] -dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "ethcore-rpc/dev", "parity-dapps/dev", "ethcore-signer/dev"] +dev = ["clippy", "ethcore/dev", "ethcore-util/dev", "ethsync/dev", "parity-rpc/dev", "parity-dapps/dev", "ethcore-signer/dev"] json-tests = ["ethcore/json-tests"] test-heavy = ["ethcore/test-heavy"] ethkey-cli = ["ethcore/ethkey-cli"] diff --git a/README.md b/README.md index f668f3218..c74b51a58 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Be sure to check out [our wiki][wiki-url] for more information. Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs. -Parity comes with a built-in wallet. To access [Parity Wallet](http://127.0.0.1:8080/) simply go to http://127.0.0.1:8080/. It +Parity comes with a built-in wallet. To access [Parity Wallet](http://web3.site/) simply go to http://web3.site/ (if you don't have access to the internet, but still want to use the service, you can also use http://127.0.0.1:8180/). It includes various functionality allowing you to: - create and manage your Ethereum accounts; - manage your Ether and any Ethereum tokens; diff --git a/dapps/src/rpc.rs b/dapps/src/rpc.rs index b743408dc..74c6d8d89 100644 --- a/dapps/src/rpc.rs +++ b/dapps/src/rpc.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use hyper; -use ethcore_rpc::{Metadata, Origin}; +use parity_rpc::{Metadata, Origin}; use jsonrpc_core::{Middleware, MetaIoHandler}; use jsonrpc_http_server::{self as http, AccessControlAllowOrigin, HttpMetaExtractor}; use jsonrpc_http_server::tokio_core::reactor::Remote; diff --git a/ethcore/light/src/client/header_chain.rs b/ethcore/light/src/client/header_chain.rs index fe3c86aad..35e6d996c 100644 --- a/ethcore/light/src/client/header_chain.rs +++ b/ethcore/light/src/client/header_chain.rs @@ -361,6 +361,22 @@ impl HeaderChain { } } + /// Get a block's hash by ID. In the case of query by number, only canonical results + /// will be returned. + pub fn block_hash(&self, id: BlockId) -> Option { + match id { + BlockId::Earliest => Some(self.genesis_hash()), + BlockId::Hash(hash) => Some(hash), + BlockId::Number(num) => { + if self.best_block.read().number < num { return None } + self.candidates.read().get(&num).map(|entry| entry.canonical_hash) + } + BlockId::Latest | BlockId::Pending => { + Some(self.best_block.read().hash) + } + } + } + /// Get a block header. In the case of query by number, only canonical blocks /// will be returned. pub fn block_header(&self, id: BlockId) -> Option { @@ -414,6 +430,28 @@ impl HeaderChain { } } + /// Get a block's chain score. + /// Returns nothing for non-canonical blocks. + pub fn score(&self, id: BlockId) -> Option { + let genesis_hash = self.genesis_hash(); + match id { + BlockId::Earliest | BlockId::Number(0) => Some(self.genesis_header.difficulty()), + BlockId::Hash(hash) if hash == genesis_hash => Some(self.genesis_header.difficulty()), + BlockId::Hash(hash) => match self.block_header(BlockId::Hash(hash)) { + Some(header) => self.candidates.read().get(&header.number()) + .and_then(|era| era.candidates.iter().find(|e| e.hash == hash)) + .map(|c| c.total_difficulty), + None => None, + }, + BlockId::Number(num) => { + let candidates = self.candidates.read(); + if self.best_block.read().number < num { return None } + candidates.get(&num).map(|era| era.candidates[0].total_difficulty) + } + BlockId::Latest | BlockId::Pending => Some(self.best_block.read().total_difficulty) + } + } + /// Get the best block's header. pub fn best_header(&self) -> encoded::Header { self.block_header(BlockId::Latest).expect("Header for best block always stored; qed") diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 5424d5d1a..7e6213273 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -31,7 +31,7 @@ use ethcore::service::ClientIoMessage; use ethcore::encoded; use io::IoChannel; -use util::{H256, Mutex, RwLock}; +use util::{H256, U256, Mutex, RwLock}; use util::kvdb::{KeyValueDB, CompactionProfile}; use self::header_chain::{AncestryIter, HeaderChain}; @@ -67,18 +67,31 @@ pub trait LightChainClient: Send + Sync { /// parent queued prior. fn queue_header(&self, header: Header) -> Result; + /// Attempt to get a block hash by block id. + fn block_hash(&self, id: BlockId) -> Option; + /// Attempt to get block header by block id. fn block_header(&self, id: BlockId) -> Option; /// Get the best block header. fn best_block_header(&self) -> encoded::Header; + /// Get a block's chain score by ID. + fn score(&self, id: BlockId) -> Option; + /// Get an iterator over a block and its ancestry. fn ancestry_iter<'a>(&'a self, start: BlockId) -> Box + 'a>; /// Get the signing network ID. fn signing_network_id(&self) -> Option; + /// Get environment info for execution at a given block. + /// Fails if that block's header is not stored. + fn env_info(&self, id: BlockId) -> Option; + + /// Get a handle to the consensus engine. + fn engine(&self) -> &Arc; + /// Query whether a block is known. fn is_known(&self, hash: &H256) -> bool; @@ -93,6 +106,9 @@ pub trait LightChainClient: Send + Sync { /// Get the `i`th CHT root. fn cht_root(&self, i: usize) -> Option; + + /// Get the EIP-86 transition block number. + fn eip86_transition(&self) -> u64; } /// Something which can be treated as a `LightChainClient`. @@ -183,6 +199,11 @@ impl Client { self.queue.queue_info() } + /// Attempt to get a block hash by block id. + pub fn block_hash(&self, id: BlockId) -> Option { + self.chain.block_hash(id) + } + /// Get a block header by Id. pub fn block_header(&self, id: BlockId) -> Option { self.chain.block_header(id) @@ -193,6 +214,11 @@ impl Client { self.chain.best_header() } + /// Get a block's chain score. + pub fn score(&self, id: BlockId) -> Option { + self.chain.score(id) + } + /// Get an iterator over a block and its ancestry. pub fn ancestry_iter(&self, start: BlockId) -> AncestryIter { self.chain.ancestry_iter(start) @@ -310,6 +336,10 @@ impl LightChainClient for Client { self.import_header(header) } + fn block_hash(&self, id: BlockId) -> Option { + Client::block_hash(self, id) + } + fn block_header(&self, id: BlockId) -> Option { Client::block_header(self, id) } @@ -318,6 +348,10 @@ impl LightChainClient for Client { Client::best_block_header(self) } + fn score(&self, id: BlockId) -> Option { + Client::score(self, id) + } + fn ancestry_iter<'a>(&'a self, start: BlockId) -> Box + 'a> { Box::new(Client::ancestry_iter(self, start)) } @@ -326,6 +360,14 @@ impl LightChainClient for Client { Client::signing_network_id(self) } + fn env_info(&self, id: BlockId) -> Option { + Client::env_info(self, id) + } + + fn engine(&self) -> &Arc { + Client::engine(self) + } + fn is_known(&self, hash: &H256) -> bool { self.status(hash) == BlockStatus::InChain } @@ -345,4 +387,8 @@ impl LightChainClient for Client { fn cht_root(&self, i: usize) -> Option { Client::cht_root(self, i) } + + fn eip86_transition(&self) -> u64 { + self.engine().params().eip86_transition + } } diff --git a/ethcore/light/src/on_demand/mod.rs b/ethcore/light/src/on_demand/mod.rs index a7c1ba2c4..c756844c9 100644 --- a/ethcore/light/src/on_demand/mod.rs +++ b/ethcore/light/src/on_demand/mod.rs @@ -35,7 +35,7 @@ use futures::sync::oneshot::{self, Sender, Receiver}; use network::PeerId; use rlp::RlpStream; use util::{Bytes, RwLock, Mutex, U256, H256}; -use util::sha3::{SHA3_NULL_RLP, SHA3_EMPTY_LIST_RLP}; +use util::sha3::{SHA3_NULL_RLP, SHA3_EMPTY, SHA3_EMPTY_LIST_RLP}; use net::{self, Handler, Status, Capabilities, Announcement, EventContext, BasicContext, ReqId}; use cache::Cache; @@ -83,7 +83,7 @@ enum Pending { HeaderByHash(request::HeaderByHash, Sender), Block(request::Body, Sender), BlockReceipts(request::BlockReceipts, Sender>), - Account(request::Account, Sender>), + Account(request::Account, Sender), Code(request::Code, Sender), TxProof(request::TransactionProof, Sender>), } @@ -136,18 +136,20 @@ pub struct OnDemand { pending_requests: RwLock>, cache: Arc>, orphaned_requests: RwLock>, + start_nonce: U256, } const RECEIVER_IN_SCOPE: &'static str = "Receiver is still in scope, so it's not dropped; qed"; impl OnDemand { /// Create a new `OnDemand` service with the given cache. - pub fn new(cache: Arc>) -> Self { + pub fn new(cache: Arc>, account_start_nonce: U256) -> Self { OnDemand { peers: RwLock::new(HashMap::new()), pending_requests: RwLock::new(HashMap::new()), cache: cache, orphaned_requests: RwLock::new(Vec::new()), + start_nonce: account_start_nonce, } } @@ -268,7 +270,7 @@ impl OnDemand { /// Request an account by address and block header -- which gives a hash to query and a state root /// to verify against. - pub fn account(&self, ctx: &BasicContext, req: request::Account) -> Receiver> { + pub fn account(&self, ctx: &BasicContext, req: request::Account) -> Receiver { let (sender, receiver) = oneshot::channel(); self.dispatch(ctx, Pending::Account(req, sender)); receiver @@ -279,7 +281,7 @@ impl OnDemand { let (sender, receiver) = oneshot::channel(); // fast path for no code. - if req.code_hash == ::util::sha3::SHA3_EMPTY { + if req.code_hash == SHA3_EMPTY { sender.send(Vec::new()).expect(RECEIVER_IN_SCOPE) } else { self.dispatch(ctx, Pending::Code(req, sender)); @@ -497,10 +499,19 @@ impl Handler for OnDemand { Pending::Account(req, sender) => { if let NetworkResponse::Account(ref response) = *response { match req.check_response(&response.proof) { - Ok(maybe_account) => { + Ok(account) => { + let account = account.unwrap_or_else(|| { + BasicAccount { + balance: 0.into(), + nonce: self.start_nonce, + code_hash: SHA3_EMPTY, + storage_root: SHA3_NULL_RLP + } + }); + // TODO: validate against request outputs. // needs engine + env info as part of request. - let _ = sender.send(maybe_account); + let _ = sender.send(account); return } Err(e) => warn!(target: "on_demand", "Error handling response for state request: {:?}", e), @@ -572,7 +583,7 @@ mod tests { #[test] fn detects_hangup() { let cache = Arc::new(Mutex::new(Cache::new(Default::default(), Duration::hours(6)))); - let on_demand = OnDemand::new(cache); + let on_demand = OnDemand::new(cache, 0.into()); let result = on_demand.header_by_hash(&FakeContext, request::HeaderByHash(H256::default())); assert!(on_demand.orphaned_requests.read().len() == 1); diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index f6d30c4d6..f7cb4daca 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -30,7 +30,8 @@ "chainID": "0x3d", "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json index f43abea4b..3091ee27b 100644 --- a/ethcore/res/ethereum/eip150_test.json +++ b/ethcore/res/ethereum/eip150_test.json @@ -14,7 +14,8 @@ "eip155Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", + "maxCodeSize": 24576 } } }, @@ -23,7 +24,8 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffffff" + "eip98Transition": "0x7fffffffffffffff", + "eip86Transition": "0x7fffffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index b51d052c9..e6e8bf3bb 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -14,7 +14,8 @@ "eip155Transition": "0x7fffffffffffffff", "eip160Transition": "0x0", "eip161abcTransition": "0x0", - "eip161dTransition": "0x0" + "eip161dTransition": "0x0", + "maxCodeSize": 24576 } } }, @@ -23,7 +24,8 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffffff" + "eip98Transition": "0x7fffffffffffffff", + "eip86Transition": "0x7fffffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index 3ec04052b..b7d22ac3e 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -30,7 +30,8 @@ "networkID": "0x1", "chainID": "0x2", "subprotocolName": "exp", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 54f10b70c..8253987f3 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -147,7 +147,8 @@ "networkID" : "0x1", "forkBlock": "0x1d4c00", "forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 7b73faa30..aab433033 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -143,7 +143,8 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index bf79729ba..6761c79f3 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -23,7 +23,8 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index 95bd85a94..25b061857 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -23,7 +23,8 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index 22f253bf8..495849daf 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -30,7 +30,8 @@ "chainID": "0x3e", "forkBlock": "0x1b34d8", "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index baf1c7d05..3d2e7baf9 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -23,7 +23,8 @@ "maximumExtraDataSize": "0x0400", "minGasLimit": "125000", "networkID" : "0x0", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index 539168279..1e350d636 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -27,7 +27,8 @@ "networkID" : "0x3", "forkBlock": 641350, "forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb", - "eip98Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index 1b502f087..41251dc8c 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -139,11 +139,12 @@ } }, "params": { - "eip98Transition": "0x7fffffffffffffff", "accountStartNonce": "0x00", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x1" + "networkID" : "0x1", + "eip98Transition": "0x7fffffffffffff", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/null.json b/ethcore/res/null.json index 3ec7ce75e..ffb0ea061 100644 --- a/ethcore/res/null.json +++ b/ethcore/res/null.json @@ -7,7 +7,8 @@ "accountStartNonce": "0x0", "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", - "networkID" : "0x2" + "networkID" : "0x2", + "eip86Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index 8da7c14b2..a983b229a 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -671,8 +671,7 @@ mod tests { use spec::*; let spec = Spec::new_test(); let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(&*spec.engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); @@ -686,16 +685,14 @@ mod tests { let engine = &*spec.engine; let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap() .close_and_lock().seal(engine, vec![]).unwrap(); let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap(); assert_eq!(e.rlp_bytes(), orig_bytes); @@ -712,8 +709,7 @@ mod tests { let engine = &*spec.engine; let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let mut open_block = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes.clone(), Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle1_header = Header::new(); @@ -727,8 +723,7 @@ mod tests { let orig_bytes = b.rlp_bytes(); let orig_db = b.drain(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let e = enact_and_seal(&orig_bytes, engine, false, db, &genesis_header, last_hashes, Default::default()).unwrap(); let bytes = e.rlp_bytes(); diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 0824bd351..5ddeef67f 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1859,15 +1859,13 @@ mod tests { #[test] fn can_contain_arbitrary_block_sequence() { - let bc_result = generate_dummy_blockchain(50); - let bc = bc_result.reference(); + let bc = generate_dummy_blockchain(50); assert_eq!(bc.best_block_number(), 49); } #[test] fn can_collect_garbage() { - let bc_result = generate_dummy_blockchain(3000); - let bc = bc_result.reference(); + let bc = generate_dummy_blockchain(3000); assert_eq!(bc.best_block_number(), 2999); let best_hash = bc.best_block_hash(); @@ -1886,15 +1884,13 @@ mod tests { #[test] fn can_contain_arbitrary_block_sequence_with_extra() { - let bc_result = generate_dummy_blockchain_with_extra(25); - let bc = bc_result.reference(); + let bc = generate_dummy_blockchain_with_extra(25); assert_eq!(bc.best_block_number(), 24); } #[test] fn can_contain_only_genesis_block() { - let bc_result = generate_dummy_empty_blockchain(); - let bc = bc_result.reference(); + let bc = generate_dummy_empty_blockchain(); assert_eq!(bc.best_block_number(), 0); } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index e63b97dfb..44d7238b9 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1054,7 +1054,7 @@ impl BlockChainClient for Client { return Err(err.into()) } } - let lower = t.gas_required(&self.engine.schedule(&env_info)).into(); + let lower = t.gas_required(&self.engine.schedule(env_info.number)).into(); if cond(lower)? { trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower); return Ok(lower) @@ -1353,7 +1353,8 @@ impl BlockChainClient for Client { .collect(); match (transaction, previous_receipts) { (Some(transaction), Some(previous_receipts)) => { - Some(transaction_receipt(transaction, previous_receipts)) + let schedule = self.engine().schedule(block_number); + Some(transaction_receipt(&schedule, transaction, previous_receipts)) }, _ => None, } @@ -1587,11 +1588,15 @@ impl BlockChainClient for Client { }) .and_then(|a| if a.is_zero() { None } else { Some(a) }) } + + fn eip86_transition(&self) -> u64 { + self.engine().params().eip86_transition + } } impl MiningBlockChainClient for Client { fn latest_schedule(&self) -> Schedule { - self.engine.schedule(&self.latest_env_info()) + self.engine.schedule(self.latest_env_info().number) } fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { @@ -1742,7 +1747,7 @@ impl Drop for Client { /// Returns `LocalizedReceipt` given `LocalizedTransaction` /// and a vector of receipts from given block up to transaction index. -fn transaction_receipt(mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { +fn transaction_receipt(schedule: &Schedule, mut tx: LocalizedTransaction, mut receipts: Vec) -> LocalizedReceipt { assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided."); let sender = tx.sender(); @@ -1761,12 +1766,12 @@ fn transaction_receipt(mut tx: LocalizedTransaction, mut receipts: Vec) transaction_hash: transaction_hash, transaction_index: transaction_index, block_hash: block_hash, - block_number:block_number, + block_number: block_number, cumulative_gas_used: receipt.gas_used, gas_used: receipt.gas_used - prior_gas_used, contract_address: match tx.action { Action::Call(_) => None, - Action::Create => Some(contract_address(&sender, &tx.nonce)) + Action::Create => Some(contract_address(schedule.create_address, &sender, &tx.nonce, &tx.data.sha3())) }, logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry { entry: log, @@ -1804,7 +1809,7 @@ mod tests { // Separate thread uncommited transaction let go = Arc::new(AtomicBool::new(false)); let go_thread = go.clone(); - let another_client = client.reference().clone(); + let another_client = client.clone(); thread::spawn(move || { let mut batch = DBTransaction::new(); another_client.chain.read().insert_block(&mut batch, &new_block, Vec::new()); @@ -1821,6 +1826,7 @@ mod tests { #[test] fn should_return_correct_log_index() { use super::transaction_receipt; + use evm::schedule::Schedule; use ethkey::KeyPair; use log_entry::{LogEntry, LocalizedLogEntry}; use receipt::{Receipt, LocalizedReceipt}; @@ -1830,6 +1836,7 @@ mod tests { // given let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap(); let secret = key.secret(); + let schedule = Schedule::new_homestead(); let block_number = 1; let block_hash = 5.into(); @@ -1873,7 +1880,7 @@ mod tests { }]; // when - let receipt = transaction_receipt(transaction, receipts); + let receipt = transaction_receipt(&schedule, transaction, receipts); // then assert_eq!(receipt, LocalizedReceipt { diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 43d75cecd..bfb62d18c 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -353,7 +353,7 @@ pub fn get_temp_state_db() -> GuardedTempResult { impl MiningBlockChainClient for TestBlockChainClient { fn latest_schedule(&self) -> Schedule { - Schedule::new_post_eip150(24576, true, true, true) + Schedule::new_post_eip150(24576, true, true, true, true) } fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock { @@ -756,6 +756,8 @@ impl BlockChainClient for TestBlockChainClient { fn registrar_address(&self) -> Option
{ None } fn registry_address(&self, _name: String) -> Option
{ None } + + fn eip86_transition(&self) -> u64 { u64::max_value() } } impl ProvingBlockChainClient for TestBlockChainClient { diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index e17c324aa..d65642610 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -272,6 +272,9 @@ pub trait BlockChainClient : Sync + Send { /// Get the address of a particular blockchain service, if available. fn registry_address(&self, name: String) -> Option
; + + /// Get the EIP-86 transition block number. + fn eip86_transition(&self) -> u64; } impl IpcConfig for BlockChainClient { } diff --git a/ethcore/src/engines/authority_round.rs b/ethcore/src/engines/authority_round.rs index 55640478e..2d158fcdb 100644 --- a/ethcore/src/engines/authority_round.rs +++ b/ethcore/src/engines/authority_round.rs @@ -26,12 +26,11 @@ use account_provider::AccountProvider; use block::*; use spec::CommonParams; use engines::{Call, Engine, Seal, EngineError}; -use header::Header; +use header::{Header, BlockNumber}; use error::{Error, TransactionError, BlockError}; use evm::Schedule; use ethjson; use io::{IoContext, IoHandler, TimerToken, IoService}; -use env_info::EnvInfo; use builtin::Builtin; use transaction::UnverifiedTransaction; use client::{Client, EngineClient}; @@ -290,8 +289,9 @@ impl Engine for AuthorityRound { ] } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { - Schedule::new_post_eip150(usize::max_value(), true, true, true) + fn schedule(&self, block_number: BlockNumber) -> Schedule { + let eip86 = block_number >= self.params.eip86_transition; + Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86) } fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { @@ -451,7 +451,6 @@ impl Engine for AuthorityRound { #[cfg(test)] mod tests { use util::*; - use env_info::EnvInfo; use header::Header; use error::{Error, BlockError}; use ethkey::Secret; @@ -472,15 +471,7 @@ mod tests { #[test] fn can_return_schedule() { let engine = Spec::new_test_round().engine; - let schedule = engine.schedule(&EnvInfo { - number: 10000000, - author: 0.into(), - timestamp: 0, - difficulty: 0.into(), - last_hashes: Arc::new(vec![]), - gas_used: 0.into(), - gas_limit: 0.into(), - }); + let schedule = engine.schedule(10000000); assert!(schedule.stack_limit > 0); } @@ -518,8 +509,8 @@ mod tests { let spec = Spec::new_test_round(); let engine = &*spec.engine; let genesis_header = spec.genesis_header(); - let db1 = spec.ensure_db_good(get_temp_state_db().take(), &Default::default()).unwrap(); - let db2 = spec.ensure_db_good(get_temp_state_db().take(), &Default::default()).unwrap(); + let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); + let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b1 = b1.close_and_lock(); diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index 35db2a486..8de683e0a 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -24,11 +24,10 @@ use block::*; use builtin::Builtin; use spec::CommonParams; use engines::{Engine, EngineError, Seal, Call, EpochChange}; -use env_info::EnvInfo; use error::{BlockError, Error}; use evm::Schedule; use ethjson; -use header::Header; +use header::{Header, BlockNumber}; use client::Client; use super::signer::EngineSigner; use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; @@ -110,7 +109,7 @@ impl Engine for BasicAuthority { /// Additional engine-specific information for the user/developer concerning `header`. fn extra_info(&self, _header: &Header) -> BTreeMap { map!["signature".to_owned() => "TODO".to_owned()] } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { + fn schedule(&self, _block_number: BlockNumber) -> Schedule { Schedule::new_homestead() } @@ -223,7 +222,6 @@ impl Engine for BasicAuthority { mod tests { use util::*; use block::*; - use env_info::EnvInfo; use error::{BlockError, Error}; use tests::helpers::*; use account_provider::AccountProvider; @@ -248,16 +246,7 @@ mod tests { #[test] fn can_return_schedule() { let engine = new_test_authority().engine; - let schedule = engine.schedule(&EnvInfo { - number: 10000000, - author: 0.into(), - timestamp: 0, - difficulty: 0.into(), - last_hashes: Arc::new(vec![]), - gas_used: 0.into(), - gas_limit: 0.into(), - }); - + let schedule = engine.schedule(10000000); assert!(schedule.stack_limit > 0); } @@ -294,8 +283,7 @@ mod tests { let engine = &*spec.engine; engine.set_signer(Arc::new(tap), addr, "".into()); let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close_and_lock(); diff --git a/ethcore/src/engines/instant_seal.rs b/ethcore/src/engines/instant_seal.rs index 45bede9f4..702afde4f 100644 --- a/ethcore/src/engines/instant_seal.rs +++ b/ethcore/src/engines/instant_seal.rs @@ -18,10 +18,10 @@ use std::collections::BTreeMap; use util::{Address, HashMap}; use builtin::Builtin; use engines::{Engine, Seal}; -use env_info::EnvInfo; use spec::CommonParams; use evm::Schedule; use block::ExecutedBlock; +use header::BlockNumber; /// An engine which does not provide any consensus mechanism, just seals blocks internally. pub struct InstantSeal { @@ -58,8 +58,9 @@ impl Engine for InstantSeal { &self.builtins } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { - Schedule::new_post_eip150(usize::max_value(), true, true, true) + fn schedule(&self, block_number: BlockNumber) -> Schedule { + let eip86 = block_number >= self.params.eip86_transition; + Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86) } fn seals_internally(&self) -> Option { Some(true) } @@ -82,8 +83,7 @@ mod tests { fn instant_can_seal() { let spec = Spec::new_instant(); let engine = &*spec.engine; - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let genesis_header = spec.genesis_header(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![]).unwrap(); diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index ad573637c..ae57976b4 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -41,13 +41,13 @@ use block::ExecutedBlock; use builtin::Builtin; use client::Client; use env_info::EnvInfo; -use error::{Error, TransactionError}; +use error::Error; use evm::Schedule; -use header::Header; -use spec::CommonParams; -use snapshot::SnapshotComponents; -use transaction::{UnverifiedTransaction, SignedTransaction}; +use header::{Header, BlockNumber}; use receipt::Receipt; +use snapshot::SnapshotComponents; +use spec::CommonParams; +use transaction::{UnverifiedTransaction, SignedTransaction}; use ethkey::Signature; use util::*; @@ -141,8 +141,8 @@ pub trait Engine : Sync + Send { /// Get the general parameters of the chain. fn params(&self) -> &CommonParams; - /// Get the EVM schedule for the given `env_info`. - fn schedule(&self, env_info: &EnvInfo) -> Schedule; + /// Get the EVM schedule for the given `block_number`. + fn schedule(&self, block_number: BlockNumber) -> Schedule; /// Builtin-contracts we would like to see in the chain. /// (In principle these are just hints for the engine since that has the last word on them.) @@ -193,14 +193,7 @@ pub trait Engine : Sync + Send { // TODO: Add flags for which bits of the transaction to check. // TODO: consider including State in the params. fn verify_transaction_basic(&self, t: &UnverifiedTransaction, _header: &Header) -> Result<(), Error> { - t.check_low_s()?; - - if let Some(n) = t.network_id() { - if n != self.params().chain_id { - return Err(TransactionError::InvalidNetworkId.into()); - } - } - + t.verify_basic(true, Some(self.params().network_id), true)?; Ok(()) } diff --git a/ethcore/src/engines/null_engine.rs b/ethcore/src/engines/null_engine.rs index 9b9fb9469..09bd07607 100644 --- a/ethcore/src/engines/null_engine.rs +++ b/ethcore/src/engines/null_engine.rs @@ -20,7 +20,7 @@ use builtin::Builtin; use engines::Engine; use spec::CommonParams; use evm::Schedule; -use env_info::EnvInfo; +use header::BlockNumber; /// An engine which does not provide any consensus mechanism and does not seal blocks. pub struct NullEngine { @@ -57,7 +57,7 @@ impl Engine for NullEngine { &self.builtins } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { + fn schedule(&self, _block_number: BlockNumber) -> Schedule { Schedule::new_homestead() } diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 8c8094117..65e11d19e 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -30,9 +30,8 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use util::*; use client::{Client, EngineClient}; use error::{Error, BlockError}; -use header::Header; +use header::{Header, BlockNumber}; use builtin::Builtin; -use env_info::EnvInfo; use rlp::UntrustedRlp; use ethkey::{recover, public_to_address, Signature}; use account_provider::AccountProvider; @@ -405,8 +404,9 @@ impl Engine for Tendermint { ] } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { - Schedule::new_post_eip150(usize::max_value(), true, true, true) + fn schedule(&self, block_number: BlockNumber) -> Schedule { + let eip86 = block_number >= self.params.eip86_transition; + Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86) } fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) { @@ -658,7 +658,6 @@ mod tests { use block::*; use error::{Error, BlockError}; use header::Header; - use env_info::EnvInfo; use ethkey::Secret; use client::chain_notify::ChainNotify; use miner::MinerService; @@ -676,8 +675,8 @@ mod tests { } fn propose_default(spec: &Spec, proposer: Address) -> (ClosedBlock, Vec) { - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = get_temp_state_db(); + let db = spec.ensure_db_good(db, &Default::default()).unwrap(); let genesis_header = spec.genesis_header(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(spec.engine.as_ref(), Default::default(), false, db.boxed_clone(), &genesis_header, last_hashes, proposer, (3141562.into(), 31415620.into()), vec![]).unwrap(); @@ -740,15 +739,7 @@ mod tests { #[test] fn can_return_schedule() { let engine = Spec::new_test_tendermint().engine; - let schedule = engine.schedule(&EnvInfo { - number: 10000000, - author: 0.into(), - timestamp: 0, - difficulty: 0.into(), - last_hashes: Arc::new(vec![]), - gas_used: 0.into(), - gas_limit: 0.into(), - }); + let schedule = engine.schedule(10000000); assert!(schedule.stack_limit > 0); } diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index cbfaa9883..39cd4f511 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -298,6 +298,7 @@ mod tests { let s0 = Secret::from_slice(&"1".sha3()).unwrap(); let v0 = tap.insert_account(s0.clone(), "").unwrap(); let v1 = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "").unwrap(); + let network_id = Spec::new_validator_safe_contract().network_id(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap)); client.engine().register_client(Arc::downgrade(&client)); let validator_contract = Address::from_str("0000000000000000000000000000000000000005").unwrap(); @@ -311,7 +312,7 @@ mod tests { action: Action::Call(validator_contract), value: 0.into(), data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), - }.sign(&s0, None); + }.sign(&s0, Some(network_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); client.update_sealing(); assert_eq!(client.chain_info().best_block_number, 1); @@ -323,7 +324,7 @@ mod tests { action: Action::Call(validator_contract), value: 0.into(), data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(), - }.sign(&s0, None); + }.sign(&s0, Some(network_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); client.update_sealing(); // The transaction is not yet included so still unable to seal. @@ -342,7 +343,7 @@ mod tests { action: Action::Call(Address::default()), value: 0.into(), data: Vec::new(), - }.sign(&s0, None); + }.sign(&s0, Some(network_id)); client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap(); client.update_sealing(); // Able to seal again. diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 0acea6f50..c7174e197 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -19,8 +19,8 @@ use util::*; use block::*; use builtin::Builtin; use env_info::EnvInfo; -use error::{BlockError, TransactionError, Error}; -use header::Header; +use error::{BlockError, Error, TransactionError}; +use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; use transaction::UnverifiedTransaction; @@ -183,19 +183,20 @@ impl Engine for Arc { map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())] } - fn schedule(&self, env_info: &EnvInfo) -> Schedule { + fn schedule(&self, block_number: BlockNumber) -> Schedule { trace!(target: "client", "Creating schedule. fCML={}, bGCML={}", self.ethash_params.homestead_transition, self.ethash_params.eip150_transition); - if env_info.number < self.ethash_params.homestead_transition { + if block_number < self.ethash_params.homestead_transition { Schedule::new_frontier() - } else if env_info.number < self.ethash_params.eip150_transition { + } else if block_number < self.ethash_params.eip150_transition { Schedule::new_homestead() } else { Schedule::new_post_eip150( self.ethash_params.max_code_size as usize, - env_info.number >= self.ethash_params.eip160_transition, - env_info.number >= self.ethash_params.eip161abc_transition, - env_info.number >= self.ethash_params.eip161d_transition + block_number >= self.ethash_params.eip160_transition, + block_number >= self.ethash_params.eip161abc_transition, + block_number >= self.ethash_params.eip161d_transition, + block_number >= self.params.eip86_transition ) } } @@ -385,20 +386,13 @@ impl Engine for Arc { } fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> result::Result<(), Error> { - if header.number() >= self.ethash_params.homestead_transition { - t.check_low_s()?; - } - - if let Some(n) = t.network_id() { - if header.number() < self.ethash_params.eip155_transition || n != self.params().chain_id { - return Err(TransactionError::InvalidNetworkId.into()) - } - } - if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price { return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into()); } + let check_low_s = header.number() >= self.ethash_params.homestead_transition; + let network_id = if header.number() >= self.ethash_params.eip155_transition { Some(self.params().chain_id) } else { None }; + t.verify_basic(check_low_s, network_id, false)?; Ok(()) } @@ -536,7 +530,6 @@ mod tests { use block::*; use tests::helpers::*; use engines::Engine; - use env_info::EnvInfo; use error::{BlockError, Error}; use header::Header; use super::super::{new_morden, new_homestead_test}; @@ -548,8 +541,7 @@ mod tests { let spec = new_morden(); let engine = &*spec.engine; let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let b = b.close(); @@ -561,8 +553,7 @@ mod tests { let spec = new_morden(); let engine = &*spec.engine; let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let last_hashes = Arc::new(vec![genesis_header.hash()]); let mut b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::zero(), (3141562.into(), 31415620.into()), vec![]).unwrap(); let mut uncle = Header::new(); @@ -585,28 +576,10 @@ mod tests { #[test] fn can_return_schedule() { let engine = new_morden().engine; - let schedule = engine.schedule(&EnvInfo { - number: 10000000, - author: 0.into(), - timestamp: 0, - difficulty: 0.into(), - last_hashes: Arc::new(vec![]), - gas_used: 0.into(), - gas_limit: 0.into(), - }); - + let schedule = engine.schedule(10000000); assert!(schedule.stack_limit > 0); - let schedule = engine.schedule(&EnvInfo { - number: 100, - author: 0.into(), - timestamp: 0, - difficulty: 0.into(), - last_hashes: Arc::new(vec![]), - gas_used: 0.into(), - gas_limit: 0.into(), - }); - + let schedule = engine.schedule(100); assert!(!schedule.have_delegate_call); } diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index ce8b84b31..b54401572 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -94,8 +94,7 @@ mod tests { let spec = new_morden(); let engine = &spec.engine; let genesis_header = spec.genesis_header(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let s = State::from_existing(db, genesis_header.state_root().clone(), engine.account_start_nonce(), Default::default()).unwrap(); assert_eq!(s.balance(&"0000000000000000000000000000000000000001".into()).unwrap(), 1u64.into()); assert_eq!(s.balance(&"0000000000000000000000000000000000000002".into()).unwrap(), 1u64.into()); diff --git a/ethcore/src/evm/ext.rs b/ethcore/src/evm/ext.rs index 352ffb7d9..e6b644874 100644 --- a/ethcore/src/evm/ext.rs +++ b/ethcore/src/evm/ext.rs @@ -41,6 +41,17 @@ pub enum MessageCallResult { Failed } +/// Specifies how an address is calculated for a new contract. +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum CreateContractAddress { + /// Address is calculated from nonce and sender. Pre EIP-86 (Metropolis) + FromSenderAndNonce, + /// Address is calculated from code hash. Default since EIP-86 + FromCodeHash, + /// Address is calculated from code hash and sender. Used by CREATE_P2SH instruction. + FromSenderAndCodeHash, +} + /// Externalities interface for EVMs // TODO: [rob] associated error type instead of `trie::Result`. Not all EVMs are trie powered. pub trait Ext { @@ -68,7 +79,7 @@ pub trait Ext { /// Creates new contract. /// /// Returns gas_left and contract address if contract creation was succesfull. - fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult; + fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult; /// Message call. /// diff --git a/ethcore/src/evm/instructions.rs b/ethcore/src/evm/instructions.rs index d93ddc437..41c9e1ea1 100644 --- a/ethcore/src/evm/instructions.rs +++ b/ethcore/src/evm/instructions.rs @@ -278,6 +278,7 @@ lazy_static! { arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero); arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special); arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Special); + arr[CREATE_P2SH as usize] = InstructionInfo::new("CREATE_P2SH", 0, 3, 1, true, GasPriceTier::Special); arr }; } @@ -553,6 +554,8 @@ pub const CALLCODE: Instruction = 0xf2; pub const RETURN: Instruction = 0xf3; /// like CALLCODE but keeps caller's value and sender pub const DELEGATECALL: Instruction = 0xf4; +/// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160 +pub const CREATE_P2SH: Instruction = 0xfb; /// halt execution and register account for later deletion pub const SUICIDE: Instruction = 0xff; diff --git a/ethcore/src/evm/interpreter/gasometer.rs b/ethcore/src/evm/interpreter/gasometer.rs index 9086200fa..fb0c86d35 100644 --- a/ethcore/src/evm/interpreter/gasometer.rs +++ b/ethcore/src/evm/interpreter/gasometer.rs @@ -223,7 +223,7 @@ impl Gasometer { Request::GasMemProvide(gas, mem, Some(requested)) }, - instructions::CREATE => { + instructions::CREATE | instructions::CREATE_P2SH => { let gas = Gas::from(schedule.create_gas); let mem = mem_needed(stack.peek(1), stack.peek(2))?; diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index 79304793e..7fbab7ebc 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -32,7 +32,7 @@ use std::marker::PhantomData; use action_params::{ActionParams, ActionValue}; use types::executed::CallType; use evm::instructions::{self, Instruction, InstructionInfo}; -use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType}; +use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType, CreateContractAddress}; use bit_set::BitSet; use util::*; @@ -182,7 +182,9 @@ impl Interpreter { fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack) -> evm::Result<()> { let schedule = ext.schedule(); - if !schedule.have_delegate_call && instruction == instructions::DELEGATECALL { + if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) || + (instruction == instructions::CREATE_P2SH && !schedule.have_create_p2sh) { + return Err(evm::Error::BadInstruction { instruction: instruction }); @@ -266,10 +268,12 @@ impl Interpreter { instructions::JUMPDEST => { // ignore }, - instructions::CREATE => { + instructions::CREATE | instructions::CREATE_P2SH => { let endowment = stack.pop_back(); let init_off = stack.pop_back(); let init_size = stack.pop_back(); + + let address_scheme = if instruction == instructions::CREATE { ext.schedule().create_address } else { CreateContractAddress::FromSenderAndCodeHash }; let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); let contract_code = self.mem.read_slice(init_off, init_size); @@ -280,7 +284,7 @@ impl Interpreter { return Ok(InstructionResult::UnusedGas(create_gas)); } - let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code); + let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme); return match create_result { ContractCreateResult::Created(address, gas_left) => { stack.push(address_to_u256(address)); diff --git a/ethcore/src/evm/mod.rs b/ethcore/src/evm/mod.rs index cc707d6ef..7906b81ff 100644 --- a/ethcore/src/evm/mod.rs +++ b/ethcore/src/evm/mod.rs @@ -32,7 +32,7 @@ mod tests; mod benches; pub use self::evm::{Evm, Error, Finalize, GasLeft, Result, CostType}; -pub use self::ext::{Ext, ContractCreateResult, MessageCallResult}; +pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress}; pub use self::factory::{Factory, VMType}; pub use self::schedule::Schedule; pub use types::executed::CallType; diff --git a/ethcore/src/evm/schedule.rs b/ethcore/src/evm/schedule.rs index 70801983d..97df4d784 100644 --- a/ethcore/src/evm/schedule.rs +++ b/ethcore/src/evm/schedule.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . //! Cost schedule and other parameterisations for the EVM. +use evm::CreateContractAddress; /// Definition of the cost schedule and other parameterisations for the EVM. pub struct Schedule { @@ -22,6 +23,8 @@ pub struct Schedule { pub exceptional_failed_code_deposit: bool, /// Does it have a delegate cal pub have_delegate_call: bool, + /// Does it have a CREATE_P2SH instruction + pub have_create_p2sh: bool, /// VM stack limit pub stack_limit: usize, /// Max number of nested calls/creates @@ -99,6 +102,8 @@ pub struct Schedule { pub no_empty: bool, /// Kill empty accounts if touched. pub kill_empty: bool, + /// Contract address generation scheme + pub create_address: CreateContractAddress, } impl Schedule { @@ -113,10 +118,11 @@ impl Schedule { } /// Schedule for the post-EIP-150-era of the Ethereum main net. - pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule { + pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_create_p2sh: bool) -> Schedule { Schedule { exceptional_failed_code_deposit: true, have_delegate_call: true, + have_create_p2sh: have_create_p2sh, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -155,13 +161,20 @@ impl Schedule { sub_gas_cap_divisor: Some(64), no_empty: no_empty, kill_empty: kill_empty, + create_address: if have_create_p2sh { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }, } } + /// Schedule for the Metropolis of the Ethereum main net. + pub fn new_metropolis() -> Schedule { + Self::new_post_eip150(24576, true, true, true, true) + } + fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule { Schedule { exceptional_failed_code_deposit: efcd, have_delegate_call: hdc, + have_create_p2sh: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -200,6 +213,7 @@ impl Schedule { sub_gas_cap_divisor: None, no_empty: false, kill_empty: false, + create_address: CreateContractAddress::FromSenderAndNonce, } } } diff --git a/ethcore/src/evm/tests.rs b/ethcore/src/evm/tests.rs index 3002c170c..b5b2341aa 100644 --- a/ethcore/src/evm/tests.rs +++ b/ethcore/src/evm/tests.rs @@ -18,7 +18,7 @@ use util::*; use action_params::{ActionParams, ActionValue}; use env_info::EnvInfo; use types::executed::CallType; -use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult}; +use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress}; use std::fmt::Debug; pub struct FakeLogEntry { @@ -111,7 +111,7 @@ impl Ext for FakeExt { self.blockhashes.get(number).unwrap_or(&H256::new()).clone() } - fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult { + fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult { self.calls.insert(FakeCall { call_type: FakeCallType::Create, gas: *gas, diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 4183a5005..dc9dcec17 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -22,7 +22,7 @@ use engines::Engine; use types::executed::CallType; use env_info::EnvInfo; use error::ExecutionError; -use evm::{self, Ext, Factory, Finalize}; +use evm::{self, Ext, Factory, Finalize, CreateContractAddress}; use externalities::*; use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer}; use transaction::{Action, SignedTransaction}; @@ -34,14 +34,29 @@ pub use types::executed::{Executed, ExecutionResult}; /// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp` const STACK_SIZE_PER_DEPTH: usize = 24*1024; -/// Returns new address created from address and given nonce. -pub fn contract_address(address: &Address, nonce: &U256) -> Address { +/// Returns new address created from address, nonce, and code hash +pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code_hash: &H256) -> Address { use rlp::RlpStream; - let mut stream = RlpStream::new_list(2); - stream.append(address); - stream.append(nonce); - From::from(stream.out().sha3()) + match address_scheme { + CreateContractAddress::FromSenderAndNonce => { + let mut stream = RlpStream::new_list(2); + stream.append(sender); + stream.append(nonce); + From::from(stream.as_raw().sha3()) + }, + CreateContractAddress::FromCodeHash => { + let mut buffer = [0u8; 20 + 32]; + &mut buffer[20..].copy_from_slice(&code_hash[..]); + From::from((&buffer[..]).sha3()) + }, + CreateContractAddress::FromSenderAndCodeHash => { + let mut buffer = [0u8; 20 + 32]; + &mut buffer[..20].copy_from_slice(&sender[..]); + &mut buffer[20..].copy_from_slice(&code_hash[..]); + From::from((&buffer[..]).sha3()) + }, + } } /// Transaction execution options. @@ -125,7 +140,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let sender = t.sender(); let nonce = self.state.nonce(&sender)?; - let schedule = self.engine.schedule(self.info); + let schedule = self.engine.schedule(self.info.number); let base_gas_required = U256::from(t.gas_required(&schedule)); if t.gas < base_gas_required { @@ -160,17 +175,20 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { } // NOTE: there can be no invalid transactions from this point. - self.state.inc_nonce(&sender)?; + if !t.is_unsigned() { + self.state.inc_nonce(&sender)?; + } self.state.sub_balance(&sender, &U256::from(gas_cost))?; let mut substate = Substate::new(); let (gas_left, output) = match t.action { Action::Create => { - let new_address = contract_address(&sender, &nonce); + let code_hash = t.data.sha3(); + let new_address = contract_address(schedule.create_address, &sender, &nonce, &code_hash); let params = ActionParams { code_address: new_address.clone(), - code_hash: t.data.sha3(), + code_hash: code_hash, address: new_address, sender: sender.clone(), origin: sender.clone(), @@ -253,7 +271,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { // backup used in case of running out of gas self.state.checkpoint(); - let schedule = self.engine.schedule(self.info); + let schedule = self.engine.schedule(self.info.number); // at first, transfer value to destination if let ActionValue::Transfer(val) = params.value { @@ -365,8 +383,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { params: ActionParams, substate: &mut Substate, tracer: &mut T, - vm_tracer: &mut V + vm_tracer: &mut V, ) -> evm::Result where T: Tracer, V: VMTracer { + + let schedule = self.engine.schedule(self.info.number); + if schedule.create_address != CreateContractAddress::FromSenderAndNonce && self.state.exists(¶ms.address)? { + return Err(evm::Error::OutOfGas); + } + // backup used in case of running out of gas self.state.checkpoint(); @@ -374,7 +398,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let mut unconfirmed_substate = Substate::new(); // create contract and transfer value to it if necessary - let schedule = self.engine.schedule(self.info); let nonce_offset = if schedule.no_empty {1} else {0}.into(); let prev_bal = self.state.balance(¶ms.address)?; if let ActionValue::Transfer(val) = params.value { @@ -423,7 +446,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { trace: Vec, vm_trace: Option ) -> ExecutionResult { - let schedule = self.engine.schedule(self.info); + let schedule = self.engine.schedule(self.info.number); // refunds from SSTORE nonzero -> zero let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count; @@ -525,7 +548,7 @@ mod tests { use util::bytes::BytesRef; use action_params::{ActionParams, ActionValue}; use env_info::EnvInfo; - use evm::{Factory, VMType}; + use evm::{Factory, VMType, CreateContractAddress}; use error::ExecutionError; use state::{Substate, CleanupMode}; use tests::helpers::*; @@ -540,22 +563,21 @@ mod tests { fn test_contract_address() { let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let expected_address = Address::from_str("3f09c73a5ed19289fb9bdc72f1742566df146f56").unwrap(); - assert_eq!(expected_address, contract_address(&address, &U256::from(88))); + assert_eq!(expected_address, contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::from(88), &H256::default())); } // TODO: replace params with transactions! evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int} fn test_sender_balance(factory: Factory) { let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); let mut params = ActionParams::default(); params.address = address.clone(); params.sender = sender.clone(); params.gas = U256::from(100_000); params.code = Some(Arc::new("3331600055".from_hex().unwrap())); params.value = ActionValue::Transfer(U256::from(0x7)); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(0x100u64), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(0); @@ -603,7 +625,7 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -613,8 +635,7 @@ mod tests { params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(0); @@ -660,7 +681,7 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -672,8 +693,7 @@ mod tests { params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); params.call_type = CallType::Call; - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(5); @@ -773,7 +793,7 @@ mod tests { let code = "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -783,8 +803,7 @@ mod tests { params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(100.into()); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(5); @@ -861,7 +880,7 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -871,8 +890,7 @@ mod tests { params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(0); @@ -914,8 +932,8 @@ mod tests { let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0".from_hex().unwrap(); let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); - let address = contract_address(&sender, &U256::zero()); - let next_address = contract_address(&address, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); + let next_address = contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::zero(), &H256::default()); let mut params = ActionParams::default(); params.address = address.clone(); params.sender = sender.clone(); @@ -923,8 +941,7 @@ mod tests { params.gas = U256::from(100_000); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from(100)); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(1024); @@ -981,8 +998,7 @@ mod tests { params.code = Some(Arc::new(code_a.clone())); params.value = ActionValue::Transfer(U256::from(100_000)); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.init_code(&address_a, code_a.clone()).unwrap(); state.init_code(&address_b, code_b.clone()).unwrap(); state.add_balance(&sender, &U256::from(100_000), CleanupMode::NoEmpty).unwrap(); @@ -1024,13 +1040,12 @@ mod tests { // 55 - sstore let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap(); let code = "600160005401600055600060006000600060003060e05a03f1600155".from_hex().unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); let mut params = ActionParams::default(); params.address = address.clone(); params.gas = U256::from(100_000); params.code = Some(Arc::new(code.clone())); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.init_code(&address, code).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(0); @@ -1060,10 +1075,9 @@ mod tests { nonce: U256::zero() }.sign(keypair.secret(), None); let sender = t.sender(); - let contract = contract_address(&sender, &U256::zero()); + let contract = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(18), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); @@ -1100,8 +1114,7 @@ mod tests { }.sign(keypair.secret(), None); let sender = t.sender(); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(17), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); @@ -1133,8 +1146,7 @@ mod tests { }.sign(keypair.secret(), None); let sender = t.sender(); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(17), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_used = U256::from(20_000); @@ -1168,8 +1180,7 @@ mod tests { }.sign(keypair.secret(), None); let sender = t.sender(); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from(100_017), CleanupMode::NoEmpty).unwrap(); let mut info = EnvInfo::default(); info.gas_limit = U256::from(100_000); @@ -1193,7 +1204,7 @@ mod tests { let code = "6064640fffffffff20600055".from_hex().unwrap(); let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); - let address = contract_address(&sender, &U256::zero()); + let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default()); // TODO: add tests for 'callcreate' //let next_address = contract_address(&address, &U256::zero()); let mut params = ActionParams::default(); @@ -1203,8 +1214,7 @@ mod tests { params.gas = U256::from(0x0186a0); params.code = Some(Arc::new(code)); params.value = ActionValue::Transfer(U256::from_str("0de0b6b3a7640000").unwrap()); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap(), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); let engine = TestEngine::new(0); diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 893ba03be..0b849033e 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -21,8 +21,9 @@ use state::{Backend as StateBackend, State, Substate}; use engines::Engine; use env_info::EnvInfo; use executive::*; -use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory}; +use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory, CreateContractAddress}; use types::executed::CallType; +use types::transaction::UNSIGNED_SENDER; use trace::{Tracer, VMTracer}; /// Policy for handling output data on `RETURN` opcode. @@ -97,7 +98,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B> depth: depth, origin_info: origin_info, substate: substate, - schedule: engine.schedule(env_info), + schedule: engine.schedule(env_info.number), output: output, tracer: tracer, vm_tracer: vm_tracer, @@ -147,10 +148,11 @@ 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]) -> ContractCreateResult { + fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address_scheme: CreateContractAddress) -> ContractCreateResult { // create new contract address + let code_hash = code.sha3(); let address = match self.state.nonce(&self.origin_info.address) { - Ok(nonce) => contract_address(&self.origin_info.address, &nonce), + Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code_hash), Err(e) => { debug!(target: "ext", "Database corruption encountered: {:?}", e); return ContractCreateResult::Failed @@ -167,14 +169,16 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> gas_price: self.origin_info.gas_price, value: ActionValue::Transfer(*value), code: Some(Arc::new(code.to_vec())), - code_hash: code.sha3(), + code_hash: code_hash, data: None, call_type: CallType::None, }; - if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { - debug!(target: "ext", "Database corruption encountered: {:?}", e); - return ContractCreateResult::Failed + if params.sender != UNSIGNED_SENDER { + if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { + debug!(target: "ext", "Database corruption encountered: {:?}", e); + return ContractCreateResult::Failed + } } let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth); @@ -346,7 +350,6 @@ mod tests { use evm::Ext; use state::{State, Substate}; use tests::helpers::*; - use devtools::GuardedTempResult; use super::*; use trace::{NoopTracer, NoopVMTracer}; use types::executed::CallType; @@ -373,7 +376,7 @@ mod tests { } struct TestSetup { - state: GuardedTempResult>, + state: State<::state_db::StateDB>, engine: Arc, sub_state: Substate, env_info: EnvInfo @@ -399,7 +402,7 @@ mod tests { #[test] fn can_be_created() { let mut setup = TestSetup::new(); - let state = setup.state.reference_mut(); + let state = &mut setup.state; let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; @@ -412,7 +415,7 @@ mod tests { #[test] fn can_return_block_hash_no_env() { let mut setup = TestSetup::new(); - let state = setup.state.reference_mut(); + let state = &mut setup.state; let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; @@ -437,7 +440,7 @@ mod tests { last_hashes.push(test_hash.clone()); env_info.last_hashes = Arc::new(last_hashes); } - let state = setup.state.reference_mut(); + let state = &mut setup.state; let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; @@ -453,7 +456,7 @@ mod tests { #[should_panic] fn can_call_fail_empty() { let mut setup = TestSetup::new(); - let state = setup.state.reference_mut(); + let state = &mut setup.state; let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; @@ -481,7 +484,7 @@ mod tests { let log_topics = vec![H256::from("af0fa234a6af46afa23faf23bcbc1c1cb4bcb7bcbe7e7e7ee3ee2edddddddddd")]; let mut setup = TestSetup::new(); - let state = setup.state.reference_mut(); + let state = &mut setup.state; let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; @@ -499,7 +502,7 @@ mod tests { let refund_account = &Address::new(); let mut setup = TestSetup::new(); - let state = setup.state.reference_mut(); + let state = &mut setup.state; let mut tracer = NoopTracer; let mut vm_tracer = NoopVMTracer; diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 987280bc1..45a4f1d52 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -48,7 +48,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { ChainEra::Frontier => ethereum::new_frontier_test(), ChainEra::Homestead => ethereum::new_homestead_test(), ChainEra::Eip150 => ethereum::new_eip150_test(), - ChainEra::Eip161 => ethereum::new_eip161_test(), + ChainEra::_Eip161 => ethereum::new_eip161_test(), ChainEra::TransitionTest => ethereum::new_transition_test(), }; spec.set_genesis_state(state); diff --git a/ethcore/src/json_tests/eip150_state.rs b/ethcore/src/json_tests/eip150_state.rs deleted file mode 100644 index fffb3f57a..000000000 --- a/ethcore/src/json_tests/eip150_state.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use super::test_common::*; -use tests::helpers::*; -use super::state::json_chain_test; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Eip150) -} - -declare_test!{StateTests_EIP150_stEIPSpecificTest, "StateTests/EIP150/stEIPSpecificTest"} -declare_test!{StateTests_EIP150_stEIPsingleCodeGasPrices, "StateTests/EIP150/stEIPsingleCodeGasPrices"} -declare_test!{StateTests_EIP150_stMemExpandingEIPCalls, "StateTests/EIP150/stMemExpandingEIPCalls"} - -declare_test!{StateTests_EIP150_stCallCodes, "StateTests/EIP150/Homestead/stCallCodes"} -declare_test!{StateTests_EIP150_stCallCreateCallCodeTest, "StateTests/EIP150/Homestead/stCallCreateCallCodeTest"} -declare_test!{StateTests_EIP150_stDelegatecallTest, "StateTests/EIP150/Homestead/stDelegatecallTest"} -declare_test!{StateTests_EIP150_stInitCodeTest, "StateTests/EIP150/Homestead/stInitCodeTest"} -declare_test!{StateTests_EIP150_stLogTests, "StateTests/EIP150/Homestead/stLogTests"} -declare_test!{heavy => StateTests_EIP150_stMemoryStressTest, "StateTests/EIP150/Homestead/stMemoryStressTest"} -declare_test!{heavy => StateTests_EIP150_stMemoryTest, "StateTests/EIP150/Homestead/stMemoryTest"} -declare_test!{StateTests_EIP150_stPreCompiledContracts, "StateTests/EIP150/Homestead/stPreCompiledContracts"} -declare_test!{heavy => StateTests_EIP150_stQuadraticComplexityTest, "StateTests/EIP150/Homestead/stQuadraticComplexityTest"} -declare_test!{StateTests_EIP150_stRecursiveCreate, "StateTests/EIP150/Homestead/stRecursiveCreate"} -declare_test!{StateTests_EIP150_stRefundTest, "StateTests/EIP150/Homestead/stRefundTest"} -declare_test!{StateTests_EIP150_stSpecialTest, "StateTests/EIP150/Homestead/stSpecialTest"} -declare_test!{StateTests_EIP150_stSystemOperationsTest, "StateTests/EIP150/Homestead/stSystemOperationsTest"} -declare_test!{StateTests_EIP150_stTransactionTest, "StateTests/EIP150/Homestead/stTransactionTest"} -declare_test!{StateTests_EIP150_stWalletTest, "StateTests/EIP150/Homestead/stWalletTest"} diff --git a/ethcore/src/json_tests/eip161_state.rs b/ethcore/src/json_tests/eip161_state.rs deleted file mode 100644 index 44ad6a30a..000000000 --- a/ethcore/src/json_tests/eip161_state.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use super::test_common::*; -use tests::helpers::*; -use super::state::json_chain_test; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Eip161) -} - -declare_test!{StateTests_EIP158_stEIP158SpecificTest, "StateTests/EIP158/stEIP158SpecificTest"} -declare_test!{StateTests_EIP158_stNonZeroCallsTest, "StateTests/EIP158/stNonZeroCallsTest"} -declare_test!{StateTests_EIP158_stZeroCallsTest, "StateTests/EIP158/stZeroCallsTest"} - -declare_test!{StateTests_EIP158_EIP150_stMemExpandingEIPCalls, "StateTests/EIP158/EIP150/stMemExpandingEIPCalls"} -declare_test!{StateTests_EIP158_EIP150_stEIPSpecificTest, "StateTests/EIP158/EIP150/stEIPSpecificTest"} -declare_test!{StateTests_EIP158_EIP150_stEIPsingleCodeGasPrices, "StateTests/EIP158/EIP150/stEIPsingleCodeGasPrices"} -declare_test!{StateTests_EIP158_EIP150_stChangedTests, "StateTests/EIP158/EIP150/stChangedTests"} - -declare_test!{StateTests_EIP158_Homestead_stBoundsTest, "StateTests/EIP158/Homestead/stBoundsTest"} -declare_test!{StateTests_EIP158_Homestead_stCallCodes, "StateTests/EIP158/Homestead/stCallCodes"} -declare_test!{StateTests_EIP158_Homestead_stCallCreateCallCodeTest, "StateTests/EIP158/Homestead/stCallCreateCallCodeTest"} -declare_test!{StateTests_EIP158_Homestead_stCallDelegateCodes, "StateTests/EIP158/Homestead/stCallDelegateCodes"} -declare_test!{StateTests_EIP158_Homestead_stCallDelegateCodesCallCode, "StateTests/EIP158/Homestead/stCallDelegateCodesCallCode"} -declare_test!{StateTests_EIP158_Homestead_stDelegatecallTest, "StateTests/EIP158/Homestead/stDelegatecallTest"} -declare_test!{StateTests_EIP158_Homestead_stHomeSteadSpecific, "StateTests/EIP158/Homestead/stHomeSteadSpecific"} -declare_test!{StateTests_EIP158_Homestead_stInitCodeTest, "StateTests/EIP158/Homestead/stInitCodeTest"} -declare_test!{StateTests_EIP158_Homestead_stLogTests, "StateTests/EIP158/Homestead/stLogTests"} -declare_test!{heavy => StateTests_EIP158_Homestead_stMemoryTest, "StateTests/EIP158/Homestead/stMemoryTest"} -declare_test!{StateTests_EIP158_Homestead_stPreCompiledContracts, "StateTests/EIP158/Homestead/stPreCompiledContracts"} -declare_test!{heavy => StateTests_EIP158_Homestead_stQuadraticComplexityTest, "StateTests/EIP158/Homestead/stQuadraticComplexityTest"} -declare_test!{StateTests_EIP158_Homestead_stRecursiveCreate, "StateTests/EIP158/Homestead/stRecursiveCreate"} -declare_test!{StateTests_EIP158_Homestead_stRefundTest, "StateTests/EIP158/Homestead/stRefundTest"} -declare_test!{StateTests_EIP158_Homestead_stSpecialTest, "StateTests/EIP158/Homestead/stSpecialTest"} -declare_test!{StateTests_EIP158_Homestead_stSystemOperationsTest, "StateTests/EIP158/Homestead/stSystemOperationsTest"} -declare_test!{StateTests_EIP158_Homestead_stTransactionTest, "StateTests/EIP158/Homestead/stTransactionTest"} -declare_test!{StateTests_EIP158_Homestead_stWalletTest, "StateTests/EIP158/Homestead/stWalletTest"} \ No newline at end of file diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index 844fa08f5..c34ad69e3 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -21,7 +21,7 @@ use executive::*; use engines::Engine; use env_info::EnvInfo; use evm; -use evm::{Schedule, Ext, Factory, Finalize, VMType, ContractCreateResult, MessageCallResult}; +use evm::{Schedule, Ext, Factory, Finalize, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress}; use externalities::*; use types::executed::CallType; use tests::helpers::*; @@ -56,7 +56,8 @@ struct TestExt<'a, T: 'a, V: 'a, B: 'a> { ext: Externalities<'a, T, V, B>, callcreates: Vec, - contract_address: Address + nonce: U256, + sender: Address, } impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B> @@ -76,9 +77,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B> vm_tracer: &'a mut V, ) -> trie::Result { Ok(TestExt { - contract_address: contract_address(&address, &state.nonce(&address)?), + nonce: state.nonce(&address)?, ext: Externalities::new(state, info, engine, vm_factory, depth, origin_info, substate, output, tracer, vm_tracer), - callcreates: vec![] + callcreates: vec![], + sender: address, }) } } @@ -114,14 +116,15 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> self.ext.blockhash(number) } - fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult { + fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult { self.callcreates.push(CallCreate { data: code.to_vec(), destination: None, gas_limit: *gas, value: *value }); - ContractCreateResult::Created(self.contract_address.clone(), *gas) + let contract_address = contract_address(address, &self.sender, &self.nonce, &code.sha3()); + ContractCreateResult::Created(contract_address, *gas) } fn call(&mut self, @@ -215,8 +218,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { } let out_of_gas = vm.out_of_gas(); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.populate_from(From::from(vm.pre_state.clone())); let info = From::from(vm.env); let engine = TestEngine::new(1); diff --git a/ethcore/src/json_tests/homestead_chain.rs b/ethcore/src/json_tests/homestead_chain.rs index aab07674b..5f0fe5769 100644 --- a/ethcore/src/json_tests/homestead_chain.rs +++ b/ethcore/src/json_tests/homestead_chain.rs @@ -14,7 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use super::test_common::*; use super::chain::json_chain_test; use tests::helpers::*; diff --git a/ethcore/src/json_tests/homestead_state.rs b/ethcore/src/json_tests/homestead_state.rs deleted file mode 100644 index c8585ff15..000000000 --- a/ethcore/src/json_tests/homestead_state.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use super::test_common::*; -use tests::helpers::*; -use super::state::json_chain_test; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Homestead) -} - -declare_test!{StateTests_Homestead_stCallCodes, "StateTests/Homestead/stCallCodes"} -declare_test!{StateTests_Homestead_stCallCreateCallCodeTest, "StateTests/Homestead/stCallCreateCallCodeTest"} -declare_test!{StateTests_Homestead_stDelegatecallTest, "StateTests/Homestead/stDelegatecallTest"} -declare_test!{StateTests_Homestead_stInitCodeTest, "StateTests/Homestead/stInitCodeTest"} -declare_test!{StateTests_Homestead_stLogTests, "StateTests/Homestead/stLogTests"} -declare_test!{heavy => StateTests_Homestead_stMemoryStressTest, "StateTests/Homestead/stMemoryStressTest"} -declare_test!{heavy => StateTests_Homestead_stMemoryTest, "StateTests/Homestead/stMemoryTest"} -declare_test!{StateTests_Homestead_stPreCompiledContracts, "StateTests/Homestead/stPreCompiledContracts"} -declare_test!{heavy => StateTests_Homestead_stQuadraticComplexityTest, "StateTests/Homestead/stQuadraticComplexityTest"} -declare_test!{StateTests_Homestead_stRecursiveCreate, "StateTests/Homestead/stRecursiveCreate"} -declare_test!{StateTests_Homestead_stRefundTest, "StateTests/Homestead/stRefundTest"} -declare_test!{StateTests_Homestead_stSpecialTest, "StateTests/Homestead/stSpecialTest"} -declare_test!{StateTests_Homestead_stSystemOperationsTest, "StateTests/Homestead/stSystemOperationsTest"} -declare_test!{StateTests_Homestead_stTransactionTest, "StateTests/Homestead/stTransactionTest"} -declare_test!{StateTests_Homestead_stWalletTest, "StateTests/Homestead/stWalletTest"} diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index 22f0dca03..406782072 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -21,8 +21,5 @@ mod transaction; mod executive; mod state; mod chain; -mod homestead_state; mod homestead_chain; -mod eip150_state; -mod eip161_state; mod trie; diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 6388daf94..c15847896 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -16,749 +16,116 @@ use super::test_common::*; use tests::helpers::*; -use pod_state::{self, PodState}; -use log_entry::LogEntry; +use pod_state::PodState; use ethereum; +use spec::Spec; use ethjson; +use ethjson::state::test::ForkSpec; +use types::transaction::SignedTransaction; +use env_info::EnvInfo; -pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { +lazy_static! { + pub static ref FRONTIER: Spec = ethereum::new_frontier_test(); + pub static ref HOMESTEAD: Spec = ethereum::new_homestead_test(); + pub static ref EIP150: Spec = ethereum::new_eip150_test(); + pub static ref EIP161: Spec = ethereum::new_eip161_test(); +} + +pub fn json_chain_test(json_data: &[u8]) -> Vec { ::ethcore_logger::init_log(); - let tests = ethjson::state::Test::load(json_data).unwrap(); + let tests = ethjson::state::test::Test::load(json_data).unwrap(); let mut failed = Vec::new(); - let engine = match era { - ChainEra::Frontier => ethereum::new_mainnet_like().engine, - ChainEra::Homestead => ethereum::new_homestead_test().engine, - ChainEra::Eip150 => ethereum::new_eip150_test().engine, - ChainEra::Eip161 => ethereum::new_eip161_test().engine, - ChainEra::TransitionTest => ethereum::new_transition_test().engine, - }; for (name, test) in tests.into_iter() { - let mut fail = false; { - let mut fail_unless = |cond: bool| if !cond && !fail { - failed.push(name.clone()); - flushln!("FAIL"); - fail = true; - true - } else {false}; - - flush!(" - {}...", name); - - let transaction = test.transaction.into(); - let post_state_root = test.post_state_root.into(); - let env = test.env.into(); + let multitransaction = test.transaction; + let env: EnvInfo = test.env.into(); let pre: PodState = test.pre_state.into(); - let post: PodState = test.post_state.into(); - let logs: Vec = test.logs.into_iter().map(Into::into).collect(); - let calc_post = sec_trie_root(post.get().iter().map(|(k, v)| (k.to_vec(), v.rlp())).collect()); + for (spec, states) in test.post_states { + let total = states.len(); + let engine = match spec { + ForkSpec::Frontier => &FRONTIER.engine, + ForkSpec::Homestead => &HOMESTEAD.engine, + ForkSpec::EIP150 => &EIP150.engine, + ForkSpec::EIP158 => &EIP161.engine, + ForkSpec::Metropolis => continue, + }; - if fail_unless(post_state_root == calc_post) { - println!("!!! {}: Trie root mismatch (got: {}, expect: {}):", name, calc_post, post_state_root); - println!("!!! Post:\n{}", post); - } else { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); - state.populate_from(pre); - state.commit() - .expect(&format!("State test {} failed due to internal error.", name)); - let res = state.apply(&env, &*engine, &transaction, false); + for (i, state) in states.into_iter().enumerate() { + let info = format!(" - {} | {:?} ({}/{}) ...", name, spec, i + 1, total); - if fail_unless(state.root() == &post_state_root) { - println!("!!! {}: State mismatch (got: {}, expect: {}):", name, state.root(), post_state_root); - let our_post = state.to_pod(); - println!("Got:\n{}", our_post); - println!("Expect:\n{}", post); - println!("Diff ---expect -> +++got:\n{}", pod_state::diff_pod(&post, &our_post)); - } - - if let Ok(r) = res { - if fail_unless(logs == r.receipt.logs) { - println!("!!! {}: Logs mismatch:", name); - println!("Got:\n{:?}", r.receipt.logs); - println!("Expect:\n{:?}", logs); + let post_root: H256 = state.hash.into(); + let transaction: SignedTransaction = multitransaction.select(&state.indexes).into(); + let mut state = get_temp_state(); + state.populate_from(pre.clone()); + if transaction.verify_basic(true, None, env.number >= engine.params().eip86_transition).is_ok() { + state.commit().expect(&format!("State test {} failed due to internal error.", name)); + let _res = state.apply(&env, &**engine, &transaction, false); + } else { + let _rest = state.commit(); + } + if state.root() != &post_root { + println!("{} !!! State mismatch (got: {}, expect: {}", info, state.root(), post_root); + flushln!("{} fail", info); + failed.push(name.clone()); + } else { + flushln!("{} ok", info); } } } } - if !fail { - flushln!("ok"); - } } - println!("!!! {:?} tests from failed.", failed.len()); + if !failed.is_empty() { + println!("!!! {:?} tests failed.", failed.len()); + } failed } -mod frontier_tests { +mod state_tests { use super::json_chain_test; - use tests::helpers::ChainEra; fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Frontier) + json_chain_test(json_data) } - declare_test!{StateTests_stBlockHashTest, "StateTests/stBlockHashTest"} - declare_test!{StateTests_stCallCodes, "StateTests/stCallCodes"} - declare_test!{StateTests_stCallCreateCallCodeTest, "StateTests/stCallCreateCallCodeTest"} - declare_test!{StateTests_stExample, "StateTests/stExample"} - declare_test!{StateTests_stInitCodeTest, "StateTests/stInitCodeTest"} - declare_test!{StateTests_stLogTests, "StateTests/stLogTests"} - declare_test!{heavy => StateTests_stMemoryStressTest, "StateTests/stMemoryStressTest"} - declare_test!{heavy => StateTests_stMemoryTest, "StateTests/stMemoryTest"} - declare_test!{StateTests_stPreCompiledContracts, "StateTests/stPreCompiledContracts"} - declare_test!{heavy => StateTests_stQuadraticComplexityTest, "StateTests/stQuadraticComplexityTest"} - declare_test!{StateTests_stRecursiveCreate, "StateTests/stRecursiveCreate"} - declare_test!{StateTests_stRefundTest, "StateTests/stRefundTest"} - declare_test!{StateTests_stSolidityTest, "StateTests/stSolidityTest"} - declare_test!{StateTests_stSpecialTest, "StateTests/stSpecialTest"} - declare_test!{StateTests_stSystemOperationsTest, "StateTests/stSystemOperationsTest"} - declare_test!{StateTests_stTransactionTest, "StateTests/stTransactionTest"} - declare_test!{StateTests_stTransitionTest, "StateTests/stTransitionTest"} - declare_test!{StateTests_stWalletTest, "StateTests/stWalletTest"} - - declare_test!{StateTests_RandomTests_st201503121803PYTHON, "StateTests/RandomTests/st201503121803PYTHON"} - declare_test!{StateTests_RandomTests_st201503121806PYTHON, "StateTests/RandomTests/st201503121806PYTHON"} - declare_test!{StateTests_RandomTests_st201503121848GO, "StateTests/RandomTests/st201503121848GO"} - declare_test!{StateTests_RandomTests_st201503121849GO, "StateTests/RandomTests/st201503121849GO"} - declare_test!{StateTests_RandomTests_st201503121850GO, "StateTests/RandomTests/st201503121850GO"} - declare_test!{StateTests_RandomTests_st201503121851GO, "StateTests/RandomTests/st201503121851GO"} - declare_test!{StateTests_RandomTests_st201503121953GO, "StateTests/RandomTests/st201503121953GO"} - declare_test!{StateTests_RandomTests_st201503122023GO, "StateTests/RandomTests/st201503122023GO"} - declare_test!{StateTests_RandomTests_st201503122023PYTHON, "StateTests/RandomTests/st201503122023PYTHON"} - declare_test!{StateTests_RandomTests_st201503122027GO, "StateTests/RandomTests/st201503122027GO"} - declare_test!{StateTests_RandomTests_st201503122054GO, "StateTests/RandomTests/st201503122054GO"} - declare_test!{StateTests_RandomTests_st201503122055GO, "StateTests/RandomTests/st201503122055GO"} - declare_test!{StateTests_RandomTests_st201503122115CPPJIT, "StateTests/RandomTests/st201503122115CPPJIT"} - declare_test!{StateTests_RandomTests_st201503122115GO, "StateTests/RandomTests/st201503122115GO"} - declare_test!{StateTests_RandomTests_st201503122123GO, "StateTests/RandomTests/st201503122123GO"} - declare_test!{StateTests_RandomTests_st201503122124GO, "StateTests/RandomTests/st201503122124GO"} - declare_test!{StateTests_RandomTests_st201503122128PYTHON, "StateTests/RandomTests/st201503122128PYTHON"} - declare_test!{StateTests_RandomTests_st201503122140GO, "StateTests/RandomTests/st201503122140GO"} - declare_test!{StateTests_RandomTests_st201503122159GO, "StateTests/RandomTests/st201503122159GO"} - declare_test!{StateTests_RandomTests_st201503122204GO, "StateTests/RandomTests/st201503122204GO"} - declare_test!{StateTests_RandomTests_st201503122212GO, "StateTests/RandomTests/st201503122212GO"} - declare_test!{StateTests_RandomTests_st201503122231GO, "StateTests/RandomTests/st201503122231GO"} - declare_test!{StateTests_RandomTests_st201503122238GO, "StateTests/RandomTests/st201503122238GO"} - declare_test!{StateTests_RandomTests_st201503122252GO, "StateTests/RandomTests/st201503122252GO"} - declare_test!{StateTests_RandomTests_st201503122316GO, "StateTests/RandomTests/st201503122316GO"} - declare_test!{StateTests_RandomTests_st201503122324GO, "StateTests/RandomTests/st201503122324GO"} - declare_test!{StateTests_RandomTests_st201503122358GO, "StateTests/RandomTests/st201503122358GO"} - declare_test!{StateTests_RandomTests_st201503130002GO, "StateTests/RandomTests/st201503130002GO"} - declare_test!{StateTests_RandomTests_st201503130005GO, "StateTests/RandomTests/st201503130005GO"} - declare_test!{StateTests_RandomTests_st201503130007GO, "StateTests/RandomTests/st201503130007GO"} - declare_test!{StateTests_RandomTests_st201503130010GO, "StateTests/RandomTests/st201503130010GO"} - declare_test!{StateTests_RandomTests_st201503130023PYTHON, "StateTests/RandomTests/st201503130023PYTHON"} - declare_test!{StateTests_RandomTests_st201503130059GO, "StateTests/RandomTests/st201503130059GO"} - declare_test!{StateTests_RandomTests_st201503130101GO, "StateTests/RandomTests/st201503130101GO"} - declare_test!{StateTests_RandomTests_st201503130109GO, "StateTests/RandomTests/st201503130109GO"} - declare_test!{StateTests_RandomTests_st201503130117GO, "StateTests/RandomTests/st201503130117GO"} - declare_test!{StateTests_RandomTests_st201503130122GO, "StateTests/RandomTests/st201503130122GO"} - declare_test!{StateTests_RandomTests_st201503130156GO, "StateTests/RandomTests/st201503130156GO"} - declare_test!{StateTests_RandomTests_st201503130156PYTHON, "StateTests/RandomTests/st201503130156PYTHON"} - declare_test!{StateTests_RandomTests_st201503130207GO, "StateTests/RandomTests/st201503130207GO"} - declare_test!{StateTests_RandomTests_st201503130219CPPJIT, "StateTests/RandomTests/st201503130219CPPJIT"} - declare_test!{StateTests_RandomTests_st201503130219GO, "StateTests/RandomTests/st201503130219GO"} - declare_test!{StateTests_RandomTests_st201503130243GO, "StateTests/RandomTests/st201503130243GO"} - declare_test!{StateTests_RandomTests_st201503130246GO, "StateTests/RandomTests/st201503130246GO"} - declare_test!{StateTests_RandomTests_st201503130321GO, "StateTests/RandomTests/st201503130321GO"} - declare_test!{StateTests_RandomTests_st201503130322GO, "StateTests/RandomTests/st201503130322GO"} - declare_test!{StateTests_RandomTests_st201503130332GO, "StateTests/RandomTests/st201503130332GO"} - declare_test!{StateTests_RandomTests_st201503130359GO, "StateTests/RandomTests/st201503130359GO"} - declare_test!{StateTests_RandomTests_st201503130405GO, "StateTests/RandomTests/st201503130405GO"} - declare_test!{StateTests_RandomTests_st201503130408GO, "StateTests/RandomTests/st201503130408GO"} - declare_test!{StateTests_RandomTests_st201503130411GO, "StateTests/RandomTests/st201503130411GO"} - declare_test!{StateTests_RandomTests_st201503130431GO, "StateTests/RandomTests/st201503130431GO"} - declare_test!{StateTests_RandomTests_st201503130437GO, "StateTests/RandomTests/st201503130437GO"} - declare_test!{StateTests_RandomTests_st201503130450GO, "StateTests/RandomTests/st201503130450GO"} - declare_test!{StateTests_RandomTests_st201503130512CPPJIT, "StateTests/RandomTests/st201503130512CPPJIT"} - declare_test!{StateTests_RandomTests_st201503130512GO, "StateTests/RandomTests/st201503130512GO"} - declare_test!{StateTests_RandomTests_st201503130615GO, "StateTests/RandomTests/st201503130615GO"} - declare_test!{StateTests_RandomTests_st201503130705GO, "StateTests/RandomTests/st201503130705GO"} - declare_test!{StateTests_RandomTests_st201503130733CPPJIT, "StateTests/RandomTests/st201503130733CPPJIT"} - declare_test!{StateTests_RandomTests_st201503130733GO, "StateTests/RandomTests/st201503130733GO"} - declare_test!{StateTests_RandomTests_st201503130747GO, "StateTests/RandomTests/st201503130747GO"} - declare_test!{StateTests_RandomTests_st201503130751GO, "StateTests/RandomTests/st201503130751GO"} - declare_test!{StateTests_RandomTests_st201503130752PYTHON, "StateTests/RandomTests/st201503130752PYTHON"} - declare_test!{StateTests_RandomTests_st201503130757PYTHON, "StateTests/RandomTests/st201503130757PYTHON"} - declare_test!{StateTests_RandomTests_st201503131658GO, "StateTests/RandomTests/st201503131658GO"} - declare_test!{StateTests_RandomTests_st201503131739GO, "StateTests/RandomTests/st201503131739GO"} - declare_test!{StateTests_RandomTests_st201503131755CPPJIT, "StateTests/RandomTests/st201503131755CPPJIT"} - declare_test!{StateTests_RandomTests_st201503131755GO, "StateTests/RandomTests/st201503131755GO"} - declare_test!{StateTests_RandomTests_st201503132001CPPJIT, "StateTests/RandomTests/st201503132001CPPJIT"} - declare_test!{StateTests_RandomTests_st201503132127PYTHON, "StateTests/RandomTests/st201503132127PYTHON"} - declare_test!{StateTests_RandomTests_st201503132201CPPJIT, "StateTests/RandomTests/st201503132201CPPJIT"} - declare_test!{StateTests_RandomTests_st201503132201GO, "StateTests/RandomTests/st201503132201GO"} - declare_test!{StateTests_RandomTests_st201503132202PYTHON, "StateTests/RandomTests/st201503132202PYTHON"} - declare_test!{StateTests_RandomTests_st201503140002PYTHON, "StateTests/RandomTests/st201503140002PYTHON"} - declare_test!{StateTests_RandomTests_st201503140240PYTHON, "StateTests/RandomTests/st201503140240PYTHON"} - declare_test!{StateTests_RandomTests_st201503140522PYTHON, "StateTests/RandomTests/st201503140522PYTHON"} - declare_test!{StateTests_RandomTests_st201503140756PYTHON, "StateTests/RandomTests/st201503140756PYTHON"} - declare_test!{StateTests_RandomTests_st201503141144PYTHON, "StateTests/RandomTests/st201503141144PYTHON"} - declare_test!{StateTests_RandomTests_st201503141510PYTHON, "StateTests/RandomTests/st201503141510PYTHON"} - declare_test!{StateTests_RandomTests_st201503150427PYTHON, "StateTests/RandomTests/st201503150427PYTHON"} - declare_test!{StateTests_RandomTests_st201503150716PYTHON, "StateTests/RandomTests/st201503150716PYTHON"} - declare_test!{StateTests_RandomTests_st201503151450PYTHON, "StateTests/RandomTests/st201503151450PYTHON"} - declare_test!{StateTests_RandomTests_st201503151516PYTHON, "StateTests/RandomTests/st201503151516PYTHON"} - declare_test!{StateTests_RandomTests_st201503151753PYTHON, "StateTests/RandomTests/st201503151753PYTHON"} - declare_test!{StateTests_RandomTests_st201503152057PYTHON, "StateTests/RandomTests/st201503152057PYTHON"} - declare_test!{StateTests_RandomTests_st201503152241PYTHON, "StateTests/RandomTests/st201503152241PYTHON"} - declare_test!{StateTests_RandomTests_st201503160014PYTHON, "StateTests/RandomTests/st201503160014PYTHON"} - declare_test!{StateTests_RandomTests_st201503160733PYTHON, "StateTests/RandomTests/st201503160733PYTHON"} - declare_test!{StateTests_RandomTests_st201503170051PYTHON, "StateTests/RandomTests/st201503170051PYTHON"} - declare_test!{StateTests_RandomTests_st201503170433PYTHON, "StateTests/RandomTests/st201503170433PYTHON"} - declare_test!{StateTests_RandomTests_st201503170523PYTHON, "StateTests/RandomTests/st201503170523PYTHON"} - declare_test!{StateTests_RandomTests_st201503171108PYTHON, "StateTests/RandomTests/st201503171108PYTHON"} - declare_test!{StateTests_RandomTests_st201503181223GO, "StateTests/RandomTests/st201503181223GO"} - declare_test!{StateTests_RandomTests_st201503181225GO, "StateTests/RandomTests/st201503181225GO"} - declare_test!{StateTests_RandomTests_st201503181226CPPJIT, "StateTests/RandomTests/st201503181226CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181227CPPJIT, "StateTests/RandomTests/st201503181227CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181227GO, "StateTests/RandomTests/st201503181227GO"} - declare_test!{StateTests_RandomTests_st201503181229GO, "StateTests/RandomTests/st201503181229GO"} - declare_test!{StateTests_RandomTests_st201503181230CPPJIT, "StateTests/RandomTests/st201503181230CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181230GO, "StateTests/RandomTests/st201503181230GO"} - declare_test!{StateTests_RandomTests_st201503181231GO, "StateTests/RandomTests/st201503181231GO"} - declare_test!{StateTests_RandomTests_st201503181232CPPJIT, "StateTests/RandomTests/st201503181232CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181232GO, "StateTests/RandomTests/st201503181232GO"} - declare_test!{StateTests_RandomTests_st201503181233GO, "StateTests/RandomTests/st201503181233GO"} - declare_test!{StateTests_RandomTests_st201503181234CPPJIT, "StateTests/RandomTests/st201503181234CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181234GO, "StateTests/RandomTests/st201503181234GO"} - declare_test!{StateTests_RandomTests_st201503181235CPPJIT, "StateTests/RandomTests/st201503181235CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181235GO, "StateTests/RandomTests/st201503181235GO"} - declare_test!{StateTests_RandomTests_st201503181236GO, "StateTests/RandomTests/st201503181236GO"} - declare_test!{StateTests_RandomTests_st201503181237GO, "StateTests/RandomTests/st201503181237GO"} - declare_test!{StateTests_RandomTests_st201503181239GO, "StateTests/RandomTests/st201503181239GO"} - declare_test!{StateTests_RandomTests_st201503181241CPPJIT, "StateTests/RandomTests/st201503181241CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181241GO, "StateTests/RandomTests/st201503181241GO"} - declare_test!{StateTests_RandomTests_st201503181243GO, "StateTests/RandomTests/st201503181243GO"} - declare_test!{StateTests_RandomTests_st201503181244GO, "StateTests/RandomTests/st201503181244GO"} - declare_test!{StateTests_RandomTests_st201503181245CPPJIT, "StateTests/RandomTests/st201503181245CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181245GO, "StateTests/RandomTests/st201503181245GO"} - declare_test!{StateTests_RandomTests_st201503181246CPPJIT, "StateTests/RandomTests/st201503181246CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181246GO, "StateTests/RandomTests/st201503181246GO"} - declare_test!{StateTests_RandomTests_st201503181247GO, "StateTests/RandomTests/st201503181247GO"} - declare_test!{StateTests_RandomTests_st201503181248GO, "StateTests/RandomTests/st201503181248GO"} - declare_test!{StateTests_RandomTests_st201503181249GO, "StateTests/RandomTests/st201503181249GO"} - declare_test!{StateTests_RandomTests_st201503181250CPPJIT, "StateTests/RandomTests/st201503181250CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181250GO, "StateTests/RandomTests/st201503181250GO"} - declare_test!{StateTests_RandomTests_st201503181251GO, "StateTests/RandomTests/st201503181251GO"} - declare_test!{StateTests_RandomTests_st201503181252CPPJIT, "StateTests/RandomTests/st201503181252CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181253GO, "StateTests/RandomTests/st201503181253GO"} - declare_test!{StateTests_RandomTests_st201503181255CPPJIT, "StateTests/RandomTests/st201503181255CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181255GO, "StateTests/RandomTests/st201503181255GO"} - declare_test!{StateTests_RandomTests_st201503181257GO, "StateTests/RandomTests/st201503181257GO"} - declare_test!{StateTests_RandomTests_st201503181258CPPJIT, "StateTests/RandomTests/st201503181258CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181258GO, "StateTests/RandomTests/st201503181258GO"} - declare_test!{StateTests_RandomTests_st201503181301CPPJIT, "StateTests/RandomTests/st201503181301CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181301GO, "StateTests/RandomTests/st201503181301GO"} - declare_test!{StateTests_RandomTests_st201503181303GO, "StateTests/RandomTests/st201503181303GO"} - declare_test!{StateTests_RandomTests_st201503181304GO, "StateTests/RandomTests/st201503181304GO"} - declare_test!{StateTests_RandomTests_st201503181305GO, "StateTests/RandomTests/st201503181305GO"} - declare_test!{StateTests_RandomTests_st201503181306GO, "StateTests/RandomTests/st201503181306GO"} - declare_test!{StateTests_RandomTests_st201503181307CPPJIT, "StateTests/RandomTests/st201503181307CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181307GO, "StateTests/RandomTests/st201503181307GO"} - declare_test!{StateTests_RandomTests_st201503181308GO, "StateTests/RandomTests/st201503181308GO"} - declare_test!{StateTests_RandomTests_st201503181309GO, "StateTests/RandomTests/st201503181309GO"} - declare_test!{StateTests_RandomTests_st201503181310GO, "StateTests/RandomTests/st201503181310GO"} - declare_test!{StateTests_RandomTests_st201503181311GO, "StateTests/RandomTests/st201503181311GO"} - declare_test!{StateTests_RandomTests_st201503181313GO, "StateTests/RandomTests/st201503181313GO"} - declare_test!{StateTests_RandomTests_st201503181314GO, "StateTests/RandomTests/st201503181314GO"} - declare_test!{StateTests_RandomTests_st201503181315CPPJIT, "StateTests/RandomTests/st201503181315CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181315GO, "StateTests/RandomTests/st201503181315GO"} - declare_test!{StateTests_RandomTests_st201503181316CPPJIT, "StateTests/RandomTests/st201503181316CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181316PYTHON, "StateTests/RandomTests/st201503181316PYTHON"} - declare_test!{StateTests_RandomTests_st201503181317GO, "StateTests/RandomTests/st201503181317GO"} - declare_test!{StateTests_RandomTests_st201503181318CPPJIT, "StateTests/RandomTests/st201503181318CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181318GO, "StateTests/RandomTests/st201503181318GO"} - declare_test!{StateTests_RandomTests_st201503181319GO, "StateTests/RandomTests/st201503181319GO"} - declare_test!{StateTests_RandomTests_st201503181319PYTHON, "StateTests/RandomTests/st201503181319PYTHON"} - declare_test!{StateTests_RandomTests_st201503181322GO, "StateTests/RandomTests/st201503181322GO"} - declare_test!{StateTests_RandomTests_st201503181323CPPJIT, "StateTests/RandomTests/st201503181323CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181323GO, "StateTests/RandomTests/st201503181323GO"} - declare_test!{StateTests_RandomTests_st201503181324GO, "StateTests/RandomTests/st201503181324GO"} - declare_test!{StateTests_RandomTests_st201503181325GO, "StateTests/RandomTests/st201503181325GO"} - declare_test!{StateTests_RandomTests_st201503181326CPPJIT, "StateTests/RandomTests/st201503181326CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181326GO, "StateTests/RandomTests/st201503181326GO"} - declare_test!{StateTests_RandomTests_st201503181327GO, "StateTests/RandomTests/st201503181327GO"} - declare_test!{StateTests_RandomTests_st201503181329CPPJIT, "StateTests/RandomTests/st201503181329CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181329GO, "StateTests/RandomTests/st201503181329GO"} - declare_test!{StateTests_RandomTests_st201503181330GO, "StateTests/RandomTests/st201503181330GO"} - declare_test!{StateTests_RandomTests_st201503181332GO, "StateTests/RandomTests/st201503181332GO"} - declare_test!{StateTests_RandomTests_st201503181333GO, "StateTests/RandomTests/st201503181333GO"} - declare_test!{StateTests_RandomTests_st201503181334GO, "StateTests/RandomTests/st201503181334GO"} - declare_test!{StateTests_RandomTests_st201503181336CPPJIT, "StateTests/RandomTests/st201503181336CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181337GO, "StateTests/RandomTests/st201503181337GO"} - declare_test!{StateTests_RandomTests_st201503181338GO, "StateTests/RandomTests/st201503181338GO"} - declare_test!{StateTests_RandomTests_st201503181339CPPJIT, "StateTests/RandomTests/st201503181339CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181339GO, "StateTests/RandomTests/st201503181339GO"} - declare_test!{StateTests_RandomTests_st201503181340GO, "StateTests/RandomTests/st201503181340GO"} - declare_test!{StateTests_RandomTests_st201503181341CPPJIT, "StateTests/RandomTests/st201503181341CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181342CPPJIT, "StateTests/RandomTests/st201503181342CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181342GO, "StateTests/RandomTests/st201503181342GO"} - declare_test!{StateTests_RandomTests_st201503181345GO, "StateTests/RandomTests/st201503181345GO"} - declare_test!{StateTests_RandomTests_st201503181346GO, "StateTests/RandomTests/st201503181346GO"} - declare_test!{StateTests_RandomTests_st201503181347CPPJIT, "StateTests/RandomTests/st201503181347CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181347GO, "StateTests/RandomTests/st201503181347GO"} - declare_test!{StateTests_RandomTests_st201503181347PYTHON, "StateTests/RandomTests/st201503181347PYTHON"} - declare_test!{StateTests_RandomTests_st201503181350CPPJIT, "StateTests/RandomTests/st201503181350CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181352GO, "StateTests/RandomTests/st201503181352GO"} - declare_test!{StateTests_RandomTests_st201503181353GO, "StateTests/RandomTests/st201503181353GO"} - declare_test!{StateTests_RandomTests_st201503181354CPPJIT, "StateTests/RandomTests/st201503181354CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181354GO, "StateTests/RandomTests/st201503181354GO"} - declare_test!{StateTests_RandomTests_st201503181355GO, "StateTests/RandomTests/st201503181355GO"} - declare_test!{StateTests_RandomTests_st201503181356CPPJIT, "StateTests/RandomTests/st201503181356CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181357CPPJIT, "StateTests/RandomTests/st201503181357CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181358CPPJIT, "StateTests/RandomTests/st201503181358CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181358GO, "StateTests/RandomTests/st201503181358GO"} - declare_test!{StateTests_RandomTests_st201503181359GO, "StateTests/RandomTests/st201503181359GO"} - declare_test!{StateTests_RandomTests_st201503181402CPPJIT, "StateTests/RandomTests/st201503181402CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181403GO, "StateTests/RandomTests/st201503181403GO"} - declare_test!{StateTests_RandomTests_st201503181406CPPJIT, "StateTests/RandomTests/st201503181406CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181406GO, "StateTests/RandomTests/st201503181406GO"} - declare_test!{StateTests_RandomTests_st201503181410GO, "StateTests/RandomTests/st201503181410GO"} - declare_test!{StateTests_RandomTests_st201503181412CPPJIT, "StateTests/RandomTests/st201503181412CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181413GO, "StateTests/RandomTests/st201503181413GO"} - declare_test!{StateTests_RandomTests_st201503181415GO, "StateTests/RandomTests/st201503181415GO"} - declare_test!{StateTests_RandomTests_st201503181416GO, "StateTests/RandomTests/st201503181416GO"} - declare_test!{StateTests_RandomTests_st201503181417CPPJIT, "StateTests/RandomTests/st201503181417CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181417GO, "StateTests/RandomTests/st201503181417GO"} - declare_test!{StateTests_RandomTests_st201503181418CPPJIT, "StateTests/RandomTests/st201503181418CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181422GO, "StateTests/RandomTests/st201503181422GO"} - declare_test!{StateTests_RandomTests_st201503181423CPPJIT, "StateTests/RandomTests/st201503181423CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181424GO, "StateTests/RandomTests/st201503181424GO"} - declare_test!{StateTests_RandomTests_st201503181426CPPJIT, "StateTests/RandomTests/st201503181426CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181426GO, "StateTests/RandomTests/st201503181426GO"} - declare_test!{StateTests_RandomTests_st201503181428GO, "StateTests/RandomTests/st201503181428GO"} - declare_test!{StateTests_RandomTests_st201503181430CPPJIT, "StateTests/RandomTests/st201503181430CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181435GO, "StateTests/RandomTests/st201503181435GO"} - declare_test!{StateTests_RandomTests_st201503181436GO, "StateTests/RandomTests/st201503181436GO"} - declare_test!{StateTests_RandomTests_st201503181437CPPJIT, "StateTests/RandomTests/st201503181437CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181437GO, "StateTests/RandomTests/st201503181437GO"} - declare_test!{StateTests_RandomTests_st201503181438CPPJIT, "StateTests/RandomTests/st201503181438CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181438GO, "StateTests/RandomTests/st201503181438GO"} - declare_test!{StateTests_RandomTests_st201503181439CPPJIT, "StateTests/RandomTests/st201503181439CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181439GO, "StateTests/RandomTests/st201503181439GO"} - declare_test!{StateTests_RandomTests_st201503181439PYTHON, "StateTests/RandomTests/st201503181439PYTHON"} - declare_test!{StateTests_RandomTests_st201503181440GO, "StateTests/RandomTests/st201503181440GO"} - declare_test!{StateTests_RandomTests_st201503181441GO, "StateTests/RandomTests/st201503181441GO"} - declare_test!{StateTests_RandomTests_st201503181442GO, "StateTests/RandomTests/st201503181442GO"} - declare_test!{StateTests_RandomTests_st201503181445CPPJIT, "StateTests/RandomTests/st201503181445CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181446GO, "StateTests/RandomTests/st201503181446GO"} - declare_test!{StateTests_RandomTests_st201503181447GO, "StateTests/RandomTests/st201503181447GO"} - declare_test!{StateTests_RandomTests_st201503181450GO, "StateTests/RandomTests/st201503181450GO"} - declare_test!{StateTests_RandomTests_st201503181451CPPJIT, "StateTests/RandomTests/st201503181451CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181453GO, "StateTests/RandomTests/st201503181453GO"} - declare_test!{StateTests_RandomTests_st201503181455GO, "StateTests/RandomTests/st201503181455GO"} - declare_test!{StateTests_RandomTests_st201503181456CPPJIT, "StateTests/RandomTests/st201503181456CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181457GO, "StateTests/RandomTests/st201503181457GO"} - declare_test!{StateTests_RandomTests_st201503181458GO, "StateTests/RandomTests/st201503181458GO"} - declare_test!{StateTests_RandomTests_st201503181459GO, "StateTests/RandomTests/st201503181459GO"} - declare_test!{StateTests_RandomTests_st201503181500GO, "StateTests/RandomTests/st201503181500GO"} - declare_test!{StateTests_RandomTests_st201503181501GO, "StateTests/RandomTests/st201503181501GO"} - declare_test!{StateTests_RandomTests_st201503181503GO, "StateTests/RandomTests/st201503181503GO"} - declare_test!{StateTests_RandomTests_st201503181504GO, "StateTests/RandomTests/st201503181504GO"} - declare_test!{StateTests_RandomTests_st201503181505GO, "StateTests/RandomTests/st201503181505GO"} - declare_test!{StateTests_RandomTests_st201503181506CPPJIT, "StateTests/RandomTests/st201503181506CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181507GO, "StateTests/RandomTests/st201503181507GO"} - declare_test!{StateTests_RandomTests_st201503181509CPPJIT, "StateTests/RandomTests/st201503181509CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181509GO, "StateTests/RandomTests/st201503181509GO"} - declare_test!{StateTests_RandomTests_st201503181510GO, "StateTests/RandomTests/st201503181510GO"} - declare_test!{StateTests_RandomTests_st201503181511GO, "StateTests/RandomTests/st201503181511GO"} - declare_test!{StateTests_RandomTests_st201503181512GO, "StateTests/RandomTests/st201503181512GO"} - declare_test!{StateTests_RandomTests_st201503181513CPPJIT, "StateTests/RandomTests/st201503181513CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181513GO, "StateTests/RandomTests/st201503181513GO"} - declare_test!{StateTests_RandomTests_st201503181514CPPJIT, "StateTests/RandomTests/st201503181514CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181514GO, "StateTests/RandomTests/st201503181514GO"} - declare_test!{StateTests_RandomTests_st201503181517CPPJIT, "StateTests/RandomTests/st201503181517CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181517GO, "StateTests/RandomTests/st201503181517GO"} - declare_test!{StateTests_RandomTests_st201503181519CPPJIT, "StateTests/RandomTests/st201503181519CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181519GO, "StateTests/RandomTests/st201503181519GO"} - declare_test!{StateTests_RandomTests_st201503181520CPPJIT, "StateTests/RandomTests/st201503181520CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181520GO, "StateTests/RandomTests/st201503181520GO"} - declare_test!{StateTests_RandomTests_st201503181521GO, "StateTests/RandomTests/st201503181521GO"} - declare_test!{StateTests_RandomTests_st201503181522GO, "StateTests/RandomTests/st201503181522GO"} - declare_test!{StateTests_RandomTests_st201503181524CPPJIT, "StateTests/RandomTests/st201503181524CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181524GO, "StateTests/RandomTests/st201503181524GO"} - declare_test!{StateTests_RandomTests_st201503181526GO, "StateTests/RandomTests/st201503181526GO"} - declare_test!{StateTests_RandomTests_st201503181527GO, "StateTests/RandomTests/st201503181527GO"} - declare_test!{StateTests_RandomTests_st201503181528CPPJIT, "StateTests/RandomTests/st201503181528CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181528GO, "StateTests/RandomTests/st201503181528GO"} - declare_test!{StateTests_RandomTests_st201503181528PYTHON, "StateTests/RandomTests/st201503181528PYTHON"} - declare_test!{StateTests_RandomTests_st201503181529GO, "StateTests/RandomTests/st201503181529GO"} - declare_test!{StateTests_RandomTests_st201503181531CPPJIT, "StateTests/RandomTests/st201503181531CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181533GO, "StateTests/RandomTests/st201503181533GO"} - declare_test!{StateTests_RandomTests_st201503181534CPPJIT, "StateTests/RandomTests/st201503181534CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181534GO, "StateTests/RandomTests/st201503181534GO"} - declare_test!{StateTests_RandomTests_st201503181536CPPJIT, "StateTests/RandomTests/st201503181536CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181536GO, "StateTests/RandomTests/st201503181536GO"} - declare_test!{StateTests_RandomTests_st201503181537GO, "StateTests/RandomTests/st201503181537GO"} - declare_test!{StateTests_RandomTests_st201503181538GO, "StateTests/RandomTests/st201503181538GO"} - declare_test!{StateTests_RandomTests_st201503181539GO, "StateTests/RandomTests/st201503181539GO"} - declare_test!{StateTests_RandomTests_st201503181540CPPJIT, "StateTests/RandomTests/st201503181540CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181540PYTHON, "StateTests/RandomTests/st201503181540PYTHON"} - declare_test!{StateTests_RandomTests_st201503181543GO, "StateTests/RandomTests/st201503181543GO"} - declare_test!{StateTests_RandomTests_st201503181544CPPJIT, "StateTests/RandomTests/st201503181544CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181544GO, "StateTests/RandomTests/st201503181544GO"} - declare_test!{StateTests_RandomTests_st201503181547GO, "StateTests/RandomTests/st201503181547GO"} - declare_test!{StateTests_RandomTests_st201503181548CPPJIT, "StateTests/RandomTests/st201503181548CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181548GO, "StateTests/RandomTests/st201503181548GO"} - declare_test!{StateTests_RandomTests_st201503181551GO, "StateTests/RandomTests/st201503181551GO"} - declare_test!{StateTests_RandomTests_st201503181552CPPJIT, "StateTests/RandomTests/st201503181552CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181553GO, "StateTests/RandomTests/st201503181553GO"} - declare_test!{StateTests_RandomTests_st201503181555CPPJIT, "StateTests/RandomTests/st201503181555CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181555GO, "StateTests/RandomTests/st201503181555GO"} - declare_test!{StateTests_RandomTests_st201503181557GO, "StateTests/RandomTests/st201503181557GO"} - declare_test!{StateTests_RandomTests_st201503181559GO, "StateTests/RandomTests/st201503181559GO"} - declare_test!{StateTests_RandomTests_st201503181601CPPJIT, "StateTests/RandomTests/st201503181601CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181601GO, "StateTests/RandomTests/st201503181601GO"} - declare_test!{StateTests_RandomTests_st201503181602GO, "StateTests/RandomTests/st201503181602GO"} - declare_test!{StateTests_RandomTests_st201503181603GO, "StateTests/RandomTests/st201503181603GO"} - declare_test!{StateTests_RandomTests_st201503181604GO, "StateTests/RandomTests/st201503181604GO"} - declare_test!{StateTests_RandomTests_st201503181605GO, "StateTests/RandomTests/st201503181605GO"} - declare_test!{StateTests_RandomTests_st201503181606GO, "StateTests/RandomTests/st201503181606GO"} - declare_test!{StateTests_RandomTests_st201503181607GO, "StateTests/RandomTests/st201503181607GO"} - declare_test!{StateTests_RandomTests_st201503181608CPPJIT, "StateTests/RandomTests/st201503181608CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181608GO, "StateTests/RandomTests/st201503181608GO"} - declare_test!{StateTests_RandomTests_st201503181609GO, "StateTests/RandomTests/st201503181609GO"} - declare_test!{StateTests_RandomTests_st201503181610CPPJIT, "StateTests/RandomTests/st201503181610CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181610GO, "StateTests/RandomTests/st201503181610GO"} - declare_test!{StateTests_RandomTests_st201503181611CPPJIT, "StateTests/RandomTests/st201503181611CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181611GO, "StateTests/RandomTests/st201503181611GO"} - declare_test!{StateTests_RandomTests_st201503181612GO, "StateTests/RandomTests/st201503181612GO"} - declare_test!{StateTests_RandomTests_st201503181614CPPJIT, "StateTests/RandomTests/st201503181614CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181614GO, "StateTests/RandomTests/st201503181614GO"} - declare_test!{StateTests_RandomTests_st201503181616CPPJIT, "StateTests/RandomTests/st201503181616CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181616GO, "StateTests/RandomTests/st201503181616GO"} - declare_test!{StateTests_RandomTests_st201503181617GO, "StateTests/RandomTests/st201503181617GO"} - declare_test!{StateTests_RandomTests_st201503181618GO, "StateTests/RandomTests/st201503181618GO"} - declare_test!{StateTests_RandomTests_st201503181619GO, "StateTests/RandomTests/st201503181619GO"} - declare_test!{StateTests_RandomTests_st201503181620CPPJIT, "StateTests/RandomTests/st201503181620CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181620GO, "StateTests/RandomTests/st201503181620GO"} - declare_test!{StateTests_RandomTests_st201503181621GO, "StateTests/RandomTests/st201503181621GO"} - declare_test!{StateTests_RandomTests_st201503181625GO, "StateTests/RandomTests/st201503181625GO"} - declare_test!{StateTests_RandomTests_st201503181626CPPJIT, "StateTests/RandomTests/st201503181626CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181626GO, "StateTests/RandomTests/st201503181626GO"} - declare_test!{StateTests_RandomTests_st201503181627GO, "StateTests/RandomTests/st201503181627GO"} - declare_test!{StateTests_RandomTests_st201503181628GO, "StateTests/RandomTests/st201503181628GO"} - declare_test!{StateTests_RandomTests_st201503181629GO, "StateTests/RandomTests/st201503181629GO"} - declare_test!{StateTests_RandomTests_st201503181630CPPJIT, "StateTests/RandomTests/st201503181630CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181630GO, "StateTests/RandomTests/st201503181630GO"} - declare_test!{StateTests_RandomTests_st201503181630PYTHON, "StateTests/RandomTests/st201503181630PYTHON"} - declare_test!{StateTests_RandomTests_st201503181632GO, "StateTests/RandomTests/st201503181632GO"} - declare_test!{StateTests_RandomTests_st201503181634CPPJIT, "StateTests/RandomTests/st201503181634CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181635GO, "StateTests/RandomTests/st201503181635GO"} - declare_test!{StateTests_RandomTests_st201503181636GO, "StateTests/RandomTests/st201503181636GO"} - declare_test!{StateTests_RandomTests_st201503181638GO, "StateTests/RandomTests/st201503181638GO"} - declare_test!{StateTests_RandomTests_st201503181639CPPJIT, "StateTests/RandomTests/st201503181639CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181641GO, "StateTests/RandomTests/st201503181641GO"} - declare_test!{StateTests_RandomTests_st201503181645GO, "StateTests/RandomTests/st201503181645GO"} - declare_test!{StateTests_RandomTests_st201503181646GO, "StateTests/RandomTests/st201503181646GO"} - declare_test!{StateTests_RandomTests_st201503181647CPPJIT, "StateTests/RandomTests/st201503181647CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181649CPPJIT, "StateTests/RandomTests/st201503181649CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181650GO, "StateTests/RandomTests/st201503181650GO"} - declare_test!{StateTests_RandomTests_st201503181652CPPJIT, "StateTests/RandomTests/st201503181652CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181653GO, "StateTests/RandomTests/st201503181653GO"} - declare_test!{StateTests_RandomTests_st201503181654GO, "StateTests/RandomTests/st201503181654GO"} - declare_test!{StateTests_RandomTests_st201503181655CPPJIT, "StateTests/RandomTests/st201503181655CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181655GO, "StateTests/RandomTests/st201503181655GO"} - declare_test!{StateTests_RandomTests_st201503181656CPPJIT, "StateTests/RandomTests/st201503181656CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181656GO, "StateTests/RandomTests/st201503181656GO"} - declare_test!{StateTests_RandomTests_st201503181657GO, "StateTests/RandomTests/st201503181657GO"} - declare_test!{StateTests_RandomTests_st201503181658GO, "StateTests/RandomTests/st201503181658GO"} - declare_test!{StateTests_RandomTests_st201503181700GO, "StateTests/RandomTests/st201503181700GO"} - declare_test!{StateTests_RandomTests_st201503181702GO, "StateTests/RandomTests/st201503181702GO"} - declare_test!{StateTests_RandomTests_st201503181703CPPJIT, "StateTests/RandomTests/st201503181703CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181703GO, "StateTests/RandomTests/st201503181703GO"} - declare_test!{StateTests_RandomTests_st201503181704GO, "StateTests/RandomTests/st201503181704GO"} - declare_test!{StateTests_RandomTests_st201503181706GO, "StateTests/RandomTests/st201503181706GO"} - declare_test!{StateTests_RandomTests_st201503181709GO, "StateTests/RandomTests/st201503181709GO"} - declare_test!{StateTests_RandomTests_st201503181711CPPJIT, "StateTests/RandomTests/st201503181711CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181711GO, "StateTests/RandomTests/st201503181711GO"} - declare_test!{StateTests_RandomTests_st201503181713CPPJIT, "StateTests/RandomTests/st201503181713CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181713GO, "StateTests/RandomTests/st201503181713GO"} - declare_test!{StateTests_RandomTests_st201503181714GO, "StateTests/RandomTests/st201503181714GO"} - declare_test!{StateTests_RandomTests_st201503181715CPPJIT, "StateTests/RandomTests/st201503181715CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181715GO, "StateTests/RandomTests/st201503181715GO"} - declare_test!{StateTests_RandomTests_st201503181716GO, "StateTests/RandomTests/st201503181716GO"} - declare_test!{StateTests_RandomTests_st201503181717GO, "StateTests/RandomTests/st201503181717GO"} - declare_test!{StateTests_RandomTests_st201503181720CPPJIT, "StateTests/RandomTests/st201503181720CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181722GO, "StateTests/RandomTests/st201503181722GO"} - declare_test!{StateTests_RandomTests_st201503181723CPPJIT, "StateTests/RandomTests/st201503181723CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181723GO, "StateTests/RandomTests/st201503181723GO"} - declare_test!{StateTests_RandomTests_st201503181724CPPJIT, "StateTests/RandomTests/st201503181724CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181724GO, "StateTests/RandomTests/st201503181724GO"} - declare_test!{StateTests_RandomTests_st201503181725GO, "StateTests/RandomTests/st201503181725GO"} - declare_test!{StateTests_RandomTests_st201503181728GO, "StateTests/RandomTests/st201503181728GO"} - declare_test!{StateTests_RandomTests_st201503181729GO, "StateTests/RandomTests/st201503181729GO"} - declare_test!{StateTests_RandomTests_st201503181730GO, "StateTests/RandomTests/st201503181730GO"} - declare_test!{StateTests_RandomTests_st201503181731CPPJIT, "StateTests/RandomTests/st201503181731CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181732GO, "StateTests/RandomTests/st201503181732GO"} - declare_test!{StateTests_RandomTests_st201503181734CPPJIT, "StateTests/RandomTests/st201503181734CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181734GO, "StateTests/RandomTests/st201503181734GO"} - declare_test!{StateTests_RandomTests_st201503181735GO, "StateTests/RandomTests/st201503181735GO"} - declare_test!{StateTests_RandomTests_st201503181737CPPJIT, "StateTests/RandomTests/st201503181737CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181737GO, "StateTests/RandomTests/st201503181737GO"} - declare_test!{StateTests_RandomTests_st201503181738CPPJIT, "StateTests/RandomTests/st201503181738CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181738GO, "StateTests/RandomTests/st201503181738GO"} - declare_test!{StateTests_RandomTests_st201503181739GO, "StateTests/RandomTests/st201503181739GO"} - declare_test!{StateTests_RandomTests_st201503181740CPPJIT, "StateTests/RandomTests/st201503181740CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181740GO, "StateTests/RandomTests/st201503181740GO"} - declare_test!{StateTests_RandomTests_st201503181742CPPJIT, "StateTests/RandomTests/st201503181742CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181743GO, "StateTests/RandomTests/st201503181743GO"} - declare_test!{StateTests_RandomTests_st201503181744GO, "StateTests/RandomTests/st201503181744GO"} - declare_test!{StateTests_RandomTests_st201503181745CPPJIT, "StateTests/RandomTests/st201503181745CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181746GO, "StateTests/RandomTests/st201503181746GO"} - declare_test!{StateTests_RandomTests_st201503181747GO, "StateTests/RandomTests/st201503181747GO"} - declare_test!{StateTests_RandomTests_st201503181748GO, "StateTests/RandomTests/st201503181748GO"} - declare_test!{StateTests_RandomTests_st201503181749GO, "StateTests/RandomTests/st201503181749GO"} - declare_test!{StateTests_RandomTests_st201503181750CPPJIT, "StateTests/RandomTests/st201503181750CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181750GO, "StateTests/RandomTests/st201503181750GO"} - declare_test!{StateTests_RandomTests_st201503181752GO, "StateTests/RandomTests/st201503181752GO"} - declare_test!{StateTests_RandomTests_st201503181753CPPJIT, "StateTests/RandomTests/st201503181753CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181754CPPJIT, "StateTests/RandomTests/st201503181754CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181754GO, "StateTests/RandomTests/st201503181754GO"} - declare_test!{StateTests_RandomTests_st201503181755CPPJIT, "StateTests/RandomTests/st201503181755CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181755GO, "StateTests/RandomTests/st201503181755GO"} - declare_test!{StateTests_RandomTests_st201503181756GO, "StateTests/RandomTests/st201503181756GO"} - declare_test!{StateTests_RandomTests_st201503181757CPPJIT, "StateTests/RandomTests/st201503181757CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181757GO, "StateTests/RandomTests/st201503181757GO"} - declare_test!{StateTests_RandomTests_st201503181759GO, "StateTests/RandomTests/st201503181759GO"} - declare_test!{StateTests_RandomTests_st201503181800GO, "StateTests/RandomTests/st201503181800GO"} - declare_test!{StateTests_RandomTests_st201503181801GO, "StateTests/RandomTests/st201503181801GO"} - declare_test!{StateTests_RandomTests_st201503181802GO, "StateTests/RandomTests/st201503181802GO"} - declare_test!{StateTests_RandomTests_st201503181803CPPJIT, "StateTests/RandomTests/st201503181803CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181803GO, "StateTests/RandomTests/st201503181803GO"} - declare_test!{StateTests_RandomTests_st201503181804GO, "StateTests/RandomTests/st201503181804GO"} - declare_test!{StateTests_RandomTests_st201503181806GO, "StateTests/RandomTests/st201503181806GO"} - declare_test!{StateTests_RandomTests_st201503181808GO, "StateTests/RandomTests/st201503181808GO"} - declare_test!{StateTests_RandomTests_st201503181809CPPJIT, "StateTests/RandomTests/st201503181809CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181812CPPJIT, "StateTests/RandomTests/st201503181812CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181812GO, "StateTests/RandomTests/st201503181812GO"} - declare_test!{StateTests_RandomTests_st201503181814CPPJIT, "StateTests/RandomTests/st201503181814CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181815GO, "StateTests/RandomTests/st201503181815GO"} - declare_test!{StateTests_RandomTests_st201503181816CPPJIT, "StateTests/RandomTests/st201503181816CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181817CPPJIT, "StateTests/RandomTests/st201503181817CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181819GO, "StateTests/RandomTests/st201503181819GO"} - declare_test!{StateTests_RandomTests_st201503181821GO, "StateTests/RandomTests/st201503181821GO"} - declare_test!{StateTests_RandomTests_st201503181822GO, "StateTests/RandomTests/st201503181822GO"} - declare_test!{StateTests_RandomTests_st201503181823GO, "StateTests/RandomTests/st201503181823GO"} - declare_test!{StateTests_RandomTests_st201503181824GO, "StateTests/RandomTests/st201503181824GO"} - declare_test!{StateTests_RandomTests_st201503181825GO, "StateTests/RandomTests/st201503181825GO"} - declare_test!{StateTests_RandomTests_st201503181829GO, "StateTests/RandomTests/st201503181829GO"} - declare_test!{StateTests_RandomTests_st201503181830CPPJIT, "StateTests/RandomTests/st201503181830CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181833GO, "StateTests/RandomTests/st201503181833GO"} - declare_test!{StateTests_RandomTests_st201503181834CPPJIT, "StateTests/RandomTests/st201503181834CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181834GO, "StateTests/RandomTests/st201503181834GO"} - declare_test!{StateTests_RandomTests_st201503181837GO, "StateTests/RandomTests/st201503181837GO"} - declare_test!{StateTests_RandomTests_st201503181840GO, "StateTests/RandomTests/st201503181840GO"} - declare_test!{StateTests_RandomTests_st201503181842GO, "StateTests/RandomTests/st201503181842GO"} - declare_test!{StateTests_RandomTests_st201503181843GO, "StateTests/RandomTests/st201503181843GO"} - declare_test!{StateTests_RandomTests_st201503181844GO, "StateTests/RandomTests/st201503181844GO"} - declare_test!{StateTests_RandomTests_st201503181845GO, "StateTests/RandomTests/st201503181845GO"} - declare_test!{StateTests_RandomTests_st201503181846GO, "StateTests/RandomTests/st201503181846GO"} - declare_test!{StateTests_RandomTests_st201503181847GO, "StateTests/RandomTests/st201503181847GO"} - declare_test!{StateTests_RandomTests_st201503181848GO, "StateTests/RandomTests/st201503181848GO"} - declare_test!{StateTests_RandomTests_st201503181849GO, "StateTests/RandomTests/st201503181849GO"} - declare_test!{StateTests_RandomTests_st201503181850GO, "StateTests/RandomTests/st201503181850GO"} - declare_test!{StateTests_RandomTests_st201503181851CPPJIT, "StateTests/RandomTests/st201503181851CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181851GO, "StateTests/RandomTests/st201503181851GO"} - declare_test!{StateTests_RandomTests_st201503181852CPPJIT, "StateTests/RandomTests/st201503181852CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181854GO, "StateTests/RandomTests/st201503181854GO"} - declare_test!{StateTests_RandomTests_st201503181855CPPJIT, "StateTests/RandomTests/st201503181855CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181857PYTHON, "StateTests/RandomTests/st201503181857PYTHON"} - declare_test!{StateTests_RandomTests_st201503181859GO, "StateTests/RandomTests/st201503181859GO"} - declare_test!{StateTests_RandomTests_st201503181900GO, "StateTests/RandomTests/st201503181900GO"} - declare_test!{StateTests_RandomTests_st201503181903GO, "StateTests/RandomTests/st201503181903GO"} - declare_test!{StateTests_RandomTests_st201503181904GO, "StateTests/RandomTests/st201503181904GO"} - declare_test!{StateTests_RandomTests_st201503181906GO, "StateTests/RandomTests/st201503181906GO"} - declare_test!{StateTests_RandomTests_st201503181907GO, "StateTests/RandomTests/st201503181907GO"} - declare_test!{StateTests_RandomTests_st201503181910GO, "StateTests/RandomTests/st201503181910GO"} - declare_test!{StateTests_RandomTests_st201503181915GO, "StateTests/RandomTests/st201503181915GO"} - declare_test!{StateTests_RandomTests_st201503181919CPPJIT, "StateTests/RandomTests/st201503181919CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181919PYTHON, "StateTests/RandomTests/st201503181919PYTHON"} - declare_test!{StateTests_RandomTests_st201503181920GO, "StateTests/RandomTests/st201503181920GO"} - declare_test!{StateTests_RandomTests_st201503181922GO, "StateTests/RandomTests/st201503181922GO"} - declare_test!{StateTests_RandomTests_st201503181926GO, "StateTests/RandomTests/st201503181926GO"} - declare_test!{StateTests_RandomTests_st201503181929GO, "StateTests/RandomTests/st201503181929GO"} - declare_test!{StateTests_RandomTests_st201503181931CPPJIT, "StateTests/RandomTests/st201503181931CPPJIT"} - declare_test!{StateTests_RandomTests_st201503181931GO, "StateTests/RandomTests/st201503181931GO"} - declare_test!{StateTests_RandomTests_st201503181931PYTHON, "StateTests/RandomTests/st201503181931PYTHON"} - declare_test!{StateTests_RandomTests_st201503191646GO, "StateTests/RandomTests/st201503191646GO"} - declare_test!{StateTests_RandomTests_st201503200837JS, "StateTests/RandomTests/st201503200837JS"} - declare_test!{StateTests_RandomTests_st201503200838JS, "StateTests/RandomTests/st201503200838JS"} - declare_test!{StateTests_RandomTests_st201503200841JS, "StateTests/RandomTests/st201503200841JS"} - declare_test!{StateTests_RandomTests_st201503200848JS, "StateTests/RandomTests/st201503200848JS"} - declare_test!{StateTests_RandomTests_st201503240609JS, "StateTests/RandomTests/st201503240609JS"} - declare_test!{StateTests_RandomTests_st201503302200JS, "StateTests/RandomTests/st201503302200JS"} - declare_test!{StateTests_RandomTests_st201503302202JS, "StateTests/RandomTests/st201503302202JS"} - declare_test!{StateTests_RandomTests_st201503302206JS, "StateTests/RandomTests/st201503302206JS"} - declare_test!{StateTests_RandomTests_st201503302208JS, "StateTests/RandomTests/st201503302208JS"} - declare_test!{StateTests_RandomTests_st201503302210JS, "StateTests/RandomTests/st201503302210JS"} - declare_test!{StateTests_RandomTests_st201503302211JS, "StateTests/RandomTests/st201503302211JS"} - declare_test!{StateTests_RandomTests_st201504011535GO, "StateTests/RandomTests/st201504011535GO"} - declare_test!{StateTests_RandomTests_st201504011536GO, "StateTests/RandomTests/st201504011536GO"} - declare_test!{StateTests_RandomTests_st201504011547GO, "StateTests/RandomTests/st201504011547GO"} - declare_test!{StateTests_RandomTests_st201504011916JS, "StateTests/RandomTests/st201504011916JS"} - declare_test!{StateTests_RandomTests_st201504012130JS, "StateTests/RandomTests/st201504012130JS"} - declare_test!{StateTests_RandomTests_st201504012259JS, "StateTests/RandomTests/st201504012259JS"} - declare_test!{StateTests_RandomTests_st201504012359JS, "StateTests/RandomTests/st201504012359JS"} - declare_test!{StateTests_RandomTests_st201504020305JS, "StateTests/RandomTests/st201504020305JS"} - declare_test!{StateTests_RandomTests_st201504020400JS, "StateTests/RandomTests/st201504020400JS"} - declare_test!{StateTests_RandomTests_st201504020428JS, "StateTests/RandomTests/st201504020428JS"} - declare_test!{StateTests_RandomTests_st201504020431JS, "StateTests/RandomTests/st201504020431JS"} - declare_test!{StateTests_RandomTests_st201504020444JS, "StateTests/RandomTests/st201504020444JS"} - declare_test!{StateTests_RandomTests_st201504020538JS, "StateTests/RandomTests/st201504020538JS"} - declare_test!{StateTests_RandomTests_st201504020639JS, "StateTests/RandomTests/st201504020639JS"} - declare_test!{StateTests_RandomTests_st201504020836JS, "StateTests/RandomTests/st201504020836JS"} - declare_test!{StateTests_RandomTests_st201504020910JS, "StateTests/RandomTests/st201504020910JS"} - declare_test!{StateTests_RandomTests_st201504021057JS, "StateTests/RandomTests/st201504021057JS"} - declare_test!{StateTests_RandomTests_st201504021104JS, "StateTests/RandomTests/st201504021104JS"} - declare_test!{StateTests_RandomTests_st201504021237CPPJIT, "StateTests/RandomTests/st201504021237CPPJIT"} - declare_test!{StateTests_RandomTests_st201504021237GO, "StateTests/RandomTests/st201504021237GO"} - declare_test!{StateTests_RandomTests_st201504021237JS, "StateTests/RandomTests/st201504021237JS"} - declare_test!{StateTests_RandomTests_st201504021237PYTHON, "StateTests/RandomTests/st201504021237PYTHON"} - declare_test!{StateTests_RandomTests_st201504021949JS, "StateTests/RandomTests/st201504021949JS"} - declare_test!{StateTests_RandomTests_st201504022003CPPJIT, "StateTests/RandomTests/st201504022003CPPJIT"} - declare_test!{StateTests_RandomTests_st201504022124JS, "StateTests/RandomTests/st201504022124JS"} - declare_test!{StateTests_RandomTests_st201504030138JS, "StateTests/RandomTests/st201504030138JS"} - declare_test!{StateTests_RandomTests_st201504030646JS, "StateTests/RandomTests/st201504030646JS"} - declare_test!{StateTests_RandomTests_st201504030709JS, "StateTests/RandomTests/st201504030709JS"} - declare_test!{StateTests_RandomTests_st201504031133JS, "StateTests/RandomTests/st201504031133JS"} - declare_test!{StateTests_RandomTests_st201504031446JS, "StateTests/RandomTests/st201504031446JS"} - declare_test!{StateTests_RandomTests_st201504031841JS, "StateTests/RandomTests/st201504031841JS"} - declare_test!{StateTests_RandomTests_st201504041605JS, "StateTests/RandomTests/st201504041605JS"} - declare_test!{StateTests_RandomTests_st201504042052JS, "StateTests/RandomTests/st201504042052JS"} - declare_test!{StateTests_RandomTests_st201504042226CPPJIT, "StateTests/RandomTests/st201504042226CPPJIT"} - declare_test!{StateTests_RandomTests_st201504042355CPPJIT, "StateTests/RandomTests/st201504042355CPPJIT"} - declare_test!{StateTests_RandomTests_st201504050059JS, "StateTests/RandomTests/st201504050059JS"} - declare_test!{StateTests_RandomTests_st201504050733JS, "StateTests/RandomTests/st201504050733JS"} - declare_test!{StateTests_RandomTests_st201504051540JS, "StateTests/RandomTests/st201504051540JS"} - declare_test!{StateTests_RandomTests_st201504051944CPPJIT, "StateTests/RandomTests/st201504051944CPPJIT"} - declare_test!{StateTests_RandomTests_st201504052008CPPJIT, "StateTests/RandomTests/st201504052008CPPJIT"} - declare_test!{StateTests_RandomTests_st201504052014GO, "StateTests/RandomTests/st201504052014GO"} - declare_test!{StateTests_RandomTests_st201504052031CPPJIT, "StateTests/RandomTests/st201504052031CPPJIT"} - declare_test!{StateTests_RandomTests_st201504060057CPPJIT, "StateTests/RandomTests/st201504060057CPPJIT"} - declare_test!{StateTests_RandomTests_st201504060418CPPJIT, "StateTests/RandomTests/st201504060418CPPJIT"} - declare_test!{StateTests_RandomTests_st201504061106CPPJIT, "StateTests/RandomTests/st201504061106CPPJIT"} - declare_test!{StateTests_RandomTests_st201504061134CPPJIT, "StateTests/RandomTests/st201504061134CPPJIT"} - declare_test!{StateTests_RandomTests_st201504062033CPPJIT, "StateTests/RandomTests/st201504062033CPPJIT"} - declare_test!{StateTests_RandomTests_st201504062046CPPJIT, "StateTests/RandomTests/st201504062046CPPJIT"} - declare_test!{StateTests_RandomTests_st201504062314CPPJIT, "StateTests/RandomTests/st201504062314CPPJIT"} - declare_test!{StateTests_RandomTests_st201504070746JS, "StateTests/RandomTests/st201504070746JS"} - declare_test!{StateTests_RandomTests_st201504070816CPPJIT, "StateTests/RandomTests/st201504070816CPPJIT"} - declare_test!{StateTests_RandomTests_st201504070836CPPJIT, "StateTests/RandomTests/st201504070836CPPJIT"} - declare_test!{StateTests_RandomTests_st201504070839CPPJIT, "StateTests/RandomTests/st201504070839CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071041CPPJIT, "StateTests/RandomTests/st201504071041CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071056CPPJIT, "StateTests/RandomTests/st201504071056CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071621CPPJIT, "StateTests/RandomTests/st201504071621CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071653CPPJIT, "StateTests/RandomTests/st201504071653CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071750CPPJIT, "StateTests/RandomTests/st201504071750CPPJIT"} - declare_test!{StateTests_RandomTests_st201504071905CPPJIT, "StateTests/RandomTests/st201504071905CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080454CPPJIT, "StateTests/RandomTests/st201504080454CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080457CPPJIT, "StateTests/RandomTests/st201504080457CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080650CPPJIT, "StateTests/RandomTests/st201504080650CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080840CPPJIT, "StateTests/RandomTests/st201504080840CPPJIT"} - declare_test!{StateTests_RandomTests_st201504080948CPPJIT, "StateTests/RandomTests/st201504080948CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081100CPPJIT, "StateTests/RandomTests/st201504081100CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081134CPPJIT, "StateTests/RandomTests/st201504081134CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081138CPPJIT, "StateTests/RandomTests/st201504081138CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081611CPPJIT, "StateTests/RandomTests/st201504081611CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081841JAVA, "StateTests/RandomTests/st201504081841JAVA"} - declare_test!{StateTests_RandomTests_st201504081842JAVA, "StateTests/RandomTests/st201504081842JAVA"} - declare_test!{StateTests_RandomTests_st201504081843JAVA, "StateTests/RandomTests/st201504081843JAVA"} - declare_test!{StateTests_RandomTests_st201504081928CPPJIT, "StateTests/RandomTests/st201504081928CPPJIT"} - declare_test!{StateTests_RandomTests_st201504081953JAVA, "StateTests/RandomTests/st201504081953JAVA"} - declare_test!{StateTests_RandomTests_st201504081954JAVA, "StateTests/RandomTests/st201504081954JAVA"} - declare_test!{StateTests_RandomTests_st201504081955JAVA, "StateTests/RandomTests/st201504081955JAVA"} - declare_test!{StateTests_RandomTests_st201504081956JAVA, "StateTests/RandomTests/st201504081956JAVA"} - declare_test!{StateTests_RandomTests_st201504081957JAVA, "StateTests/RandomTests/st201504081957JAVA"} - declare_test!{StateTests_RandomTests_st201504082000JAVA, "StateTests/RandomTests/st201504082000JAVA"} - declare_test!{StateTests_RandomTests_st201504082001JAVA, "StateTests/RandomTests/st201504082001JAVA"} - declare_test!{StateTests_RandomTests_st201504082002JAVA, "StateTests/RandomTests/st201504082002JAVA"} - declare_test!{StateTests_RandomTests_st201504090553CPPJIT, "StateTests/RandomTests/st201504090553CPPJIT"} - declare_test!{StateTests_RandomTests_st201504090657CPPJIT, "StateTests/RandomTests/st201504090657CPPJIT"} - declare_test!{StateTests_RandomTests_st201504091403CPPJIT, "StateTests/RandomTests/st201504091403CPPJIT"} - declare_test!{StateTests_RandomTests_st201504091641CPPJIT, "StateTests/RandomTests/st201504091641CPPJIT"} - declare_test!{StateTests_RandomTests_st201504092303CPPJIT, "StateTests/RandomTests/st201504092303CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100125CPPJIT, "StateTests/RandomTests/st201504100125CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100215CPPJIT, "StateTests/RandomTests/st201504100215CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100226PYTHON, "StateTests/RandomTests/st201504100226PYTHON"} - declare_test!{StateTests_RandomTests_st201504100308CPPJIT, "StateTests/RandomTests/st201504100308CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100337CPPJIT, "StateTests/RandomTests/st201504100337CPPJIT"} - declare_test!{StateTests_RandomTests_st201504100341CPPJIT, "StateTests/RandomTests/st201504100341CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101009CPPJIT, "StateTests/RandomTests/st201504101009CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101150CPPJIT, "StateTests/RandomTests/st201504101150CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101223CPPJIT, "StateTests/RandomTests/st201504101223CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101338CPPJIT, "StateTests/RandomTests/st201504101338CPPJIT"} - declare_test!{StateTests_RandomTests_st201504101754PYTHON, "StateTests/RandomTests/st201504101754PYTHON"} - declare_test!{StateTests_RandomTests_st201504111554CPPJIT, "StateTests/RandomTests/st201504111554CPPJIT"} - declare_test!{StateTests_RandomTests_st201504130653JS, "StateTests/RandomTests/st201504130653JS"} - declare_test!{StateTests_RandomTests_st201504131821CPPJIT, "StateTests/RandomTests/st201504131821CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140229CPPJIT, "StateTests/RandomTests/st201504140229CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140236CPPJIT, "StateTests/RandomTests/st201504140236CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140359CPPJIT, "StateTests/RandomTests/st201504140359CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140750CPPJIT, "StateTests/RandomTests/st201504140750CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140818CPPJIT, "StateTests/RandomTests/st201504140818CPPJIT"} - declare_test!{StateTests_RandomTests_st201504140900CPPJIT, "StateTests/RandomTests/st201504140900CPPJIT"} - declare_test!{StateTests_RandomTests_st201504150854CPPJIT, "StateTests/RandomTests/st201504150854CPPJIT"} - declare_test!{StateTests_RandomTests_st201504151057CPPJIT, "StateTests/RandomTests/st201504151057CPPJIT"} - declare_test!{StateTests_RandomTests_st201504202124CPPJIT, "StateTests/RandomTests/st201504202124CPPJIT"} - declare_test!{StateTests_RandomTests_st201504210245CPPJIT, "StateTests/RandomTests/st201504210245CPPJIT"} - declare_test!{StateTests_RandomTests_st201504210957CPPJIT, "StateTests/RandomTests/st201504210957CPPJIT"} - declare_test!{StateTests_RandomTests_st201504211739CPPJIT, "StateTests/RandomTests/st201504211739CPPJIT"} - declare_test!{StateTests_RandomTests_st201504212038CPPJIT, "StateTests/RandomTests/st201504212038CPPJIT"} - declare_test!{StateTests_RandomTests_st201504230729CPPJIT, "StateTests/RandomTests/st201504230729CPPJIT"} - declare_test!{StateTests_RandomTests_st201504231639CPPJIT, "StateTests/RandomTests/st201504231639CPPJIT"} - declare_test!{StateTests_RandomTests_st201504231710CPPJIT, "StateTests/RandomTests/st201504231710CPPJIT"} - declare_test!{StateTests_RandomTests_st201504231742CPPJIT, "StateTests/RandomTests/st201504231742CPPJIT"} - declare_test!{StateTests_RandomTests_st201504232350CPPJIT, "StateTests/RandomTests/st201504232350CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240140CPPJIT, "StateTests/RandomTests/st201504240140CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240220CPPJIT, "StateTests/RandomTests/st201504240220CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240351CPPJIT, "StateTests/RandomTests/st201504240351CPPJIT"} - declare_test!{StateTests_RandomTests_st201504240817CPPJIT, "StateTests/RandomTests/st201504240817CPPJIT"} - declare_test!{StateTests_RandomTests_st201504241118CPPJIT, "StateTests/RandomTests/st201504241118CPPJIT"} - declare_test!{StateTests_RandomTests_st201505021810CPPJIT, "StateTests/RandomTests/st201505021810CPPJIT"} - declare_test!{StateTests_RandomTests_st201505050557JS, "StateTests/RandomTests/st201505050557JS"} - declare_test!{StateTests_RandomTests_st201505050929GO, "StateTests/RandomTests/st201505050929GO"} - declare_test!{StateTests_RandomTests_st201505050942PYTHON, "StateTests/RandomTests/st201505050942PYTHON"} - declare_test!{StateTests_RandomTests_st201505051004PYTHON, "StateTests/RandomTests/st201505051004PYTHON"} - declare_test!{StateTests_RandomTests_st201505051016PYTHON, "StateTests/RandomTests/st201505051016PYTHON"} - declare_test!{StateTests_RandomTests_st201505051114GO, "StateTests/RandomTests/st201505051114GO"} - declare_test!{StateTests_RandomTests_st201505051238GO, "StateTests/RandomTests/st201505051238GO"} - declare_test!{StateTests_RandomTests_st201505051249GO, "StateTests/RandomTests/st201505051249GO"} - declare_test!{StateTests_RandomTests_st201505051558PYTHON, "StateTests/RandomTests/st201505051558PYTHON"} - declare_test!{StateTests_RandomTests_st201505051611PYTHON, "StateTests/RandomTests/st201505051611PYTHON"} - declare_test!{StateTests_RandomTests_st201505051648JS, "StateTests/RandomTests/st201505051648JS"} - declare_test!{StateTests_RandomTests_st201505051710GO, "StateTests/RandomTests/st201505051710GO"} - declare_test!{StateTests_RandomTests_st201505052013GO, "StateTests/RandomTests/st201505052013GO"} - declare_test!{StateTests_RandomTests_st201505052102JS, "StateTests/RandomTests/st201505052102JS"} - declare_test!{StateTests_RandomTests_st201505052235GO, "StateTests/RandomTests/st201505052235GO"} - declare_test!{StateTests_RandomTests_st201505052238JS, "StateTests/RandomTests/st201505052238JS"} - declare_test!{StateTests_RandomTests_st201505052242PYTHON, "StateTests/RandomTests/st201505052242PYTHON"} - declare_test!{StateTests_RandomTests_st201505052343PYTHON, "StateTests/RandomTests/st201505052343PYTHON"} - declare_test!{StateTests_RandomTests_st201505060120GO, "StateTests/RandomTests/st201505060120GO"} - declare_test!{StateTests_RandomTests_st201505060121GO, "StateTests/RandomTests/st201505060121GO"} - declare_test!{StateTests_RandomTests_st201505060136PYTHON, "StateTests/RandomTests/st201505060136PYTHON"} - declare_test!{StateTests_RandomTests_st201505060646JS, "StateTests/RandomTests/st201505060646JS"} - declare_test!{StateTests_RandomTests_st201505252314CPPJIT, "StateTests/RandomTests/st201505252314CPPJIT"} - declare_test!{StateTests_RandomTests_st201505272131CPPJIT, "StateTests/RandomTests/st201505272131CPPJIT"} - declare_test!{StateTests_RandomTests_st201506040034GO, "StateTests/RandomTests/st201506040034GO"} - declare_test!{StateTests_RandomTests_st201506040157GO, "StateTests/RandomTests/st201506040157GO"} - declare_test!{StateTests_RandomTests_st201506052130GO, "StateTests/RandomTests/st201506052130GO"} - declare_test!{StateTests_RandomTests_st201506060929GO, "StateTests/RandomTests/st201506060929GO"} - declare_test!{StateTests_RandomTests_st201506061255GO, "StateTests/RandomTests/st201506061255GO"} - declare_test!{StateTests_RandomTests_st201506062331GO, "StateTests/RandomTests/st201506062331GO"} - declare_test!{StateTests_RandomTests_st201506070548GO, "StateTests/RandomTests/st201506070548GO"} - declare_test!{StateTests_RandomTests_st201506071050GO, "StateTests/RandomTests/st201506071050GO"} - declare_test!{StateTests_RandomTests_st201506071624GO, "StateTests/RandomTests/st201506071624GO"} - declare_test!{StateTests_RandomTests_st201506071819GO, "StateTests/RandomTests/st201506071819GO"} - declare_test!{StateTests_RandomTests_st201506072007GO, "StateTests/RandomTests/st201506072007GO"} - declare_test!{StateTests_RandomTests_st201506080556GO, "StateTests/RandomTests/st201506080556GO"} - declare_test!{StateTests_RandomTests_st201506080721GO, "StateTests/RandomTests/st201506080721GO"} - declare_test!{StateTests_RandomTests_st201506091836GO, "StateTests/RandomTests/st201506091836GO"} - declare_test!{StateTests_RandomTests_st201506092032GO, "StateTests/RandomTests/st201506092032GO"} - declare_test!{StateTests_RandomTests_st201506101359JS, "StateTests/RandomTests/st201506101359JS"} - declare_test!{StateTests_RandomTests_st201507030359GO, "StateTests/RandomTests/st201507030359GO"} + declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"} + declare_test!{GeneralStateTest_stBlockHashTest, "GeneralStateTests/stBlockHashTest/"} + declare_test!{GeneralStateTest_stBoundsTest, "GeneralStateTests/stBoundsTest/"} + declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"} + declare_test!{skip => [ "createJS_ExampleContract" ], GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"} + declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} + declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"} + declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} + declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"} + declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"} + declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} + declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} + declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} + declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} + declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} + declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} + declare_test!{GeneralStateTest_stLogTests, "GeneralStateTests/stLogTests/"} + declare_test!{GeneralStateTest_stMemExpandingEIP150Calls, "GeneralStateTests/stMemExpandingEIP150Calls/"} + declare_test!{heavy => GeneralStateTest_stMemoryStressTest, "GeneralStateTests/stMemoryStressTest/"} + declare_test!{GeneralStateTest_stMemoryTest, "GeneralStateTests/stMemoryTest/"} + declare_test!{GeneralStateTest_stNonZeroCallsTest, "GeneralStateTests/stNonZeroCallsTest/"} + declare_test!{GeneralStateTest_stPreCompiledContracts, "GeneralStateTests/stPreCompiledContracts/"} + declare_test!{heavy => GeneralStateTest_stQuadraticComplexityTest, "GeneralStateTests/stQuadraticComplexityTest/"} + declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"} + declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} + declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} + declare_test!{skip => [ "RevertDepthCreateAddressCollision" ], GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} + declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"} + declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"} + declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"} + declare_test!{GeneralStateTest_stSystemOperationsTest, "GeneralStateTests/stSystemOperationsTest/"} + declare_test!{GeneralStateTest_stTransactionTest, "GeneralStateTests/stTransactionTest/"} + declare_test!{GeneralStateTest_stTransitionTest, "GeneralStateTests/stTransitionTest/"} + declare_test!{GeneralStateTest_stWalletTest, "GeneralStateTests/stWalletTest/"} + declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} + declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} } + diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index fd612b994..f9716d221 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -15,21 +15,63 @@ // along with Parity. If not, see . pub use util::*; +use std::fs::{File, read_dir}; +use std::path::Path; +use std::ffi::OsString; + +pub fn run_test_path(p: &Path, skip: &[&'static str], runner: fn (json_data: &[u8]) -> Vec) { + let path = Path::new(p); + let s: HashSet = skip.iter().map(|s| { + let mut os: OsString = s.into(); + os.push(".json"); + os + }).collect(); + if path.is_dir() { + for p in read_dir(path).unwrap().filter_map(|e| { + let e = e.unwrap(); + if s.contains(&e.file_name()) { + None + } else { + Some(e.path()) + }}) { + run_test_path(&p, skip, runner) + } + } else { + let mut path = p.to_path_buf(); + path.set_extension("json"); + run_test_file(&path, runner) + } +} + +pub fn run_test_file(path: &Path, runner: fn (json_data: &[u8]) -> Vec) { + let mut data = Vec::new(); + let mut file = File::open(&path).expect("Error opening test file"); + file.read_to_end(&mut data).expect("Error reading test file"); + let results = runner(&data); + assert!(results.is_empty()); +} macro_rules! test { - ($name: expr) => { - assert!(do_json_test(include_bytes!(concat!("../../res/ethereum/tests/", $name, ".json"))).is_empty()); + ($name: expr, $skip: expr) => { + ::json_tests::test_common::run_test_path(::std::path::Path::new(concat!("res/ethereum/tests/", $name)), &$skip, do_json_test); } } #[macro_export] macro_rules! declare_test { + (skip => $arr: expr, $id: ident, $name: expr) => { + #[test] + #[allow(non_snake_case)] + fn $id() { + test!($name, $arr); + } + }; (ignore => $id: ident, $name: expr) => { #[ignore] #[test] #[allow(non_snake_case)] fn $id() { - test!($name); + test!($name, []); } }; (heavy => $id: ident, $name: expr) => { @@ -37,14 +79,14 @@ macro_rules! declare_test { #[test] #[allow(non_snake_case)] fn $id() { - test!($name); + test!($name, []); } }; ($id: ident, $name: expr) => { #[test] #[allow(non_snake_case)] fn $id() { - test!($name); + test!($name, []); } } } diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index f400180ee..a3c3c889d 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -18,35 +18,37 @@ use super::test_common::*; use evm; use ethjson; use rlp::UntrustedRlp; -use transaction::{Action, UnverifiedTransaction}; -use ethstore::ethkey::public_to_address; +use transaction::{Action, UnverifiedTransaction, SignedTransaction}; fn do_json_test(json_data: &[u8]) -> Vec { let tests = ethjson::transaction::Test::load(json_data).unwrap(); let mut failed = Vec::new(); - let old_schedule = evm::Schedule::new_frontier(); - let new_schedule = evm::Schedule::new_homestead(); + let frontier_schedule = evm::Schedule::new_frontier(); + let homestead_schedule = evm::Schedule::new_homestead(); + let metropolis_schedule = evm::Schedule::new_metropolis(); for (name, test) in tests.into_iter() { let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); }; let number: Option = test.block_number.map(Into::into); let schedule = match number { - None => &old_schedule, - Some(x) if x < 1_150_000 => &old_schedule, - Some(_) => &new_schedule + None => &frontier_schedule, + Some(x) if x < 1_150_000 => &frontier_schedule, + Some(x) if x < 3_000_000 => &homestead_schedule, + Some(_) => &metropolis_schedule }; let allow_network_id_of_one = number.map_or(false, |n| n >= 2_675_000); + let allow_unsigned = number.map_or(false, |n| n >= 3_000_000); let rlp: Vec = test.rlp.into(); let res = UntrustedRlp::new(&rlp) .as_val() .map_err(From::from) - .and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one)); + .and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one, allow_unsigned)); fail_unless(test.transaction.is_none() == res.is_err(), "Validity different"); if let (Some(tx), Some(sender)) = (test.transaction, test.sender) { let t = res.unwrap(); - fail_unless(public_to_address(&t.recover_public().unwrap()) == sender.into(), "sender mismatch"); + fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch"); let is_acceptable_network_id = match t.network_id() { None => true, Some(1) if allow_network_id_of_one => true, @@ -84,3 +86,7 @@ declare_test!{TransactionTests_Homestead_ttTransactionTestEip155VitaliksTests, " declare_test!{TransactionTests_EIP155_ttTransactionTest, "TransactionTests/EIP155/ttTransactionTest"} declare_test!{TransactionTests_EIP155_ttTransactionTestEip155VitaliksTests, "TransactionTests/EIP155/ttTransactionTestEip155VitaliksTests"} declare_test!{TransactionTests_EIP155_ttTransactionTestVRule, "TransactionTests/EIP155/ttTransactionTestVRule"} + +declare_test!{TransactionTests_Metropolis_ttMetropolisTest, "TransactionTests/Metropolis/ttMetropolisTest"} +declare_test!{TransactionTests_Metropolis_ttTransactionTest, "TransactionTests/Metropolis/ttTransactionTest"} +declare_test!{TransactionTests_Metropolis_ttTransactionTestZeroSig, "TransactionTests/Metropolis/ttTransactionTestZeroSig"} diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 8f9ed2e5f..980bdd25c 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -170,3 +170,4 @@ mod json_tests; pub use types::*; pub use executive::contract_address; +pub use evm::CreateContractAddress; diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index ac1695b52..286a89bc1 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -1048,7 +1048,7 @@ impl MinerService for Miner { Action::Call(_) => None, Action::Create => { let sender = tx.sender(); - Some(contract_address(&sender, &tx.nonce)) + Some(contract_address(self.engine.schedule(pending.header().number()).create_address, &sender, &tx.nonce, &tx.data.sha3())) } }, logs: receipt.logs.clone(), @@ -1327,6 +1327,10 @@ mod tests { } fn transaction() -> SignedTransaction { + transaction_with_network_id(2) + } + + fn transaction_with_network_id(id: u64) -> SignedTransaction { let keypair = Random.generate().unwrap(); Transaction { action: Action::Create, @@ -1335,7 +1339,7 @@ mod tests { gas: U256::from(100_000), gas_price: U256::zero(), nonce: U256::zero(), - }.sign(keypair.secret(), None) + }.sign(keypair.secret(), Some(id)) } #[test] @@ -1411,21 +1415,21 @@ mod tests { #[test] fn internal_seals_without_work() { - let miner = Miner::with_spec(&Spec::new_instant()); + let spec = Spec::new_instant(); + let miner = Miner::with_spec(&spec); - let c = generate_dummy_client(2); - let client = c.reference().as_ref(); + let client = generate_dummy_client(2); - assert_eq!(miner.import_external_transactions(client, vec![transaction().into()]).pop().unwrap().unwrap(), TransactionImportResult::Current); + assert_eq!(miner.import_external_transactions(&*client, vec![transaction_with_network_id(spec.network_id()).into()]).pop().unwrap().unwrap(), TransactionImportResult::Current); - miner.update_sealing(client); + miner.update_sealing(&*client); client.flush_queue(); assert!(miner.pending_block().is_none()); assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber); - assert_eq!(miner.import_own_transaction(client, PendingTransaction::new(transaction().into(), None)).unwrap(), TransactionImportResult::Current); + assert_eq!(miner.import_own_transaction(&*client, PendingTransaction::new(transaction_with_network_id(spec.network_id()).into(), None)).unwrap(), TransactionImportResult::Current); - miner.update_sealing(client); + miner.update_sealing(&*client); client.flush_queue(); assert!(miner.pending_block().is_none()); assert_eq!(client.chain_info().best_block_number, 4 as BlockNumber); diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 9051bcbcf..c258d89cb 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -57,6 +57,8 @@ pub struct CommonParams { pub eip98_transition: BlockNumber, /// Validate block receipts root. pub validate_receipts_transition: u64, + /// Number of first block where EIP-86 (Metropolis) rules begin. + pub eip86_transition: BlockNumber, } impl From for CommonParams { @@ -71,6 +73,7 @@ impl From for CommonParams { fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None }, eip98_transition: p.eip98_transition.map_or(0, Into::into), validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into), + eip86_transition: p.eip86_transition.map_or(BlockNumber::max_value(), Into::into), } } } @@ -306,6 +309,7 @@ impl Spec { call_type: CallType::None, }; let mut substate = Substate::new(); + state.kill_account(address); { let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref(), &factories.vm); if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) { @@ -391,9 +395,9 @@ mod tests { #[test] fn genesis_constructor() { + ::ethcore_logger::init_log(); let spec = Spec::new_test_constructor(); - let mut db_result = get_temp_state_db(); - let db = spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let state = State::from_existing(db.boxed_clone(), spec.state_root(), spec.engine.account_start_nonce(), Default::default()).unwrap(); let expected = H256::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); assert_eq!(state.storage_at(&Address::from_str("0000000000000000000000000000000000000005").unwrap(), &H256::zero()).unwrap(), expected); diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index b1594dd9b..639fac053 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -939,7 +939,6 @@ mod tests { use ethkey::Secret; use util::{U256, H256, Address, Hashable}; use tests::helpers::*; - use devtools::*; use env_info::EnvInfo; use spec::*; use transaction::*; @@ -955,8 +954,7 @@ mod tests { fn should_apply_create_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -998,9 +996,8 @@ mod tests { let a = Address::zero(); - let temp = RandomTempPath::new(); let mut state = { - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); assert_eq!(state.exists(&a).unwrap(), false); state.inc_nonce(&a).unwrap(); state.commit().unwrap(); @@ -1015,8 +1012,7 @@ mod tests { fn should_trace_failed_create_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1052,8 +1048,7 @@ mod tests { fn should_trace_call_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1095,8 +1090,7 @@ mod tests { fn should_trace_basic_call_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1137,8 +1131,7 @@ mod tests { fn should_trace_call_transaction_to_builtin() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1179,8 +1172,7 @@ mod tests { fn should_not_trace_subcall_transaction_to_builtin() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1222,8 +1214,7 @@ mod tests { fn should_not_trace_callcode() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1281,15 +1272,14 @@ mod tests { fn should_not_trace_delegatecall() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); info.number = 0x789b0; let engine = &*Spec::new_test().engine; - println!("schedule.have_delegate_call: {:?}", engine.schedule(&info).have_delegate_call); + println!("schedule.have_delegate_call: {:?}", engine.schedule(info.number).have_delegate_call); let t = Transaction { nonce: 0.into(), @@ -1343,8 +1333,7 @@ mod tests { fn should_trace_failed_call_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1383,8 +1372,7 @@ mod tests { fn should_trace_call_with_subcall_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1443,8 +1431,7 @@ mod tests { fn should_trace_call_with_basic_subcall_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1498,8 +1485,7 @@ mod tests { fn should_not_trace_call_with_invalid_basic_subcall_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1541,8 +1527,7 @@ mod tests { fn should_trace_failed_subcall_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1597,8 +1582,7 @@ mod tests { fn should_trace_call_with_subcall_with_subcall_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1672,8 +1656,7 @@ mod tests { fn should_trace_failed_subcall_with_subcall_transaction() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1745,8 +1728,7 @@ mod tests { fn should_trace_suicide() { init_log(); - let temp = RandomTempPath::new(); - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); let mut info = EnvInfo::default(); info.gas_limit = 1_000_000.into(); @@ -1797,9 +1779,8 @@ mod tests { #[test] fn code_from_database() { let a = Address::zero(); - let temp = RandomTempPath::new(); let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}).unwrap(); state.init_code(&a, vec![1, 2, 3]).unwrap(); assert_eq!(state.code(&a).unwrap(), Some(Arc::new([1u8, 2, 3].to_vec()))); @@ -1815,9 +1796,8 @@ mod tests { #[test] fn storage_at_from_database() { let a = Address::zero(); - let temp = RandomTempPath::new(); let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(69u64))).unwrap(); state.commit().unwrap(); state.drop() @@ -1830,9 +1810,8 @@ mod tests { #[test] fn get_from_database() { let a = Address::zero(); - let temp = RandomTempPath::new(); let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); state.inc_nonce(&a).unwrap(); state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty).unwrap(); state.commit().unwrap(); @@ -1848,8 +1827,7 @@ mod tests { #[test] fn remove() { let a = Address::zero(); - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); assert_eq!(state.exists(&a).unwrap(), false); assert_eq!(state.exists_and_not_null(&a).unwrap(), false); state.inc_nonce(&a).unwrap(); @@ -1865,8 +1843,7 @@ mod tests { #[test] fn empty_account_is_not_created() { let a = Address::zero(); - let path = RandomTempPath::new(); - let db = get_temp_state_db_in(path.as_path()); + let db = get_temp_state_db(); let (root, db) = { let mut state = State::new(db, U256::from(0), Default::default()); state.add_balance(&a, &U256::default(), CleanupMode::NoEmpty).unwrap(); // create an empty account @@ -1881,8 +1858,7 @@ mod tests { #[test] fn empty_account_exists_when_creation_forced() { let a = Address::zero(); - let path = RandomTempPath::new(); - let db = get_temp_state_db_in(path.as_path()); + let db = get_temp_state_db(); let (root, db) = { let mut state = State::new(db, U256::from(0), Default::default()); state.add_balance(&a, &U256::default(), CleanupMode::ForceCreate).unwrap(); // create an empty account @@ -1897,9 +1873,8 @@ mod tests { #[test] fn remove_from_database() { let a = Address::zero(); - let temp = RandomTempPath::new(); let (root, db) = { - let mut state = get_temp_state_in(temp.as_path()); + let mut state = get_temp_state(); state.inc_nonce(&a).unwrap(); state.commit().unwrap(); assert_eq!(state.exists(&a).unwrap(), true); @@ -1925,8 +1900,7 @@ mod tests { #[test] fn alter_balance() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); let a = Address::zero(); let b = 1u64.into(); state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty).unwrap(); @@ -1947,8 +1921,7 @@ mod tests { #[test] fn alter_nonce() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); let a = Address::zero(); state.inc_nonce(&a).unwrap(); assert_eq!(state.nonce(&a).unwrap(), U256::from(1u64)); @@ -1964,8 +1937,7 @@ mod tests { #[test] fn balance_nonce() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); let a = Address::zero(); assert_eq!(state.balance(&a).unwrap(), U256::from(0u64)); assert_eq!(state.nonce(&a).unwrap(), U256::from(0u64)); @@ -1976,8 +1948,7 @@ mod tests { #[test] fn ensure_cached() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); let a = Address::zero(); state.require(&a, false).unwrap(); state.commit().unwrap(); @@ -1986,8 +1957,7 @@ mod tests { #[test] fn checkpoint_basic() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); let a = Address::zero(); state.checkpoint(); state.add_balance(&a, &U256::from(69u64), CleanupMode::NoEmpty).unwrap(); @@ -2003,8 +1973,7 @@ mod tests { #[test] fn checkpoint_nested() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); let a = Address::zero(); state.checkpoint(); state.checkpoint(); @@ -2018,16 +1987,14 @@ mod tests { #[test] fn create_empty() { - let mut state_result = get_temp_state(); - let mut state = state_result.reference_mut(); + let mut state = get_temp_state(); state.commit().unwrap(); assert_eq!(state.root().hex(), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); } #[test] fn should_not_panic_on_state_diff_with_storage() { - let state = get_temp_state(); - let mut state = state.reference().clone(); + let mut state = get_temp_state(); let a: Address = 0xa.into(); state.init_code(&a, b"abcdefg".to_vec()).unwrap();; diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs index 2831d2f9b..6bf8bbd8e 100644 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -463,8 +463,7 @@ mod tests { fn state_db_smoke() { init_log(); - let mut state_db_result = get_temp_state_db(); - let state_db = state_db_result.take(); + let state_db = get_temp_state_db(); let root_parent = H256::random(); let address = Address::random(); let h0 = H256::random(); diff --git a/ethcore/src/tests/client.rs b/ethcore/src/tests/client.rs index 7d630fbee..02db15617 100644 --- a/ethcore/src/tests/client.rs +++ b/ethcore/src/tests/client.rs @@ -72,8 +72,7 @@ fn should_return_registrar() { #[test] fn returns_state_root_basic() { - let client_result = generate_dummy_client(6); - let client = client_result.reference(); + let client = generate_dummy_client(6); let test_spec = get_test_spec(); let genesis_header = test_spec.genesis_header(); @@ -125,8 +124,7 @@ fn query_none_block() { #[test] fn query_bad_block() { - let client_result = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]); - let client = client_result.reference(); + let client = get_test_client_with_blocks(vec![get_bad_state_dummy_block()]); let bad_block: Option<_> = client.block_header(BlockId::Number(1)); assert!(bad_block.is_none()); @@ -135,8 +133,7 @@ fn query_bad_block() { #[test] fn returns_chain_info() { let dummy_block = get_good_dummy_block(); - let client_result = get_test_client_with_blocks(vec![dummy_block.clone()]); - let client = client_result.reference(); + let client = get_test_client_with_blocks(vec![dummy_block.clone()]); let block = BlockView::new(&dummy_block); let info = client.chain_info(); assert_eq!(info.best_block_hash, block.header().hash()); @@ -145,8 +142,7 @@ fn returns_chain_info() { #[test] fn returns_logs() { let dummy_block = get_good_dummy_block(); - let client_result = get_test_client_with_blocks(vec![dummy_block.clone()]); - let client = client_result.reference(); + let client = get_test_client_with_blocks(vec![dummy_block.clone()]); let logs = client.logs(Filter { from_block: BlockId::Earliest, to_block: BlockId::Latest, @@ -160,14 +156,13 @@ fn returns_logs() { #[test] fn returns_logs_with_limit() { let dummy_block = get_good_dummy_block(); - let client_result = get_test_client_with_blocks(vec![dummy_block.clone()]); - let client = client_result.reference(); + let client = get_test_client_with_blocks(vec![dummy_block.clone()]); let logs = client.logs(Filter { from_block: BlockId::Earliest, to_block: BlockId::Latest, address: None, topics: vec![], - limit: Some(2), + limit: None, }); assert_eq!(logs.len(), 0); } @@ -175,8 +170,7 @@ fn returns_logs_with_limit() { #[test] fn returns_block_body() { let dummy_block = get_good_dummy_block(); - let client_result = get_test_client_with_blocks(vec![dummy_block.clone()]); - let client = client_result.reference(); + let client = get_test_client_with_blocks(vec![dummy_block.clone()]); let block = BlockView::new(&dummy_block); let body = client.block_body(BlockId::Hash(block.header().hash())).unwrap(); let body = body.rlp(); @@ -187,8 +181,7 @@ fn returns_block_body() { #[test] fn imports_block_sequence() { - let client_result = generate_dummy_client(6); - let client = client_result.reference(); + let client = generate_dummy_client(6); let block = client.block_header(BlockId::Number(5)).unwrap(); assert!(!block.into_inner().is_empty()); @@ -196,8 +189,7 @@ fn imports_block_sequence() { #[test] fn can_collect_garbage() { - let client_result = generate_dummy_client(100); - let client = client_result.reference(); + let client = generate_dummy_client(100); client.tick(); assert!(client.blockchain_cache_info().blocks < 100 * 1024); } @@ -205,19 +197,16 @@ fn can_collect_garbage() { #[test] fn can_generate_gas_price_median() { - let client_result = generate_dummy_client_with_data(3, 1, slice_into![1, 2, 3]); - let client = client_result.reference(); + let client = generate_dummy_client_with_data(3, 1, slice_into![1, 2, 3]); assert_eq!(Some(&U256::from(2)), client.gas_price_corpus(3).median()); - let client_result = generate_dummy_client_with_data(4, 1, slice_into![1, 4, 3, 2]); - let client = client_result.reference(); + let client = generate_dummy_client_with_data(4, 1, slice_into![1, 4, 3, 2]); assert_eq!(Some(&U256::from(3)), client.gas_price_corpus(3).median()); } #[test] fn can_generate_gas_price_histogram() { - let client_result = generate_dummy_client_with_data(20, 1, slice_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]); - let client = client_result.reference(); + let client = generate_dummy_client_with_data(20, 1, slice_into![6354,8593,6065,4842,7845,7002,689,4958,4250,6098,5804,4320,643,8895,2296,8589,7145,2000,2512,1408]); let hist = client.gas_price_corpus(20).histogram(5).unwrap(); let correct_hist = ::stats::Histogram { bucket_bounds: vec_into![643, 2294, 3945, 5596, 7247, 8898], counts: vec![4,2,4,6,4] }; @@ -226,32 +215,29 @@ fn can_generate_gas_price_histogram() { #[test] fn empty_gas_price_histogram() { - let client_result = generate_dummy_client_with_data(20, 0, slice_into![]); - let client = client_result.reference(); + let client = generate_dummy_client_with_data(20, 0, slice_into![]); assert!(client.gas_price_corpus(20).histogram(5).is_none()); } #[test] fn corpus_is_sorted() { - let client_result = generate_dummy_client_with_data(2, 1, slice_into![U256::from_str("11426908979").unwrap(), U256::from_str("50426908979").unwrap()]); - let client = client_result.reference(); + let client = generate_dummy_client_with_data(2, 1, slice_into![U256::from_str("11426908979").unwrap(), U256::from_str("50426908979").unwrap()]); let corpus = client.gas_price_corpus(20); assert!(corpus[0] < corpus[1]); } #[test] fn can_handle_long_fork() { - let client_result = generate_dummy_client(1200); - let client = client_result.reference(); + let client = generate_dummy_client(1200); for _ in 0..20 { client.import_verified_blocks(); } assert_eq!(1200, client.chain_info().best_block_number); - push_blocks_to_client(client, 45, 1201, 800); - push_blocks_to_client(client, 49, 1201, 800); - push_blocks_to_client(client, 53, 1201, 600); + push_blocks_to_client(&client, 45, 1201, 800); + push_blocks_to_client(&client, 49, 1201, 800); + push_blocks_to_client(&client, 53, 1201, 600); for _ in 0..400 { client.import_verified_blocks(); @@ -262,8 +248,7 @@ fn can_handle_long_fork() { #[test] fn can_mine() { let dummy_blocks = get_good_dummy_block_seq(2); - let client_result = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]); - let client = client_result.reference(); + let client = get_test_client_with_blocks(vec![dummy_blocks[0].clone()]); let b = client.prepare_open_block(Address::default(), (3141562.into(), 31415620.into()), vec![]).close(); @@ -329,14 +314,13 @@ fn does_not_propagate_delayed_transactions() { value: 0.into(), data: Vec::new(), }.sign(secret, None), None); - let client_result = generate_dummy_client(1); - let client = client_result.reference(); + let client = generate_dummy_client(1); - client.miner().import_own_transaction(&**client, tx0).unwrap(); - client.miner().import_own_transaction(&**client, tx1).unwrap(); + client.miner().import_own_transaction(&*client, tx0).unwrap(); + client.miner().import_own_transaction(&*client, tx1).unwrap(); assert_eq!(0, client.ready_transactions().len()); assert_eq!(2, client.miner().pending_transactions().len()); - push_blocks_to_client(client, 53, 2, 2); + push_blocks_to_client(&client, 53, 2, 2); client.flush_queue(); assert_eq!(2, client.ready_transactions().len()); assert_eq!(2, client.miner().pending_transactions().len()); @@ -346,8 +330,7 @@ fn does_not_propagate_delayed_transactions() { fn transaction_proof() { use ::client::ProvingBlockChainClient; - let client_result = generate_dummy_client(0); - let client = client_result.reference(); + let client = generate_dummy_client(0); let address = Address::random(); let test_spec = Spec::new_test(); for _ in 0..20 { diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 2f55fd581..548187e48 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -27,10 +27,8 @@ use builtin::Builtin; use state::*; use evm::Schedule; use engines::Engine; -use env_info::EnvInfo; use ethereum; use ethereum::ethash::EthashParams; -use devtools::*; use miner::Miner; use header::Header; use transaction::{Action, Transaction, SignedTransaction}; @@ -42,7 +40,7 @@ pub enum ChainEra { Frontier, Homestead, Eip150, - Eip161, + _Eip161, TransitionTest, } @@ -73,7 +71,7 @@ impl Engine for TestEngine { self.engine.builtins() } - fn schedule(&self, _env_info: &EnvInfo) -> Schedule { + fn schedule(&self, _block_number: u64) -> Schedule { let mut schedule = Schedule::new_frontier(); schedule.max_depth = self.max_depth; schedule @@ -133,28 +131,26 @@ pub fn create_test_block_with_data(header: &Header, transactions: &[SignedTransa rlp.out() } -pub fn generate_dummy_client(block_number: u32) -> GuardedTempResult> { +pub fn generate_dummy_client(block_number: u32) -> Arc { generate_dummy_client_with_spec_and_data(Spec::new_test, block_number, 0, &[]) } -pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> { +pub fn generate_dummy_client_with_data(block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc { generate_dummy_client_with_spec_and_data(Spec::new_null, block_number, txs_per_block, tx_gas_prices) } -pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> where F: Fn()->Spec { +pub fn generate_dummy_client_with_spec_and_data(get_test_spec: F, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { generate_dummy_client_with_spec_accounts_and_data(get_test_spec, None, block_number, txs_per_block, tx_gas_prices) } -pub fn generate_dummy_client_with_spec_and_accounts(get_test_spec: F, accounts: Option>) -> GuardedTempResult> where F: Fn()->Spec { +pub fn generate_dummy_client_with_spec_and_accounts(get_test_spec: F, accounts: Option>) -> Arc where F: Fn()->Spec { generate_dummy_client_with_spec_accounts_and_data(get_test_spec, accounts, 0, 0, &[]) } -pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, accounts: Option>, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> GuardedTempResult> where F: Fn()->Spec { - let dir = RandomTempPath::new(); +pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, accounts: Option>, block_number: u32, txs_per_block: usize, tx_gas_prices: &[U256]) -> Arc where F: Fn()->Spec { let test_spec = get_test_spec(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = new_db(); let client = Client::new( ClientConfig::default(), @@ -165,8 +161,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac ).unwrap(); let test_engine = &*test_spec.engine; - let mut db_result = get_temp_state_db(); - let mut db = test_spec.ensure_db_good(db_result.take(), &Default::default()).unwrap(); + let mut db = test_spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap(); let genesis_header = test_spec.genesis_header(); let mut rolling_timestamp = 40; @@ -205,7 +200,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac action: Action::Create, data: vec![], value: U256::zero(), - }.sign(kp.secret(), None), None).unwrap(); + }.sign(kp.secret(), Some(test_spec.network_id())), None).unwrap(); n += 1; } @@ -220,11 +215,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data(get_test_spec: F, ac } client.flush_queue(); client.import_verified_blocks(); - - GuardedTempResult::> { - _temp: dir, - result: Some(client) - } + client } pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting_number: usize, block_number: usize) { @@ -256,11 +247,9 @@ pub fn push_blocks_to_client(client: &Arc, timestamp_salt: u64, starting } } -pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { - let dir = RandomTempPath::new(); +pub fn get_test_client_with_blocks(blocks: Vec) -> Arc { let test_spec = get_test_spec(); - let db_config = DatabaseConfig::with_columns(::db::NUM_COLUMNS); - let client_db = Arc::new(Database::open(&db_config, dir.as_path().to_str().unwrap()).unwrap()); + let client_db = new_db(); let client = Client::new( ClientConfig::default(), @@ -277,23 +266,15 @@ pub fn get_test_client_with_blocks(blocks: Vec) -> GuardedTempResult> { - _temp: dir, - result: Some(client) - } + client } -fn new_db(path: &str) -> Arc { - Arc::new( - Database::open(&DatabaseConfig::with_columns(::db::NUM_COLUMNS), path) - .expect("Opening database for tests should always work.") - ) +fn new_db() -> Arc { + Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))) } -pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult { - let temp = RandomTempPath::new(); - let db = new_db(temp.as_str()); +pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain { + let db = new_db(); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); let mut batch = db.transaction(); @@ -302,16 +283,11 @@ pub fn generate_dummy_blockchain(block_number: u32) -> GuardedTempResult { - _temp: temp, - result: Some(bc) - } + bc } -pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempResult { - let temp = RandomTempPath::new(); - let db = new_db(temp.as_str()); +pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> BlockChain { + let db = new_db(); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); @@ -321,58 +297,29 @@ pub fn generate_dummy_blockchain_with_extra(block_number: u32) -> GuardedTempRes bc.commit(); } db.write(batch).unwrap(); - - GuardedTempResult:: { - _temp: temp, - result: Some(bc) - } + bc } -pub fn generate_dummy_empty_blockchain() -> GuardedTempResult { - let temp = RandomTempPath::new(); - let db = new_db(temp.as_str()); +pub fn generate_dummy_empty_blockchain() -> BlockChain { + let db = new_db(); let bc = BlockChain::new(BlockChainConfig::default(), &create_unverifiable_block(0, H256::zero()), db.clone()); - - GuardedTempResult:: { - _temp: temp, - result: Some(bc) - } + bc } -pub fn get_temp_state_db() -> GuardedTempResult { - let temp = RandomTempPath::new(); - let journal_db = get_temp_state_db_in(temp.as_path()); - - GuardedTempResult { - _temp: temp, - result: Some(journal_db) - } -} - -pub fn get_temp_state() -> GuardedTempResult> { - let temp = RandomTempPath::new(); - let journal_db = get_temp_state_db_in(temp.as_path()); - - GuardedTempResult { - _temp: temp, - result: Some(State::new(journal_db, U256::from(0), Default::default())), - } -} - -pub fn get_temp_state_db_in(path: &Path) -> StateDB { - let db = new_db(path.to_str().expect("Only valid utf8 paths for tests.")); - let journal_db = journaldb::new(db.clone(), journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); - StateDB::new(journal_db, 5 * 1024 * 1024) -} - -pub fn get_temp_state_in(path: &Path) -> State<::state_db::StateDB> { - let journal_db = get_temp_state_db_in(path); +pub fn get_temp_state() -> State<::state_db::StateDB> { + let journal_db = get_temp_state_db(); State::new(journal_db, U256::from(0), Default::default()) } +pub fn get_temp_state_db() -> StateDB { + let db = new_db(); + let journal_db = journaldb::new(db, journaldb::Algorithm::EarlyMerge, ::db::COL_STATE); + StateDB::new(journal_db, 5 * 1024 * 1024) +} + pub fn get_good_dummy_block_seq(count: usize) -> Vec { let test_spec = get_test_spec(); - get_good_dummy_block_fork_seq(1, count, &test_spec.genesis_header().hash()) + get_good_dummy_block_fork_seq(1, count, &test_spec.genesis_header().hash()) } pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_hash: &H256) -> Vec { @@ -394,7 +341,6 @@ pub fn get_good_dummy_block_fork_seq(start_number: usize, count: usize, parent_h rolling_timestamp = rolling_timestamp + 10; r.push(create_test_block(&block_header)); - } r } diff --git a/ethcore/src/types/encoded.rs b/ethcore/src/types/encoded.rs index 0a4164044..125a00fd0 100644 --- a/ethcore/src/types/encoded.rs +++ b/ethcore/src/types/encoded.rs @@ -199,6 +199,12 @@ impl Block { /// Decode to a full block. pub fn decode(&self) -> FullBlock { ::rlp::decode(&self.0) } + /// Decode the header. + pub fn decode_header(&self) -> FullHeader { self.rlp().val_at(0) } + + /// Clone the encoded header. + pub fn header(&self) -> Header { Header(self.rlp().at(0).as_raw().to_vec()) } + /// Get the rlp of this block. #[inline] pub fn rlp(&self) -> Rlp { diff --git a/ethcore/src/types/transaction.rs b/ethcore/src/types/transaction.rs index 79e27d97d..f9e9f2c47 100644 --- a/ethcore/src/types/transaction.rs +++ b/ethcore/src/types/transaction.rs @@ -19,13 +19,16 @@ use std::ops::Deref; use rlp::*; use util::sha3::Hashable; -use util::{H256, Address, U256, Bytes, HeapSizeOf}; +use util::{H256, Address, U256, Bytes, HeapSizeOf, Uint}; use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError}; use error::*; use evm::Schedule; use header::BlockNumber; use ethjson; +/// Fake address for unsigned transactions as defined by EIP-86. +pub const UNSIGNED_SENDER: Address = ::util::H160([0xff; 20]); + #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "ipc", binary)] /// Transaction action type. @@ -110,8 +113,8 @@ impl HeapSizeOf for Transaction { impl From for SignedTransaction { fn from(t: ethjson::state::Transaction) -> Self { let to: Option = t.to.into(); - let secret = Secret::from_slice(&t.secret.0).expect("Valid secret expected."); - Transaction { + let secret = t.secret.map(|s| Secret::from_slice(&s.0).expect("Valid secret expected.")); + let tx = Transaction { nonce: t.nonce.into(), gas_price: t.gas_price.into(), gas: t.gas_limit.into(), @@ -121,7 +124,11 @@ impl From for SignedTransaction { }, value: t.value.into(), data: t.data.into(), - }.sign(&secret, None) + }; + match secret { + Some(s) => tx.sign(&s, None), + None => tx.null_sign(), + } } } @@ -180,8 +187,8 @@ impl Transaction { pub fn invalid_sign(self) -> UnverifiedTransaction { UnverifiedTransaction { unsigned: self, - r: U256::default(), - s: U256::default(), + r: U256::one(), + s: U256::one(), v: 0, hash: 0.into(), }.compute_hash() @@ -192,13 +199,28 @@ impl Transaction { SignedTransaction { transaction: UnverifiedTransaction { unsigned: self, - r: U256::default(), - s: U256::default(), + r: U256::one(), + s: U256::one(), v: 0, hash: 0.into(), }.compute_hash(), sender: from, - public: Public::default(), + public: None, + } + } + + /// Add EIP-86 compatible empty signature. + pub fn null_sign(self) -> SignedTransaction { + SignedTransaction { + transaction: UnverifiedTransaction { + unsigned: self, + r: U256::zero(), + s: U256::zero(), + v: 0, + hash: 0.into(), + }.compute_hash(), + sender: UNSIGNED_SENDER, + public: None, } } @@ -276,6 +298,11 @@ impl UnverifiedTransaction { self } + /// Checks is signature is empty. + pub fn is_unsigned(&self) -> bool { + self.r.is_zero() && self.s.is_zero() + } + /// Append object with a signature into RLP stream fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) { s.begin_list(9); @@ -307,6 +334,7 @@ impl UnverifiedTransaction { /// The network ID, or `None` if this is a global transaction. pub fn network_id(&self) -> Option { match self.v { + v if self.is_unsigned() => Some(v), v if v > 36 => Some((v - 35) / 2), _ => None, } @@ -340,21 +368,33 @@ impl UnverifiedTransaction { // TODO: consider use in block validation. #[cfg(test)] #[cfg(feature = "json-tests")] - pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool) -> Result { - if require_low && !self.signature().is_low_s() { + pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool, allow_empty_signature: bool) -> Result { + let chain_id = if allow_network_id_of_one { Some(1) } else { None }; + self.verify_basic(require_low, chain_id, allow_empty_signature)?; + if !allow_empty_signature || !self.is_unsigned() { + self.recover_public()?; + } + if self.gas < U256::from(self.gas_required(&schedule)) { + return Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) + } + Ok(self) + } + + /// Verify basic signature params. Does not attempt sender recovery. + pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), Error> { + if check_low_s && !(allow_empty_signature && self.is_unsigned()) { + self.check_low_s()?; + } + // EIP-86: Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account 0. + if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) { return Err(EthkeyError::InvalidSignature.into()) } - match self.network_id() { - None => {}, - Some(1) if allow_network_id_of_one => {}, + match (self.network_id(), chain_id) { + (None, _) => {}, + (Some(n), Some(m)) if n == m => {}, _ => return Err(TransactionError::InvalidNetworkId.into()), - } - self.recover_public()?; - if self.gas < U256::from(self.gas_required(&schedule)) { - Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) - } else { - Ok(self) - } + }; + Ok(()) } } @@ -363,7 +403,7 @@ impl UnverifiedTransaction { pub struct SignedTransaction { transaction: UnverifiedTransaction, sender: Address, - public: Public, + public: Option, } impl HeapSizeOf for SignedTransaction { @@ -392,13 +432,21 @@ impl From for UnverifiedTransaction { impl SignedTransaction { /// Try to verify transaction and recover sender. pub fn new(transaction: UnverifiedTransaction) -> Result { - let public = transaction.recover_public()?; - let sender = public_to_address(&public); - Ok(SignedTransaction { - transaction: transaction, - sender: sender, - public: public, - }) + if transaction.is_unsigned() { + Ok(SignedTransaction { + transaction: transaction, + sender: UNSIGNED_SENDER, + public: None, + }) + } else { + let public = transaction.recover_public()?; + let sender = public_to_address(&public); + Ok(SignedTransaction { + transaction: transaction, + sender: sender, + public: Some(public), + }) + } } /// Returns transaction sender. @@ -407,9 +455,14 @@ impl SignedTransaction { } /// Returns a public key of the sender. - pub fn public_key(&self) -> Public { + pub fn public_key(&self) -> Option { self.public } + + /// Checks is signature is empty. + pub fn is_unsigned(&self) -> bool { + self.transaction.is_unsigned() + } } /// Signed Transaction that is a part of canon blockchain. @@ -435,6 +488,9 @@ impl LocalizedTransaction { if let Some(sender) = self.cached_sender { return sender; } + if self.is_unsigned() { + return UNSIGNED_SENDER.clone(); + } let sender = public_to_address(&self.recover_public() .expect("LocalizedTransaction is always constructed from transaction from blockchain; Blockchain only stores verified transactions; qed")); self.cached_sender = Some(sender); diff --git a/ethstore/src/account/crypto.rs b/ethstore/src/account/crypto.rs index 8c4825a22..343e44cb4 100755 --- a/ethstore/src/account/crypto.rs +++ b/ethstore/src/account/crypto.rs @@ -73,10 +73,12 @@ impl From for String { } impl Crypto { + /// Encrypt account secret pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Self { Crypto::with_plain(&*secret, password, iterations) } + /// Encrypt custom plain data pub fn with_plain(plain: &[u8], password: &str, iterations: u32) -> Self { let salt: [u8; 32] = Random::random(); let iv: [u8; 16] = Random::random(); @@ -113,6 +115,7 @@ impl Crypto { } } + /// Try to decrypt and convert result to account secret pub fn secret(&self, password: &str) -> Result { if self.ciphertext.len() > 32 { return Err(Error::InvalidSecret); @@ -122,6 +125,7 @@ impl Crypto { Ok(Secret::from_slice(&secret)?) } + /// Try to decrypt and return result as is pub fn decrypt(&self, password: &str) -> Result, Error> { let expected_len = self.ciphertext.len(); self.do_decrypt(password, expected_len) diff --git a/evmbin/src/ext.rs b/evmbin/src/ext.rs index a293ccc80..781120c36 100644 --- a/evmbin/src/ext.rs +++ b/evmbin/src/ext.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use std::collections::HashMap; use util::{U256, H256, Address, Bytes, trie}; use ethcore::client::EnvInfo; -use ethcore::evm::{self, Ext, ContractCreateResult, MessageCallResult, Schedule, CallType}; +use ethcore::evm::{self, Ext, ContractCreateResult, MessageCallResult, Schedule, CallType, CreateContractAddress}; pub struct FakeExt { schedule: Schedule, @@ -31,7 +31,7 @@ pub struct FakeExt { impl Default for FakeExt { fn default() -> Self { FakeExt { - schedule: Schedule::new_post_eip150(usize::max_value(), true, true, true), + schedule: Schedule::new_post_eip150(usize::max_value(), true, true, true, true), store: HashMap::new(), depth: 1, } @@ -68,7 +68,7 @@ impl Ext for FakeExt { unimplemented!(); } - fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8]) -> ContractCreateResult { + fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8], _address: CreateContractAddress) -> ContractCreateResult { unimplemented!(); } diff --git a/hash-fetch/src/client.rs b/hash-fetch/src/client.rs index cffc10e63..40682a89c 100644 --- a/hash-fetch/src/client.rs +++ b/hash-fetch/src/client.rs @@ -92,6 +92,7 @@ pub struct Client { contract: URLHintContract, fetch: F, remote: Remote, + random_path: Arc PathBuf + Sync + Send>, } impl Client { @@ -109,6 +110,7 @@ impl Client { contract: URLHintContract::new(contract), fetch: fetch, remote: remote, + random_path: Arc::new(random_temp_path), } } } @@ -131,6 +133,7 @@ impl HashFetch for Client { match url { Err(err) => on_done(Err(err)), Ok(url) => { + let random_path = self.random_path.clone(); let future = self.fetch.fetch(&url).then(move |result| { fn validate_hash(path: PathBuf, hash: H256, result: Result) -> Result { let response = result?; @@ -155,12 +158,12 @@ impl HashFetch for Client { } debug!(target: "fetch", "Content fetched, validating hash ({:?})", hash); - let path = random_temp_path(); + let path = random_path(); let res = validate_hash(path.clone(), hash, result); if let Err(ref err) = res { trace!(target: "fetch", "Error: {:?}", err); // Remove temporary file in case of error - let _ = fs::remove_dir_all(&path); + let _ = fs::remove_file(&path); } on_done(res); @@ -192,7 +195,7 @@ mod tests { use fetch::{self, Fetch}; use parity_reactor::Remote; use urlhint::tests::{FakeRegistrar, URLHINT}; - use super::{Error, Client, HashFetch}; + use super::{Error, Client, HashFetch, random_temp_path}; #[derive(Clone)] @@ -262,12 +265,16 @@ mod tests { let result = rx.recv().unwrap(); assert_eq!(result.unwrap_err(), Error::InvalidStatus); } + #[test] fn should_return_hash_mismatch() { // given let registrar = Arc::new(registrar()); let fetch = FakeFetch { return_success: true }; - let client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let mut client = Client::with_fetch(registrar.clone(), fetch, Remote::new_sync()); + let path = random_temp_path(); + let path2 = path.clone(); + client.random_path = Arc::new(move || path2.clone()); // when let (tx, rx) = mpsc::channel(); @@ -279,6 +286,7 @@ mod tests { let result = rx.recv().unwrap(); let hash = "0x06b0a4f426f6713234b2d4b2468640bc4e0bb72657a920ad24c5087153c593c8".into(); assert_eq!(result.unwrap_err(), Error::HashMismatch { expected: 2.into(), got: hash }); + assert!(!path.exists(), "Temporary file should be removed."); } #[test] diff --git a/js/package.json b/js/package.json index 56806ef41..07314f84d 100644 --- a/js/package.json +++ b/js/package.json @@ -1,6 +1,6 @@ { "name": "parity.js", - "version": "1.7.49", + "version": "1.7.57", "main": "release/index.js", "jsnext:main": "src/index.js", "author": "Parity Team ", diff --git a/js/src/api/api.js b/js/src/api/api.js index 5be20371e..526ecbf1b 100644 --- a/js/src/api/api.js +++ b/js/src/api/api.js @@ -55,11 +55,12 @@ export default class Api extends EventEmitter { .nodeKind() .then((nodeKind) => { if (nodeKind.availability === 'public') { - return new LocalAccountsMiddleware(transport); + return LocalAccountsMiddleware; } return null; - }); + }) + .catch(() => null); transport.addMiddleware(middleware); } diff --git a/js/src/api/local/ethkey/index.spec.js b/js/src/api/local/ethkey/index.spec.js index c727e1d51..781c49b5c 100644 --- a/js/src/api/local/ethkey/index.spec.js +++ b/js/src/api/local/ethkey/index.spec.js @@ -18,8 +18,8 @@ import { randomPhrase } from '@parity/wordlist'; import { phraseToAddress, phraseToWallet } from './'; describe('api/local/ethkey', () => { - describe.skip('phraseToAddress', function () { - this.timeout(10000); + describe('phraseToAddress', function () { + this.timeout(30000); it('generates a valid address', () => { const phrase = randomPhrase(12); @@ -37,8 +37,8 @@ describe('api/local/ethkey', () => { }); }); - describe.skip('phraseToWallet', function () { - this.timeout(10000); + describe('phraseToWallet', function () { + this.timeout(30000); it('generates a valid wallet object', () => { const phrase = randomPhrase(12); diff --git a/js/src/api/local/ethkey/worker.js b/js/src/api/local/ethkey/worker.js index 00f4a0bed..ffb99d0e8 100644 --- a/js/src/api/local/ethkey/worker.js +++ b/js/src/api/local/ethkey/worker.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -import secp256k1 from 'secp256k1/js'; +import secp256k1 from 'secp256k1'; import { keccak_256 as keccak256 } from 'js-sha3'; import { bytesToHex } from '~/api/util/format'; @@ -28,11 +28,9 @@ if (!isWorker) { } // keythereum should never be used outside of the browser -let keythereum = null; +let keythereum = require('keythereum'); if (isWorker) { - require('keythereum/dist/keythereum'); - keythereum = self.keythereum; } @@ -109,9 +107,13 @@ const actions = { }; self.onmessage = function ({ data }) { - const result = route(data); + try { + const result = route(data); - postMessage(result); + postMessage([null, result]); + } catch (err) { + postMessage([err, null]); + } }; // Emulate a web worker in Node.js @@ -119,9 +121,13 @@ class KeyWorker { postMessage (data) { // Force async setTimeout(() => { - const result = route(data); + try { + const result = route(data); - this.onmessage({ data: result }); + this.onmessage({ data: [null, result] }); + } catch (err) { + this.onmessage({ data: [err, null] }); + } }, 0); } diff --git a/js/src/api/local/ethkey/workerPool.js b/js/src/api/local/ethkey/workerPool.js index ff5315898..e4e4a5134 100644 --- a/js/src/api/local/ethkey/workerPool.js +++ b/js/src/api/local/ethkey/workerPool.js @@ -33,8 +33,15 @@ class WorkerContainer { return new Promise((resolve, reject) => { this._worker.postMessage({ action, payload }); this._worker.onmessage = ({ data }) => { + const [err, result] = data; + this.busy = false; - resolve(data); + + if (err) { + reject(err); + } else { + resolve(result); + } }; }); } diff --git a/js/src/api/local/index.js b/js/src/api/local/index.js index c1d4b60ca..1000fa330 100644 --- a/js/src/api/local/index.js +++ b/js/src/api/local/index.js @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export LocalAccountsMiddleware from './middleware'; +export LocalAccountsMiddleware from './localAccountsMiddleware'; diff --git a/js/src/api/local/middleware.js b/js/src/api/local/localAccountsMiddleware.js similarity index 94% rename from js/src/api/local/middleware.js rename to js/src/api/local/localAccountsMiddleware.js index 36a8cd2cf..753de8a4c 100644 --- a/js/src/api/local/middleware.js +++ b/js/src/api/local/localAccountsMiddleware.js @@ -23,15 +23,6 @@ import { phraseToWallet, phraseToAddress, verifySecret } from './ethkey'; import { randomPhrase } from '@parity/wordlist'; export default class LocalAccountsMiddleware extends Middleware { - // Maps transaction requests to transaction hashes. - // This allows the locally-signed transactions to emulate the signer. - transactionHashes = {}; - transactions = {}; - - // Current transaction id. This doesn't need to be stored, as it's - // only relevant for the current the session. - transactionId = 1; - constructor (transport) { super(transport); @@ -170,13 +161,27 @@ export default class LocalAccountsMiddleware extends Middleware { data } = Object.assign(transactions.get(id), modify); + transactions.lock(id); + const account = accounts.get(from); return Promise.all([ this.rpcRequest('parity_nextNonce', [from]), account.decryptPrivateKey(password) ]) + .catch((err) => { + transactions.unlock(id); + + // transaction got unlocked, can propagate rejection further + throw err; + }) .then(([nonce, privateKey]) => { + if (!privateKey) { + transactions.unlock(id); + + throw new Error('Invalid password'); + } + const tx = new EthereumTx({ nonce, to, diff --git a/js/src/api/local/localAccountsMiddleware.spec.js b/js/src/api/local/localAccountsMiddleware.spec.js new file mode 100644 index 000000000..7408b4b1e --- /dev/null +++ b/js/src/api/local/localAccountsMiddleware.spec.js @@ -0,0 +1,154 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import LocalAccountsMiddleware from './localAccountsMiddleware'; +import JsonRpcBase from '../transport/jsonRpcBase'; + +const RPC_RESPONSE = Symbol('RPC response'); +const ADDRESS = '0x00a329c0648769a73afac7f9381e08fb43dbea72'; +const SECRET = '0x4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7'; +const PASSWORD = 'password'; + +const FOO_PHRASE = 'foobar'; +const FOO_PASSWORD = 'foopass'; +const FOO_ADDRESS = '0x007ef7ac1058e5955e366ab9d6b6c4ebcc937e7e'; + +class MockedTransport extends JsonRpcBase { + _execute (method, params) { + return RPC_RESPONSE; + } +} + +describe('api/local/LocalAccountsMiddleware', function () { + this.timeout(30000); + + let transport; + + beforeEach(() => { + transport = new MockedTransport(); + transport.addMiddleware(LocalAccountsMiddleware); + + // Same as `parity_newAccountFromPhrase` with empty phrase + return transport + .execute('parity_newAccountFromSecret', SECRET, PASSWORD) + .catch((_err) => { + // Ignore the error - all instances of LocalAccountsMiddleware + // share account storage + }); + }); + + it('registers all necessary methods', () => { + return Promise + .all([ + 'eth_accounts', + 'eth_coinbase', + 'parity_accountsInfo', + 'parity_allAccountsInfo', + 'parity_changePassword', + 'parity_checkRequest', + 'parity_defaultAccount', + 'parity_generateSecretPhrase', + 'parity_getNewDappsAddresses', + 'parity_hardwareAccountsInfo', + 'parity_newAccountFromPhrase', + 'parity_newAccountFromSecret', + 'parity_setAccountMeta', + 'parity_setAccountName', + 'parity_postTransaction', + 'parity_phraseToAddress', + 'parity_useLocalAccounts', + 'parity_listGethAccounts', + 'parity_listRecentDapps', + 'parity_killAccount', + 'parity_testPassword', + 'signer_confirmRequest', + 'signer_rejectRequest', + 'signer_requestsToConfirm' + ].map((method) => { + return transport + .execute(method) + .then((result) => { + expect(result).not.to.be.equal(RPC_RESPONSE); + }) + // Some errors are expected here since we are calling methods + // without parameters. + .catch((_) => {}); + })); + }); + + it('allows non-registered methods through', () => { + return transport + .execute('eth_getBalance', '0x407d73d8a49eeb85d32cf465507dd71d507100c1') + .then((result) => { + expect(result).to.be.equal(RPC_RESPONSE); + }); + }); + + it('can handle `eth_accounts`', () => { + return transport + .execute('eth_accounts') + .then((accounts) => { + expect(accounts.length).to.be.equal(1); + expect(accounts[0]).to.be.equal(ADDRESS); + }); + }); + + it('can handle `parity_defaultAccount`', () => { + return transport + .execute('parity_defaultAccount') + .then((address) => { + expect(address).to.be.equal(ADDRESS); + }); + }); + + it('can handle `parity_phraseToAddress`', () => { + return transport + .execute('parity_phraseToAddress', '') + .then((address) => { + expect(address).to.be.equal(ADDRESS); + + return transport.execute('parity_phraseToAddress', FOO_PHRASE); + }) + .then((address) => { + expect(address).to.be.equal(FOO_ADDRESS); + }); + }); + + it('can create and kill an account', () => { + return transport + .execute('parity_newAccountFromPhrase', FOO_PHRASE, FOO_PASSWORD) + .then((address) => { + expect(address).to.be.equal(FOO_ADDRESS); + + return transport.execute('eth_accounts'); + }) + .then((accounts) => { + expect(accounts.length).to.be.equal(2); + expect(accounts.includes(FOO_ADDRESS)).to.be.true; + + return transport.execute('parity_killAccount', FOO_ADDRESS, FOO_PASSWORD); + }) + .then((result) => { + expect(result).to.be.true; + + return transport.execute('eth_accounts'); + }) + .then((accounts) => { + expect(accounts.length).to.be.equal(1); + expect(accounts.includes(FOO_ADDRESS)).to.be.false; + }); + }); +}); diff --git a/js/src/api/local/transactions.js b/js/src/api/local/transactions.js index 57d1eee62..421e73012 100644 --- a/js/src/api/local/transactions.js +++ b/js/src/api/local/transactions.js @@ -18,6 +18,7 @@ import { toHex } from '../util/format'; import { TransportError } from '../transport'; const AWAITING = Symbol('awaiting'); +const LOCKED = Symbol('locked'); const CONFIRMED = Symbol('confirmed'); const REJECTED = Symbol('rejected'); @@ -57,6 +58,26 @@ class Transactions { return state.transaction; } + lock (id) { + const state = this._states[id]; + + if (!state || state.status !== AWAITING) { + throw new Error('Trying to lock an invalid transaction'); + } + + state.status = LOCKED; + } + + unlock (id) { + const state = this._states[id]; + + if (!state || state.status !== LOCKED) { + throw new Error('Trying to unlock an invalid transaction'); + } + + state.status = AWAITING; + } + hash (id) { const state = this._states[id]; @@ -76,9 +97,12 @@ class Transactions { confirm (id, hash) { const state = this._states[id]; + const status = state ? state.status : null; - if (!state || state.status !== AWAITING) { - throw new Error('Trying to confirm an invalid transaction'); + switch (status) { + case AWAITING: break; + case LOCKED: break; + default: throw new Error('Trying to confirm an invalid transaction'); } state.hash = hash; diff --git a/js/src/api/local/transactions.spec.js b/js/src/api/local/transactions.spec.js index 84482ff57..65f2d8ddc 100644 --- a/js/src/api/local/transactions.spec.js +++ b/js/src/api/local/transactions.spec.js @@ -65,4 +65,21 @@ describe('api/local/transactions', () => { expect(requests.length).to.be.equal(0); expect(() => transactions.hash(id)).to.throw(TransportError); }); + + it('can lock and confirm transactions', () => { + const id = transactions.add(DUMMY_TX); + const hash = '0x1111111111111111111111111111111111111111'; + + transactions.lock(id); + + const requests = transactions.requestsToConfirm(); + + expect(requests.length).to.be.equal(0); + expect(transactions.get(id)).to.be.null; + expect(transactions.hash(id)).to.be.null; + + transactions.confirm(id, hash); + + expect(transactions.hash(id)).to.be.equal(hash); + }); }); diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js index f38e29e7b..16b14eaef 100644 --- a/js/src/api/rpc/parity/parity.js +++ b/js/src/api/rpc/parity/parity.js @@ -522,6 +522,11 @@ export default class Parity { .then(outNumber); } + signMessage (address, password, messageHash) { + return this._transport + .execute('parity_signMessage', inAddress(address), password, inHex(messageHash)); + } + testPassword (account, password) { return this._transport .execute('parity_testPassword', inAddress(account), password); diff --git a/js/src/api/transport/jsonRpcBase.js b/js/src/api/transport/jsonRpcBase.js index 573204c3e..819e1f496 100644 --- a/js/src/api/transport/jsonRpcBase.js +++ b/js/src/api/transport/jsonRpcBase.js @@ -38,20 +38,20 @@ export default class JsonRpcBase extends EventEmitter { return json; } - addMiddleware (middleware) { + addMiddleware (Middleware) { this._middlewareList = Promise .all([ - middleware, + Middleware, this._middlewareList ]) - .then(([middleware, middlewareList]) => { + .then(([Middleware, middlewareList]) => { // Do nothing if `handlerPromise` resolves to a null-y value. - if (middleware == null) { + if (Middleware == null) { return middlewareList; } // don't mutate the original array - return middlewareList.concat([middleware]); + return middlewareList.concat([new Middleware(this)]); }); } @@ -80,8 +80,8 @@ export default class JsonRpcBase extends EventEmitter { const res = middleware.handle(method, params); if (res != null) { - // If `res` isn't a promise, we need to wrap it - return Promise.resolve(res) + return Promise + .resolve(res) .then((res) => { const result = this._wrapSuccessResult(res); const json = this.encode(method, params); diff --git a/js/src/api/transport/middleware.js b/js/src/api/transport/middleware.js index 5a4945e7e..7d7199f95 100644 --- a/js/src/api/transport/middleware.js +++ b/js/src/api/transport/middleware.js @@ -28,9 +28,7 @@ export default class Middleware { const handler = this._handlers[method]; if (handler != null) { - const response = handler(params); - - return response; + return handler(params); } return null; diff --git a/js/src/api/transport/middleware.spec.js b/js/src/api/transport/middleware.spec.js index 27b81c49f..4ae894135 100644 --- a/js/src/api/transport/middleware.spec.js +++ b/js/src/api/transport/middleware.spec.js @@ -25,17 +25,21 @@ class MockTransport extends JsonRpcBase { } } +class MockMiddleware extends Middleware { + constructor (transport) { + super(transport); + + this.register('mock_rpc', ([num]) => num); + this.register('mock_null', () => null); + } +} + describe('api/transport/Middleware', () => { - let middleware; let transport; beforeEach(() => { transport = new MockTransport(); - middleware = new Middleware(transport); - - middleware.register('mock_rpc', ([num]) => num); - middleware.register('mock_null', () => null); - transport.addMiddleware(middleware); + transport.addMiddleware(MockMiddleware); }); it('Routes requests to middleware', () => { diff --git a/js/src/contracts/tokenreg.js b/js/src/contracts/tokenreg.js index 22e3c834d..2bbf639bf 100644 --- a/js/src/contracts/tokenreg.js +++ b/js/src/contracts/tokenreg.js @@ -27,7 +27,7 @@ export default class TokenReg { } getInstance () { - return this.getContract().instance; + return this.getContract().then((contract) => contract.instance); } tokenCount () { diff --git a/js/src/i18n/nl/account.js b/js/src/i18n/nl/account.js index 57701292a..ee211bbca 100755 --- a/js/src/i18n/nl/account.js +++ b/js/src/i18n/nl/account.js @@ -16,13 +16,17 @@ export default { button: { - delete: `verwijder account`, + delete: `verwijder`, edit: `bewerk`, + faucet: `Kovan ETH`, password: `wachtwoord`, shapeshift: `shapeshift`, transfer: `verzend`, verify: `verifieer` }, + hardware: { + confirmDelete: `Weet je zeker dat je de volgende hardware adressen van je account lijst wilt verwijderen?` + }, header: { outgoingTransactions: `{count} uitgaande transacties`, uuid: `uuid: {uuid}` diff --git a/js/src/i18n/nl/accounts.js b/js/src/i18n/nl/accounts.js index 315324632..e213bddb2 100755 --- a/js/src/i18n/nl/accounts.js +++ b/js/src/i18n/nl/accounts.js @@ -16,8 +16,8 @@ export default { button: { - newAccount: `nieuw account`, - newWallet: `nieuw wallet`, + newAccount: `account`, + newWallet: `wallet`, vaults: `kluizen` }, summary: { @@ -27,5 +27,8 @@ export default { tooltip: { actions: `voor de huidige weergave zijn koppelingen beschikbaar op de werkbalk voor snelle toegang: het uitvoeren van acties of het creëren van een nieuw item`, overview: `hier vind je een overzichtelijke weergave van je accounts, waarin je meta informatie kunt bewerken en transacties kunt uitvoeren en bekijken` + }, + tooltips: { + owner: `{name} (eigenaar)` } }; diff --git a/js/src/i18n/nl/addAddress.js b/js/src/i18n/nl/addAddress.js index 1b2281888..e048988e9 100755 --- a/js/src/i18n/nl/addAddress.js +++ b/js/src/i18n/nl/addAddress.js @@ -19,6 +19,7 @@ export default { add: `Adres Opslaan`, close: `Annuleer` }, + header: `Om een nieuwe invoer aan je adresboek toe te voegen, heb je het netwerk adres van het account nodig en kun je optioneel een beschrijving toevoegen. Zodra de nieuwe invoer is toegevoegd, zal het in je adresboek verschijnen.`, input: { address: { hint: `het netwerk adres van het item`, @@ -33,5 +34,5 @@ export default { label: `Adres Naam` } }, - label: `voeg opgeslagen adres toe` + label: `voeg een opgeslagen adres toe` }; diff --git a/js/src/i18n/nl/address.js b/js/src/i18n/nl/address.js new file mode 100644 index 000000000..fc9d2eab1 --- /dev/null +++ b/js/src/i18n/nl/address.js @@ -0,0 +1,28 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + buttons: { + edit: `bewerken`, + forget: `vergeten`, + save: `opslaan` + }, + delete: { + confirmInfo: `Weet je zeker dat je het volgende adres uit je adresboek wilt verwijderen?`, + title: `bevestig verwijderen` + }, + title: `Adres Informatie` +}; diff --git a/js/src/api/local/ethkey/dummy.js b/js/src/i18n/nl/addresses.js similarity index 81% rename from js/src/api/local/ethkey/dummy.js rename to js/src/i18n/nl/addresses.js index 38f7c84de..c16c5f234 100644 --- a/js/src/api/local/ethkey/dummy.js +++ b/js/src/i18n/nl/addresses.js @@ -14,6 +14,12 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export default function () { - // empty file included while building parity.js (don't include local keygen) -} +export default { + buttons: { + add: `adres` + }, + errors: { + invalidFile: `Het opgegeven bestand is ongeldig...` + }, + title: `Opgeslagen Adressen` +}; diff --git a/js/src/i18n/nl/application.js b/js/src/i18n/nl/application.js index 1a6b2ee5c..bcb110b88 100755 --- a/js/src/i18n/nl/application.js +++ b/js/src/i18n/nl/application.js @@ -15,6 +15,9 @@ // along with Parity. If not, see . export default { + frame: { + error: `FOUT: Deze applicatie kan niet en zou niet geladen moeten worden in een embedded iFrame` + }, status: { consensus: { capable: `Capable`, diff --git a/js/src/i18n/nl/contract.js b/js/src/i18n/nl/contract.js index 5f2ca39cc..9818f5edd 100755 --- a/js/src/i18n/nl/contract.js +++ b/js/src/i18n/nl/contract.js @@ -15,5 +15,27 @@ // along with Parity. If not, see . export default { - minedBlock: `Opgenomen in blok #{blockNumber}` + buttons: { + close: `Sluit`, + details: `details`, + edit: `bewerken`, + execute: `uitvoeren`, + forget: `vergeten` + }, + details: { + title: `contract details` + }, + events: { + eventPending: `pending`, + noEvents: `Er zijn vanuit dit contract nog geen events verzonden.`, + title: `events` + }, + minedBlock: `Opgenomen in blok #{blockNumber}`, + queries: { + buttons: { + query: `Query` + }, + title: `queries` + }, + title: `Contract Informatie` }; diff --git a/js/src/i18n/nl/contracts.js b/js/src/i18n/nl/contracts.js new file mode 100644 index 000000000..18ab842a0 --- /dev/null +++ b/js/src/i18n/nl/contracts.js @@ -0,0 +1,28 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + buttons: { + deploy: `publiceer`, + develop: `ontwikkel`, + watch: `bekijk` + }, + sortOrder: { + date: `datum`, + minedBlock: `opgenomen blok` + }, + title: `Contracten` +}; diff --git a/js/src/i18n/nl/createAccount.js b/js/src/i18n/nl/createAccount.js index 69585df35..98b7ac26b 100755 --- a/js/src/i18n/nl/createAccount.js +++ b/js/src/i18n/nl/createAccount.js @@ -20,10 +20,6 @@ export default { hint: `Het netwerk adres van het account`, label: `adres` }, - name: { - hint: `Een beschrijvende naam van het account`, - label: `account naam` - }, phrase: { hint: `De account herstel zin`, label: `Eigenaar's herstel zin (houd deze woorden veilig en prive want hiermee kun je volledige, ongelimiteerde toegang tot het account verkrijgen).` @@ -35,31 +31,38 @@ export default { button: { back: `Terug`, cancel: `Annuleer`, - close: `Sluit`, create: `Aanmaken`, + done: `Klaar`, import: `Importeer`, next: `Volgende`, print: `Herstel zin afdrukken` }, creationType: { fromGeth: { - label: `Importeer accounts uit Geth keystore` + description: `Importeer accounts uit Geth keystore met het originele wachtwoord`, + label: `Geth keystore` }, fromJSON: { - label: `Importeer account uit een opgeslagen JSON file` + description: `Importeer account uit een JSON sleutelbestand met het originele wachtwoord`, + label: `JSON bestand` }, fromNew: { - label: `Handmatig account aanmaken` + description: `Selecteer je identiteits-icoon en kies je wachtwoord`, + label: `Nieuw Account` }, fromPhrase: { - label: `Herstel account met een herstel zin` + description: `Herstel je account met een eerder bewaarde herstel zin en een nieuw wachtwoord`, + label: `Herstel zin` }, fromPresale: { - label: `Importeer account van een Ethereum voor-verkoop (pre-sale) wallet` + description: `Importeer een Ethereum voor-verkoop (pre-sale) wallet bestand met het originele wachtwoord`, + label: `voor-verkoop wallet` }, fromRaw: { - label: `Importeer een prive sleutel (raw private key)` - } + description: `Importeer een eerder gemaakte prive sleutel (raw private key) met een nieuw wachtwoord`, + label: `Prive sleutel` + }, + info: `Selecteer de manier waarop je je account wilt aanmaken of importeren. Maak een nieuw account aan met een naam en wachtwoord, of importeer/herstel een bestaand account vanuit verschillende bronnen zoals een herstel zin of een sleutelbestand. Met behulp van deze wizard word je door het proces begeleid om een account aan te maken.` }, newAccount: { hint: { @@ -80,6 +83,7 @@ export default { } }, newGeth: { + available: `Er zijn momenteel {count} importeerbare sleutels (keys) beschikbaar vanuit Geth keystore, welke nog niet in je Parity installatie beschikbaar zijn. Selecteer de accounts die je wilt importeren en ga verder naar de volgende stap om het importeren te voltooien.`, noKeys: `Er zijn momenteel geen importeerbare sleutels (keys) beschikbaar in de Geth keystore; of ze zijn al in je Parity installatie beschikbaar` }, newImport: { diff --git a/js/src/i18n/nl/createWallet.js b/js/src/i18n/nl/createWallet.js index 6acd2e2c8..9f3419497 100644 --- a/js/src/i18n/nl/createWallet.js +++ b/js/src/i18n/nl/createWallet.js @@ -53,7 +53,7 @@ export default { label: `wallet naam` }, ownerMulti: { - hint: `het eigenaars account van dit contract`, + hint: `het account wat eigenaar is van dit contract`, label: `van account (contract eigenaar)` }, ownersMulti: { @@ -80,6 +80,7 @@ export default { }, states: { completed: `Het contract is succesvol aangemaakt`, + confirmationNeeded: `Voor het aanmaken van dit contract is bevestiging door andere eigenaren van het Wallet vereist`, preparing: `Transactie aan het voorbereiden voor verzending op het netwerk`, validatingCode: `De contract code van het aangemaakte contract wordt gevalideerd`, waitingConfirm: `Wachten tot de transactie bevestigd is in de Parity Secure Signer`, @@ -93,7 +94,7 @@ export default { }, type: { multisig: { - description: `Creëer/Maak een {link} Wallet aan`, + description: `Maak een {link} Wallet aan`, label: `Multi-Sig wallet`, link: `standaard multi-signature` }, diff --git a/js/src/i18n/nl/dapps.js b/js/src/i18n/nl/dapps.js index 3c7cf6d7b..6949c4d48 100644 --- a/js/src/i18n/nl/dapps.js +++ b/js/src/i18n/nl/dapps.js @@ -36,11 +36,10 @@ export default { }, external: { accept: `Ik begrijp dat deze toepassingen niet bij Parity zijn aangesloten`, - warning: `Deze applicaties gepuliceerd door derde partijen zijn niet bij Parity aangesloten, noch worden ze gepubliceerd door Parity. Alle applicaties blijven in beheer van hun eigen auteur. Zorg ervoor dat je snapt wat het doel van een applicatie is voordat je ermee aan de slag gaat.` + warning: `Deze applicaties zijn gepuliceerd door derde partijen welke niet verwant zijn aan Parity en zijn dus ook niet door Parity uitgebracht. Alle applicaties blijven in beheer van hun eigen auteur. Zorg ervoor dat je snapt wat het doel van een applicatie is voordat je ermee aan de slag gaat.` }, label: `Gedecentraliseerde Applicaties`, permissions: { - description: `{activeIcon} account is beschikbaar voor applicaties, {defaultIcon} account is het standaard account`, label: `zichtbare dapp accounts` } }; diff --git a/js/src/i18n/nl/deployContract.js b/js/src/i18n/nl/deployContract.js index 478992464..042d52276 100644 --- a/js/src/i18n/nl/deployContract.js +++ b/js/src/i18n/nl/deployContract.js @@ -37,6 +37,13 @@ export default { hint: `het account wat eigenaar is van dit contract`, label: `van account (contract eigenaar)` }, + advanced: { + label: `geavanceerde verzend opties` + }, + amount: { + hint: `de naar het contract te verzenden hoeveelheid`, + label: `te verzenden hoeveelheid (in {tag})` + }, code: { hint: `de gecompileerde code van het aan te maken contract`, label: `code` @@ -65,6 +72,7 @@ export default { }, state: { completed: `Het contract is succesvol aangemaakt`, + confirmationNeeded: `Deze actie vereist de bevestiging van de andere eigenaren van het contract`, preparing: `Transactie aan het voorbereiden om te verzenden op het netwerk`, validatingCode: `De contract code van het aangemaakte contract valideren`, waitReceipt: `Wachten tot het aanmaken van het contract bevestigd is`, @@ -74,6 +82,7 @@ export default { completed: `voltooid`, deployment: `aangemaakt`, details: `contract details`, + extras: `extra informatie`, failed: `aanmaken mislukt`, parameters: `contract parameters`, rejected: `afgewezen` diff --git a/js/src/i18n/nl/faucet.js b/js/src/i18n/nl/faucet.js new file mode 100644 index 000000000..f35acc0b7 --- /dev/null +++ b/js/src/i18n/nl/faucet.js @@ -0,0 +1,28 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + buttons: { + close: `sluit`, + done: `klaar`, + request: `verzoek` + }, + summary: { + done: `Jouw Kovan ETH is aangevraagd bij het faucet, wat reageerde met het volgende bericht -`, + info: `Om een hoeveelheid Kovan ETH aan te vragen voor dit adres, moet je ervoor zorgen dat het adres op het mainnet sms-geverifieerd is. Zodra je dit uitvoert, zal het faucet Kovan ETH naar je huidige account verzenden.` + }, + title: `Kovan ETH Faucet` +}; diff --git a/js/src/i18n/nl/firstRun.js b/js/src/i18n/nl/firstRun.js index d182c76e1..9c7c4cf5d 100755 --- a/js/src/i18n/nl/firstRun.js +++ b/js/src/i18n/nl/firstRun.js @@ -17,16 +17,33 @@ export default { button: { close: `Sluiten`, - create: `creëer`, - next: `volgende`, + create: `Creëer`, + next: `Volgende`, print: `Woorden Afdrukken`, skip: `Overslaan` }, + completed: { + congrats: `Gefeliciteerd! Je node configuratie is succesvol afgerond en het programma is klaar voor gebruikt.`, + next: `Om je snel aan de slag te laten gaan krijg je in de volgende stap een korte algemene inleiding in het gebruik van het programma en lopen we door de beschikbare funcies.` + }, title: { completed: `voltooid`, newAccount: `nieuw account`, recovery: `herstelzin`, terms: `voorwaarden`, welcome: `welkom` + }, + tnc: { + accept: `Ik accepteer de voorwaarden en condities` + }, + welcome: { + description: `Als onderdeel van een nieuwe installatie, begeleiden we je in de enkele hierna volgende stappen met het configureren van je Parity node en jouw bijbehorende accounts. Ons doel hiervan is om het je zo gemakkelijk mogelijk te maken and zodat je binnen de kortste tijd klaar bent voor gebruik, dus heb even geduld en blijf bij ons. Zodra je de wizard voltooid hebt, heb je -`, + greeting: `Welkom bij Parity, de snelste en makkelijkste manier om je eigen node te draaien.`, + next: `Klik volgende om door te gaan.`, + step: { + account: `Je eerste Parity account aangemaakt;`, + privacy: `Onze privacybeleid en bedrijfsvoorwaarden begrepen;`, + recovery: `De mogelijkheid om je account te herstellen.` + } } }; diff --git a/js/src/i18n/nl/index.js b/js/src/i18n/nl/index.js index 281e9974c..0d11be8f1 100755 --- a/js/src/i18n/nl/index.js +++ b/js/src/i18n/nl/index.js @@ -18,10 +18,13 @@ import account from './account'; import accounts from './accounts'; import addAddress from './addAddress'; import addContract from './addContract'; +import address from './address'; +import addresses from './addresses'; import addressSelect from './addressSelect'; import application from './application'; import connection from './connection'; import contract from './contract'; +import contracts from './contracts'; import createAccount from './createAccount'; import createWallet from './createWallet'; import dapp from './dapp'; @@ -32,31 +35,41 @@ import editMeta from './editMeta'; import errors from './errors'; import executeContract from './executeContract'; import extension from './extension'; +import faucet from './faucet'; import firstRun from './firstRun'; import home from './home'; import loadContract from './loadContract'; import parityBar from './parityBar'; import passwordChange from './passwordChange'; +import saveContract from './saveContract'; import settings from './settings'; import shapeshift from './shapeshift'; +import signer from './signer'; +import status from './status'; import tabBar from './tabBar'; import transfer from './transfer'; import txEditor from './txEditor'; import ui from './ui'; import upgradeParity from './upgradeParity'; import vaults from './vaults'; +import verification from './verification'; +import wallet from './wallet'; import walletSettings from './walletSettings'; import web from './web'; +import writeContract from './writeContract'; export default { account, accounts, addAddress, addContract, + address, + addresses, addressSelect, application, connection, contract, + contracts, createAccount, createWallet, dapp, @@ -67,19 +80,26 @@ export default { errors, executeContract, extension, + faucet, firstRun, home, loadContract, parityBar, passwordChange, + saveContract, settings, shapeshift, + signer, + status, tabBar, transfer, txEditor, ui, upgradeParity, vaults, + verification, + wallet, walletSettings, - web + web, + writeContract }; diff --git a/js/src/i18n/nl/passwordChange.js b/js/src/i18n/nl/passwordChange.js index c59e50eed..eca3fd919 100644 --- a/js/src/i18n/nl/passwordChange.js +++ b/js/src/i18n/nl/passwordChange.js @@ -30,6 +30,7 @@ export default { label: `nieuw wachtwoord` }, passwordHint: { + display: `Hint {hint}`, hint: `hint voor het nieuwe wachtwoord`, label: `(optioneel) nieuwe wachtwoord hint` }, diff --git a/js/src/i18n/nl/saveContract.js b/js/src/i18n/nl/saveContract.js new file mode 100644 index 000000000..e51a3be3d --- /dev/null +++ b/js/src/i18n/nl/saveContract.js @@ -0,0 +1,27 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + buttons: { + cancel: `Annuleer`, + save: `Opslaan` + }, + name: { + hint: `kies een naam voor dit contract`, + label: `contract naam` + }, + title: `contract opslaan` +}; diff --git a/js/src/i18n/nl/settings.js b/js/src/i18n/nl/settings.js index 81f485696..f6705df78 100644 --- a/js/src/i18n/nl/settings.js +++ b/js/src/i18n/nl/settings.js @@ -22,6 +22,18 @@ export default { label: `achtergrond` }, parity: { + chains: { + chain_classic: `Parity synchroniseert met het Ethereum Classic netwerk`, + chain_dev: `Parity gebruikt een lokale ontwikkelaars chain`, + chain_expanse: `Parity synchroniseert met het Expanse netwerk`, + chain_foundation: `Parity synchroniseert met het Ethereum netwerk wat door de Ethereum Foundation is uitgebracht`, + chain_kovan: `Parity synchroniseert met het Kovan test netwerk`, + chain_olympic: `Parity synchroniseert met het Olympic test netwerk`, + chain_ropsten: `Parity synchroniseert met het Ropsten test netwerk`, + cmorden_kovan: `Parity synchroniseert met het Morden (Classic) test netwerk`, + hint: `de chain waarmee de Parity node synchroniseert`, + label: `te synchroniseren chain/netwerk` + }, languages: { hint: `de taal waarin deze interface wordt weergegeven`, label: `Weergave taal` @@ -35,7 +47,7 @@ export default { mode_offline: `Parity synchroniseert niet`, mode_passive: `Parity synchroniseert in het begin. Daarna slaapt Parity en wordt regelmatig wakker voor synchronisatie` }, - overview_0: `Pas de Parity node instellingen aan en kies de synchronisatie modus in dit menu.`, + overview_0: `Pas de Parity node instellingen aan en kies de manier van synchroniseren in dit menu.`, label: `parity` }, proxy: { @@ -53,7 +65,7 @@ export default { label: `Accounts` }, addresses: { - description: `Een overzicht van alle contacten en adresboek items die door deze Parity installatie worden beheerd. Monitor en volg accounts waarbij je transactie details met slechts een muisklik kunt weergeven.`, + description: `Een overzicht van alle door deze Parity installatie beheerde contacten en adresboek items. Monitor en volg accounts waarbij je transactie details met slechts een muisklik kunt weergeven.`, label: `Adresboek` }, apps: { @@ -64,10 +76,10 @@ export default { description: `Monitor, volg en maak gebruik van specifieke contracten die op het netwerk zijn gezet. Dit is een meer technisch gerichte omgeving, voornamelijk bedoeld voor geavanceerde gebruikers die de werking van bepaalde contracten goed begrijpen.`, label: `Contracten` }, - overview_0: `Beheer de beschikbare weergaven van deze interface en selecteer enkel de delen van de applicatie die voor jou van belang zijn.`, + overview_0: `Beheer de beschikbare weergaven van deze interface, en selecteer enkel de delen van de applicatie die voor jou van belang zijn.`, overview_1: `Ben je een eind gebruiker? De standaard instellingen zijn geschikt voor zowel beginners als gevorderde gebruikers.`, overview_2: `Ben je een ontwikkelaar? Voeg enkele functies toe om je contracten te beheren en gebruik te maken van gedecentraliseerde applicaties.`, - overview_3: `Ben je een miner of run je een grootschalige node? Voeg enkele functies toe om je alle informatie te geven die je nodig hebt om je node te monitoren.`, + overview_3: `Ben je een miner of draai je een grootschalige node? Voeg enkele functies toe om je alle informatie te geven die je nodig hebt om je node te monitoren.`, settings: { description: `Deze weergave. Hiermee kun je Parity aan passen in termen van opties, bediening en look en feel.`, label: `Instellingen` diff --git a/js/src/i18n/nl/signer.js b/js/src/i18n/nl/signer.js new file mode 100644 index 000000000..ec7ee96f8 --- /dev/null +++ b/js/src/i18n/nl/signer.js @@ -0,0 +1,103 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + embedded: { + noPending: `Er zijn momenteel geen lopende verzoeken die op je goedkeuring wachten` + }, + mainDetails: { + editTx: `Bewerk condities/gas/gasprijs`, + tooltips: { + total1: `De waarde van de transactie inclusief de miningskosten is {total} {type}.`, + total2: `(Dit is inclusief een miners vergoeding van {fee} {token})`, + value1: `De waarde van de transactie.` + } + }, + requestOrigin: { + dapp: `door een dapp op {url}`, + ipc: `via IPC sessie`, + rpc: `via RPC {rpc}`, + signerCurrent: `via huidige tab`, + signerUI: `via UI sessie`, + unknownInterface: `via onbekende interface`, + unknownRpc: `niet geïdentificeerd`, + unknownUrl: `onbekende URL` + }, + requestsPage: { + noPending: `Er zijn geen verzoeken die je goedkeuring vereisen.`, + pendingTitle: `Openstaande Verzoeken`, + queueTitle: `Lokale Transacties` + }, + sending: { + hardware: { + confirm: `Bevestig de transactie op je aangesloten hardware wallet`, + connect: `Sluit je hardware wallet aan voordat je de transactie bevestigd` + } + }, + signRequest: { + request: `Een verzoek om data te ondertekenen met jouw account:`, + state: { + confirmed: `Bevestigd`, + rejected: `Afgewezen` + }, + unknownBinary: `(Onbekende binary data)`, + warning: `WAARSCHUWING: Deze gevolgen hiervan kunnen ernstig zijn. Bevestig het verzoek alleen als je het zeker weet.` + }, + title: `Trusted Signer`, + txPending: { + buttons: { + viewToggle: `bekijk transactie` + } + }, + txPendingConfirm: { + buttons: { + confirmBusy: `Bevestigen...`, + confirmRequest: `Bevestig Verzoek` + }, + errors: { + invalidWallet: `Opgegeven wallet bestand is ongeldig.` + }, + password: { + decrypt: { + hint: `open (decrypt) de sleutel met je wachtwoord`, + label: `Sleutel Wachtwoord` + }, + unlock: { + hint: `ontgrendel het account`, + label: `Account Wachtwoord` + } + }, + passwordHint: `(hint) {passwordHint}`, + selectKey: { + hint: `De sleutelbestand (keyfile) die je voor dit account wilt gebruiken`, + label: `Selecteer Lokale Sleutel (key)` + }, + tooltips: { + password: `Geef een wachtwoord voor dit account` + } + }, + txPendingForm: { + changedMind: `Ik heb me bedacht`, + reject: `wijs verzoek af` + }, + txPendingReject: { + buttons: { + reject: `Wijs Verzoek Af` + }, + info: `Weet je zeker dat je dit verzoek wilt afwijzen?`, + undone: `Dit kan niet ongedaan gemaakt worden` + } +}; diff --git a/js/src/i18n/nl/status.js b/js/src/i18n/nl/status.js new file mode 100644 index 000000000..9c0294ab0 --- /dev/null +++ b/js/src/i18n/nl/status.js @@ -0,0 +1,66 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + debug: { + reverse: `Omgekeerde volgorde`, + stopped: `De live weergave van de Parity logboeken is momenteel gestopt via de UI, start de live weergave om de laatste updates te zien.`, + title: `Node Logboeken` + }, + miningSettings: { + input: { + author: { + hint: `de mining auteur`, + label: `auteur` + }, + extradata: { + hint: `extra data voor mined blokken`, + label: `extra data` + }, + gasFloor: { + hint: `het gas-floor doel voor mining`, + label: `gas-floor doel` + }, + gasPrice: { + hint: `de minimale gas prijs voor mining`, + label: `minimale gas prijs` + } + }, + title: `mining instellingen` + }, + status: { + hashrate: `{hashrate} H/s`, + input: { + chain: `chain`, + enode: `enode`, + no: `nee`, + peers: `peers`, + port: `netwerk poort`, + rpcEnabled: `rpc ingeschakeld`, + rpcInterface: `rpc interface`, + rpcPort: `rpc poort`, + yes: `ja` + }, + title: { + bestBlock: `beste block`, + hashRate: `hash rate`, + network: `netwerk instellingen`, + node: `Node`, + peers: `peers` + } + }, + title: `Status` +}; diff --git a/js/src/i18n/nl/transfer.js b/js/src/i18n/nl/transfer.js index 1370711b4..29866470b 100644 --- a/js/src/i18n/nl/transfer.js +++ b/js/src/i18n/nl/transfer.js @@ -21,7 +21,41 @@ export default { label: `transactie data` } }, + buttons: { + back: `Terug`, + cancel: `Annuleer`, + close: `Sluit`, + next: `Volgende`, + send: `Verzend` + }, + details: { + advanced: { + label: `geavanceerde verzend opties` + }, + amount: { + hint: `de naar de ontvanger te verzenden hoeveelheid`, + label: `te verzenden hoeveelheid (in {tag})` + }, + fullBalance: { + label: `volledige account balans` + }, + recipient: { + hint: `het ontvangende adres`, + label: `ontvanger adres` + }, + sender: { + hint: `het verzendende adres`, + label: `Verzender adres` + }, + total: { + label: `totale transactie hoeveelheid` + } + }, + wallet: { + confirmation: `Deze transactie vereist bevestiging van andere eigenaren.`, + operationHash: `hash van deze bewerking` + }, warning: { - wallet_spent_limit: `Deze transactie waarde is boven de toegestane dag limiet en zal moeten worden bevestigd door andere eigenaren.` + wallet_spent_limit: `De waarde van deze transactie is hoger dan de toegestane dag limiet en zal moeten worden bevestigd door andere eigenaren.` } }; diff --git a/js/src/i18n/nl/ui.js b/js/src/i18n/nl/ui.js index c0454e9f6..1b7a9163b 100644 --- a/js/src/i18n/nl/ui.js +++ b/js/src/i18n/nl/ui.js @@ -15,8 +15,40 @@ // along with Parity. If not, see . export default { + actionbar: { + export: { + button: { + export: `exporteer` + } + }, + import: { + button: { + cancel: `Annuleer`, + confirm: `Bevestig`, + import: `importeer` + }, + confirm: `Bevestig dat dit is wat je wilt importeren.`, + error: `Er is een fout opgetreden: {errorText}`, + step: { + error: `fout`, + select: `selecteer een bestand`, + validate: `valideer` + }, + title: `Importeer vanuit een bestand` + }, + search: { + hint: `Voer zoekopdracht in...` + }, + sort: { + sortBy: `Sorteer op {label}`, + typeDefault: `Standaard`, + typeEth: `Sorteer op ETH`, + typeName: `Sorteer op naam`, + typeTags: `Sorteer op tags` + } + }, balance: { - none: `Er zijn geen tegoeden gekoppeld aan dit account` + none: `Geen tegoeden gekoppeld aan dit account` }, blockStatus: { bestBlock: `{blockNumber} beste blok`, @@ -28,10 +60,61 @@ export default { no: `nee`, yes: `ja` }, + copyToClipboard: { + copied: `{data} is naar het klembord gekopierd` + }, + errors: { + close: `sluit` + }, + fileSelect: { + defaultLabel: `Sleep hier een bestand naartoe, of klik om een bestand te selecteren voor uploaden` + }, + gasPriceSelector: { + customTooltip: { + transactions: `{number} {number, plural, one {transaction} other {transactions}} met een ingestelde gasprijs tussen de {minPrice} en {maxPrice}` + } + }, identityName: { null: `NUL`, unnamed: `NAAMLOOS` }, + methodDecoding: { + condition: { + block: `, {historic, select, true {Submitted} false {Submission}} in blok {blockNumber}`, + time: `, {historic, select, true {Submitted} false {Submission}} op {timestamp}` + }, + deploy: { + address: `Een contract aangemaakt op adres`, + params: `met de volgende parameters:`, + willDeploy: `Zal een contract aanmaken`, + withValue: `, verzenden van {value}` + }, + gasUsed: `({gas} gas gebruikt)`, + gasValues: `{gas} gas ({gasPrice}M/{tag})`, + input: { + data: `data`, + input: `input`, + withInput: `met de {inputDesc} {inputValue}` + }, + receive: { + contract: `het contract`, + info: `{historic, select, true {Received} false {Will receive}} {valueEth} van {aContract}{address}` + }, + signature: { + info: `{historic, select, true {Executed} false {Will execute}} the {method} function on the contract {address} transferring {ethValue}{inputLength, plural, zero {,} other {passing the following {inputLength, plural, one {parameter} other {parameters}}}}` + }, + token: { + transfer: `{historic, select, true {Transferred} false {Will transfer}} {value} naar {address}` + }, + transfer: { + contract: `het contract`, + info: `{historic, select, true {Transferred} false {Will transfer}} {valueEth} naar {aContract}{address}` + }, + txValues: `{historic, select, true {Provided} false {Provides}} {gasProvided}{gasUsed} voor een totale transactie waarde van {totalEthValue}`, + unknown: { + info: `{historic, select, true {Executed} false {Will execute}} the {method} on the contract {address} transferring {ethValue}.` + } + }, passwordStrength: { label: `wachtwoord sterkte` }, @@ -48,6 +131,10 @@ export default { posted: `De transactie is op het netwerk geplaatst met hash {hashLink}`, waiting: `wachten op bevestigingen` }, + vaultSelect: { + hint: `de kluis waaraan dit account gekoppeld is`, + label: `gekoppelde kluis` + }, verification: { gatherData: { accountHasRequested: { @@ -60,10 +147,6 @@ export default { pending: `Aan het controleren of je account is geverifieerd…`, true: `Je account is al geverifieerd.` }, - email: { - hint: `de code zal naar dit adres worden verzonden`, - label: `e-mail adres` - }, fee: `De extra vergoeding is {amount} ETH.`, isAbleToRequest: { pending: `Valideren van je invoer…` @@ -74,10 +157,6 @@ export default { true: `De verificatie server is actief.` }, nofee: `Er zijn geen extra kosten.`, - phoneNumber: { - hint: `De SMS zal naar dit nummer worden verstuurd`, - label: `telefoonnummer in internationaal formaat` - }, termsOfService: `Ik ga akkoord met de voorwaarden en condities hieronder.` } } diff --git a/js/src/i18n/nl/upgradeParity.js b/js/src/i18n/nl/upgradeParity.js index c057c9e7d..732a7b267 100644 --- a/js/src/i18n/nl/upgradeParity.js +++ b/js/src/i18n/nl/upgradeParity.js @@ -15,13 +15,13 @@ // along with Parity. If not, see . export default { - busy: `Parity wordt momenteel bijgewerkt naar versie {newversion}`, + busy: `Parity wordt momenteel bijgewerkt naar versie {newversion}. Wacht tot het proces is voltooid.`, button: { close: `sluiten`, done: `klaar`, upgrade: `werk nu bij` }, - completed: `Het bijwerken naar Parity {newversion} is succesvol voltooid.`, + completed: `Het bijwerken naar Parity {newversion} is succesvol voltooid. Klik op "klaar" om het programma automatisch opnieuw op te starten.`, consensus: { capable: `Je huidige versie van Parity voldoet aan de netwerk vereisten.`, capableUntil: `Je huidige versie van Parity voldoet aan de netwerk vereisten tot aan blok {blockNumber}`, @@ -30,7 +30,10 @@ export default { }, failed: `Het bijwerken naar Parity {newversion} gaf een fout en is mislukt.`, info: { - upgrade: `Een nieuwe versie van Parity, version {newversion} is beschikbaar als upgrade vanaf je huidige versie {currentversion}` + currentVersion: `Je huidige versie is {currentversion}`, + next: `Klik op "werk nu bij" om het bijwerken van je Parity te starten.`, + upgrade: `Een nieuwe versie {newversion} is beschikbaar`, + welcome: `Welkom bij de Parity upgrade wizard, deze stelt je in staat om Parity op zeer eenvoudige wijze bij te werken naar de nieuwste versie.` }, step: { completed: `bijwerken voltooid`, diff --git a/js/src/i18n/nl/vaults.js b/js/src/i18n/nl/vaults.js index b16c6807e..3659fb7d7 100644 --- a/js/src/i18n/nl/vaults.js +++ b/js/src/i18n/nl/vaults.js @@ -26,8 +26,9 @@ export default { button: { accounts: `accounts`, add: `Maak kluis`, - close: `sluit kluis`, - open: `open kluis` + close: `sluit`, + edit: `bewerk`, + open: `open` }, confirmClose: { info: `Je staat op het punt op een kluis te sluiten. Alle aan deze kluis verbonden accounts zullen niet meer zichtbaar zijn na het voltooien van deze actie. Om deze accounts weer zichtbaar te maken dien je de kluis weer te openen.`, @@ -70,6 +71,38 @@ export default { }, title: `Maak een nieuwe kluis aan` }, + editMeta: { + allowPassword: `Wijzig kluis wachtwoord`, + button: { + close: `sluit`, + save: `opslaan` + }, + currentPassword: { + hint: `je huidige kluis wachtwoord`, + label: `huidige wachtwoord` + }, + description: { + hint: `de omschrijving van deze kluis`, + label: `kluis omschrijving` + }, + password: { + hint: `een sterk, uniek wachtwoord`, + label: `nieuw wachtwoord` + }, + password2: { + hint: `verifieer je nieuwe wachtwoord`, + label: `nieuw wachtwoord (herhaal)` + }, + passwordHint: { + hint: `je wachtwoord hint voor deze kluis`, + label: `wachtwoord hint` + }, + title: `Bewerk Kluis Metadata` + }, empty: `Er zijn momenteel geen kluizen om weer tegeven.`, + selector: { + noneAvailable: `Er zijn momenteel geen kluizen geopend en beschikbaar voor selectie. Maak eerst een kluis aan en open deze, voordat je een kluis selecteert voor het verplaatsen van een account.`, + title: `Selecteer Account Kluis` + }, title: `Kluis Beheer` }; diff --git a/js/src/i18n/nl/verification.js b/js/src/i18n/nl/verification.js new file mode 100644 index 000000000..bd0ba1c28 --- /dev/null +++ b/js/src/i18n/nl/verification.js @@ -0,0 +1,85 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + button: { + cancel: `Annuleer`, + done: `Klaar`, + next: `Volgende` + }, + code: { + error: `ongeldige code`, + hint: `Voer de ontvangen code in.`, + label: `verificatie code`, + sent: `De verificatie code is verstuurd naar {receiver}.` + }, + confirmation: { + authorise: `De verificatie code zal naar het contract worden verzonden. Gebruik de Parity Signer om dit goed te keuren.`, + windowOpen: `Houd dit scherm open.` + }, + done: { + message: `Gefeliciteerd, je account is geverifieerd!` + }, + email: { + enterCode: `Voer de code in die je per e-email hebt ontvangen.` + }, + gatherData: { + email: { + hint: `de code zal naar dit adres worden verstuurd`, + label: `e-mail adres` + }, + phoneNumber: { + hint: `De SMS zal naar dit nummer worden verstuurd`, + label: `telefoon nummer in internationaal formaat` + } + }, + gatherDate: { + email: { + error: `ongeldig e-mail adres` + }, + phoneNumber: { + error: `ongeldig telefoon nummer` + } + }, + loading: `Laden van verificatie data.`, + request: { + authorise: `Een verificatie verzoek zal naar het contract worden verzonden. Gebruik de Parity Signer om dit goed te keuren.`, + requesting: `Een code aanvragen bij de Parity-server en wachten tot de puzzel in het contract opgenomen wordt.`, + windowOpen: `Houd dit scherm open.` + }, + sms: { + enterCode: `Voer de code in die je per SMS hebt ontvangen.` + }, + steps: { + code: `Voer Code in`, + completed: `Voltooi`, + confirm: `Bevestig`, + data: `Voer Data in`, + method: `Methode`, + request: `Verzoek` + }, + title: `verifieer je account`, + types: { + email: { + description: `De hash van het e-mail adres waarvan je bewijst dat het van jou is, zal worden opgeslagen in de blockchain.`, + label: `E-mail Verificatie` + }, + sms: { + description: `Het zal in de blockchain worden vast gelegd dat jij in het bezit bent van een telefoon nummer (not which).`, + label: `SMS Verificatie` + } + } +}; diff --git a/js/src/i18n/nl/wallet.js b/js/src/i18n/nl/wallet.js new file mode 100644 index 000000000..d0460e58f --- /dev/null +++ b/js/src/i18n/nl/wallet.js @@ -0,0 +1,45 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + buttons: { + edit: `bewerk`, + forget: `vergeet`, + settings: `instellingen`, + transfer: `verzend` + }, + confirmations: { + buttons: { + confirmAs: `Bevestig als...`, + revokeAs: `Herroep als...` + }, + none: `Er zijn momenteel geen transacties die op bevestiging wachten.`, + tooltip: { + confirmed: `Bevestigd door {number}/{required} eigenaren` + } + }, + details: { + requiredOwners: `Dit wallet vereist ten minste {owners} voor de goedkeuring van elke actie (transactions, modifications).`, + requiredOwnersNumber: `{number} {numberValue, plural, one {owner} other {owners}}`, + spent: `{spent} is vandaag besteed, van de {limit} ingestelde daglimiet. De daglimiet is op {date} opnieuw ingesteld`, + title: `Details` + }, + title: `Wallet Beheer`, + transactions: { + none: `Er zijn geen verzonden transacties.`, + title: `Transacties` + } +}; diff --git a/js/src/i18n/nl/walletSettings.js b/js/src/i18n/nl/walletSettings.js index ca0842944..66fd70001 100644 --- a/js/src/i18n/nl/walletSettings.js +++ b/js/src/i18n/nl/walletSettings.js @@ -15,6 +15,16 @@ // along with Parity. If not, see . export default { + addOwner: { + title: `Eigenaar toevoegen` + }, + buttons: { + cancel: `Annuleer`, + close: `Sluit`, + next: `Volgende`, + send: `Verzend`, + sending: `Verzenden...` + }, changes: { modificationString: `Om je wijzigingen door te voeren zullen andere eigenaren deze zelfde wijzigingen moeten verzenden. Om het @@ -25,7 +35,8 @@ export default { edit: { message: `Om de instellingen van dit contract de wijzigen zullen minimaal {owners, number} {owners, plural, one {owner } other {owners }} precies dezelfde - wijzigingen moeten verzenden. Je kunt hier de wijzigingen in string-vorm plakken.` + wijzigingen moeten verzenden. Je kunt de wijzigingen hier + in string-vorm plakken.` }, modifications: { daylimit: { @@ -47,11 +58,12 @@ export default { label: `van account (wallet eigenaar)` } }, - rejected: { - busyStep: { - state: `De wallet instellingen zullen niet worden gewijzigd. Je kunt dit venster veilig sluiten.`, - title: `De wijzigingen zijn afgewezen.` - }, - title: `afgewezen` + ownersChange: { + details: `van {from} naar {to}`, + title: `Wijzig Vereiste Eigenaren` + }, + rejected: `De transactie #{txid} is afgewezen`, + removeOwner: { + title: `Verwijder Eigenaar` } }; diff --git a/js/src/i18n/nl/writeContract.js b/js/src/i18n/nl/writeContract.js new file mode 100644 index 000000000..e264ac83a --- /dev/null +++ b/js/src/i18n/nl/writeContract.js @@ -0,0 +1,62 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default { + buttons: { + autoCompile: `Auto-Compile`, + compile: `Compileer`, + deploy: `Maak Aan`, + import: `Importeer Solidity`, + load: `Laad`, + new: `Nieuw`, + optimise: `Optimaliseer`, + save: `Opslaan` + }, + compiling: { + action: `Compileer de bron code.`, + busy: `Compileren...` + }, + details: { + saved: `(opgeslagen {timestamp})` + }, + error: { + noContract: `Er is geen contract gevonden.`, + params: `Een fout is opgetreden met de volgende omschrijving` + }, + input: { + abi: `ABI Interface`, + code: `Bytecode`, + metadata: `Metadata`, + swarm: `Swarm Metadata Hash` + }, + title: { + contract: `Selecteer een contract`, + loading: `Laden...`, + main: `Schrijf een Contract`, + messages: `Compiler berichten`, + new: `Nieuw Solidity Contract`, + parameters: `Parameters`, + saved: `opgeslagen @ {timestamp}`, + selectSolidity: `Selecteer een Solidity versie`, + solidity: `Solidity {version} laden` + }, + type: { + humanErc20: `Implementatie van het Human Token Contract`, + implementErc20: `Implementatie van ERC20 Token Contract`, + multisig: `Implementatie van een multisig Wallet`, + standardErc20: `Standaard ERC20 Token Contract` + } +}; diff --git a/js/src/i18n/zh/writeContract.js b/js/src/i18n/zh/writeContract.js index fc1100b77..62f83dd4d 100644 --- a/js/src/i18n/zh/writeContract.js +++ b/js/src/i18n/zh/writeContract.js @@ -37,7 +37,7 @@ export default { params: `An error occurred with the following description` }, input: { - abi: `ABI Interface`, + abi: `ABI Definition`, code: `Bytecode`, metadata: `Metadata`, swarm: `Swarm Metadata Hash` diff --git a/js/src/index.ejs b/js/src/index.ejs index ec8592b88..305568f5b 100644 --- a/js/src/index.ejs +++ b/js/src/index.ejs @@ -8,6 +8,7 @@