Merge remote-tracking branch 'origin/master'

This commit is contained in:
kaikun213 2017-07-15 12:14:26 +02:00
commit ea14290f52
153 changed files with 1413 additions and 1102 deletions

304
Cargo.lock generated
View File

@ -253,6 +253,16 @@ dependencies = [
"unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "common-types"
version = "0.1.0"
dependencies = [
"ethcore-util 1.8.0",
"ethjson 0.1.0",
"rlp 0.2.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "conv" name = "conv"
version = "0.3.3" version = "0.3.3"
@ -419,7 +429,7 @@ dependencies = [
[[package]] [[package]]
name = "ethash" name = "ethash"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -429,32 +439,33 @@ dependencies = [
[[package]] [[package]]
name = "ethcore" name = "ethcore"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bloomchain 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bn 0.4.4 (git+https://github.com/paritytech/bn)", "bn 0.4.4 (git+https://github.com/paritytech/bn)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.7.0", "ethash 1.8.0",
"ethcore-bloom-journal 0.1.0", "ethcore-bloom-journal 0.1.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"ethcore-stratum 1.7.0", "ethcore-stratum 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethjson 0.1.0", "ethjson 0.1.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"ethstore 0.1.0", "ethstore 0.1.0",
"evmjit 1.7.0", "evm 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"hardware-wallet 1.7.0", "hardware-wallet 1.8.0",
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@ -464,7 +475,6 @@ dependencies = [
"native-contracts 0.1.0", "native-contracts 0.1.0",
"num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0", "rlp 0.2.0",
"rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
@ -474,7 +484,6 @@ dependencies = [
"stats 0.1.0", "stats 0.1.0",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
] ]
[[package]] [[package]]
@ -497,14 +506,14 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-devtools" name = "ethcore-devtools"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "ethcore-io" name = "ethcore-io"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -515,17 +524,17 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-ipc" name = "ethcore-ipc"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "ethcore-ipc-codegen" name = "ethcore-ipc-codegen"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
@ -540,9 +549,9 @@ dependencies = [
name = "ethcore-ipc-hypervisor" name = "ethcore-ipc-hypervisor"
version = "1.2.0" version = "1.2.0"
dependencies = [ dependencies = [
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -551,9 +560,9 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-ipc-nano" name = "ethcore-ipc-nano"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
@ -563,11 +572,11 @@ dependencies = [
name = "ethcore-ipc-tests" name = "ethcore-ipc-tests"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)", "nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -575,16 +584,17 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-light" name = "ethcore-light"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-network 1.7.0", "ethcore-network 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"evm 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -599,7 +609,7 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-logger" name = "ethcore-logger"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", "arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
@ -614,15 +624,15 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-network" name = "ethcore-network"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -647,13 +657,13 @@ version = "1.0.0"
dependencies = [ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@ -675,15 +685,15 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-stratum" name = "ethcore-stratum"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "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-core 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-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)",
@ -696,7 +706,7 @@ dependencies = [
[[package]] [[package]]
name = "ethcore-util" name = "ethcore-util"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
@ -705,8 +715,8 @@ dependencies = [
"eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)",
"ethcore-bigint 0.1.3", "ethcore-bigint 0.1.3",
"ethcore-bloom-journal 0.1.0", "ethcore-bloom-journal 0.1.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
@ -746,7 +756,7 @@ name = "ethjson"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -815,19 +825,19 @@ dependencies = [
[[package]] [[package]]
name = "ethsync" name = "ethsync"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"ethcore-light 1.7.0", "ethcore-light 1.8.0",
"ethcore-network 1.7.0", "ethcore-network 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -839,13 +849,32 @@ dependencies = [
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "evm"
version = "0.1.0"
dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"common-types 0.1.0",
"ethcore-util 1.8.0",
"ethjson 0.1.0",
"evmjit 1.8.0",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-wasm 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)",
]
[[package]] [[package]]
name = "evmbin" name = "evmbin"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"evm 0.1.0",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -853,7 +882,7 @@ dependencies = [
[[package]] [[package]]
name = "evmjit" name = "evmjit"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"tiny-keccak 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -958,7 +987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "hardware-wallet" name = "hardware-wallet"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ethcore-bigint 0.1.3", "ethcore-bigint 0.1.3",
"ethkey 0.2.0", "ethkey 0.2.0",
@ -1085,11 +1114,11 @@ dependencies = [
[[package]] [[package]]
name = "ipc-common-types" name = "ipc-common-types"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1483,7 +1512,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"native-contract-generator 0.1.0", "native-contract-generator 0.1.0",
] ]
@ -1682,20 +1711,20 @@ dependencies = [
"daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "daemonize 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-hypervisor 1.2.0", "ethcore-ipc-hypervisor 1.2.0",
"ethcore-ipc-nano 1.7.0", "ethcore-ipc-nano 1.8.0",
"ethcore-ipc-tests 0.1.0", "ethcore-ipc-tests 0.1.0",
"ethcore-light 1.7.0", "ethcore-light 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"ethcore-secretstore 1.0.0", "ethcore-secretstore 1.0.0",
"ethcore-stratum 1.7.0", "ethcore-stratum 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"ethsync 1.7.0", "ethsync 1.8.0",
"fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1704,14 +1733,14 @@ dependencies = [
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps 1.7.0", "parity-dapps 1.8.0",
"parity-hash-fetch 1.7.0", "parity-hash-fetch 1.8.0",
"parity-ipfs-api 1.7.0", "parity-ipfs-api 1.8.0",
"parity-local-store 0.1.0", "parity-local-store 0.1.0",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
"parity-rpc 1.7.0", "parity-rpc 1.8.0",
"parity-rpc-client 1.4.0", "parity-rpc-client 1.4.0",
"parity-updater 1.7.0", "parity-updater 1.8.0",
"path 0.1.0", "path 0.1.0",
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1732,13 +1761,13 @@ dependencies = [
[[package]] [[package]]
name = "parity-dapps" name = "parity-dapps"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "base32 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1750,9 +1779,9 @@ dependencies = [
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ntp 0.2.0 (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-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.7.0", "parity-hash-fetch 1.8.0",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
"parity-ui 1.7.0", "parity-ui 1.8.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1780,10 +1809,10 @@ dependencies = [
[[package]] [[package]]
name = "parity-hash-fetch" name = "parity-hash-fetch"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1797,11 +1826,11 @@ dependencies = [
[[package]] [[package]]
name = "parity-ipfs-api" name = "parity-ipfs-api"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"jsonrpc-http-server 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)",
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1812,9 +1841,9 @@ dependencies = [
name = "parity-local-store" name = "parity-local-store"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0", "rlp 0.2.0",
@ -1833,23 +1862,24 @@ dependencies = [
[[package]] [[package]]
name = "parity-rpc" name = "parity-rpc"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clippy 0.0.103 (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", "ethash 1.8.0",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-devtools 1.7.0", "ethcore-devtools 1.8.0",
"ethcore-io 1.7.0", "ethcore-io 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-light 1.7.0", "ethcore-light 1.8.0",
"ethcore-logger 1.7.0", "ethcore-logger 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethcrypto 0.1.0", "ethcrypto 0.1.0",
"ethjson 0.1.0", "ethjson 0.1.0",
"ethkey 0.2.0", "ethkey 0.2.0",
"ethstore 0.1.0", "ethstore 0.1.0",
"ethsync 1.7.0", "ethsync 1.8.0",
"evm 0.1.0",
"fetch 0.1.0", "fetch 0.1.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1864,7 +1894,7 @@ dependencies = [
"multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
"parity-updater 1.7.0", "parity-updater 1.8.0",
"pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"rlp 0.2.0", "rlp 0.2.0",
@ -1884,13 +1914,13 @@ dependencies = [
name = "parity-rpc-client" name = "parity-rpc-client"
version = "1.4.0" version = "1.4.0"
dependencies = [ dependencies = [
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "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-core 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)", "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)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.7.0", "parity-rpc 1.8.0",
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1917,16 +1947,16 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui" name = "parity-ui"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"parity-ui-dev 1.7.0", "parity-ui-dev 1.8.0",
"parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)", "parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)",
"rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "parity-ui-dev" name = "parity-ui-dev"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -1934,25 +1964,25 @@ dependencies = [
[[package]] [[package]]
name = "parity-ui-precompiled" name = "parity-ui-precompiled"
version = "1.4.0" version = "1.4.0"
source = "git+https://github.com/paritytech/js-precompiled.git#fa572f52beb3a7b6f6473a5a5cf07518d899c4d9" source = "git+https://github.com/paritytech/js-precompiled.git#92627cfd287eb5176c016089b9e2350107f8869a"
dependencies = [ dependencies = [
"parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-dapps-glue 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
name = "parity-updater" name = "parity-updater"
version = "1.7.0" version = "1.8.0"
dependencies = [ dependencies = [
"ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.7.0", "ethcore 1.8.0",
"ethcore-ipc 1.7.0", "ethcore-ipc 1.8.0",
"ethcore-ipc-codegen 1.7.0", "ethcore-ipc-codegen 1.8.0",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"ethsync 1.7.0", "ethsync 1.8.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"ipc-common-types 1.7.0", "ipc-common-types 1.8.0",
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-hash-fetch 1.7.0", "parity-hash-fetch 1.8.0",
"parity-reactor 0.1.0", "parity-reactor 0.1.0",
"path 0.1.0", "path 0.1.0",
"target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2294,9 +2324,9 @@ name = "rpc-cli"
version = "1.4.0" version = "1.4.0"
dependencies = [ dependencies = [
"bigint 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "bigint 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-util 1.7.0", "ethcore-util 1.8.0",
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-rpc 1.7.0", "parity-rpc 1.8.0",
"parity-rpc-client 1.4.0", "parity-rpc-client 1.4.0",
"rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]

View File

@ -81,14 +81,6 @@ Once you have rustup, install parity or download and build from source
---- ----
## Quick build and install
```bash
cargo install --git https://github.com/paritytech/parity.git parity
```
----
## Install from the snap store ## Install from the snap store
In any of the [supported Linux distros](https://snapcraft.io/docs/core/install): In any of the [supported Linux distros](https://snapcraft.io/docs/core/install):

View File

@ -1,7 +1,7 @@
[package] [package]
description = "Parity Dapps crate" description = "Parity Dapps crate"
name = "parity-dapps" name = "parity-dapps"
version = "1.7.0" version = "1.8.0"
license = "GPL-3.0" license = "GPL-3.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]

View File

@ -3,7 +3,7 @@ description = "Ethcore Parity UI"
homepage = "http://parity.io" homepage = "http://parity.io"
license = "GPL-3.0" license = "GPL-3.0"
name = "parity-ui" name = "parity-ui"
version = "1.7.0" version = "1.8.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[build-dependencies] [build-dependencies]

View File

@ -3,7 +3,7 @@ description = "Ethcore development/test/build tools"
homepage = "http://parity.io" homepage = "http://parity.io"
license = "GPL-3.0" license = "GPL-3.0"
name = "ethcore-devtools" name = "ethcore-devtools"
version = "1.7.0" version = "1.8.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "ethash" name = "ethash"
version = "1.7.0" version = "1.8.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
[lib] [lib]

View File

@ -3,7 +3,7 @@ description = "Ethcore library"
homepage = "http://parity.io" homepage = "http://parity.io"
license = "GPL-3.0" license = "GPL-3.0"
name = "ethcore" name = "ethcore"
version = "1.7.0" version = "1.8.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs" build = "build.rs"
@ -16,6 +16,7 @@ bloomchain = "0.1"
bn = { git = "https://github.com/paritytech/bn" } bn = { git = "https://github.com/paritytech/bn" }
byteorder = "1.0" byteorder = "1.0"
clippy = { version = "0.0.103", optional = true} clippy = { version = "0.0.103", optional = true}
common-types = { path = "types" }
crossbeam = "0.2.9" crossbeam = "0.2.9"
env_logger = "0.4" env_logger = "0.4"
ethabi = "2.0" ethabi = "2.0"
@ -31,7 +32,7 @@ ethcore-util = { path = "../util" }
ethjson = { path = "../json" } ethjson = { path = "../json" }
ethkey = { path = "../ethkey" } ethkey = { path = "../ethkey" }
ethstore = { path = "../ethstore" } ethstore = { path = "../ethstore" }
evmjit = { path = "../evmjit", optional = true } evm = { path = "evm" }
futures = "0.1" futures = "0.1"
hardware-wallet = { path = "../hw" } hardware-wallet = { path = "../hw" }
hyper = { git = "https://github.com/paritytech/hyper", default-features = false } hyper = { git = "https://github.com/paritytech/hyper", default-features = false }
@ -52,14 +53,12 @@ semver = "0.6"
stats = { path = "../util/stats" } stats = { path = "../util/stats" }
time = "0.1" time = "0.1"
transient-hashmap = "0.4" transient-hashmap = "0.4"
parity-wasm = "0.12"
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
[dev-dependencies] [dev-dependencies]
native-contracts = { path = "native_contracts", features = ["test_contracts"] } native-contracts = { path = "native_contracts", features = ["test_contracts"] }
[features] [features]
jit = ["evmjit"] jit = ["evm/jit"]
evm-debug = ["slow-blocks"] evm-debug = ["slow-blocks"]
evm-debug-tests = ["evm-debug"] evm-debug-tests = ["evm-debug"]
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms

View File

@ -17,7 +17,6 @@
extern crate ethcore_ipc_codegen; extern crate ethcore_ipc_codegen;
fn main() { fn main() {
ethcore_ipc_codegen::derive_binary("src/types/mod.rs.in").unwrap();
ethcore_ipc_codegen::derive_ipc_cond("src/client/traits.rs", cfg!(feature="ipc")).unwrap(); ethcore_ipc_codegen::derive_ipc_cond("src/client/traits.rs", cfg!(feature="ipc")).unwrap();
ethcore_ipc_codegen::derive_ipc_cond("src/snapshot/snapshot_service_trait.rs", cfg!(feature="ipc")).unwrap(); ethcore_ipc_codegen::derive_ipc_cond("src/snapshot/snapshot_service_trait.rs", cfg!(feature="ipc")).unwrap();
ethcore_ipc_codegen::derive_ipc_cond("src/client/chain_notify.rs", cfg!(feature="ipc")).unwrap(); ethcore_ipc_codegen::derive_ipc_cond("src/client/chain_notify.rs", cfg!(feature="ipc")).unwrap();

23
ethcore/evm/Cargo.toml Normal file
View File

@ -0,0 +1,23 @@
[package]
name = "evm"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
bit-set = "0.4"
byteorder = "1.0"
common-types = { path = "../types" }
ethcore-util = { path = "../../util" }
evmjit = { path = "../../evmjit", optional = true }
ethjson = { path = "../../json" }
lazy_static = "0.2"
log = "0.3"
rlp = { path = "../../util/rlp" }
parity-wasm = "0.12"
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
[dev-dependencies]
rustc-hex = "1.0"
[features]
jit = ["evmjit"]

View File

@ -19,7 +19,8 @@ use util::{Address, Bytes, U256};
use util::hash::{H256}; use util::hash::{H256};
use util::sha3::{Hashable, SHA3_EMPTY}; use util::sha3::{Hashable, SHA3_EMPTY};
use ethjson; use ethjson;
use types::executed::CallType;
use {CallType};
use std::sync::Arc; use std::sync::Arc;

View File

@ -25,7 +25,7 @@ extern crate test;
use self::test::{Bencher, black_box}; use self::test::{Bencher, black_box};
use util::*; use util::*;
use action_params::ActionParams; use evm::action_params::ActionParams;
use evm::{self, Factory, VMType}; use evm::{self, Factory, VMType};
use evm::tests::FakeExt; use evm::tests::FakeExt;

View File

@ -0,0 +1,70 @@
//! EVM call types.
use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp};
/// The type of the call-like instruction.
#[derive(Debug, PartialEq, Clone)]
pub enum CallType {
/// Not a CALL.
None,
/// CALL.
Call,
/// CALLCODE.
CallCode,
/// DELEGATECALL.
DelegateCall,
/// STATICCALL
StaticCall,
}
impl Encodable for CallType {
fn rlp_append(&self, s: &mut RlpStream) {
let v = match *self {
CallType::None => 0u32,
CallType::Call => 1,
CallType::CallCode => 2,
CallType::DelegateCall => 3,
CallType::StaticCall => 4,
};
Encodable::rlp_append(&v, s);
}
}
impl Decodable for CallType {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
rlp.as_val().and_then(|v| Ok(match v {
0u32 => CallType::None,
1 => CallType::Call,
2 => CallType::CallCode,
3 => CallType::DelegateCall,
4 => CallType::StaticCall,
_ => return Err(DecoderError::Custom("Invalid value of CallType item")),
}))
}
}
#[cfg(test)]
mod tests {
use rlp::*;
use super::CallType;
#[test]
fn encode_call_type() {
let ct = CallType::Call;
let mut s = RlpStream::new_list(2);
s.append(&ct);
assert!(!s.is_finished(), "List shouldn't finished yet");
s.append(&ct);
assert!(s.is_finished(), "List should be finished now");
s.out();
}
#[test]
fn should_encode_and_decode_call_type() {
let original = CallType::Call;
let encoded = encode(&original);
let decoded = decode(&encoded);
assert_eq!(original, decoded);
}
}

View File

@ -19,7 +19,7 @@
use std::cmp; use std::cmp;
use std::sync::Arc; use std::sync::Arc;
use util::{U256, Address, H256, Hashable}; use util::{U256, Address, H256, Hashable};
use header::BlockNumber; use types::BlockNumber;
use ethjson; use ethjson;
/// Simple vector of hashes, should be at most 256 items large, can be smaller if being used /// Simple vector of hashes, should be at most 256 items large, can be smaller if being used
@ -82,7 +82,7 @@ mod tests {
use ethjson; use ethjson;
#[test] #[test]
fn it_serializes_form_json() { fn it_serializes_from_json() {
let env_info = EnvInfo::from(ethjson::vm::Env { let env_info = EnvInfo::from(ethjson::vm::Env {
author: ethjson::hash::Address(Address::from_str("000000f00000000f000000000000f00000000f00").unwrap()), author: ethjson::hash::Address(Address::from_str("000000f00000000f000000000000f00000000f00").unwrap()),
number: ethjson::uint::Uint(U256::from(1_112_339)), number: ethjson::uint::Uint(U256::from(1_112_339)),

View File

@ -19,8 +19,8 @@
use std::{ops, cmp, fmt}; use std::{ops, cmp, fmt};
use util::{U128, U256, U512, trie}; use util::{U128, U256, U512, trie};
use action_params::ActionParams; use action_params::ActionParams;
use evm::Ext; use {Ext};
use builtin;
use super::wasm; use super::wasm;
/// Evm errors. /// Evm errors.
@ -77,12 +77,6 @@ impl From<Box<trie::TrieError>> for Error {
} }
} }
impl From<builtin::Error> for Error {
fn from(err: builtin::Error) -> Self {
Error::BuiltIn(err.0)
}
}
impl From<wasm::RuntimeError> for Error { impl From<wasm::RuntimeError> for Error {
fn from(err: wasm::RuntimeError) -> Self { fn from(err: wasm::RuntimeError) -> Self {
Error::Wasm(format!("Runtime error: {:?}", err)) Error::Wasm(format!("Runtime error: {:?}", err))
@ -109,7 +103,6 @@ impl fmt::Display for Error {
/// A specialized version of Result over EVM errors. /// A specialized version of Result over EVM errors.
pub type Result<T> = ::std::result::Result<T, Error>; pub type Result<T> = ::std::result::Result<T, Error>;
/// Return data buffer. Holds memory from a previous call and a slice into that memory. /// Return data buffer. Holds memory from a previous call and a slice into that memory.
#[derive(Debug)] #[derive(Debug)]
pub struct ReturnData { pub struct ReturnData {

View File

@ -17,9 +17,10 @@
//! Interface for Evm externalities. //! Interface for Evm externalities.
use util::*; use util::*;
use evm::{self, Schedule, ReturnData}; use call_type::CallType;
use env_info::*; use env_info::EnvInfo;
use types::executed::CallType; use schedule::Schedule;
use evm::{self, ReturnData};
/// Result of externalities create function. /// Result of externalities create function.
pub enum ContractCreateResult { pub enum ContractCreateResult {

View File

@ -16,10 +16,11 @@
use util::*; use util::*;
use super::u256_to_address; use super::u256_to_address;
use evm::{self, CostType};
use evm::instructions::{self, Instruction, InstructionInfo}; use {evm, ext};
use evm::interpreter::stack::Stack; use instructions::{self, Instruction, InstructionInfo};
use evm::schedule::Schedule; use interpreter::stack::Stack;
use schedule::Schedule;
macro_rules! overflowing { macro_rules! overflowing {
($x: expr) => {{ ($x: expr) => {{
@ -30,26 +31,26 @@ macro_rules! overflowing {
} }
#[cfg_attr(feature="dev", allow(enum_variant_names))] #[cfg_attr(feature="dev", allow(enum_variant_names))]
enum Request<Cost: CostType> { enum Request<Cost: ::evm::CostType> {
Gas(Cost), Gas(Cost),
GasMem(Cost, Cost), GasMem(Cost, Cost),
GasMemProvide(Cost, Cost, Option<U256>), GasMemProvide(Cost, Cost, Option<U256>),
GasMemCopy(Cost, Cost, Cost) GasMemCopy(Cost, Cost, Cost)
} }
pub struct InstructionRequirements<Cost: CostType> { pub struct InstructionRequirements<Cost> {
pub gas_cost: Cost, pub gas_cost: Cost,
pub provide_gas: Option<Cost>, pub provide_gas: Option<Cost>,
pub memory_total_gas: Cost, pub memory_total_gas: Cost,
pub memory_required_size: usize, pub memory_required_size: usize,
} }
pub struct Gasometer<Gas: CostType> { pub struct Gasometer<Gas> {
pub current_gas: Gas, pub current_gas: Gas,
pub current_mem_gas: Gas, pub current_mem_gas: Gas,
} }
impl<Gas: CostType> Gasometer<Gas> { impl<Gas: evm::CostType> Gasometer<Gas> {
pub fn new(current_gas: Gas) -> Self { pub fn new(current_gas: Gas) -> Self {
Gasometer { Gasometer {
@ -106,7 +107,7 @@ impl<Gas: CostType> Gasometer<Gas> {
/// it will be the amount of gas that the current context provides to the child context. /// it will be the amount of gas that the current context provides to the child context.
pub fn requirements( pub fn requirements(
&mut self, &mut self,
ext: &evm::Ext, ext: &ext::Ext,
instruction: Instruction, instruction: Instruction,
info: &InstructionInfo, info: &InstructionInfo,
stack: &Stack<U256>, stack: &Stack<U256>,
@ -290,7 +291,7 @@ impl<Gas: CostType> Gasometer<Gas> {
}) })
} }
fn mem_gas_cost(&self, schedule: &evm::Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> { fn mem_gas_cost(&self, schedule: &Schedule, current_mem_size: usize, mem_size: &Gas) -> evm::Result<(Gas, Gas, usize)> {
let gas_for_mem = |mem_size: Gas| { let gas_for_mem = |mem_size: Gas| {
let s = mem_size >> 5; let s = mem_size >> 5;
// s * memory_gas + s * s / quad_coeff_div // s * memory_gas + s * s / quad_coeff_div
@ -318,12 +319,12 @@ impl<Gas: CostType> Gasometer<Gas> {
#[inline] #[inline]
fn mem_needed_const<Gas: CostType>(mem: &U256, add: usize) -> evm::Result<Gas> { fn mem_needed_const<Gas: evm::CostType>(mem: &U256, add: usize) -> evm::Result<Gas> {
Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add)))) Gas::from_u256(overflowing!(mem.overflowing_add(U256::from(add))))
} }
#[inline] #[inline]
fn mem_needed<Gas: CostType>(offset: &U256, size: &U256) -> evm::Result<Gas> { fn mem_needed<Gas: evm::CostType>(offset: &U256, size: &U256) -> evm::Result<Gas> {
if size.is_zero() { if size.is_zero() {
return Ok(Gas::from(0)); return Ok(Gas::from(0));
} }
@ -332,7 +333,7 @@ fn mem_needed<Gas: CostType>(offset: &U256, size: &U256) -> evm::Result<Gas> {
} }
#[inline] #[inline]
fn add_gas_usize<Gas: CostType>(value: Gas, num: usize) -> (Gas, bool) { fn add_gas_usize<Gas: evm::CostType>(value: Gas, num: usize) -> (Gas, bool) {
value.overflow_add(Gas::from(num)) value.overflow_add(Gas::from(num))
} }
@ -340,7 +341,7 @@ fn add_gas_usize<Gas: CostType>(value: Gas, num: usize) -> (Gas, bool) {
fn test_mem_gas_cost() { fn test_mem_gas_cost() {
// given // given
let gasometer = Gasometer::<U256>::new(U256::zero()); let gasometer = Gasometer::<U256>::new(U256::zero());
let schedule = evm::Schedule::default(); let schedule = Schedule::default();
let current_mem_size = 5; let current_mem_size = 5;
let mem_size = !U256::zero(); let mem_size = !U256::zero();
@ -357,7 +358,7 @@ fn test_mem_gas_cost() {
fn test_calculate_mem_cost() { fn test_calculate_mem_cost() {
// given // given
let gasometer = Gasometer::<usize>::new(0); let gasometer = Gasometer::<usize>::new(0);
let schedule = evm::Schedule::default(); let schedule = Schedule::default();
let current_mem_size = 0; let current_mem_size = 0;
let mem_size = 5; let mem_size = 5;

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use util::U256; use util::U256;
use evm::ReturnData; use {ReturnData};
const MAX_RETURN_WASTE_BYTES: usize = 16384; const MAX_RETURN_WASTE_BYTES: usize = 16384;

View File

@ -30,9 +30,10 @@ pub use self::shared_cache::SharedCache;
use std::marker::PhantomData; use std::marker::PhantomData;
use action_params::{ActionParams, ActionValue}; use action_params::{ActionParams, ActionValue};
use types::executed::CallType; use call_type::CallType;
use evm::instructions::{self, Instruction, InstructionInfo}; use instructions::{self, Instruction, InstructionInfo};
use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType, CreateContractAddress, ReturnData}; use evm::{self, GasLeft, CostType, ReturnData};
use ext::{self, MessageCallResult, ContractCreateResult, CreateContractAddress};
use bit_set::BitSet; use bit_set::BitSet;
use util::*; use util::*;
@ -107,7 +108,7 @@ pub struct Interpreter<Cost: CostType> {
} }
impl<Cost: CostType> evm::Evm for Interpreter<Cost> { impl<Cost: CostType> evm::Evm for Interpreter<Cost> {
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> { fn exec(&mut self, params: ActionParams, ext: &mut ext::Ext) -> evm::Result<GasLeft> {
self.mem.clear(); self.mem.clear();
let mut informant = informant::EvmInformant::new(ext.depth()); let mut informant = informant::EvmInformant::new(ext.depth());
@ -204,7 +205,7 @@ impl<Cost: CostType> Interpreter<Cost> {
} }
} }
fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> { fn verify_instruction(&self, ext: &ext::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
let schedule = ext.schedule(); let schedule = ext.schedule();
if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) || if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
@ -270,7 +271,7 @@ impl<Cost: CostType> Interpreter<Cost> {
&mut self, &mut self,
gas: Cost, gas: Cost,
params: &ActionParams, params: &ActionParams,
ext: &mut evm::Ext, ext: &mut ext::Ext,
instruction: Instruction, instruction: Instruction,
code: &mut CodeReader, code: &mut CodeReader,
stack: &mut Stack<U256>, stack: &mut Stack<U256>,

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::fmt; use std::fmt;
use evm::instructions; use instructions;
/// Stack trait with VM-friendly API /// Stack trait with VM-friendly API
pub trait Stack<T> { pub trait Stack<T> {

View File

@ -18,7 +18,7 @@
use util::*; use util::*;
use evmjit; use evmjit;
use evm::{self, GasLeft}; use evm::{self, GasLeft};
use types::executed::CallType; use evm::CallType;
/// Should be used to convert jit types to ethcore /// Should be used to convert jit types to ethcore
trait FromJit<T>: Sized { trait FromJit<T>: Sized {

View File

@ -16,16 +16,41 @@
//! Ethereum virtual machine. //! Ethereum virtual machine.
extern crate byteorder;
extern crate bit_set;
extern crate common_types as types;
extern crate ethcore_util as util;
extern crate ethjson;
extern crate rlp;
extern crate parity_wasm;
extern crate wasm_utils;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[cfg(feature = "jit")]
extern crate evmjit;
#[cfg(test)]
extern crate rustc_hex;
pub mod action_params;
pub mod call_type;
pub mod env_info;
pub mod ext; pub mod ext;
pub mod evm; pub mod evm;
pub mod interpreter; pub mod interpreter;
#[macro_use]
pub mod factory;
pub mod schedule; pub mod schedule;
pub mod wasm; pub mod wasm;
#[macro_use]
pub mod factory;
mod vmtype; mod vmtype;
mod instructions; mod instructions;
#[cfg(feature = "jit" )] #[cfg(feature = "jit" )]
mod jit; mod jit;
@ -34,10 +59,12 @@ mod tests;
#[cfg(all(feature="benches", test))] #[cfg(all(feature="benches", test))]
mod benches; mod benches;
pub use self::action_params::ActionParams;
pub use self::call_type::CallType;
pub use self::env_info::EnvInfo;
pub use self::evm::{Evm, Error, Finalize, FinalizationResult, GasLeft, Result, CostType, ReturnData}; pub use self::evm::{Evm, Error, Finalize, FinalizationResult, GasLeft, Result, CostType, ReturnData};
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress}; pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes}; pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes};
pub use self::vmtype::VMType; pub use self::vmtype::VMType;
pub use self::factory::Factory; pub use self::factory::Factory;
pub use self::schedule::{Schedule, CleanDustMode}; pub use self::schedule::{Schedule, CleanDustMode};
pub use types::executed::CallType;

View File

@ -15,7 +15,6 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Cost schedule and other parameterisations for the EVM. //! Cost schedule and other parameterisations for the EVM.
use spec::CommonParams;
/// Definition of the cost schedule and other parameterisations for the EVM. /// Definition of the cost schedule and other parameterisations for the EVM.
pub struct Schedule { pub struct Schedule {
@ -185,26 +184,6 @@ impl Schedule {
} }
} }
/// Schedule for the post-EIP-150-era of the Ethereum main net.
pub fn from_params(block_number: u64, params: &CommonParams) -> Schedule {
let mut schedule = Schedule::new_post_eip150(usize::max_value(), true, true, true);
schedule.apply_params(block_number, params);
schedule
}
/// Apply common spec config parameters to the schedule.
pub fn apply_params(&mut self, block_number: u64, params: &CommonParams) {
self.have_create2 = block_number >= params.eip86_transition;
self.have_revert = block_number >= params.eip140_transition;
self.have_static_call = block_number >= params.eip214_transition;
if block_number >= params.eip210_transition {
self.blockhash_gas = 350;
}
if block_number >= params.dust_protection_transition {
self.kill_dust = if params.remove_dust_contracts { CleanDustMode::WithCodeAndStorage } else { CleanDustMode::BasicOnly };
}
}
/// Schedule for the Metropolis of the Ethereum main net. /// Schedule for the Metropolis of the Ethereum main net.
pub fn new_metropolis() -> Schedule { pub fn new_metropolis() -> Schedule {
let mut schedule = Self::new_post_eip150(24576, true, true, true); let mut schedule = Self::new_post_eip150(24576, true, true, true);

View File

@ -19,13 +19,12 @@ use rustc_hex::FromHex;
use util::*; use util::*;
use action_params::{ActionParams, ActionValue}; use action_params::{ActionParams, ActionValue};
use env_info::EnvInfo; use env_info::EnvInfo;
use types::executed::CallType; use call_type::CallType;
use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData}; use schedule::Schedule;
use tests::helpers::*; use evm::{self, GasLeft, ReturnData};
use types::transaction::SYSTEM_ADDRESS; use ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
use executive::Executive; use factory::Factory;
use state::Substate; use vmtype::VMType;
use trace::{NoopVMTracer, NoopTracer};
pub struct FakeLogEntry { pub struct FakeLogEntry {
topics: Vec<H256>, topics: Vec<H256>,
@ -438,67 +437,6 @@ fn test_blockhash(factory: super::Factory) {
assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash); assert_eq!(ext.store.get(&H256::new()).unwrap(), &blockhash);
} }
evm_test!{test_blockhash_eip210: test_blockhash_eip210_jit, test_blockhash_eip210_int}
fn test_blockhash_eip210(factory: super::Factory) {
let get_prev_hash_code = Arc::new("600143034060205260206020f3".from_hex().unwrap()); // this returns previous block hash
let get_prev_hash_code_hash = get_prev_hash_code.sha3();
// This is same as DEFAULT_BLOCKHASH_CONTRACT except for metropolis transition block check removed.
let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b";
let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap());
let blockhash_contract_code_hash = blockhash_contract_code.sha3();
let engine = TestEngine::new_metropolis();
let mut env_info = EnvInfo::default();
// populate state with 256 last hashes
let mut state = get_temp_state_with_factory(factory);
let contract_address: Address = 0xf0.into();
state.init_code(&contract_address, (*blockhash_contract_code).clone()).unwrap();
for i in 1 .. 257 {
env_info.number = i.into();
let params = ActionParams {
code_address: contract_address.clone(),
address: contract_address,
sender: SYSTEM_ADDRESS.clone(),
origin: SYSTEM_ADDRESS.clone(),
gas: 100000.into(),
gas_price: 0.into(),
value: ActionValue::Transfer(0.into()),
code: Some(blockhash_contract_code.clone()),
code_hash: Some(blockhash_contract_code_hash),
data: Some(H256::from(i - 1).to_vec()),
call_type: CallType::Call,
};
let mut ex = Executive::new(&mut state, &env_info, &engine);
let mut substate = Substate::new();
let mut output = [];
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
panic!("Encountered error on updating last hashes: {}", e);
}
}
env_info.number = 256;
let params = ActionParams {
code_address: Address::new(),
address: Address::new(),
sender: Address::new(),
origin: Address::new(),
gas: 100000.into(),
gas_price: 0.into(),
value: ActionValue::Transfer(0.into()),
code: Some(get_prev_hash_code),
code_hash: Some(get_prev_hash_code_hash),
data: None,
call_type: CallType::Call,
};
let mut ex = Executive::new(&mut state, &env_info, &engine);
let mut substate = Substate::new();
let mut output = H256::new();
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
panic!("Encountered error on getting last hash: {}", e);
}
assert_eq!(output, 255.into());
}
evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int} evm_test!{test_calldataload: test_calldataload_jit, test_calldataload_int}
fn test_calldataload(factory: super::Factory) { fn test_calldataload(factory: super::Factory) {
let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap(); let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();

View File

@ -58,7 +58,7 @@ impl WasmInterpreter {
impl evm::Evm for WasmInterpreter { impl evm::Evm for WasmInterpreter {
fn exec(&mut self, params: ActionParams, ext: &mut evm::Ext) -> evm::Result<GasLeft> { fn exec(&mut self, params: ActionParams, ext: &mut ::ext::Ext) -> evm::Result<GasLeft> {
use parity_wasm::elements::Deserialize; use parity_wasm::elements::Deserialize;
let code = params.code.expect("exec is only called on contract with code; qed"); let code = params.code.expect("exec is only called on contract with code; qed");
@ -76,7 +76,7 @@ impl evm::Evm for WasmInterpreter {
if params.gas > ::std::u64::MAX.into() { if params.gas > ::std::u64::MAX.into() {
return Err(evm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned())); return Err(evm::Error::Wasm("Wasm interpreter cannot run contracts with gas >= 2^64".to_owned()));
} }
let mut runtime = Runtime::with_params( let mut runtime = Runtime::with_params(
ext, ext,
env_memory, env_memory,
@ -106,7 +106,7 @@ impl evm::Evm for WasmInterpreter {
{ {
let execution_params = interpreter::ExecutionParams::with_external( let execution_params = interpreter::ExecutionParams::with_external(
"env".into(), "env".into(),
Arc::new( Arc::new(
interpreter::env_native_module(env_instance, native_bindings(&mut runtime)) interpreter::env_native_module(env_instance, native_bindings(&mut runtime))
.map_err(|err| { .map_err(|err| {
@ -115,7 +115,7 @@ impl evm::Evm for WasmInterpreter {
})? })?
) )
).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32)); ).add_argument(interpreter::RuntimeValue::I32(d_ptr.as_raw() as i32));
let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals)) let module_instance = self.program.add_module("contract", contract_module, Some(&execution_params.externals))
.map_err(|err| { .map_err(|err| {
trace!(target: "wasm", "Error adding contract module: {:?}", err); trace!(target: "wasm", "Error adding contract module: {:?}", err);
@ -138,11 +138,11 @@ impl evm::Evm for WasmInterpreter {
// todo: use memory views to avoid copy // todo: use memory views to avoid copy
self.result.extend(result.pop(&*runtime.memory())?); self.result.extend(result.pop(&*runtime.memory())?);
let len = self.result.len(); let len = self.result.len();
Ok(GasLeft::NeedsReturn { Ok(GasLeft::NeedsReturn {
gas_left: runtime.gas_left()?.into(), gas_left: runtime.gas_left()?.into(),
data: ReturnData::new( data: ReturnData::new(
::std::mem::replace(&mut self.result, Vec::with_capacity(DEFAULT_RESULT_BUFFER)), ::std::mem::replace(&mut self.result, Vec::with_capacity(DEFAULT_RESULT_BUFFER)),
0, 0,
len, len,
), ),
apply_state: true, apply_state: true,
@ -156,4 +156,4 @@ fn native_bindings<'a>(runtime: &'a mut Runtime) -> interpreter::UserFunctions<'
executor: runtime, executor: runtime,
functions: ::std::borrow::Cow::from(env::SIGNATURES), functions: ::std::borrow::Cow::from(env::SIGNATURES),
} }
} }

View File

@ -20,7 +20,7 @@ use std::sync::Arc;
use byteorder::{LittleEndian, ByteOrder}; use byteorder::{LittleEndian, ByteOrder};
use evm; use ext;
use parity_wasm::interpreter; use parity_wasm::interpreter;
use util::{Address, H256, U256}; use util::{Address, H256, U256};
@ -62,16 +62,16 @@ pub struct Runtime<'a> {
gas_counter: u64, gas_counter: u64,
gas_limit: u64, gas_limit: u64,
dynamic_top: u32, dynamic_top: u32,
ext: &'a mut evm::Ext, ext: &'a mut ext::Ext,
memory: Arc<interpreter::MemoryInstance>, memory: Arc<interpreter::MemoryInstance>,
} }
impl<'a> Runtime<'a> { impl<'a> Runtime<'a> {
/// New runtime for wasm contract with specified params /// New runtime for wasm contract with specified params
pub fn with_params<'b>( pub fn with_params<'b>(
ext: &'b mut evm::Ext, ext: &'b mut ext::Ext,
memory: Arc<interpreter::MemoryInstance>, memory: Arc<interpreter::MemoryInstance>,
stack_space: u32, stack_space: u32,
gas_limit: u64, gas_limit: u64,
) -> Runtime<'b> { ) -> Runtime<'b> {
Runtime { Runtime {
@ -84,7 +84,7 @@ impl<'a> Runtime<'a> {
} }
/// Write to the storage from wasm memory /// Write to the storage from wasm memory
pub fn storage_write(&mut self, context: interpreter::CallerContext) pub fn storage_write(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let mut context = context; let mut context = context;
@ -99,12 +99,12 @@ impl<'a> Runtime<'a> {
} }
/// Read from the storage to wasm memory /// Read from the storage to wasm memory
pub fn storage_read(&mut self, context: interpreter::CallerContext) pub fn storage_read(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let mut context = context; let mut context = context;
let val_ptr = context.value_stack.pop_as::<i32>()?; let val_ptr = context.value_stack.pop_as::<i32>()?;
let key = self.pop_h256(&mut context)?; let key = self.pop_h256(&mut context)?;
let val = self.ext.storage_at(&key) let val = self.ext.storage_at(&key)
.map_err(|_| interpreter::Error::Trap("Storage read error".to_owned()))?; .map_err(|_| interpreter::Error::Trap("Storage read error".to_owned()))?;
@ -115,11 +115,11 @@ impl<'a> Runtime<'a> {
} }
/// Pass suicide to state runtime /// Pass suicide to state runtime
pub fn suicide(&mut self, context: interpreter::CallerContext) pub fn suicide(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let mut context = context; let mut context = context;
let refund_address = self.pop_address(&mut context)?; let refund_address = self.pop_address(&mut context)?;
self.ext.suicide(&refund_address) self.ext.suicide(&refund_address)
.map_err(|_| interpreter::Error::Trap("Suicide error".to_owned()))?; .map_err(|_| interpreter::Error::Trap("Suicide error".to_owned()))?;
@ -128,7 +128,7 @@ impl<'a> Runtime<'a> {
} }
/// Invoke create in the state runtime /// Invoke create in the state runtime
pub fn create(&mut self, context: interpreter::CallerContext) pub fn create(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
// //
@ -139,11 +139,11 @@ impl<'a> Runtime<'a> {
trace!(target: "wasm", "runtime: create contract"); trace!(target: "wasm", "runtime: create contract");
let mut context = context; let mut context = context;
let result_ptr = context.value_stack.pop_as::<i32>()? as u32; let result_ptr = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " result_ptr: {:?}", result_ptr); trace!(target: "wasm", " result_ptr: {:?}", result_ptr);
let code_len = context.value_stack.pop_as::<i32>()? as u32; let code_len = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " code_len: {:?}", code_len); trace!(target: "wasm", " code_len: {:?}", code_len);
let code_ptr = context.value_stack.pop_as::<i32>()? as u32; let code_ptr = context.value_stack.pop_as::<i32>()? as u32;
trace!(target: "wasm", " code_ptr: {:?}", code_ptr); trace!(target: "wasm", " code_ptr: {:?}", code_ptr);
let endowment = self.pop_u256(&mut context)?; let endowment = self.pop_u256(&mut context)?;
trace!(target: "wasm", " val: {:?}", endowment); trace!(target: "wasm", " val: {:?}", endowment);
@ -152,15 +152,15 @@ impl<'a> Runtime<'a> {
let gas_left = self.gas_left() let gas_left = self.gas_left()
.map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))? .map_err(|_| interpreter::Error::Trap("Gas state error".to_owned()))?
.into(); .into();
match self.ext.create(&gas_left, &endowment, &code, evm::CreateContractAddress::FromSenderAndCodeHash) { match self.ext.create(&gas_left, &endowment, &code, ext::CreateContractAddress::FromSenderAndCodeHash) {
evm::ContractCreateResult::Created(address, gas_left) => { ext::ContractCreateResult::Created(address, gas_left) => {
self.memory.set(result_ptr, &*address)?; self.memory.set(result_ptr, &*address)?;
self.gas_counter = self.gas_limit - gas_left.low_u64(); self.gas_counter = self.gas_limit - gas_left.low_u64();
trace!(target: "wasm", "runtime: create contract success (@{:?})", address); trace!(target: "wasm", "runtime: create contract success (@{:?})", address);
Ok(Some(0i32.into())) Ok(Some(0i32.into()))
}, },
evm::ContractCreateResult::Failed => { ext::ContractCreateResult::Failed => {
trace!(target: "wasm", "runtime: create contract fail"); trace!(target: "wasm", "runtime: create contract fail");
Ok(Some((-1i32).into())) Ok(Some((-1i32).into()))
} }
@ -168,7 +168,7 @@ impl<'a> Runtime<'a> {
} }
/// Allocate memory using the wasm stack params /// Allocate memory using the wasm stack params
pub fn malloc(&mut self, context: interpreter::CallerContext) pub fn malloc(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let amount = context.value_stack.pop_as::<i32>()? as u32; let amount = context.value_stack.pop_as::<i32>()? as u32;
@ -185,14 +185,14 @@ impl<'a> Runtime<'a> {
} }
/// Report gas cost with the params passed in wasm stack /// Report gas cost with the params passed in wasm stack
fn gas(&mut self, context: interpreter::CallerContext) fn gas(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let amount = context.value_stack.pop_as::<i32>()? as u64; let amount = context.value_stack.pop_as::<i32>()? as u64;
if self.charge_gas(amount) { if self.charge_gas(amount) {
Ok(None) Ok(None)
} else { } else {
Err(interpreter::Error::Trap(format!("Gas exceeds limits of {}", self.gas_limit))) Err(interpreter::Error::Trap(format!("Gas exceeds limits of {}", self.gas_limit)))
} }
} }
@ -204,13 +204,13 @@ impl<'a> Runtime<'a> {
} else { } else {
self.gas_counter = prev + amount; self.gas_counter = prev + amount;
true true
} }
} }
fn h256_at(&self, ptr: WasmPtr) -> Result<H256, interpreter::Error> { fn h256_at(&self, ptr: WasmPtr) -> Result<H256, interpreter::Error> {
Ok(H256::from_slice(&ptr.slice(32, &*self.memory) Ok(H256::from_slice(&ptr.slice(32, &*self.memory)
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))? .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?
)) ))
} }
fn pop_h256(&self, context: &mut interpreter::CallerContext) -> Result<H256, interpreter::Error> { fn pop_h256(&self, context: &mut interpreter::CallerContext) -> Result<H256, interpreter::Error> {
@ -228,7 +228,7 @@ impl<'a> Runtime<'a> {
fn address_at(&self, ptr: WasmPtr) -> Result<Address, interpreter::Error> { fn address_at(&self, ptr: WasmPtr) -> Result<Address, interpreter::Error> {
Ok(Address::from_slice(&ptr.slice(20, &*self.memory) Ok(Address::from_slice(&ptr.slice(20, &*self.memory)
.map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))? .map_err(|_| interpreter::Error::Trap("Memory access violation".to_owned()))?
)) ))
} }
fn pop_address(&self, context: &mut interpreter::CallerContext) -> Result<Address, interpreter::Error> { fn pop_address(&self, context: &mut interpreter::CallerContext) -> Result<Address, interpreter::Error> {
@ -237,13 +237,13 @@ impl<'a> Runtime<'a> {
self.address_at(ptr) self.address_at(ptr)
} }
fn user_trap(&mut self, _context: interpreter::CallerContext) fn user_trap(&mut self, _context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
Err(interpreter::Error::Trap("unknown trap".to_owned())) Err(interpreter::Error::Trap("unknown trap".to_owned()))
} }
fn user_noop(&mut self, fn user_noop(&mut self,
_context: interpreter::CallerContext _context: interpreter::CallerContext
) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> { ) -> Result<Option<interpreter::RuntimeValue>, interpreter::Error> {
Ok(None) Ok(None)
@ -270,16 +270,16 @@ impl<'a> Runtime<'a> {
self.memory.set(args_ptr+40, &call_args.origin)?; self.memory.set(args_ptr+40, &call_args.origin)?;
self.memory.set(args_ptr+60, &call_args.value)?; self.memory.set(args_ptr+60, &call_args.value)?;
self.memory.set(args_ptr+92, &call_args.data)?; self.memory.set(args_ptr+92, &call_args.data)?;
Ok(d_ptr.into()) Ok(d_ptr.into())
} }
fn debug_log(&mut self, context: interpreter::CallerContext) fn debug_log(&mut self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let msg_len = context.value_stack.pop_as::<i32>()? as u32; let msg_len = context.value_stack.pop_as::<i32>()? as u32;
let msg_ptr = context.value_stack.pop_as::<i32>()? as u32; let msg_ptr = context.value_stack.pop_as::<i32>()? as u32;
let msg = String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?) let msg = String::from_utf8(self.memory.get(msg_ptr, msg_len as usize)?)
.map_err(|_| interpreter::Error::Trap("Debug log utf-8 decoding error".to_owned()))?; .map_err(|_| interpreter::Error::Trap("Debug log utf-8 decoding error".to_owned()))?;
@ -299,8 +299,8 @@ impl<'a> Runtime<'a> {
&*self.memory &*self.memory
} }
fn mem_copy(&self, context: interpreter::CallerContext) fn mem_copy(&self, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
let len = context.value_stack.pop_as::<i32>()? as u32; let len = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32; let dst = context.value_stack.pop_as::<i32>()? as u32;
@ -314,7 +314,7 @@ impl<'a> Runtime<'a> {
} }
impl<'a> interpreter::UserFunctionExecutor for Runtime<'a> { impl<'a> interpreter::UserFunctionExecutor for Runtime<'a> {
fn execute(&mut self, name: &str, context: interpreter::CallerContext) fn execute(&mut self, name: &str, context: interpreter::CallerContext)
-> Result<Option<interpreter::RuntimeValue>, interpreter::Error> -> Result<Option<interpreter::RuntimeValue>, interpreter::Error>
{ {
match name { match name {
@ -353,4 +353,4 @@ impl<'a> interpreter::UserFunctionExecutor for Runtime<'a> {
} }
} }
} }
} }

View File

@ -1,22 +1,31 @@
use std::path::PathBuf; // Copyright 2015-2017 Parity Technologies (UK) Ltd.
use std::fs::File; // This file is part of Parity.
use std::io::Read;
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::sync::Arc; use std::sync::Arc;
use ethcore_logger::init_log;
use super::super::tests::{FakeExt, FakeCall, FakeCallType}; use super::super::tests::{FakeExt, FakeCall, FakeCallType};
use super::WasmInterpreter; use super::WasmInterpreter;
use evm::{self, Evm, GasLeft}; use evm::{self, Evm, GasLeft};
use action_params::{ActionParams, ActionValue}; use action_params::{ActionParams, ActionValue};
use util::{U256, H256, Address}; use util::{U256, H256, Address};
fn load_sample(name: &str) -> Vec<u8> { macro_rules! load_sample {
let mut path = PathBuf::from("./res/wasm-tests/compiled"); ($name: expr) => {
path.push(name); include_bytes!(concat!("../../../res/wasm-tests/compiled/", $name)).to_vec()
let mut file = File::open(path).expect(&format!("File {} for test to exist", name)); }
let mut data = vec![];
file.read_to_end(&mut data).expect(&format!("Test {} to load ok", name));
data
} }
fn test_finalize(res: Result<GasLeft, evm::Error>) -> Result<U256, evm::Error> { fn test_finalize(res: Result<GasLeft, evm::Error>) -> Result<U256, evm::Error> {
@ -34,9 +43,7 @@ fn wasm_interpreter() -> WasmInterpreter {
/// Empty contract does almost nothing except producing 1 (one) local node debug log message /// Empty contract does almost nothing except producing 1 (one) local node debug log message
#[test] #[test]
fn empty() { fn empty() {
init_log(); let code = load_sample!("empty.wasm");
let code = load_sample("empty.wasm");
let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let mut params = ActionParams::default(); let mut params = ActionParams::default();
@ -58,9 +65,7 @@ fn empty() {
// logger.wasm writes all these provided fixed header fields to some arbitrary storage keys. // logger.wasm writes all these provided fixed header fields to some arbitrary storage keys.
#[test] #[test]
fn logger() { fn logger() {
init_log(); let code = load_sample!("logger.wasm");
let code = load_sample("logger.wasm");
let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let sender: Address = "0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d".parse().unwrap(); let sender: Address = "0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d".parse().unwrap();
let origin: Address = "0102030405060708090a0b0c0d0e0f1011121314".parse().unwrap(); let origin: Address = "0102030405060708090a0b0c0d0e0f1011121314".parse().unwrap();
@ -113,9 +118,7 @@ fn logger() {
// if it has any result. // if it has any result.
#[test] #[test]
fn identity() { fn identity() {
init_log(); let code = load_sample!("identity.wasm");
let code = load_sample("identity.wasm");
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let mut params = ActionParams::default(); let mut params = ActionParams::default();
@ -143,14 +146,12 @@ fn identity() {
} }
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with // Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
// their modulo 19 dopant. // their modulo 19 dopant.
// The result is always twice as long as the input. // The result is always twice as long as the input.
// This also tests byte-perfect memory allocation and in/out ptr lifecycle. // This also tests byte-perfect memory allocation and in/out ptr lifecycle.
#[test] #[test]
fn dispersion() { fn dispersion() {
init_log(); let code = load_sample!("dispersion.wasm");
let code = load_sample("dispersion.wasm");
let mut params = ActionParams::default(); let mut params = ActionParams::default();
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
@ -179,9 +180,7 @@ fn dispersion() {
#[test] #[test]
fn suicide_not() { fn suicide_not() {
init_log(); let code = load_sample!("suicidal.wasm");
let code = load_sample("suicidal.wasm");
let mut params = ActionParams::default(); let mut params = ActionParams::default();
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
@ -205,14 +204,12 @@ fn suicide_not() {
assert_eq!( assert_eq!(
result, result,
vec![0u8] vec![0u8]
); );
} }
#[test] #[test]
fn suicide() { fn suicide() {
init_log(); let code = load_sample!("suicidal.wasm");
let code = load_sample("suicidal.wasm");
let refund: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); let refund: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
let mut params = ActionParams::default(); let mut params = ActionParams::default();
@ -242,11 +239,9 @@ fn suicide() {
#[test] #[test]
fn create() { fn create() {
init_log();
let mut params = ActionParams::default(); let mut params = ActionParams::default();
params.gas = U256::from(100_000); params.gas = U256::from(100_000);
params.code = Some(Arc::new(load_sample("creator.wasm"))); params.code = Some(Arc::new(load_sample!("creator.wasm")));
params.data = Some(vec![0u8, 2, 4, 8, 16, 32, 64, 128]); params.data = Some(vec![0u8, 2, 4, 8, 16, 32, 64, 128]);
params.value = ActionValue::transfer(1_000_000_000); params.value = ActionValue::transfer(1_000_000_000);
@ -276,4 +271,4 @@ fn create() {
} }
)); ));
assert_eq!(gas_left, U256::from(99_768)); assert_eq!(gas_left, U256::from(99_768));
} }

View File

@ -3,7 +3,7 @@ description = "Parity Light Client Implementation"
homepage = "http://parity.io" homepage = "http://parity.io"
license = "GPL-3.0" license = "GPL-3.0"
name = "ethcore-light" name = "ethcore-light"
version = "1.7.0" version = "1.8.0"
authors = ["Parity Technologies <admin@parity.io>"] authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs" build = "build.rs"
@ -18,6 +18,7 @@ ethcore-network = { path = "../../util/network" }
ethcore-io = { path = "../../util/io" } ethcore-io = { path = "../../util/io" }
ethcore-ipc = { path = "../../ipc/rpc", optional = true } ethcore-ipc = { path = "../../ipc/rpc", optional = true }
ethcore-devtools = { path = "../../devtools" } ethcore-devtools = { path = "../../devtools" }
evm = { path = "../evm" }
rlp = { path = "../../util/rlp" } rlp = { path = "../../util/rlp" }
time = "0.1" time = "0.1"
smallvec = "0.4" smallvec = "0.4"

View File

@ -18,10 +18,10 @@
use std::sync::{Weak, Arc}; use std::sync::{Weak, Arc};
use ethcore::block_import_error::BlockImportError;
use ethcore::block_status::BlockStatus; use ethcore::block_status::BlockStatus;
use ethcore::client::{ClientReport, EnvInfo}; use ethcore::client::{ClientReport, EnvInfo};
use ethcore::engines::Engine; use ethcore::engines::Engine;
use ethcore::error::BlockImportError;
use ethcore::ids::BlockId; use ethcore::ids::BlockId;
use ethcore::header::Header; use ethcore::header::Header;
use ethcore::verification::queue::{self, HeaderQueue}; use ethcore::verification::queue::{self, HeaderQueue};

View File

@ -71,6 +71,7 @@ extern crate ethcore_io as io;
extern crate ethcore_network as network; extern crate ethcore_network as network;
extern crate ethcore_util as util; extern crate ethcore_util as util;
extern crate ethcore; extern crate ethcore;
extern crate evm;
extern crate futures; extern crate futures;
extern crate itertools; extern crate itertools;
extern crate rand; extern crate rand;

View File

@ -21,10 +21,10 @@ use std::sync::Arc;
use ethcore::basic_account::BasicAccount; use ethcore::basic_account::BasicAccount;
use ethcore::encoded; use ethcore::encoded;
use ethcore::engines::Engine; use ethcore::engines::Engine;
use ethcore::env_info::EnvInfo;
use ethcore::receipt::Receipt; use ethcore::receipt::Receipt;
use ethcore::state::{self, ProvedExecution}; use ethcore::state::{self, ProvedExecution};
use ethcore::transaction::SignedTransaction; use ethcore::transaction::SignedTransaction;
use evm::env_info::EnvInfo;
use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field}; use request::{self as net_request, IncompleteRequest, CompleteRequest, Output, OutputKind, Field};

View File

@ -26,9 +26,8 @@
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use ethcore::error::TransactionError; use ethcore::error::{TransactionError, TransactionImportResult};
use ethcore::transaction::{Condition, PendingTransaction, SignedTransaction}; use ethcore::transaction::{Condition, PendingTransaction, SignedTransaction};
use ethcore::transaction_import::TransactionImportResult;
use util::{Address, U256, H256, H256FastMap}; use util::{Address, U256, H256, H256FastMap};
// Knowledge of an account's current nonce. // Knowledge of an account's current nonce.

View File

@ -64,7 +64,9 @@ pub enum SignError {
/// Low-level hardware device error. /// Low-level hardware device error.
Hardware(HardwareError), Hardware(HardwareError),
/// Low-level error from store /// Low-level error from store
SStore(SSError) SStore(SSError),
/// Inappropriate chain
InappropriateChain,
} }
impl fmt::Display for SignError { impl fmt::Display for SignError {
@ -74,6 +76,7 @@ impl fmt::Display for SignError {
SignError::NotFound => write!(f, "Account does not exist"), SignError::NotFound => write!(f, "Account does not exist"),
SignError::Hardware(ref e) => write!(f, "{}", e), SignError::Hardware(ref e) => write!(f, "{}", e),
SignError::SStore(ref e) => write!(f, "{}", e), SignError::SStore(ref e) => write!(f, "{}", e),
SignError::InappropriateChain => write!(f, "Inappropriate chain"),
} }
} }
} }

View File

@ -16,13 +16,11 @@
//! Ethcore basic typenames. //! Ethcore basic typenames.
use util::hash::H2048;
/// Type for a 2048-bit log-bloom, as used by our blocks. /// Type for a 2048-bit log-bloom, as used by our blocks.
pub type LogBloom = H2048; pub type LogBloom = ::log_entry::LogBloom;
/// Constant 2048-bit datum for 0. Often used as a default. /// Constant 2048-bit datum for 0. Often used as a default.
pub static ZERO_LOGBLOOM: LogBloom = H2048([0x00; 256]); pub static ZERO_LOGBLOOM: LogBloom = ::util::hash::H2048([0x00; 256]);
#[cfg_attr(feature="dev", allow(enum_variant_names))] #[cfg_attr(feature="dev", allow(enum_variant_names))]
/// Semantic boolean for when a seal/signature is included. /// Semantic boolean for when a seal/signature is included.

View File

@ -25,7 +25,7 @@ use util::{Bytes, Address, Hashable, U256, H256, ordered_trie_root, SHA3_NULL_RL
use util::error::{Mismatch, OutOfBounds}; use util::error::{Mismatch, OutOfBounds};
use basic_types::{LogBloom, Seal}; use basic_types::{LogBloom, Seal};
use env_info::{EnvInfo, LastHashes}; use evm::env_info::{EnvInfo, LastHashes};
use engines::Engine; use engines::Engine;
use error::{Error, BlockError, TransactionError}; use error::{Error, BlockError, TransactionError};
use factory::Factories; use factory::Factories;
@ -200,7 +200,7 @@ pub trait IsBlock {
/// Trait for a object that has a state database. /// Trait for a object that has a state database.
pub trait Drain { pub trait Drain {
/// Drop this object and return the underlieing database. /// Drop this object and return the underlying database.
fn drain(self) -> StateDB; fn drain(self) -> StateDB;
} }
@ -370,6 +370,22 @@ impl<'x> OpenBlock<'x> {
} }
} }
/// Push transactions onto the block.
pub fn push_transactions(&mut self, transactions: &[SignedTransaction]) -> Result<(), Error> {
push_transactions(self, transactions)
}
/// Populate self from a header.
pub fn populate_from(&mut self, header: &Header) {
self.set_difficulty(*header.difficulty());
self.set_gas_limit(*header.gas_limit());
self.set_timestamp(header.timestamp());
self.set_author(header.author().clone());
self.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
self.set_uncles_hash(header.uncles_hash().clone());
self.set_transactions_root(header.transactions_root().clone());
}
/// Turn this into a `ClosedBlock`. /// Turn this into a `ClosedBlock`.
pub fn close(self) -> ClosedBlock { pub fn close(self) -> ClosedBlock {
let mut s = self; let mut s = self;
@ -579,18 +595,13 @@ pub fn enact(
is_epoch_begin, is_epoch_begin,
)?; )?;
b.set_difficulty(*header.difficulty()); b.populate_from(header);
b.set_gas_limit(*header.gas_limit()); b.push_transactions(transactions)?;
b.set_timestamp(header.timestamp());
b.set_author(header.author().clone());
b.set_extra_data(header.extra_data().clone()).unwrap_or_else(|e| warn!("Couldn't set extradata: {}. Ignoring.", e));
b.set_uncles_hash(header.uncles_hash().clone());
b.set_transactions_root(header.transactions_root().clone());
push_transactions(&mut b, transactions)?;
for u in uncles { for u in uncles {
b.push_uncle(u.clone())?; b.push_uncle(u.clone())?;
} }
Ok(b.close_and_lock()) Ok(b.close_and_lock())
} }
@ -656,7 +667,7 @@ mod tests {
use tests::helpers::*; use tests::helpers::*;
use super::*; use super::*;
use engines::Engine; use engines::Engine;
use env_info::LastHashes; use evm::env_info::LastHashes;
use error::Error; use error::Error;
use header::Header; use header::Header;
use factory::Factories; use factory::Factories;
@ -681,7 +692,36 @@ mod tests {
let header = block.header(); let header = block.header();
let transactions: Result<Vec<_>, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect(); let transactions: Result<Vec<_>, Error> = block.transactions().into_iter().map(SignedTransaction::new).collect();
let transactions = transactions?; let transactions = transactions?;
enact(&header, &transactions, &block.uncles(), engine, tracing, db, parent, last_hashes, factories, false)
{
if ::log::max_log_level() >= ::log::LogLevel::Trace {
let s = State::from_existing(db.boxed_clone(), parent.state_root().clone(), engine.account_start_nonce(parent.number() + 1), factories.clone())?;
trace!(target: "enact", "num={}, root={}, author={}, author_balance={}\n",
header.number(), s.root(), header.author(), s.balance(&header.author())?);
}
}
let mut b = OpenBlock::new(
engine,
factories,
tracing,
db,
parent,
last_hashes,
Address::new(),
(3141562.into(), 31415620.into()),
vec![],
false,
)?;
b.populate_from(&header);
b.push_transactions(&transactions)?;
for u in &block.uncles() {
b.push_uncle(u.clone())?;
}
Ok(b.close_and_lock())
} }
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards /// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards

View File

@ -36,6 +36,12 @@ impl From<&'static str> for Error {
} }
} }
impl Into<::evm::Error> for Error {
fn into(self) -> ::evm::Error {
::evm::Error::BuiltIn(self.0)
}
}
/// Native implementation of a built-in contract. /// Native implementation of a built-in contract.
pub trait Impl: Send + Sync { pub trait Impl: Send + Sync {
/// execute this built-in on the given input, writing to the given output. /// execute this built-in on the given input, writing to the given output.

View File

@ -17,7 +17,6 @@
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque}; use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
use std::fmt;
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
use std::time::{Instant}; use std::time::{Instant};
use time::precise_time_ns; use time::precise_time_ns;
@ -43,8 +42,8 @@ use client::{
}; };
use encoded; use encoded;
use engines::{Engine, EpochTransition}; use engines::{Engine, EpochTransition};
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use env_info::LastHashes; use evm::env_info::LastHashes;
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError}; use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
use evm::{Factory as EvmFactory, Schedule}; use evm::{Factory as EvmFactory, Schedule};
use executive::{Executive, Executed, TransactOptions, contract_address}; use executive::{Executive, Executed, TransactOptions, contract_address};
@ -84,12 +83,6 @@ const MAX_TX_QUEUE_SIZE: usize = 4096;
const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2; const MAX_QUEUE_SIZE_TO_SLEEP_ON: usize = 2;
const MIN_HISTORY_SIZE: u64 = 8; const MIN_HISTORY_SIZE: u64 = 8;
impl fmt::Display for BlockChainInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "#{}.{}", self.best_block_number, self.best_block_hash)
}
}
/// Report on the status of a client. /// Report on the status of a client.
#[derive(Default, Clone, Debug, Eq, PartialEq)] #[derive(Default, Clone, Debug, Eq, PartialEq)]
pub struct ClientReport { pub struct ClientReport {
@ -537,7 +530,7 @@ impl Client {
} else { } else {
imported_blocks.push(header.hash()); imported_blocks.push(header.hash());
let route = self.commit_block(closed_block, &header.hash(), &block.bytes); let route = self.commit_block(closed_block, &header, &block.bytes);
import_results.push(route); import_results.push(route);
self.report.write().accrue_block(&block); self.report.write().accrue_block(&block);
@ -642,10 +635,14 @@ impl Client {
Ok(hash) Ok(hash)
} }
fn commit_block<B>(&self, block: B, hash: &H256, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain { // NOTE: the header of the block passed here is not necessarily sealed, as
let number = block.header().number(); // it is for reconstructing the state transition.
let parent = block.header().parent_hash().clone(); //
let header = block.header().clone(); // TODO: optimize and avoid copy. // The header passed is from the original block data and is sealed.
fn commit_block<B>(&self, block: B, header: &Header, block_data: &[u8]) -> ImportRoute where B: IsBlock + Drain {
let hash = &header.hash();
let number = header.number();
let parent = header.parent_hash();
let chain = self.chain.read(); let chain = self.chain.read();
// Commit results // Commit results
@ -655,6 +652,8 @@ impl Client {
.map(Into::into) .map(Into::into)
.collect(); .collect();
assert_eq!(header.hash(), BlockView::new(block_data).header_view().sha3());
//let traces = From::from(block.traces().clone().unwrap_or_else(Vec::new)); //let traces = From::from(block.traces().clone().unwrap_or_else(Vec::new));
let mut batch = DBTransaction::new(); let mut batch = DBTransaction::new();
@ -664,6 +663,17 @@ impl Client {
// TODO: Prove it with a test. // TODO: Prove it with a test.
let mut state = block.drain(); let mut state = block.drain();
// check epoch end signal, potentially generating a proof on the current
// state.
self.check_epoch_end_signal(
&header,
block_data,
&receipts,
&state,
&chain,
&mut batch,
);
state.journal_under(&mut batch, number, hash).expect("DB commit failed"); state.journal_under(&mut batch, number, hash).expect("DB commit failed");
let route = chain.insert_block(&mut batch, block_data, receipts.clone()); let route = chain.insert_block(&mut batch, block_data, receipts.clone());
@ -681,10 +691,6 @@ impl Client {
self.db.read().write_buffered(batch); self.db.read().write_buffered(batch);
chain.commit(); chain.commit();
// check for epoch end. do this after writing first batch so we can prove
// transactions on the block's state.
// TODO: work these changes into the existing DBTransaction.
self.check_epoch_end_signal(&header, block_data, &receipts, &chain);
self.check_epoch_end(&header, &chain); self.check_epoch_end(&header, &chain);
self.update_last_hashes(&parent, hash); self.update_last_hashes(&parent, hash);
@ -698,38 +704,82 @@ impl Client {
// check for epoch end signal and write pending transition if it occurs. // check for epoch end signal and write pending transition if it occurs.
// state for the given block must be available. // state for the given block must be available.
fn check_epoch_end_signal(&self, header: &Header, block: &[u8], receipts: &[Receipt], chain: &BlockChain) { fn check_epoch_end_signal(
&self,
header: &Header,
block_bytes: &[u8],
receipts: &[Receipt],
state_db: &StateDB,
chain: &BlockChain,
batch: &mut DBTransaction,
) {
use engines::EpochChange; use engines::EpochChange;
let hash = header.hash(); let hash = header.hash();
match self.engine.signals_epoch_end(header, Some(block), Some(&receipts)) { match self.engine.signals_epoch_end(header, Some(block_bytes), Some(&receipts)) {
EpochChange::Yes(proof) => { EpochChange::Yes(proof) => {
use engines::epoch::PendingTransition; use engines::epoch::PendingTransition;
use engines::Proof; use engines::Proof;
let proof = match proof { let proof = match proof {
Proof::Known(proof) => proof, Proof::Known(proof) => proof,
Proof::WithState(with_state) => Proof::WithState(with_state) => {
match self.with_proving_caller(BlockId::Hash(hash), move |c| with_state(c)) { let env_info = EnvInfo {
number: header.number(),
author: header.author().clone(),
timestamp: header.timestamp(),
difficulty: header.difficulty().clone(),
last_hashes: self.build_last_hashes(header.parent_hash().clone()),
gas_used: U256::default(),
gas_limit: u64::max_value().into(),
};
let call = move |addr, data| {
let mut state_db = state_db.boxed_clone();
let backend = ::state::backend::Proving::new(state_db.as_hashdb_mut());
let transaction =
self.contract_call_tx(BlockId::Hash(*header.parent_hash()), addr, data);
let mut state = State::from_existing(
backend,
header.state_root().clone(),
self.engine.account_start_nonce(header.number()),
self.factories.clone(),
).expect("state known to be available for just-imported block; qed");
let options = TransactOptions { tracing: false, vm_tracing: false, check_nonce: false };
let res = Executive::new(&mut state, &env_info, &*self.engine)
.transact(&transaction, options);
let res = match res {
Err(ExecutionError::Internal(e)) =>
Err(format!("Internal error: {}", e)),
Err(e) => {
trace!(target: "client", "Proved call failed: {}", e);
Ok((Vec::new(), state.drop().1.extract_proof()))
}
Ok(res) => Ok((res.output, state.drop().1.extract_proof())),
};
res.map(|(output, proof)| (output, proof.into_iter().map(|x| x.into_vec()).collect()))
};
match (with_state)(&call) {
Ok(proof) => proof, Ok(proof) => proof,
Err(e) => { Err(e) => {
warn!(target: "client", "Failed to generate transition proof for block {}: {}", hash, e); warn!(target: "client", "Failed to generate transition proof for block {}: {}", hash, e);
warn!(target: "client", "Snapshots produced by this client may be incomplete"); warn!(target: "client", "Snapshots produced by this client may be incomplete");
Vec::new() Vec::new()
} }
}, }
}
}; };
debug!(target: "client", "Block {} signals epoch end.", hash); debug!(target: "client", "Block {} signals epoch end.", hash);
// write pending transition to DB.
let mut batch = DBTransaction::new();
let pending = PendingTransition { proof: proof }; let pending = PendingTransition { proof: proof };
chain.insert_pending_transition(&mut batch, hash, pending); chain.insert_pending_transition(batch, hash, pending);
self.db.read().write_buffered(batch);
}, },
EpochChange::No => {}, EpochChange::No => {},
EpochChange::Unsure(_) => { EpochChange::Unsure(_) => {
@ -756,7 +806,11 @@ impl Client {
block_number: header.number(), block_number: header.number(),
proof: proof, proof: proof,
}); });
self.db.read().write_buffered(batch);
// always write the batch directly since epoch transition proofs are
// fetched from a DB iterator and DB iterators are only available on
// flushed data.
self.db.read().write(batch).expect("DB flush failed");
} }
} }
@ -1773,7 +1827,9 @@ impl MiningBlockChainClient for Client {
let number = block.header().number(); let number = block.header().number();
let block_data = block.rlp_bytes(); let block_data = block.rlp_bytes();
let route = self.commit_block(block, &h, &block_data); let header = block.header().clone();
let route = self.commit_block(block, &header, &block_data);
trace!(target: "client", "Imported sealed block #{} ({})", number, h); trace!(target: "client", "Imported sealed block #{} ({})", number, h);
self.state_db.lock().sync_cache(&route.enacted, &route.retracted, false); self.state_db.lock().sync_cache(&route.enacted, &route.retracted, false);
route route

View File

@ -17,14 +17,16 @@
use std::str::FromStr; use std::str::FromStr;
use std::path::Path; use std::path::Path;
use std::fmt::{Display, Formatter, Error as FmtError}; use std::fmt::{Display, Formatter, Error as FmtError};
use mode::Mode as IpcMode;
use verification::{VerifierType, QueueConfig};
use util::{journaldb, CompactionProfile};
pub use std::time::Duration; pub use std::time::Duration;
pub use blockchain::Config as BlockChainConfig; pub use blockchain::Config as BlockChainConfig;
pub use trace::Config as TraceConfig; pub use trace::Config as TraceConfig;
pub use evm::VMType; pub use evm::VMType;
use verification::{VerifierType, QueueConfig};
use util::{journaldb, CompactionProfile};
/// Client state db compaction profile /// Client state db compaction profile
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum DatabaseCompactionProfile { pub enum DatabaseCompactionProfile {
@ -98,6 +100,29 @@ impl Display for Mode {
} }
} }
impl Into<IpcMode> for Mode {
fn into(self) -> IpcMode {
match self {
Mode::Off => IpcMode::Off,
Mode::Dark(timeout) => IpcMode::Dark(timeout.as_secs()),
Mode::Passive(timeout, alarm) => IpcMode::Passive(timeout.as_secs(), alarm.as_secs()),
Mode::Active => IpcMode::Active,
}
}
}
impl From<IpcMode> for Mode {
fn from(mode: IpcMode) -> Self {
match mode {
IpcMode::Off => Mode::Off,
IpcMode::Dark(timeout) => Mode::Dark(Duration::from_secs(timeout)),
IpcMode::Passive(timeout, alarm) => Mode::Passive(Duration::from_secs(timeout), Duration::from_secs(alarm)),
IpcMode::Active => Mode::Active,
}
}
}
/// Client configuration. Includes configs for all sub-systems. /// Client configuration. Includes configs for all sub-systems.
#[derive(Debug, PartialEq, Default)] #[derive(Debug, PartialEq, Default)]
pub struct ClientConfig { pub struct ClientConfig {

View File

@ -23,7 +23,7 @@ use util::kvdb::{self, KeyValueDB};
use {state, state_db, client, executive, trace, db, spec}; use {state, state_db, client, executive, trace, db, spec};
use factory::Factories; use factory::Factories;
use evm::{self, VMType}; use evm::{self, VMType};
use action_params::ActionParams; use evm::action_params::ActionParams;
/// EVM test Error. /// EVM test Error.
#[derive(Debug)] #[derive(Debug)]

View File

@ -40,11 +40,9 @@ pub use types::pruning_info::PruningInfo;
pub use types::call_analytics::CallAnalytics; pub use types::call_analytics::CallAnalytics;
pub use executive::{Executed, Executive, TransactOptions}; pub use executive::{Executed, Executive, TransactOptions};
pub use env_info::{LastHashes, EnvInfo}; pub use evm::env_info::{LastHashes, EnvInfo};
pub use block_import_error::BlockImportError; pub use error::{BlockImportError, TransactionImportError, TransactionImportResult};
pub use transaction_import::TransactionImportResult;
pub use transaction_import::TransactionImportError;
pub use verification::VerifierType; pub use verification::VerifierType;
/// IPC interfaces /// IPC interfaces

View File

@ -15,24 +15,27 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::collections::BTreeMap; use std::collections::BTreeMap;
use util::{U256, Address, H256, H2048, Bytes, Itertools};
use util::hashdb::DBValue;
use blockchain::TreeRoute;
use verification::queue::QueueInfo as BlockQueueInfo;
use block::{OpenBlock, SealedBlock, ClosedBlock}; use block::{OpenBlock, SealedBlock, ClosedBlock};
use header::{BlockNumber}; use blockchain::TreeRoute;
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction}; use encoded;
use transaction_import::TransactionImportResult; use evm::env_info::LastHashes;
use log_entry::LocalizedLogEntry;
use filter::Filter;
use error::{ImportResult, CallError, Error as EthcoreError}; use error::{ImportResult, CallError, Error as EthcoreError};
use receipt::LocalizedReceipt; use error::{TransactionImportResult, BlockImportError};
use trace::LocalizedTrace;
use evm::{Factory as EvmFactory, Schedule}; use evm::{Factory as EvmFactory, Schedule};
use executive::Executed; use executive::Executed;
use env_info::LastHashes; use filter::Filter;
use block_import_error::BlockImportError; use header::{BlockNumber};
use ipc::IpcConfig; use ipc::IpcConfig;
use log_entry::LocalizedLogEntry;
use receipt::LocalizedReceipt;
use trace::LocalizedTrace;
use transaction::{LocalizedTransaction, PendingTransaction, SignedTransaction};
use verification::queue::QueueInfo as BlockQueueInfo;
use util::{U256, Address, H256, H2048, Bytes, Itertools};
use util::hashdb::DBValue;
use types::ids::*; use types::ids::*;
use types::basic_account::BasicAccount; use types::basic_account::BasicAccount;
use types::trace_filter::Filter as TraceFilter; use types::trace_filter::Filter as TraceFilter;
@ -41,7 +44,6 @@ use types::blockchain_info::BlockChainInfo;
use types::block_status::BlockStatus; use types::block_status::BlockStatus;
use types::mode::Mode; use types::mode::Mode;
use types::pruning_info::PruningInfo; use types::pruning_info::PruningInfo;
use encoded;
#[ipc(client_ident="RemoteClient")] #[ipc(client_ident="RemoteClient")]
/// Blockchain database client. Owns and manages a blockchain and a block queue. /// Blockchain database client. Owns and manages a blockchain and a block queue.

View File

@ -66,6 +66,7 @@ impl RollingFinality {
let entry = self.sign_count.entry(signer); let entry = self.sign_count.entry(signer);
if let (true, &Entry::Vacant(_)) = (would_be_finalized, &entry) { if let (true, &Entry::Vacant(_)) = (would_be_finalized, &entry) {
trace!(target: "finality", "Encountered already finalized block {}", hash);
break break
} }
@ -75,6 +76,7 @@ impl RollingFinality {
self.headers.push_front((hash, signer)); self.headers.push_front((hash, signer));
} }
trace!(target: "finality", "Rolling finality state: {:?}", self.headers);
Ok(()) Ok(())
} }
@ -128,6 +130,9 @@ impl RollingFinality {
} }
} }
trace!(target: "finality", "Blocks finalized by {:?}: {:?}", head, newly_finalized);
self.last_pushed = Some(head);
Ok(newly_finalized) Ok(newly_finalized)
} }
} }

View File

@ -220,9 +220,9 @@ pub struct AuthorityRound {
builtins: BTreeMap<Address, Builtin>, builtins: BTreeMap<Address, Builtin>,
transition_service: IoService<()>, transition_service: IoService<()>,
step: Arc<Step>, step: Arc<Step>,
proposed: AtomicBool, can_propose: AtomicBool,
client: RwLock<Option<Weak<EngineClient>>>, client: RwLock<Option<Weak<EngineClient>>>,
signer: EngineSigner, signer: RwLock<EngineSigner>,
validators: Box<ValidatorSet>, validators: Box<ValidatorSet>,
validate_score_transition: u64, validate_score_transition: u64,
eip155_transition: u64, eip155_transition: u64,
@ -311,7 +311,7 @@ fn verify_external<F: Fn(Report)>(header: &Header, validators: &ValidatorSet, st
// Give one step slack if step is lagging, double vote is still not possible. // Give one step slack if step is lagging, double vote is still not possible.
if step.is_future(header_step) { if step.is_future(header_step) {
trace!(target: "engine", "verify_block_unordered: block from the future"); trace!(target: "engine", "verify_block_external: block from the future");
report(Report::Benign(*header.author(), header.number())); report(Report::Benign(*header.author(), header.number()));
Err(BlockError::InvalidSeal)? Err(BlockError::InvalidSeal)?
} else { } else {
@ -321,7 +321,7 @@ fn verify_external<F: Fn(Report)>(header: &Header, validators: &ValidatorSet, st
!verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())?; !verify_address(&correct_proposer, &proposer_signature, &header.bare_hash())?;
if is_invalid_proposer { if is_invalid_proposer {
trace!(target: "engine", "verify_block_unordered: bad proposer for step: {}", header_step); trace!(target: "engine", "verify_block_external: bad proposer for step: {}", header_step);
Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))? Err(EngineError::NotProposer(Mismatch { expected: correct_proposer, found: header.author().clone() }))?
} else { } else {
Ok(()) Ok(())
@ -372,7 +372,7 @@ impl AuthorityRound {
calibrate: our_params.start_step.is_none(), calibrate: our_params.start_step.is_none(),
duration: our_params.step_duration, duration: our_params.step_duration,
}), }),
proposed: AtomicBool::new(false), can_propose: AtomicBool::new(true),
client: RwLock::new(None), client: RwLock::new(None),
signer: Default::default(), signer: Default::default(),
validators: our_params.validators, validators: our_params.validators,
@ -439,7 +439,7 @@ impl Engine for AuthorityRound {
fn step(&self) { fn step(&self) {
self.step.increment(); self.step.increment();
self.proposed.store(false, AtomicOrdering::SeqCst); self.can_propose.store(true, AtomicOrdering::SeqCst);
if let Some(ref weak) = *self.client.read() { if let Some(ref weak) = *self.client.read() {
if let Some(c) = weak.upgrade() { if let Some(c) = weak.upgrade() {
c.update_sealing(); c.update_sealing();
@ -471,7 +471,7 @@ impl Engine for AuthorityRound {
} }
fn seals_internally(&self) -> Option<bool> { fn seals_internally(&self) -> Option<bool> {
Some(self.signer.address() != Address::default()) Some(self.signer.read().is_some())
} }
/// Attempt to seal the block internally. /// Attempt to seal the block internally.
@ -481,7 +481,7 @@ impl Engine for AuthorityRound {
fn generate_seal(&self, block: &ExecutedBlock) -> Seal { fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
// first check to avoid generating signature most of the time // first check to avoid generating signature most of the time
// (but there's still a race to the `compare_and_swap`) // (but there's still a race to the `compare_and_swap`)
if self.proposed.load(AtomicOrdering::SeqCst) { return Seal::None; } if !self.can_propose.load(AtomicOrdering::SeqCst) { return Seal::None; }
let header = block.header(); let header = block.header();
let step = self.step.load(); let step = self.step.load();
@ -512,11 +512,11 @@ impl Engine for AuthorityRound {
}; };
if is_step_proposer(validators, header.parent_hash(), step, header.author()) { if is_step_proposer(validators, header.parent_hash(), step, header.author()) {
if let Ok(signature) = self.signer.sign(header.bare_hash()) { if let Ok(signature) = self.sign(header.bare_hash()) {
trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step); trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step);
// only issue the seal if we were the first to reach the compare_and_swap. // only issue the seal if we were the first to reach the compare_and_swap.
if !self.proposed.compare_and_swap(false, true, AtomicOrdering::SeqCst) { if self.can_propose.compare_and_swap(true, false, AtomicOrdering::SeqCst) {
return Seal::Regular(vec![encode(&step).into_vec(), encode(&(&H520::from(signature) as &[u8])).into_vec()]); return Seal::Regular(vec![encode(&step).into_vec(), encode(&(&H520::from(signature) as &[u8])).into_vec()]);
} }
} else { } else {
@ -532,7 +532,7 @@ impl Engine for AuthorityRound {
fn on_new_block( fn on_new_block(
&self, &self,
block: &mut ExecutedBlock, block: &mut ExecutedBlock,
last_hashes: Arc<::env_info::LastHashes>, last_hashes: Arc<::evm::env_info::LastHashes>,
epoch_begin: bool, epoch_begin: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let parent_hash = block.fields().header.parent_hash().clone(); let parent_hash = block.fields().header.parent_hash().clone();
@ -614,16 +614,18 @@ impl Engine for AuthorityRound {
Err(EngineError::DoubleVote(header.author().clone()))?; Err(EngineError::DoubleVote(header.author().clone()))?;
} }
// Report skipped primaries. // Report skipped primaries.
if step > parent_step + 1 { if let (true, Some(me)) = (step > parent_step + 1, self.signer.read().address()) {
// TODO: use epochmanager to get correct validator set for reporting? debug!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}",
// or just rely on the fact that in general these will be the same
// and some reports might go missing?
trace!(target: "engine", "Author {} built block with step gap. current step: {}, parent step: {}",
header.author(), step, parent_step); header.author(), step, parent_step);
let mut reported = HashSet::new();
for s in parent_step + 1..step { for s in parent_step + 1..step {
let skipped_primary = step_proposer(&*self.validators, &parent.hash(), s); let skipped_primary = step_proposer(&*self.validators, &parent.hash(), s);
self.validators.report_benign(&skipped_primary, header.number(), header.number()); // Do not report this signer.
if skipped_primary != me {
self.validators.report_benign(&skipped_primary, header.number(), header.number());
}
// Stop reporting once validators start repeating.
if !reported.insert(skipped_primary) { break; }
} }
} }
@ -723,6 +725,9 @@ impl Engine for AuthorityRound {
if epoch_manager.finality_checker.subchain_head() != Some(*chain_head.parent_hash()) { if epoch_manager.finality_checker.subchain_head() != Some(*chain_head.parent_hash()) {
// build new finality checker from ancestry of chain head, // build new finality checker from ancestry of chain head,
// not including chain head itself yet. // not including chain head itself yet.
trace!(target: "finality", "Building finality up to parent of {} ({})",
chain_head.hash(), chain_head.parent_hash());
let mut hash = chain_head.parent_hash().clone(); let mut hash = chain_head.parent_hash().clone();
let epoch_transition_hash = epoch_manager.epoch_transition_hash; let epoch_transition_hash = epoch_manager.epoch_transition_hash;
@ -734,6 +739,8 @@ impl Engine for AuthorityRound {
if header.number() == 0 { return None } if header.number() == 0 { return None }
let res = (hash, header.author().clone()); let res = (hash, header.author().clone());
trace!(target: "finality", "Ancestry iteration: yielding {:?}", res);
hash = header.parent_hash().clone(); hash = header.parent_hash().clone();
Some(res) Some(res)
}) })
@ -766,6 +773,16 @@ impl Engine for AuthorityRound {
let finality_proof = ::rlp::encode_list(&finality_proof); let finality_proof = ::rlp::encode_list(&finality_proof);
epoch_manager.note_new_epoch(); epoch_manager.note_new_epoch();
info!(target: "engine", "Applying validator set change signalled at block {}", signal_number);
// We turn off can_propose here because upon validator set change there can
// be two valid proposers for a single step: one from the old set and
// one from the new.
//
// This way, upon encountering an epoch change, the proposer from the
// new set will be forced to wait until the next step to avoid sealing a
// block that breaks the invariant that the parent's step < the block's step.
self.can_propose.store(false, AtomicOrdering::SeqCst);
return Some(combine_proofs(signal_number, &pending.proof, &*finality_proof)); return Some(combine_proofs(signal_number, &pending.proof, &*finality_proof));
} }
} }
@ -816,11 +833,11 @@ impl Engine for AuthorityRound {
} }
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) { fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
self.signer.set(ap, address, password); self.signer.write().set(ap, address, password);
} }
fn sign(&self, hash: H256) -> Result<Signature, Error> { fn sign(&self, hash: H256) -> Result<Signature, Error> {
self.signer.sign(hash).map_err(Into::into) self.signer.read().sign(hash).map_err(Into::into)
} }
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> { fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {
@ -1018,6 +1035,12 @@ mod tests {
header.set_gas_limit(U256::from_str("222222").unwrap()); header.set_gas_limit(U256::from_str("222222").unwrap());
header.set_seal(vec![encode(&3usize).into_vec()]); header.set_seal(vec![encode(&3usize).into_vec()]);
// Do not report when signer not present.
assert!(aura.verify_block_family(&header, &parent_header, None).is_ok());
assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0);
aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), Default::default());
assert!(aura.verify_block_family(&header, &parent_header, None).is_ok()); assert!(aura.verify_block_family(&header, &parent_header, None).is_ok());
assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 1); assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 1);
} }

View File

@ -82,7 +82,7 @@ pub struct BasicAuthority {
params: CommonParams, params: CommonParams,
gas_limit_bound_divisor: U256, gas_limit_bound_divisor: U256,
builtins: BTreeMap<Address, Builtin>, builtins: BTreeMap<Address, Builtin>,
signer: EngineSigner, signer: RwLock<EngineSigner>,
validators: Box<ValidatorSet>, validators: Box<ValidatorSet>,
} }
@ -129,7 +129,7 @@ impl Engine for BasicAuthority {
} }
fn seals_internally(&self) -> Option<bool> { fn seals_internally(&self) -> Option<bool> {
Some(self.signer.address() != Address::default()) Some(self.signer.read().is_some())
} }
/// Attempt to seal the block internally. /// Attempt to seal the block internally.
@ -138,7 +138,7 @@ impl Engine for BasicAuthority {
let author = header.author(); let author = header.author();
if self.validators.contains(header.parent_hash(), author) { if self.validators.contains(header.parent_hash(), author) {
// account should be pernamently unlocked, otherwise sealing will fail // account should be pernamently unlocked, otherwise sealing will fail
if let Ok(signature) = self.signer.sign(header.bare_hash()) { if let Ok(signature) = self.sign(header.bare_hash()) {
return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8])).into_vec()]); return Seal::Regular(vec![::rlp::encode(&(&H520::from(signature) as &[u8])).into_vec()]);
} else { } else {
trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable"); trace!(target: "basicauthority", "generate_seal: FAIL: accounts secret key unavailable");
@ -240,11 +240,11 @@ impl Engine for BasicAuthority {
} }
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) { fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
self.signer.set(ap, address, password); self.signer.write().set(ap, address, password);
} }
fn sign(&self, hash: H256) -> Result<Signature, Error> { fn sign(&self, hash: H256) -> Result<Signature, Error> {
self.signer.sign(hash).map_err(Into::into) self.signer.read().sign(hash).map_err(Into::into)
} }
fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> { fn snapshot_components(&self) -> Option<Box<::snapshot::SnapshotComponents>> {

View File

@ -43,7 +43,7 @@ use account_provider::AccountProvider;
use block::ExecutedBlock; use block::ExecutedBlock;
use builtin::Builtin; use builtin::Builtin;
use client::Client; use client::Client;
use env_info::{EnvInfo, LastHashes}; use evm::env_info::{EnvInfo, LastHashes};
use error::Error; use error::Error;
use evm::Schedule; use evm::Schedule;
use header::{Header, BlockNumber}; use header::{Header, BlockNumber};
@ -193,7 +193,7 @@ pub trait Engine : Sync + Send {
/// Get the EVM schedule for the given `block_number`. /// Get the EVM schedule for the given `block_number`.
fn schedule(&self, block_number: BlockNumber) -> Schedule { fn schedule(&self, block_number: BlockNumber) -> Schedule {
Schedule::from_params(block_number, self.params()) self.params().schedule(block_number)
} }
/// Builtin-contracts we would like to see in the chain. /// Builtin-contracts we would like to see in the chain.
@ -394,12 +394,12 @@ pub trait Engine : Sync + Send {
/// Common engine utilities /// Common engine utilities
pub mod common { pub mod common {
use block::ExecutedBlock; use block::ExecutedBlock;
use env_info::{EnvInfo, LastHashes}; use evm::env_info::{EnvInfo, LastHashes};
use error::Error; use error::Error;
use transaction::SYSTEM_ADDRESS; use transaction::SYSTEM_ADDRESS;
use executive::Executive; use executive::Executive;
use types::executed::CallType; use evm::CallType;
use action_params::{ActionParams, ActionValue}; use evm::action_params::{ActionParams, ActionValue};
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
use state::Substate; use state::Substate;

View File

@ -16,21 +16,21 @@
//! A signer used by Engines which need to sign messages. //! A signer used by Engines which need to sign messages.
use util::{Arc, Mutex, RwLock, H256, Address}; use util::{Arc, H256, Address};
use ethkey::Signature; use ethkey::Signature;
use account_provider::{self, AccountProvider}; use account_provider::{self, AccountProvider};
/// Everything that an Engine needs to sign messages. /// Everything that an Engine needs to sign messages.
pub struct EngineSigner { pub struct EngineSigner {
account_provider: Mutex<Arc<AccountProvider>>, account_provider: Arc<AccountProvider>,
address: RwLock<Address>, address: Option<Address>,
password: RwLock<Option<String>>, password: Option<String>,
} }
impl Default for EngineSigner { impl Default for EngineSigner {
fn default() -> Self { fn default() -> Self {
EngineSigner { EngineSigner {
account_provider: Mutex::new(Arc::new(AccountProvider::transient_provider())), account_provider: Arc::new(AccountProvider::transient_provider()),
address: Default::default(), address: Default::default(),
password: Default::default(), password: Default::default(),
} }
@ -39,25 +39,30 @@ impl Default for EngineSigner {
impl EngineSigner { impl EngineSigner {
/// Set up the signer to sign with given address and password. /// Set up the signer to sign with given address and password.
pub fn set(&self, ap: Arc<AccountProvider>, address: Address, password: String) { pub fn set(&mut self, ap: Arc<AccountProvider>, address: Address, password: String) {
*self.account_provider.lock() = ap; self.account_provider = ap;
*self.address.write() = address; self.address = Some(address);
*self.password.write() = Some(password); self.password = Some(password);
debug!(target: "poa", "Setting Engine signer to {}", address); debug!(target: "poa", "Setting Engine signer to {}", address);
} }
/// Sign a consensus message hash. /// Sign a consensus message hash.
pub fn sign(&self, hash: H256) -> Result<Signature, account_provider::SignError> { pub fn sign(&self, hash: H256) -> Result<Signature, account_provider::SignError> {
self.account_provider.lock().sign(*self.address.read(), self.password.read().clone(), hash) self.account_provider.sign(self.address.unwrap_or_else(Default::default), self.password.clone(), hash)
} }
/// Signing address. /// Signing address.
pub fn address(&self) -> Address { pub fn address(&self) -> Option<Address> {
self.address.read().clone() self.address.clone()
} }
/// Check if the given address is the signing address. /// Check if the given address is the signing address.
pub fn is_address(&self, address: &Address) -> bool { pub fn is_address(&self, address: &Address) -> bool {
*self.address.read() == *address self.address.map_or(false, |a| a == *address)
}
/// Check if the signing address was set.
pub fn is_some(&self) -> bool {
self.address.is_some()
} }
} }

View File

@ -86,7 +86,7 @@ pub struct Tendermint {
/// Vote accumulator. /// Vote accumulator.
votes: VoteCollector<ConsensusMessage>, votes: VoteCollector<ConsensusMessage>,
/// Used to sign messages and proposals. /// Used to sign messages and proposals.
signer: EngineSigner, signer: RwLock<EngineSigner>,
/// Message for the last PoLC. /// Message for the last PoLC.
lock_change: RwLock<Option<ConsensusMessage>>, lock_change: RwLock<Option<ConsensusMessage>>,
/// Last lock view. /// Last lock view.
@ -159,19 +159,22 @@ impl Tendermint {
let r = self.view.load(AtomicOrdering::SeqCst); let r = self.view.load(AtomicOrdering::SeqCst);
let s = *self.step.read(); let s = *self.step.read();
let vote_info = message_info_rlp(&VoteStep::new(h, r, s), block_hash); let vote_info = message_info_rlp(&VoteStep::new(h, r, s), block_hash);
match self.signer.sign(vote_info.sha3()).map(Into::into) { match (self.signer.read().address(), self.sign(vote_info.sha3()).map(Into::into)) {
Ok(signature) => { (Some(validator), Ok(signature)) => {
let message_rlp = message_full_rlp(&signature, &vote_info); let message_rlp = message_full_rlp(&signature, &vote_info);
let message = ConsensusMessage::new(signature, h, r, s, block_hash); let message = ConsensusMessage::new(signature, h, r, s, block_hash);
let validator = self.signer.address();
self.votes.vote(message.clone(), &validator); self.votes.vote(message.clone(), &validator);
debug!(target: "engine", "Generated {:?} as {}.", message, validator); debug!(target: "engine", "Generated {:?} as {}.", message, validator);
self.handle_valid_message(&message); self.handle_valid_message(&message);
Some(message_rlp) Some(message_rlp)
}, },
Err(e) => { (None, _) => {
trace!(target: "engine", "Could not sign the message {}", e); trace!(target: "engine", "No message, since there is no engine signer.");
None
},
(Some(v), Err(e)) => {
trace!(target: "engine", "{} could not sign the message {}", v, e);
None None
}, },
} }
@ -272,7 +275,7 @@ impl Tendermint {
/// Check if current signer is the current proposer. /// Check if current signer is the current proposer.
fn is_signer_proposer(&self, bh: &H256) -> bool { fn is_signer_proposer(&self, bh: &H256) -> bool {
let proposer = self.view_proposer(bh, self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst)); let proposer = self.view_proposer(bh, self.height.load(AtomicOrdering::SeqCst), self.view.load(AtomicOrdering::SeqCst));
self.signer.is_address(&proposer) self.signer.read().is_address(&proposer)
} }
fn is_height(&self, message: &ConsensusMessage) -> bool { fn is_height(&self, message: &ConsensusMessage) -> bool {
@ -420,7 +423,7 @@ impl Engine for Tendermint {
/// Should this node participate. /// Should this node participate.
fn seals_internally(&self) -> Option<bool> { fn seals_internally(&self) -> Option<bool> {
Some(self.signer.address() != Address::default()) Some(self.signer.read().is_some())
} }
/// Attempt to seal generate a proposal seal. /// Attempt to seal generate a proposal seal.
@ -436,7 +439,7 @@ impl Engine for Tendermint {
let view = self.view.load(AtomicOrdering::SeqCst); let view = self.view.load(AtomicOrdering::SeqCst);
let bh = Some(header.bare_hash()); let bh = Some(header.bare_hash());
let vote_info = message_info_rlp(&VoteStep::new(height, view, Step::Propose), bh.clone()); let vote_info = message_info_rlp(&VoteStep::new(height, view, Step::Propose), bh.clone());
if let Ok(signature) = self.signer.sign(vote_info.sha3()).map(Into::into) { if let Ok(signature) = self.sign(vote_info.sha3()).map(Into::into) {
// Insert Propose vote. // Insert Propose vote.
debug!(target: "engine", "Submitting proposal {} at height {} view {}.", header.bare_hash(), height, view); debug!(target: "engine", "Submitting proposal {} at height {} view {}.", header.bare_hash(), height, view);
self.votes.vote(ConsensusMessage::new(signature, height, view, Step::Propose, bh), author); self.votes.vote(ConsensusMessage::new(signature, height, view, Step::Propose, bh), author);
@ -565,13 +568,13 @@ impl Engine for Tendermint {
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) { fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
{ {
self.signer.set(ap, address, password); self.signer.write().set(ap, address, password);
} }
self.to_step(Step::Propose); self.to_step(Step::Propose);
} }
fn sign(&self, hash: H256) -> Result<Signature, Error> { fn sign(&self, hash: H256) -> Result<Signature, Error> {
self.signer.sign(hash).map_err(Into::into) self.signer.read().sign(hash).map_err(Into::into)
} }
fn stop(&self) { fn stop(&self) {
@ -901,7 +904,7 @@ mod tests {
#[test] #[test]
fn seal_submission() { fn seal_submission() {
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use types::transaction::{Transaction, Action}; use transaction::{Transaction, Action};
use client::BlockChainClient; use client::BlockChainClient;
let tap = Arc::new(AccountProvider::transient_provider()); let tap = Arc::new(AccountProvider::transient_provider());

View File

@ -110,6 +110,9 @@ fn prove_initial(provider: &Provider, header: &Header, caller: &Call) -> Result<
trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes", trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
validators.len(), proof.len()); validators.len(), proof.len());
info!(target: "engine", "Signal for switch to contract-based validator set.");
info!(target: "engine", "Initial contract validators: {:?}", validators);
proof proof
}) })
} }
@ -231,9 +234,7 @@ impl ValidatorSet for ValidatorSafeContract {
.map(|out| (out, Vec::new()))) // generate no proofs in general .map(|out| (out, Vec::new()))) // generate no proofs in general
} }
fn on_epoch_begin(&self, first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> { fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> {
if first { return Ok(()) } // only signalled changes need to be noted.
self.provider.finalize_change(caller) self.provider.finalize_change(caller)
.wait() .wait()
.map_err(::engines::EngineError::FailedSystemCall) .map_err(::engines::EngineError::FailedSystemCall)
@ -271,8 +272,9 @@ impl ValidatorSet for ValidatorSafeContract {
None => ::engines::EpochChange::Unsure(::engines::Unsure::NeedsReceipts), None => ::engines::EpochChange::Unsure(::engines::Unsure::NeedsReceipts),
Some(receipts) => match self.extract_from_event(bloom, header, receipts) { Some(receipts) => match self.extract_from_event(bloom, header, receipts) {
None => ::engines::EpochChange::No, None => ::engines::EpochChange::No,
Some(_) => { Some(list) => {
debug!(target: "engine", "signalling transition within contract"); info!(target: "engine", "Signal for transition within contract. New list: {:?}",
&*list);
let proof = encode_proof(&header, receipts); let proof = encode_proof(&header, receipts);
::engines::EpochChange::Yes(::engines::Proof::Known(proof)) ::engines::EpochChange::Yes(::engines::Proof::Known(proof))
@ -297,7 +299,7 @@ impl ValidatorSet for ValidatorSafeContract {
let (old_header, state_items) = decode_first_proof(&rlp)?; let (old_header, state_items) = decode_first_proof(&rlp)?;
let old_hash = old_header.hash(); let old_hash = old_header.hash();
let env_info = ::env_info::EnvInfo { let env_info = ::evm::env_info::EnvInfo {
number: old_header.number(), number: old_header.number(),
author: *old_header.author(), author: *old_header.author(),
difficulty: *old_header.difficulty(), difficulty: *old_header.difficulty(),

View File

@ -22,13 +22,12 @@ use header::BlockNumber;
use basic_types::LogBloom; use basic_types::LogBloom;
use client::Error as ClientError; use client::Error as ClientError;
use ipc::binary::{BinaryConvertError, BinaryConvertable}; use ipc::binary::{BinaryConvertError, BinaryConvertable};
use types::block_import_error::BlockImportError;
use snapshot::Error as SnapshotError; use snapshot::Error as SnapshotError;
use engines::EngineError; use engines::EngineError;
use ethkey::Error as EthkeyError; use ethkey::Error as EthkeyError;
use account_provider::SignError as AccountsError; use account_provider::SignError as AccountsError;
pub use types::executed::{ExecutionError, CallError}; pub use executed::{ExecutionError, CallError};
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
/// Errors concerning transaction processing. /// Errors concerning transaction processing.
@ -239,6 +238,53 @@ impl fmt::Display for ImportError {
f.write_fmt(format_args!("Block import error ({})", msg)) f.write_fmt(format_args!("Block import error ({})", msg))
} }
} }
/// Error dedicated to import block function
#[derive(Debug)]
pub enum BlockImportError {
/// Import error
Import(ImportError),
/// Block error
Block(BlockError),
/// Other error
Other(String),
}
impl From<Error> for BlockImportError {
fn from(e: Error) -> Self {
match e {
Error::Block(block_error) => BlockImportError::Block(block_error),
Error::Import(import_error) => BlockImportError::Import(import_error),
_ => BlockImportError::Other(format!("other block import error: {:?}", e)),
}
}
}
/// Represents the result of importing transaction.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum TransactionImportResult {
/// Transaction was imported to current queue.
Current,
/// Transaction was imported to future queue.
Future
}
/// Api-level error for transaction import
#[derive(Debug, Clone)]
pub enum TransactionImportError {
/// Transaction error
Transaction(TransactionError),
/// Other error
Other(String),
}
impl From<Error> for TransactionImportError {
fn from(e: Error) -> Self {
match e {
Error::Transaction(transaction_error) => TransactionImportError::Transaction(transaction_error),
_ => TransactionImportError::Other(format!("other block import error: {:?}", e)),
}
}
}
#[derive(Debug)] #[derive(Debug)]
/// General error type which should be capable of representing all errors in ethcore. /// General error type which should be capable of representing all errors in ethcore.

View File

@ -19,7 +19,7 @@ use ethash::{quick_get_difficulty, slow_get_seedhash, EthashManager};
use util::*; use util::*;
use block::*; use block::*;
use builtin::Builtin; use builtin::Builtin;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use error::{BlockError, Error, TransactionError}; use error::{BlockError, Error, TransactionError};
use header::{Header, BlockNumber}; use header::{Header, BlockNumber};
use state::CleanupMode; use state::CleanupMode;
@ -29,7 +29,7 @@ use engines::{self, Engine};
use evm::Schedule; use evm::Schedule;
use ethjson; use ethjson;
use rlp::{self, UntrustedRlp}; use rlp::{self, UntrustedRlp};
use env_info::LastHashes; use evm::env_info::LastHashes;
/// Parity tries to round block.gas_limit to multiple of this constant /// Parity tries to round block.gas_limit to multiple of this constant
pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]);
@ -209,7 +209,8 @@ impl Engine for Arc<Ethash> {
block_number >= self.ethash_params.eip160_transition, block_number >= self.ethash_params.eip160_transition,
block_number >= self.ethash_params.eip161abc_transition, block_number >= self.ethash_params.eip161abc_transition,
block_number >= self.ethash_params.eip161d_transition); block_number >= self.ethash_params.eip161d_transition);
schedule.apply_params(block_number, self.params());
self.params().update_schedule(block_number, &mut schedule);
schedule schedule
} }
} }
@ -1027,7 +1028,7 @@ mod tests {
#[test] #[test]
fn rejects_transactions_below_min_gas_price() { fn rejects_transactions_below_min_gas_price() {
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use types::transaction::{Transaction, Action}; use transaction::{Transaction, Action};
let spec = new_homestead_test(); let spec = new_homestead_test();
let mut ethparams = get_default_ethash_params(); let mut ethparams = get_default_ethash_params();

View File

@ -17,58 +17,15 @@
//! Transaction execution format module. //! Transaction execution format module.
use util::{Bytes, U256, Address, U512, trie}; use util::{Bytes, U256, Address, U512, trie};
use rlp::*;
use evm; use evm;
use trace::{VMTrace, FlatTrace}; use trace::{VMTrace, FlatTrace};
use types::log_entry::LogEntry; use log_entry::LogEntry;
use types::state_diff::StateDiff; use state_diff::StateDiff;
use std::fmt; use std::fmt;
/// The type of the call-like instruction.
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum CallType {
/// Not a CALL.
None,
/// CALL.
Call,
/// CALLCODE.
CallCode,
/// DELEGATECALL.
DelegateCall,
/// STATICCALL
StaticCall,
}
impl Encodable for CallType {
fn rlp_append(&self, s: &mut RlpStream) {
let v = match *self {
CallType::None => 0u32,
CallType::Call => 1,
CallType::CallCode => 2,
CallType::DelegateCall => 3,
CallType::StaticCall => 4,
};
Encodable::rlp_append(&v, s);
}
}
impl Decodable for CallType {
fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
rlp.as_val().and_then(|v| Ok(match v {
0u32 => CallType::None,
1 => CallType::Call,
2 => CallType::CallCode,
3 => CallType::DelegateCall,
4 => CallType::StaticCall,
_ => return Err(DecoderError::Custom("Invalid value of CallType item")),
}))
}
}
/// Transaction execution receipt. /// Transaction execution receipt.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Executed { pub struct Executed {
/// True if the outer call/create resulted in an exceptional exit. /// True if the outer call/create resulted in an exceptional exit.
pub exception: Option<evm::Error>, pub exception: Option<evm::Error>,
@ -112,7 +69,6 @@ pub struct Executed {
/// Result of executing the transaction. /// Result of executing the transaction.
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum ExecutionError { pub enum ExecutionError {
/// Returned when there gas paid for transaction execution is /// Returned when there gas paid for transaction execution is
/// lower than base gas required. /// lower than base gas required.
@ -192,7 +148,6 @@ impl fmt::Display for ExecutionError {
/// Result of executing the transaction. /// Result of executing the transaction.
#[derive(PartialEq, Debug, Clone)] #[derive(PartialEq, Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum CallError { pub enum CallError {
/// Couldn't find the transaction in the chain. /// Couldn't find the transaction in the chain.
TransactionNotFound, TransactionNotFound,
@ -230,29 +185,3 @@ impl fmt::Display for CallError {
/// Transaction execution result. /// Transaction execution result.
pub type ExecutionResult = Result<Executed, ExecutionError>; pub type ExecutionResult = Result<Executed, ExecutionError>;
#[cfg(test)]
mod tests {
use rlp::*;
use super::CallType;
#[test]
fn encode_call_type() {
let ct = CallType::Call;
let mut s = RlpStream::new_list(2);
s.append(&ct);
assert!(!s.is_finished(), "List shouldn't finished yet");
s.append(&ct);
assert!(s.is_finished(), "List should be finished now");
s.out();
}
#[test]
fn should_encode_and_decode_call_type() {
let original = CallType::Call;
let encoded = encode(&original);
let decoded = decode(&encoded);
assert_eq!(original, decoded);
}
}

View File

@ -16,18 +16,18 @@
//! Transaction Execution environment. //! Transaction Execution environment.
use util::*; use util::*;
use action_params::{ActionParams, ActionValue}; use evm::action_params::{ActionParams, ActionValue};
use state::{Backend as StateBackend, State, Substate, CleanupMode}; use state::{Backend as StateBackend, State, Substate, CleanupMode};
use engines::Engine; use engines::Engine;
use types::executed::CallType; use evm::CallType;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use error::ExecutionError; use error::ExecutionError;
use evm::{self, wasm, Factory, Ext, Finalize, CreateContractAddress, FinalizationResult, ReturnData, CleanDustMode}; use evm::{self, wasm, Factory, Ext, Finalize, CreateContractAddress, FinalizationResult, ReturnData, CleanDustMode};
use externalities::*; use externalities::*;
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer}; use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer};
use transaction::{Action, SignedTransaction}; use transaction::{Action, SignedTransaction};
use crossbeam; use crossbeam;
pub use types::executed::{Executed, ExecutionResult}; pub use executed::{Executed, ExecutionResult};
/// Roughly estimate what stack size each level of evm depth will use /// Roughly estimate what stack size each level of evm depth will use
/// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132) /// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132)
@ -602,8 +602,8 @@ mod tests {
use super::*; use super::*;
use util::{H256, U256, U512, Address, FromStr}; use util::{H256, U256, U512, Address, FromStr};
use util::bytes::BytesRef; use util::bytes::BytesRef;
use action_params::{ActionParams, ActionValue}; use evm::action_params::{ActionParams, ActionValue};
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use evm::{Factory, VMType, CreateContractAddress}; use evm::{Factory, VMType, CreateContractAddress};
use error::ExecutionError; use error::ExecutionError;
use state::{Substate, CleanupMode}; use state::{Substate, CleanupMode};
@ -613,7 +613,7 @@ mod tests {
use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer}; use trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, VMTracer, NoopVMTracer, ExecutiveVMTracer};
use transaction::{Action, Transaction}; use transaction::{Action, Transaction};
use types::executed::CallType; use evm::CallType;
#[test] #[test]
fn test_contract_address() { fn test_contract_address() {

View File

@ -16,14 +16,14 @@
//! Transaction Execution environment. //! Transaction Execution environment.
use util::*; use util::*;
use action_params::{ActionParams, ActionValue}; use evm::action_params::{ActionParams, ActionValue};
use state::{Backend as StateBackend, State, Substate, CleanupMode}; use state::{Backend as StateBackend, State, Substate, CleanupMode};
use engines::Engine; use engines::Engine;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use executive::*; use executive::*;
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData}; use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData};
use types::executed::CallType; use evm::CallType;
use types::transaction::UNSIGNED_SENDER; use transaction::UNSIGNED_SENDER;
use trace::{Tracer, VMTracer}; use trace::{Tracer, VMTracer};
/// Policy for handling output data on `RETURN` opcode. /// Policy for handling output data on `RETURN` opcode.
@ -396,13 +396,13 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E>
mod tests { mod tests {
use util::*; use util::*;
use engines::Engine; use engines::Engine;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use evm::Ext; use evm::Ext;
use state::{State, Substate}; use state::{State, Substate};
use tests::helpers::*; use tests::helpers::*;
use super::*; use super::*;
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
use types::executed::CallType; use evm::CallType;
fn get_test_origin() -> OriginInfo { fn get_test_origin() -> OriginInfo {
OriginInfo { OriginInfo {

View File

@ -25,8 +25,7 @@ use std::cell::RefCell;
pub use basic_types::Seal; pub use basic_types::Seal;
/// Type for Block number pub use types::BlockNumber;
pub type BlockNumber = u64;
/// A block header. /// A block header.
/// ///

View File

@ -15,15 +15,15 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
use super::test_common::*; use super::test_common::*;
use action_params::ActionParams; use evm::action_params::ActionParams;
use state::{Backend as StateBackend, State, Substate}; use state::{Backend as StateBackend, State, Substate};
use executive::*; use executive::*;
use engines::Engine; use engines::Engine;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use evm; use evm;
use evm::{Schedule, Ext, Finalize, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData}; use evm::{Schedule, Ext, Finalize, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData};
use externalities::*; use externalities::*;
use types::executed::CallType; use evm::CallType;
use tests::helpers::*; use tests::helpers::*;
use ethjson; use ethjson;
use trace::{Tracer, NoopTracer}; use trace::{Tracer, NoopTracer};

View File

@ -21,8 +21,8 @@ use ethereum;
use spec::Spec; use spec::Spec;
use ethjson; use ethjson;
use ethjson::state::test::ForkSpec; use ethjson::state::test::ForkSpec;
use types::transaction::SignedTransaction; use transaction::SignedTransaction;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
lazy_static! { lazy_static! {
pub static ref FRONTIER: Spec = ethereum::new_frontier_test(); pub static ref FRONTIER: Spec = ethereum::new_frontier_test();

View File

@ -76,6 +76,7 @@ extern crate bloomchain;
extern crate bn; extern crate bn;
extern crate byteorder; extern crate byteorder;
extern crate crossbeam; extern crate crossbeam;
extern crate common_types as types;
extern crate crypto; extern crate crypto;
extern crate env_logger; extern crate env_logger;
extern crate ethabi; extern crate ethabi;
@ -105,8 +106,6 @@ extern crate semver;
extern crate stats; extern crate stats;
extern crate time; extern crate time;
extern crate transient_hashmap; extern crate transient_hashmap;
extern crate parity_wasm;
extern crate wasm_utils;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
@ -116,6 +115,8 @@ extern crate ethcore_util as util;
extern crate lazy_static; extern crate lazy_static;
#[macro_use] #[macro_use]
extern crate ethcore_ipc as ipc; extern crate ethcore_ipc as ipc;
#[cfg_attr(test, macro_use)]
extern crate evm;
#[cfg(feature = "jit" )] #[cfg(feature = "jit" )]
extern crate evmjit; extern crate evmjit;
@ -123,26 +124,26 @@ extern crate evmjit;
pub extern crate ethstore; pub extern crate ethstore;
pub mod account_provider; pub mod account_provider;
pub mod engines;
pub mod block; pub mod block;
pub mod client; pub mod client;
pub mod db;
pub mod encoded;
pub mod engines;
pub mod error; pub mod error;
pub mod ethereum; pub mod ethereum;
pub mod executed;
pub mod header; pub mod header;
pub mod service;
pub mod trace;
pub mod spec;
pub mod views;
pub mod pod_state;
pub mod migrations; pub mod migrations;
pub mod miner; pub mod miner;
pub mod pod_state;
pub mod service;
pub mod snapshot; pub mod snapshot;
pub mod action_params; pub mod spec;
pub mod db;
pub mod verification;
pub mod state; pub mod state;
pub mod env_info; pub mod trace;
#[macro_use] pub mod evm; pub mod transaction;
pub mod verification;
pub mod views;
mod cache_manager; mod cache_manager;
mod blooms; mod blooms;
@ -154,7 +155,6 @@ mod builtin;
mod executive; mod executive;
mod externalities; mod externalities;
mod blockchain; mod blockchain;
mod types;
mod factory; mod factory;
#[cfg(test)] #[cfg(test)]

View File

@ -98,6 +98,8 @@ pub struct MinerOptions {
pub tx_gas_limit: U256, pub tx_gas_limit: U256,
/// Maximum size of the transaction queue. /// Maximum size of the transaction queue.
pub tx_queue_size: usize, pub tx_queue_size: usize,
/// Maximum memory usage of transactions in the queue (current / future).
pub tx_queue_memory_limit: Option<usize>,
/// Strategy to use for prioritizing transactions in the queue. /// Strategy to use for prioritizing transactions in the queue.
pub tx_queue_strategy: PrioritizationStrategy, pub tx_queue_strategy: PrioritizationStrategy,
/// Whether we should fallback to providing all the queue's transactions or just pending. /// Whether we should fallback to providing all the queue's transactions or just pending.
@ -123,8 +125,9 @@ impl Default for MinerOptions {
reseal_on_own_tx: true, reseal_on_own_tx: true,
reseal_on_uncle: false, reseal_on_uncle: false,
tx_gas_limit: !U256::zero(), tx_gas_limit: !U256::zero(),
tx_queue_size: 1024, tx_queue_size: 8192,
tx_queue_gas_limit: GasLimit::Auto, tx_queue_memory_limit: Some(2 * 1024 * 1024),
tx_queue_gas_limit: GasLimit::None,
tx_queue_strategy: PrioritizationStrategy::GasPriceOnly, tx_queue_strategy: PrioritizationStrategy::GasPriceOnly,
pending_set: PendingSet::AlwaysQueue, pending_set: PendingSet::AlwaysQueue,
reseal_min_period: Duration::from_secs(2), reseal_min_period: Duration::from_secs(2),
@ -252,8 +255,15 @@ impl Miner {
GasLimit::Fixed(ref limit) => *limit, GasLimit::Fixed(ref limit) => *limit,
_ => !U256::zero(), _ => !U256::zero(),
}; };
let mem_limit = options.tx_queue_memory_limit.unwrap_or_else(usize::max_value);
let txq = TransactionQueue::with_limits(options.tx_queue_strategy, options.tx_queue_size, gas_limit, options.tx_gas_limit); let txq = TransactionQueue::with_limits(
options.tx_queue_strategy,
options.tx_queue_size,
mem_limit,
gas_limit,
options.tx_gas_limit
);
let txq = match options.tx_queue_banning { let txq = match options.tx_queue_banning {
Banning::Disabled => BanningTransactionQueue::new(txq, Threshold::NeverBan, Duration::from_secs(180)), Banning::Disabled => BanningTransactionQueue::new(txq, Threshold::NeverBan, Duration::from_secs(180)),
Banning::Enabled { ban_duration, min_offends, .. } => BanningTransactionQueue::new( Banning::Enabled { ban_duration, min_offends, .. } => BanningTransactionQueue::new(
@ -804,9 +814,15 @@ impl MinerService for Miner {
// | Make sure to release the locks before calling that method. | // | Make sure to release the locks before calling that method. |
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
self.engine.set_signer(ap.clone(), address, password); self.engine.set_signer(ap.clone(), address, password);
Ok(())
} else {
warn!(target: "miner", "No account provider");
Err(AccountError::NotFound)
} }
} else {
warn!(target: "miner", "Cannot set engine signer on a PoW chain.");
Err(AccountError::InappropriateChain)
} }
Ok(())
} }
fn set_extra_data(&self, extra_data: Bytes) { fn set_extra_data(&self, extra_data: Bytes) {
@ -1085,6 +1101,10 @@ impl MinerService for Miner {
self.transaction_queue.read().last_nonce(address) self.transaction_queue.read().last_nonce(address)
} }
fn can_produce_work_package(&self) -> bool {
self.engine.seals_internally().is_none()
}
/// Update sealing if required. /// Update sealing if required.
/// Prepare the block and work if the Engine does not seal internally. /// Prepare the block and work if the Engine does not seal internally.
fn update_sealing(&self, chain: &MiningBlockChainClient) { fn update_sealing(&self, chain: &MiningBlockChainClient) {
@ -1113,7 +1133,7 @@ impl MinerService for Miner {
} }
} }
fn is_sealing(&self) -> bool { fn is_currently_sealing(&self) -> bool {
self.sealing_work.lock().queue.is_in_use() self.sealing_work.lock().queue.is_in_use()
} }
@ -1270,9 +1290,9 @@ mod tests {
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult}; use client::{BlockChainClient, TestBlockChainClient, EachBlockWith, TransactionImportResult};
use header::BlockNumber; use header::BlockNumber;
use types::transaction::{SignedTransaction, Transaction, PendingTransaction, Action}; use transaction::{SignedTransaction, Transaction, PendingTransaction, Action};
use spec::Spec; use spec::Spec;
use tests::helpers::{generate_dummy_client}; use tests::helpers::{generate_dummy_client, generate_dummy_client_with_spec_and_accounts};
#[test] #[test]
fn should_prepare_block_to_seal() { fn should_prepare_block_to_seal() {
@ -1318,6 +1338,7 @@ mod tests {
reseal_max_period: Duration::from_secs(120), reseal_max_period: Duration::from_secs(120),
tx_gas_limit: !U256::zero(), tx_gas_limit: !U256::zero(),
tx_queue_size: 1024, tx_queue_size: 1024,
tx_queue_memory_limit: None,
tx_queue_gas_limit: GasLimit::None, tx_queue_gas_limit: GasLimit::None,
tx_queue_strategy: PrioritizationStrategy::GasFactorAndGasPrice, tx_queue_strategy: PrioritizationStrategy::GasFactorAndGasPrice,
pending_set: PendingSet::AlwaysSealing, pending_set: PendingSet::AlwaysSealing,
@ -1440,4 +1461,22 @@ mod tests {
assert!(miner.pending_block().is_none()); assert!(miner.pending_block().is_none());
assert_eq!(client.chain_info().best_block_number, 4 as BlockNumber); assert_eq!(client.chain_info().best_block_number, 4 as BlockNumber);
} }
#[test]
fn should_fail_setting_engine_signer_on_pow() {
let spec = Spec::new_pow_test_spec;
let tap = Arc::new(AccountProvider::transient_provider());
let addr = tap.insert_account("1".sha3().into(), "").unwrap();
let client = generate_dummy_client_with_spec_and_accounts(spec, Some(tap.clone()));
assert!(match client.miner().set_engine_signer(addr, "".into()) { Err(AccountError::InappropriateChain) => true, _ => false })
}
#[test]
fn should_fail_setting_engine_signer_without_account_provider() {
let spec = Spec::new_instant;
let tap = Arc::new(AccountProvider::transient_provider());
let addr = tap.insert_account("1".sha3().into(), "").unwrap();
let client = generate_dummy_client_with_spec_and_accounts(spec, None);
assert!(match client.miner().set_engine_signer(addr, "".into()) { Err(AccountError::NotFound) => true, _ => false });
}
} }

View File

@ -136,6 +136,9 @@ pub trait MinerService : Send + Sync {
/// Called when blocks are imported to chain, updates transactions queue. /// Called when blocks are imported to chain, updates transactions queue.
fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]); fn chain_new_blocks(&self, chain: &MiningBlockChainClient, imported: &[H256], invalid: &[H256], enacted: &[H256], retracted: &[H256]);
/// PoW chain - can produce work package
fn can_produce_work_package(&self) -> bool;
/// New chain head event. Restart mining operation. /// New chain head event. Restart mining operation.
fn update_sealing(&self, chain: &MiningBlockChainClient); fn update_sealing(&self, chain: &MiningBlockChainClient);
@ -176,7 +179,7 @@ pub trait MinerService : Send + Sync {
fn last_nonce(&self, address: &Address) -> Option<U256>; fn last_nonce(&self, address: &Address) -> Option<U256>;
/// Is it currently sealing? /// Is it currently sealing?
fn is_sealing(&self) -> bool; fn is_currently_sealing(&self) -> bool;
/// Suggested gas price. /// Suggested gas price.
fn sensible_gas_price(&self) -> U256; fn sensible_gas_price(&self) -> U256;

View File

@ -105,7 +105,7 @@ use std::cmp::Ordering;
use std::cmp; use std::cmp;
use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap}; use std::collections::{HashSet, HashMap, BTreeSet, BTreeMap};
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use util::{Address, H256, U256}; use util::{Address, H256, U256, HeapSizeOf};
use util::table::Table; use util::table::Table;
use transaction::*; use transaction::*;
use error::{Error, TransactionError}; use error::{Error, TransactionError};
@ -171,6 +171,8 @@ struct TransactionOrder {
/// Gas (limit) of the transaction. Usage depends on strategy. /// Gas (limit) of the transaction. Usage depends on strategy.
/// Low gas limit = High priority (processed earlier) /// Low gas limit = High priority (processed earlier)
gas: U256, gas: U256,
/// Heap usage of this transaction.
mem_usage: usize,
/// Transaction ordering strategy /// Transaction ordering strategy
strategy: PrioritizationStrategy, strategy: PrioritizationStrategy,
/// Hash to identify associated transaction /// Hash to identify associated transaction
@ -191,8 +193,9 @@ impl TransactionOrder {
TransactionOrder { TransactionOrder {
nonce_height: tx.nonce() - base_nonce, nonce_height: tx.nonce() - base_nonce,
gas_price: tx.transaction.gas_price, gas_price: tx.transaction.gas_price,
gas: tx.transaction.gas,
gas_factor: factor, gas_factor: factor,
gas: tx.transaction.gas,
mem_usage: tx.transaction.heap_size_of_children(),
strategy: strategy, strategy: strategy,
hash: tx.hash(), hash: tx.hash(),
insertion_id: tx.insertion_id, insertion_id: tx.insertion_id,
@ -370,7 +373,8 @@ struct TransactionSet {
by_address: Table<Address, U256, TransactionOrder>, by_address: Table<Address, U256, TransactionOrder>,
by_gas_price: GasPriceQueue, by_gas_price: GasPriceQueue,
limit: usize, limit: usize,
gas_limit: U256, total_gas_limit: U256,
memory_limit: usize,
} }
impl TransactionSet { impl TransactionSet {
@ -402,18 +406,24 @@ impl TransactionSet {
/// Returns addresses and lowest nonces of transactions removed because of limit. /// Returns addresses and lowest nonces of transactions removed because of limit.
fn enforce_limit(&mut self, by_hash: &mut HashMap<H256, VerifiedTransaction>, local: &mut LocalTransactionsList) -> Option<HashMap<Address, U256>> { fn enforce_limit(&mut self, by_hash: &mut HashMap<H256, VerifiedTransaction>, local: &mut LocalTransactionsList) -> Option<HashMap<Address, U256>> {
let mut count = 0; let mut count = 0;
let mut mem_usage = 0;
let mut gas: U256 = 0.into(); let mut gas: U256 = 0.into();
let to_drop : Vec<(Address, U256)> = { let to_drop : Vec<(Address, U256)> = {
self.by_priority self.by_priority
.iter() .iter()
.filter(|order| { .filter(|order| {
count = count + 1; // update transaction count and mem usage
count += 1;
mem_usage += order.mem_usage;
// calculate current gas usage
let r = gas.overflowing_add(order.gas); let r = gas.overflowing_add(order.gas);
if r.1 { return false } if r.1 { return false }
gas = r.0; gas = r.0;
let is_own_or_retracted = order.origin.is_local() || order.origin == TransactionOrigin::RetractedBlock;
// Own and retracted transactions are allowed to go above all limits. // Own and retracted transactions are allowed to go above all limits.
order.origin != TransactionOrigin::Local && order.origin != TransactionOrigin::RetractedBlock && !is_own_or_retracted && (mem_usage > self.memory_limit || count > self.limit || gas > self.total_gas_limit)
(gas > self.gas_limit || count > self.limit)
}) })
.map(|order| by_hash.get(&order.hash) .map(|order| by_hash.get(&order.hash)
.expect("All transactions in `self.by_priority` and `self.by_address` are kept in sync with `by_hash`.")) .expect("All transactions in `self.by_priority` and `self.by_address` are kept in sync with `by_hash`."))
@ -502,6 +512,10 @@ const GAS_LIMIT_HYSTERESIS: usize = 200; // (100/GAS_LIMIT_HYSTERESIS) %
/// `new_gas_price > old_gas_price + old_gas_price >> SHIFT` /// `new_gas_price > old_gas_price + old_gas_price >> SHIFT`
const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25% const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
/// Future queue limits are lower from current queue limits:
/// `future_limit = current_limit >> SHIFT`
const FUTURE_QUEUE_LIMITS_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
/// Describes the strategy used to prioritize transactions in the queue. /// Describes the strategy used to prioritize transactions in the queue.
#[cfg_attr(feature="dev", allow(enum_variant_names))] #[cfg_attr(feature="dev", allow(enum_variant_names))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -557,7 +571,7 @@ pub struct TransactionQueue {
/// The maximum amount of gas any individual transaction may use. /// The maximum amount of gas any individual transaction may use.
tx_gas_limit: U256, tx_gas_limit: U256,
/// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0) /// Current gas limit (block gas limit * factor). Transactions above the limit will not be accepted (default to !0)
gas_limit: U256, total_gas_limit: U256,
/// Maximal time transaction may occupy the queue. /// Maximal time transaction may occupy the queue.
/// When we reach `max_time_in_queue / 2^3` we re-validate /// When we reach `max_time_in_queue / 2^3` we re-validate
/// account balance. /// account balance.
@ -585,35 +599,43 @@ impl Default for TransactionQueue {
impl TransactionQueue { impl TransactionQueue {
/// Creates new instance of this Queue /// Creates new instance of this Queue
pub fn new(strategy: PrioritizationStrategy) -> Self { pub fn new(strategy: PrioritizationStrategy) -> Self {
Self::with_limits(strategy, 1024, !U256::zero(), !U256::zero()) Self::with_limits(strategy, 8192, usize::max_value(), !U256::zero(), !U256::zero())
} }
/// Create new instance of this Queue with specified limits /// Create new instance of this Queue with specified limits
pub fn with_limits(strategy: PrioritizationStrategy, limit: usize, gas_limit: U256, tx_gas_limit: U256) -> Self { pub fn with_limits(
strategy: PrioritizationStrategy,
limit: usize,
memory_limit: usize,
total_gas_limit: U256,
tx_gas_limit: U256,
) -> Self {
let current = TransactionSet { let current = TransactionSet {
by_priority: BTreeSet::new(), by_priority: BTreeSet::new(),
by_address: Table::new(), by_address: Table::new(),
by_gas_price: Default::default(), by_gas_price: Default::default(),
limit: limit, limit,
gas_limit: gas_limit, total_gas_limit,
memory_limit,
}; };
let future = TransactionSet { let future = TransactionSet {
by_priority: BTreeSet::new(), by_priority: BTreeSet::new(),
by_address: Table::new(), by_address: Table::new(),
by_gas_price: Default::default(), by_gas_price: Default::default(),
limit: limit, total_gas_limit: total_gas_limit >> FUTURE_QUEUE_LIMITS_SHIFT,
gas_limit: gas_limit, limit: limit >> FUTURE_QUEUE_LIMITS_SHIFT,
memory_limit: memory_limit >> FUTURE_QUEUE_LIMITS_SHIFT,
}; };
TransactionQueue { TransactionQueue {
strategy: strategy, strategy,
minimal_gas_price: U256::zero(), minimal_gas_price: U256::zero(),
tx_gas_limit: tx_gas_limit, total_gas_limit: !U256::zero(),
gas_limit: !U256::zero(), tx_gas_limit,
max_time_in_queue: DEFAULT_QUEUING_PERIOD, max_time_in_queue: DEFAULT_QUEUING_PERIOD,
current: current, current,
future: future, future,
by_hash: HashMap::new(), by_hash: HashMap::new(),
last_nonces: HashMap::new(), last_nonces: HashMap::new(),
local_transactions: LocalTransactionsList::default(), local_transactions: LocalTransactionsList::default(),
@ -624,7 +646,7 @@ impl TransactionQueue {
/// Set the new limit for `current` and `future` queue. /// Set the new limit for `current` and `future` queue.
pub fn set_limit(&mut self, limit: usize) { pub fn set_limit(&mut self, limit: usize) {
self.current.set_limit(limit); self.current.set_limit(limit);
self.future.set_limit(limit); self.future.set_limit(limit >> FUTURE_QUEUE_LIMITS_SHIFT);
// And ensure the limits // And ensure the limits
self.current.enforce_limit(&mut self.by_hash, &mut self.local_transactions); self.current.enforce_limit(&mut self.by_hash, &mut self.local_transactions);
self.future.enforce_limit(&mut self.by_hash, &mut self.local_transactions); self.future.enforce_limit(&mut self.by_hash, &mut self.local_transactions);
@ -657,16 +679,17 @@ impl TransactionQueue {
pub fn set_gas_limit(&mut self, gas_limit: U256) { pub fn set_gas_limit(&mut self, gas_limit: U256) {
let extra = gas_limit / U256::from(GAS_LIMIT_HYSTERESIS); let extra = gas_limit / U256::from(GAS_LIMIT_HYSTERESIS);
self.gas_limit = match gas_limit.overflowing_add(extra) { let total_gas_limit = match gas_limit.overflowing_add(extra) {
(_, true) => !U256::zero(), (_, true) => !U256::zero(),
(val, false) => val, (val, false) => val,
}; };
self.total_gas_limit = total_gas_limit;
} }
/// Sets new total gas limit. /// Sets new total gas limit.
pub fn set_total_gas_limit(&mut self, gas_limit: U256) { pub fn set_total_gas_limit(&mut self, total_gas_limit: U256) {
self.future.gas_limit = gas_limit; self.current.total_gas_limit = total_gas_limit;
self.current.gas_limit = gas_limit; self.future.total_gas_limit = total_gas_limit >> FUTURE_QUEUE_LIMITS_SHIFT;
self.future.enforce_limit(&mut self.by_hash, &mut self.local_transactions); self.future.enforce_limit(&mut self.by_hash, &mut self.local_transactions);
} }
@ -796,16 +819,17 @@ impl TransactionQueue {
})); }));
} }
if tx.gas > self.gas_limit || tx.gas > self.tx_gas_limit { let gas_limit = cmp::min(self.tx_gas_limit, self.total_gas_limit);
if tx.gas > gas_limit {
trace!(target: "txqueue", trace!(target: "txqueue",
"Dropping transaction above gas limit: {:?} ({} > min({}, {}))", "Dropping transaction above gas limit: {:?} ({} > min({}, {}))",
tx.hash(), tx.hash(),
tx.gas, tx.gas,
self.gas_limit, self.total_gas_limit,
self.tx_gas_limit self.tx_gas_limit
); );
return Err(Error::Transaction(TransactionError::GasLimitExceeded { return Err(Error::Transaction(TransactionError::GasLimitExceeded {
limit: self.gas_limit, limit: gas_limit,
got: tx.gas, got: tx.gas,
})); }));
} }
@ -1591,7 +1615,13 @@ pub mod test {
#[test] #[test]
fn should_return_correct_nonces_when_dropped_because_of_limit() { fn should_return_correct_nonces_when_dropped_because_of_limit() {
// given // given
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 2, !U256::zero(), !U256::zero()); let mut txq = TransactionQueue::with_limits(
PrioritizationStrategy::GasPriceOnly,
2,
usize::max_value(),
!U256::zero(),
!U256::zero(),
);
let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into()); let (tx1, tx2) = new_tx_pair(123.into(), 1.into(), 1.into(), 0.into());
let sender = tx1.sender(); let sender = tx1.sender();
let nonce = tx1.nonce; let nonce = tx1.nonce;
@ -1631,7 +1661,8 @@ pub mod test {
by_address: Table::new(), by_address: Table::new(),
by_gas_price: Default::default(), by_gas_price: Default::default(),
limit: 1, limit: 1,
gas_limit: !U256::zero(), total_gas_limit: !U256::zero(),
memory_limit: usize::max_value(),
}; };
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None, 0, 0); let tx1 = VerifiedTransaction::new(tx1, TransactionOrigin::External, None, 0, 0);
@ -1672,7 +1703,8 @@ pub mod test {
by_address: Table::new(), by_address: Table::new(),
by_gas_price: Default::default(), by_gas_price: Default::default(),
limit: 1, limit: 1,
gas_limit: !U256::zero(), total_gas_limit: !U256::zero(),
memory_limit: 0,
}; };
// Create two transactions with same nonce // Create two transactions with same nonce
// (same hash) // (same hash)
@ -1721,7 +1753,8 @@ pub mod test {
by_address: Table::new(), by_address: Table::new(),
by_gas_price: Default::default(), by_gas_price: Default::default(),
limit: 2, limit: 2,
gas_limit: !U256::zero(), total_gas_limit: !U256::zero(),
memory_limit: 0,
}; };
let tx = new_tx_default(); let tx = new_tx_default();
let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None, 0, 0); let tx1 = VerifiedTransaction::new(tx.clone(), TransactionOrigin::External, None, 0, 0);
@ -1739,7 +1772,8 @@ pub mod test {
by_address: Table::new(), by_address: Table::new(),
by_gas_price: Default::default(), by_gas_price: Default::default(),
limit: 1, limit: 1,
gas_limit: !U256::zero(), total_gas_limit: !U256::zero(),
memory_limit: 0,
}; };
assert_eq!(set.gas_price_entry_limit(), 0.into()); assert_eq!(set.gas_price_entry_limit(), 0.into());
@ -1884,17 +1918,17 @@ pub mod test {
} }
#[test] #[test]
fn gas_limit_should_never_overflow() { fn tx_gas_limit_should_never_overflow() {
// given // given
let mut txq = TransactionQueue::default(); let mut txq = TransactionQueue::default();
txq.set_gas_limit(U256::zero()); txq.set_gas_limit(U256::zero());
assert_eq!(txq.gas_limit, U256::zero()); assert_eq!(txq.total_gas_limit, U256::zero());
// when // when
txq.set_gas_limit(!U256::zero()); txq.set_gas_limit(!U256::zero());
// then // then
assert_eq!(txq.gas_limit, !U256::zero()); assert_eq!(txq.total_gas_limit, !U256::zero());
} }
#[test] #[test]
@ -2352,7 +2386,13 @@ pub mod test {
#[test] #[test]
fn should_drop_old_transactions_when_hitting_the_limit() { fn should_drop_old_transactions_when_hitting_the_limit() {
// given // given
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 1, !U256::zero(), !U256::zero()); let mut txq = TransactionQueue::with_limits(
PrioritizationStrategy::GasPriceOnly,
1,
usize::max_value(),
!U256::zero(),
!U256::zero()
);
let (tx, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx, tx2) = new_tx_pair_default(1.into(), 0.into());
let sender = tx.sender(); let sender = tx.sender();
let nonce = tx.nonce; let nonce = tx.nonce;
@ -2373,7 +2413,13 @@ pub mod test {
#[test] #[test]
fn should_limit_future_transactions() { fn should_limit_future_transactions() {
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 1, !U256::zero(), !U256::zero()); let mut txq = TransactionQueue::with_limits(
PrioritizationStrategy::GasPriceOnly,
1 << FUTURE_QUEUE_LIMITS_SHIFT,
usize::max_value(),
!U256::zero(),
!U256::zero(),
);
txq.current.set_limit(10); txq.current.set_limit(10);
let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into()); let (tx1, tx2) = new_tx_pair_default(4.into(), 1.into());
let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into()); let (tx3, tx4) = new_tx_pair_default(4.into(), 2.into());
@ -2392,7 +2438,13 @@ pub mod test {
#[test] #[test]
fn should_limit_by_gas() { fn should_limit_by_gas() {
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero()); let mut txq = TransactionQueue::with_limits(
PrioritizationStrategy::GasPriceOnly,
100,
usize::max_value(),
default_gas_val() * U256::from(2),
!U256::zero()
);
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap(); txq.add(tx1.clone(), TransactionOrigin::External, 0, None, &default_tx_provider()).unwrap();
@ -2405,7 +2457,13 @@ pub mod test {
#[test] #[test]
fn should_keep_own_transactions_above_gas_limit() { fn should_keep_own_transactions_above_gas_limit() {
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 100, default_gas_val() * U256::from(2), !U256::zero()); let mut txq = TransactionQueue::with_limits(
PrioritizationStrategy::GasPriceOnly,
100,
usize::max_value(),
default_gas_val() * U256::from(2),
!U256::zero()
);
let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1)); let (tx1, tx2) = new_tx_pair_default(U256::from(1), U256::from(1));
let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx3, tx4) = new_tx_pair_default(U256::from(1), U256::from(2));
let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2)); let (tx5, _) = new_tx_pair_default(U256::from(1), U256::from(2));
@ -2679,7 +2737,13 @@ pub mod test {
#[test] #[test]
fn should_keep_right_order_in_future() { fn should_keep_right_order_in_future() {
// given // given
let mut txq = TransactionQueue::with_limits(PrioritizationStrategy::GasPriceOnly, 1, !U256::zero(), !U256::zero()); let mut txq = TransactionQueue::with_limits(
PrioritizationStrategy::GasPriceOnly,
1 << FUTURE_QUEUE_LIMITS_SHIFT,
usize::max_value(),
!U256::zero(),
!U256::zero()
);
let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into()); let (tx1, tx2) = new_tx_pair_default(1.into(), 0.into());
let prev_nonce = default_account_details().nonce - U256::one(); let prev_nonce = default_account_details().nonce - U256::one();

View File

@ -134,7 +134,7 @@ mod tests {
use views::BlockView; use views::BlockView;
use block::Block; use block::Block;
use super::AbridgedBlock; use super::AbridgedBlock;
use types::transaction::{Action, Transaction}; use transaction::{Action, Transaction};
use util::{Address, H256, U256, Bytes}; use util::{Address, H256, U256, Bytes};

View File

@ -20,10 +20,10 @@ use rustc_hex::FromHex;
use super::genesis::Genesis; use super::genesis::Genesis;
use super::seal::Generic as GenericSeal; use super::seal::Generic as GenericSeal;
use action_params::{ActionValue, ActionParams}; use evm::action_params::{ActionValue, ActionParams};
use builtin::Builtin; use builtin::Builtin;
use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT}; use engines::{Engine, NullEngine, InstantSeal, BasicAuthority, AuthorityRound, Tendermint, DEFAULT_BLOCKHASH_CONTRACT};
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use error::Error; use error::Error;
use ethereum; use ethereum;
use ethjson; use ethjson;
@ -36,7 +36,7 @@ use state_db::StateDB;
use state::{Backend, State, Substate}; use state::{Backend, State, Substate};
use state::backend::Basic as BasicBackend; use state::backend::Basic as BasicBackend;
use trace::{NoopTracer, NoopVMTracer}; use trace::{NoopTracer, NoopVMTracer};
use types::executed::CallType; use evm::CallType;
use util::*; use util::*;
/// Parameters common to all engines. /// Parameters common to all engines.
@ -87,6 +87,31 @@ pub struct CommonParams {
pub wasm: bool, pub wasm: bool,
} }
impl CommonParams {
/// Schedule for an EVM in the post-EIP-150-era of the Ethereum main net.
pub fn schedule(&self, block_number: u64) -> ::evm::Schedule {
let mut schedule = ::evm::Schedule::new_post_eip150(usize::max_value(), true, true, true);
self.update_schedule(block_number, &mut schedule);
schedule
}
/// Apply common spec config parameters to the schedule.
pub fn update_schedule(&self, block_number: u64, schedule: &mut ::evm::Schedule) {
schedule.have_create2 = block_number >= self.eip86_transition;
schedule.have_revert = block_number >= self.eip140_transition;
schedule.have_static_call = block_number >= self.eip214_transition;
if block_number >= self.eip210_transition {
schedule.blockhash_gas = 350;
}
if block_number >= self.dust_protection_transition {
schedule.kill_dust = match self.remove_dust_contracts {
true => ::evm::CleanDustMode::WithCodeAndStorage,
false => ::evm::CleanDustMode::BasicOnly,
};
}
}
}
impl From<ethjson::spec::Params> for CommonParams { impl From<ethjson::spec::Params> for CommonParams {
fn from(p: ethjson::spec::Params) -> Self { fn from(p: ethjson::spec::Params) -> Self {
CommonParams { CommonParams {
@ -451,6 +476,9 @@ impl Spec {
/// Create a new Spec with BasicAuthority which uses multiple validator sets changing with height. /// Create a new Spec with BasicAuthority which uses multiple validator sets changing with height.
/// Account with secrets "0".sha3() is the validator for block 1 and with "1".sha3() onwards. /// Account with secrets "0".sha3() is the validator for block 1 and with "1".sha3() onwards.
pub fn new_validator_multi() -> Self { load_bundled!("validator_multi") } pub fn new_validator_multi() -> Self { load_bundled!("validator_multi") }
/// Create a new spec for a PoW chain
pub fn new_pow_test_spec() -> Self { load_bundled!("ethereum/olympic") }
} }
#[cfg(test)] #[cfg(test)]

View File

@ -24,7 +24,7 @@ use std::collections::hash_map::Entry;
use receipt::Receipt; use receipt::Receipt;
use engines::Engine; use engines::Engine;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use error::Error; use error::Error;
use executive::{Executive, TransactOptions}; use executive::{Executive, TransactOptions};
use factory::Factories; use factory::Factories;
@ -32,7 +32,7 @@ use trace::FlatTrace;
use pod_account::*; use pod_account::*;
use pod_state::{self, PodState}; use pod_state::{self, PodState};
use types::basic_account::BasicAccount; use types::basic_account::BasicAccount;
use types::executed::{Executed, ExecutionError}; use executed::{Executed, ExecutionError};
use types::state_diff::StateDiff; use types::state_diff::StateDiff;
use transaction::SignedTransaction; use transaction::SignedTransaction;
use state_db::StateDB; use state_db::StateDB;
@ -982,12 +982,12 @@ mod tests {
use ethkey::Secret; use ethkey::Secret;
use util::{U256, H256, Address, Hashable}; use util::{U256, H256, Address, Hashable};
use tests::helpers::*; use tests::helpers::*;
use env_info::EnvInfo; use evm::env_info::EnvInfo;
use spec::*; use spec::*;
use transaction::*; use transaction::*;
use ethcore_logger::init_log; use ethcore_logger::init_log;
use trace::{FlatTrace, TraceError, trace}; use trace::{FlatTrace, TraceError, trace};
use types::executed::CallType; use evm::CallType;
fn secret() -> Secret { fn secret() -> Secret {
"".sha3().into() "".sha3().into()

76
ethcore/src/tests/evm.rs Normal file
View File

@ -0,0 +1,76 @@
//! Tests of EVM integration with transaction execution.
use evm::action_params::{ActionParams, ActionValue};
use evm::env_info::EnvInfo;
use evm::{Factory, VMType};
use evm::call_type::CallType;
use executive::Executive;
use state::Substate;
use tests::helpers::*;
use trace::{NoopVMTracer, NoopTracer};
use transaction::SYSTEM_ADDRESS;
use rustc_hex::FromHex;
use util::*;
evm_test!{test_blockhash_eip210: test_blockhash_eip210_jit, test_blockhash_eip210_int}
fn test_blockhash_eip210(factory: Factory) {
let get_prev_hash_code = Arc::new("600143034060205260206020f3".from_hex().unwrap()); // this returns previous block hash
let get_prev_hash_code_hash = get_prev_hash_code.sha3();
// This is same as DEFAULT_BLOCKHASH_CONTRACT except for metropolis transition block check removed.
let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b";
let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap());
let blockhash_contract_code_hash = blockhash_contract_code.sha3();
let engine = TestEngine::new_metropolis();
let mut env_info = EnvInfo::default();
// populate state with 256 last hashes
let mut state = get_temp_state_with_factory(factory);
let contract_address: Address = 0xf0.into();
state.init_code(&contract_address, (*blockhash_contract_code).clone()).unwrap();
for i in 1 .. 257 {
env_info.number = i.into();
let params = ActionParams {
code_address: contract_address.clone(),
address: contract_address,
sender: SYSTEM_ADDRESS.clone(),
origin: SYSTEM_ADDRESS.clone(),
gas: 100000.into(),
gas_price: 0.into(),
value: ActionValue::Transfer(0.into()),
code: Some(blockhash_contract_code.clone()),
code_hash: Some(blockhash_contract_code_hash),
data: Some(H256::from(i - 1).to_vec()),
call_type: CallType::Call,
};
let mut ex = Executive::new(&mut state, &env_info, &engine);
let mut substate = Substate::new();
let mut output = [];
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
panic!("Encountered error on updating last hashes: {}", e);
}
}
env_info.number = 256;
let params = ActionParams {
code_address: Address::new(),
address: Address::new(),
sender: Address::new(),
origin: Address::new(),
gas: 100000.into(),
gas_price: 0.into(),
value: ActionValue::Transfer(0.into()),
code: Some(get_prev_hash_code),
code_hash: Some(get_prev_hash_code_hash),
data: None,
call_type: CallType::Call,
};
let mut ex = Executive::new(&mut state, &env_info, &engine);
let mut substate = Substate::new();
let mut output = H256::new();
if let Err(e) = ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer) {
panic!("Encountered error on getting last hash: {}", e);
}
assert_eq!(output, 255.into());
}

View File

@ -16,5 +16,8 @@
pub mod helpers; pub mod helpers;
mod client; mod client;
mod evm;
#[cfg(feature="ipc")] #[cfg(feature="ipc")]
mod rpc; mod rpc;

View File

@ -410,7 +410,7 @@ mod tests {
use trace::{Filter, LocalizedTrace, AddressesFilter, TraceError}; use trace::{Filter, LocalizedTrace, AddressesFilter, TraceError};
use trace::trace::{Call, Action, Res}; use trace::trace::{Call, Action, Res};
use trace::flat::{FlatTrace, FlatBlockTraces, FlatTransactionTraces}; use trace::flat::{FlatTrace, FlatBlockTraces, FlatTransactionTraces};
use types::executed::CallType; use evm::CallType;
struct NoopExtras; struct NoopExtras;

View File

@ -17,7 +17,7 @@
//! Simple executive tracer. //! Simple executive tracer.
use util::{Bytes, Address, U256}; use util::{Bytes, Address, U256};
use action_params::ActionParams; use evm::action_params::ActionParams;
use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide}; use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide};
use trace::{Tracer, VMTracer, FlatTrace, TraceError}; use trace::{Tracer, VMTracer, FlatTrace, TraceError};

View File

@ -22,21 +22,24 @@ mod db;
mod executive_tracer; mod executive_tracer;
mod import; mod import;
mod noop_tracer; mod noop_tracer;
mod types;
pub use types::trace_types::{filter, flat, localized, trace};
pub use types::trace_types::error::Error as TraceError;
pub use self::config::Config; pub use self::config::Config;
pub use self::db::TraceDB; pub use self::db::TraceDB;
pub use types::trace_types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff};
pub use types::trace_types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
pub use self::noop_tracer::{NoopTracer, NoopVMTracer}; pub use self::noop_tracer::{NoopTracer, NoopVMTracer};
pub use self::executive_tracer::{ExecutiveTracer, ExecutiveVMTracer}; pub use self::executive_tracer::{ExecutiveTracer, ExecutiveVMTracer};
pub use types::trace_types::filter::{Filter, AddressesFilter};
pub use self::import::ImportRequest; pub use self::import::ImportRequest;
pub use self::localized::LocalizedTrace; pub use self::localized::LocalizedTrace;
pub use self::types::{filter, flat, localized, trace};
pub use self::types::error::Error as TraceError;
pub use self::types::trace::{VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff};
pub use self::types::flat::{FlatTrace, FlatTransactionTraces, FlatBlockTraces};
pub use self::types::filter::{Filter, AddressesFilter};
use util::{Bytes, Address, U256, H256, DBTransaction}; use util::{Bytes, Address, U256, H256, DBTransaction};
use self::trace::{Call, Create}; use self::trace::{Call, Create};
use action_params::ActionParams; use evm::action_params::ActionParams;
use header::BlockNumber; use header::BlockNumber;
/// This trait is used by executive to build traces. /// This trait is used by executive to build traces.

View File

@ -17,7 +17,7 @@
//! Nonoperative tracer. //! Nonoperative tracer.
use util::{Bytes, Address, U256}; use util::{Bytes, Address, U256};
use action_params::ActionParams; use evm::action_params::ActionParams;
use trace::{Tracer, VMTracer, FlatTrace, TraceError}; use trace::{Tracer, VMTracer, FlatTrace, TraceError};
use trace::trace::{Call, Create, VMTrace}; use trace::trace::{Call, Create, VMTrace};

View File

@ -22,7 +22,6 @@ use evm::Error as EvmError;
/// Trace evm errors. /// Trace evm errors.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum Error { pub enum Error {
/// `OutOfGas` is returned when transaction execution runs out of gas. /// `OutOfGas` is returned when transaction execution runs out of gas.
OutOfGas, OutOfGas,
@ -34,7 +33,7 @@ pub enum Error {
/// `StackUnderflow` when there is not enough stack elements to execute instruction /// `StackUnderflow` when there is not enough stack elements to execute instruction
StackUnderflow, StackUnderflow,
/// When execution would exceed defined Stack Limit /// When execution would exceed defined Stack Limit
OutOfStack, OutOfStack,
/// When builtin contract failed on input data /// When builtin contract failed on input data
BuiltIn, BuiltIn,
/// Returned on evm internal error. Should never be ignored during development. /// Returned on evm internal error. Should never be ignored during development.

View File

@ -23,13 +23,12 @@ use util::sha3::Hashable;
use util::bloom::Bloomable; use util::bloom::Bloomable;
use basic_types::LogBloom; use basic_types::LogBloom;
use trace::flat::FlatTrace; use trace::flat::FlatTrace;
use types::trace_types::trace::{Action, Res}; use super::trace::{Action, Res};
/// Addresses filter. /// Addresses filter.
/// ///
/// Used to create bloom possibilities and match filters. /// Used to create bloom possibilities and match filters.
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct AddressesFilter { pub struct AddressesFilter {
list: Vec<Address> list: Vec<Address>
} }
@ -76,7 +75,6 @@ impl AddressesFilter {
} }
#[derive(Debug)] #[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
/// Traces filter. /// Traces filter.
pub struct Filter { pub struct Filter {
/// Block range. /// Block range.
@ -143,7 +141,7 @@ mod tests {
use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide}; use trace::trace::{Action, Call, Res, Create, CreateResult, Suicide};
use trace::flat::FlatTrace; use trace::flat::FlatTrace;
use trace::{Filter, AddressesFilter, TraceError}; use trace::{Filter, AddressesFilter, TraceError};
use types::executed::CallType; use evm::CallType;
#[test] #[test]
fn empty_trace_filter_bloom_possibilities() { fn empty_trace_filter_bloom_possibilities() {

View File

@ -26,7 +26,6 @@ use super::trace::{Action, Res};
/// ///
/// Parent and children indexes refer to positions in this vector. /// Parent and children indexes refer to positions in this vector.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct FlatTrace { pub struct FlatTrace {
/// Type of action performed by a transaction. /// Type of action performed by a transaction.
pub action: Action, pub action: Action,
@ -164,7 +163,7 @@ mod tests {
use rlp::*; use rlp::*;
use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace}; use super::{FlatBlockTraces, FlatTransactionTraces, FlatTrace};
use trace::trace::{Action, Res, CallResult, Call, Suicide}; use trace::trace::{Action, Res, CallResult, Call, Suicide};
use types::executed::CallType; use evm::CallType;
#[test] #[test]
fn encode_flat_transaction_traces() { fn encode_flat_transaction_traces() {

View File

@ -22,7 +22,6 @@ use header::BlockNumber;
/// Localized trace. /// Localized trace.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedTrace { pub struct LocalizedTrace {
/// Type of action performed by a transaction. /// Type of action performed by a transaction.
pub action: Action, pub action: Action,

View File

@ -21,9 +21,9 @@ use util::sha3::Hashable;
use util::bloom::Bloomable; use util::bloom::Bloomable;
use rlp::*; use rlp::*;
use action_params::ActionParams; use evm::action_params::ActionParams;
use basic_types::LogBloom; use basic_types::LogBloom;
use types::executed::CallType; use evm::CallType;
use super::error::Error; use super::error::Error;
/// `Call` result. /// `Call` result.

View File

@ -32,9 +32,8 @@ pub const UNSIGNED_SENDER: Address = ::util::H160([0xff; 20]);
/// System sender address for internal state updates. /// System sender address for internal state updates.
pub const SYSTEM_ADDRESS: Address = ::util::H160([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xfe]); pub const SYSTEM_ADDRESS: Address = ::util::H160([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0xff, 0xfe]);
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
/// Transaction action type. /// Transaction action type.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Action { pub enum Action {
/// Create creates new contract. /// Create creates new contract.
Create, Create,
@ -59,7 +58,6 @@ impl Decodable for Action {
/// Transaction activation condition. /// Transaction activation condition.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum Condition { pub enum Condition {
/// Valid at this block number or later. /// Valid at this block number or later.
Number(BlockNumber), Number(BlockNumber),
@ -70,7 +68,6 @@ pub enum Condition {
/// A set of information describing an externally-originating message call /// A set of information describing an externally-originating message call
/// or contract creation operation. /// or contract creation operation.
#[derive(Default, Debug, Clone, PartialEq, Eq)] #[derive(Default, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Transaction { pub struct Transaction {
/// Nonce. /// Nonce.
pub nonce: U256, pub nonce: U256,
@ -241,9 +238,8 @@ impl Transaction {
} }
} }
/// Signed transaction information. /// Signed transaction information without verified signature.
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct UnverifiedTransaction { pub struct UnverifiedTransaction {
/// Plain Transaction. /// Plain Transaction.
unsigned: Transaction, unsigned: Transaction,
@ -470,7 +466,6 @@ impl SignedTransaction {
/// Signed Transaction that is a part of canon blockchain. /// Signed Transaction that is a part of canon blockchain.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedTransaction { pub struct LocalizedTransaction {
/// Signed part. /// Signed part.
pub signed: UnverifiedTransaction, pub signed: UnverifiedTransaction,
@ -511,7 +506,6 @@ impl Deref for LocalizedTransaction {
/// Queued transaction with additional information. /// Queued transaction with additional information.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct PendingTransaction { pub struct PendingTransaction {
/// Signed transaction data. /// Signed transaction data.
pub transaction: SignedTransaction, pub transaction: SignedTransaction,
@ -544,91 +538,97 @@ impl From<SignedTransaction> for PendingTransaction {
} }
} }
#[test] #[cfg(test)]
fn sender_test() { mod tests {
let t: UnverifiedTransaction = decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap()); use super::*;
assert_eq!(t.data, b""); use util::{Hashable, U256};
assert_eq!(t.gas, U256::from(0x5208u64));
assert_eq!(t.gas_price, U256::from(0x01u64)); #[test]
assert_eq!(t.nonce, U256::from(0x00u64)); fn sender_test() {
if let Action::Call(ref to) = t.action { let t: UnverifiedTransaction = decode(&::rustc_hex::FromHex::from_hex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a0efffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804").unwrap());
assert_eq!(*to, "095e7baea6a6c7c4c2dfeb977efac326af552d87".into()); assert_eq!(t.data, b"");
} else { panic!(); } assert_eq!(t.gas, U256::from(0x5208u64));
assert_eq!(t.value, U256::from(0x0au64)); assert_eq!(t.gas_price, U256::from(0x01u64));
assert_eq!(public_to_address(&t.recover_public().unwrap()), "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into()); assert_eq!(t.nonce, U256::from(0x00u64));
assert_eq!(t.network_id(), None); if let Action::Call(ref to) = t.action {
} assert_eq!(*to, "095e7baea6a6c7c4c2dfeb977efac326af552d87".into());
} else { panic!(); }
#[test] assert_eq!(t.value, U256::from(0x0au64));
fn signing() { assert_eq!(public_to_address(&t.recover_public().unwrap()), "0f65fe9276bc9a24ae7083ae28e2660ef72df99e".into());
use ethkey::{Random, Generator}; assert_eq!(t.network_id(), None);
}
let key = Random.generate().unwrap();
let t = Transaction { #[test]
action: Action::Create, fn signing() {
nonce: U256::from(42), use ethkey::{Random, Generator};
gas_price: U256::from(3000),
gas: U256::from(50_000), let key = Random.generate().unwrap();
value: U256::from(1), let t = Transaction {
data: b"Hello!".to_vec() action: Action::Create,
}.sign(&key.secret(), None); nonce: U256::from(42),
assert_eq!(Address::from(key.public().sha3()), t.sender()); gas_price: U256::from(3000),
assert_eq!(t.network_id(), None); gas: U256::from(50_000),
} value: U256::from(1),
data: b"Hello!".to_vec()
#[test] }.sign(&key.secret(), None);
fn fake_signing() { assert_eq!(Address::from(key.public().sha3()), t.sender());
let t = Transaction { assert_eq!(t.network_id(), None);
action: Action::Create, }
nonce: U256::from(42),
gas_price: U256::from(3000), #[test]
gas: U256::from(50_000), fn fake_signing() {
value: U256::from(1), let t = Transaction {
data: b"Hello!".to_vec() action: Action::Create,
}.fake_sign(Address::from(0x69)); nonce: U256::from(42),
assert_eq!(Address::from(0x69), t.sender()); gas_price: U256::from(3000),
assert_eq!(t.network_id(), None); gas: U256::from(50_000),
value: U256::from(1),
let t = t.clone(); data: b"Hello!".to_vec()
assert_eq!(Address::from(0x69), t.sender()); }.fake_sign(Address::from(0x69));
assert_eq!(t.network_id(), None); assert_eq!(Address::from(0x69), t.sender());
} assert_eq!(t.network_id(), None);
#[test] let t = t.clone();
fn should_recover_from_network_specific_signing() { assert_eq!(Address::from(0x69), t.sender());
use ethkey::{Random, Generator}; assert_eq!(t.network_id(), None);
let key = Random.generate().unwrap(); }
let t = Transaction {
action: Action::Create, #[test]
nonce: U256::from(42), fn should_recover_from_network_specific_signing() {
gas_price: U256::from(3000), use ethkey::{Random, Generator};
gas: U256::from(50_000), let key = Random.generate().unwrap();
value: U256::from(1), let t = Transaction {
data: b"Hello!".to_vec() action: Action::Create,
}.sign(&key.secret(), Some(69)); nonce: U256::from(42),
assert_eq!(Address::from(key.public().sha3()), t.sender()); gas_price: U256::from(3000),
assert_eq!(t.network_id(), Some(69)); gas: U256::from(50_000),
} value: U256::from(1),
data: b"Hello!".to_vec()
#[test] }.sign(&key.secret(), Some(69));
fn should_agree_with_vitalik() { assert_eq!(Address::from(key.public().sha3()), t.sender());
use rustc_hex::FromHex; assert_eq!(t.network_id(), Some(69));
}
let test_vector = |tx_data: &str, address: &'static str| {
let signed = decode(&FromHex::from_hex(tx_data).unwrap()); #[test]
let signed = SignedTransaction::new(signed).unwrap(); fn should_agree_with_vitalik() {
assert_eq!(signed.sender(), address.into()); use rustc_hex::FromHex;
flushln!("networkid: {:?}", signed.network_id());
}; let test_vector = |tx_data: &str, address: &'static str| {
let signed = decode(&FromHex::from_hex(tx_data).unwrap());
test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce"); let signed = SignedTransaction::new(signed).unwrap();
test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112"); assert_eq!(signed.sender(), address.into());
test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be"); flushln!("networkid: {:?}", signed.network_id());
test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0"); };
test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554");
test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4"); test_vector("f864808504a817c800825208943535353535353535353535353535353535353535808025a0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116da0044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", "0xf0f6f18bca1b28cd68e4357452947e021241e9ce");
test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35"); test_vector("f864018504a817c80182a410943535353535353535353535353535353535353535018025a0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bcaa0489efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", "0x23ef145a395ea3fa3deb533b8a9e1b4c6c25d112");
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332"); test_vector("f864028504a817c80282f618943535353535353535353535353535353535353535088025a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5a02d7c5bef027816a800da1736444fb58a807ef4c9603b7848673f7e3a68eb14a5", "0x2e485e0c23b4c3c542628a5f672eeab0ad4888be");
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029"); test_vector("f865038504a817c803830148209435353535353535353535353535353535353535351b8025a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4e0a02a80e1ef1d7842f27f2e6be0972bb708b9a135c38860dbe73c27c3486c34f4de", "0x82a88539669a3fd524d669e858935de5e5410cf0");
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f"); test_vector("f865048504a817c80483019a28943535353535353535353535353535353535353535408025a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c063a013600b294191fc92924bb3ce4b969c1e7e2bab8f4c93c3fc6d0a51733df3c060", "0xf9358f2538fd5ccfeb848b64a96b743fcc930554");
test_vector("f865058504a817c8058301ec309435353535353535353535353535353535353535357d8025a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1a04eebf77a833b30520287ddd9478ff51abbdffa30aa90a8d655dba0e8a79ce0c1", "0xa8f7aba377317440bc5b26198a363ad22af1f3a4");
test_vector("f866068504a817c80683023e3894353535353535353535353535353535353535353581d88025a06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2fa06455bf8ea6e7463a1046a0b52804526e119b4bf5136279614e0b1e8e296a4e2d", "0xf1f571dc362a0e5b2696b8e775f8491d3e50de35");
test_vector("f867078504a817c807830290409435353535353535353535353535353535353535358201578025a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021a052f1a9b320cab38e5da8a8f97989383aab0a49165fc91c737310e4f7e9821021", "0xd37922162ab7cea97c97a87551ed02c9a38b7332");
test_vector("f867088504a817c8088302e2489435353535353535353535353535353535353535358202008025a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c12a064b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10", "0x9bddad43f934d313c2b79ca28a432dd2b7281029");
test_vector("f867098504a817c809830334509435353535353535353535353535353535353535358202d98025a052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afba052f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb", "0x3c24d7329e92f84f08556ceb6df1cdb0104ca49f");
}
} }

View File

@ -1,42 +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 <http://www.gnu.org/licenses/>.
//! Block import error related types
use error::{ImportError, BlockError, Error};
use std::convert::From;
/// Error dedicated to import block function
#[derive(Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub enum BlockImportError {
/// Import error
Import(ImportError),
/// Block error
Block(BlockError),
/// Other error
Other(String),
}
impl From<Error> for BlockImportError {
fn from(e: Error) -> Self {
match e {
Error::Block(block_error) => BlockImportError::Block(block_error),
Error::Import(import_error) => BlockImportError::Import(import_error),
_ => BlockImportError::Other(format!("other block import error: {:?}", e)),
}
}
}

View File

@ -1,42 +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 <http://www.gnu.org/licenses/>.
//! Block status description module
use verification::queue::Status as QueueStatus;
/// General block status
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum BlockStatus {
/// Part of the blockchain.
InChain,
/// Queued for import.
Queued,
/// Known as bad.
Bad,
/// Unknown.
Unknown,
}
impl From<QueueStatus> for BlockStatus {
fn from(status: QueueStatus) -> Self {
match status {
QueueStatus::Queued => BlockStatus::Queued,
QueueStatus::Bad => BlockStatus::Bad,
QueueStatus::Unknown => BlockStatus::Unknown,
}
}
}

View File

@ -1,50 +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 <http://www.gnu.org/licenses/>.
//! Transaction import result related types
use ipc::binary::{BinaryConvertError, BinaryConvertable};
use error::{TransactionError, Error};
#[derive(Debug, Clone, Copy, PartialEq)]
/// Represents the result of importing transaction.
pub enum TransactionImportResult {
/// Transaction was imported to current queue.
Current,
/// Transaction was imported to future queue.
Future
}
binary_fixed_size!(TransactionImportResult);
/// Api-level error for transaction import
#[derive(Debug, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub enum TransactionImportError {
/// Transaction error
Transaction(TransactionError),
/// Other error
Other(String),
}
impl From<Error> for TransactionImportError {
fn from(e: Error) -> Self {
match e {
Error::Transaction(transaction_error) => TransactionImportError::Transaction(transaction_error),
_ => TransactionImportError::Other(format!("other block import error: {:?}", e)),
}
}
}

View File

@ -115,6 +115,17 @@ pub enum Status {
Unknown, Unknown,
} }
impl Into<::block_status::BlockStatus> for Status {
fn into(self) -> ::block_status::BlockStatus {
use ::block_status::BlockStatus;
match self {
Status::Queued => BlockStatus::Queued,
Status::Bad => BlockStatus::Bad,
Status::Unknown => BlockStatus::Unknown,
}
}
}
// the internal queue sizes. // the internal queue sizes.
struct Sizes { struct Sizes {
unverified: AtomicUsize, unverified: AtomicUsize,

View File

@ -585,7 +585,7 @@ mod tests {
#[test] #[test]
fn dust_protection() { fn dust_protection() {
use ethkey::{Generator, Random}; use ethkey::{Generator, Random};
use types::transaction::{Transaction, Action}; use transaction::{Transaction, Action};
use engines::NullEngine; use engines::NullEngine;
let mut params = CommonParams::default(); let mut params = CommonParams::default();

13
ethcore/types/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "common-types"
description = "Common types used throughout the codebase"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
rlp = { path = "../../util/rlp" }
ethcore-util = { path = "../../util" }
ethjson = { path = "../../json" }
[dev-dependencies]
rustc-hex= "1.0"

View File

@ -20,12 +20,10 @@ use std::cmp::*;
use std::fmt; use std::fmt;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use util::{U256, H256, Bytes}; use util::{U256, H256, Bytes};
use ipc::binary::BinaryConvertable;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
/// Diff type for specifying a change (or not). /// Diff type for specifying a change (or not).
pub enum Diff<T> where T: Eq + BinaryConvertable { pub enum Diff<T> where T: Eq {
/// Both sides are the same. /// Both sides are the same.
Same, Same,
/// Left (pre, source) side doesn't include value, right side (post, destination) does. /// Left (pre, source) side doesn't include value, right side (post, destination) does.
@ -36,7 +34,7 @@ pub enum Diff<T> where T: Eq + BinaryConvertable {
Died(T), Died(T),
} }
impl<T> Diff<T> where T: Eq + BinaryConvertable { impl<T> Diff<T> where T: Eq {
/// Construct new object with given `pre` and `post`. /// Construct new object with given `pre` and `post`.
pub fn new(pre: T, post: T) -> Self { if pre == post { Diff::Same } else { Diff::Changed(pre, post) } } pub fn new(pre: T, post: T) -> Self { if pre == post { Diff::Same } else { Diff::Changed(pre, post) } }

View File

@ -14,12 +14,15 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! Types used in the public api /// General block status
#[derive(Debug, Eq, PartialEq)]
#![cfg_attr(feature = "ipc", allow(dead_code, unused_assignments, unused_variables))] // codegen issues pub enum BlockStatus {
/// Part of the blockchain.
#[cfg(feature = "ipc")] InChain,
include!(concat!(env!("OUT_DIR"), "/mod.rs.in")); /// Queued for import.
Queued,
#[cfg(not(feature = "ipc"))] /// Known as bad.
include!("mod.rs.in"); Bad,
/// Unknown.
Unknown,
}

View File

@ -16,13 +16,14 @@
//! Blockhain info type definition //! Blockhain info type definition
use std::fmt;
use util::{U256, H256}; use util::{U256, H256};
use header::BlockNumber; use security_level::SecurityLevel;
use types::security_level::SecurityLevel; use {BlockNumber};
/// Information about the blockchain gathered together. /// Information about the blockchain gathered together.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct BlockChainInfo { pub struct BlockChainInfo {
/// Blockchain difficulty. /// Blockchain difficulty.
pub total_difficulty: U256, pub total_difficulty: U256,
@ -57,3 +58,9 @@ impl BlockChainInfo {
} }
} }
} }
impl fmt::Display for BlockChainInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "#{}.{}", self.best_block_number, self.best_block_hash)
}
}

View File

@ -18,7 +18,6 @@
/// Options concerning what analytics we run on the call. /// Options concerning what analytics we run on the call.
#[derive(Eq, PartialEq, Default, Clone, Copy, Debug)] #[derive(Eq, PartialEq, Default, Clone, Copy, Debug)]
#[cfg_attr(feature = "ipc", binary)]
pub struct CallAnalytics { pub struct CallAnalytics {
/// Make a transaction trace. /// Make a transaction trace.
pub transaction_tracing: bool, pub transaction_tracing: bool,

View File

@ -18,12 +18,11 @@
use util::{Address, H256, Hashable, H2048}; use util::{Address, H256, Hashable, H2048};
use util::bloom::Bloomable; use util::bloom::Bloomable;
use client::BlockId; use ids::BlockId;
use log_entry::LogEntry; use log_entry::LogEntry;
/// Blockchain Filter. /// Blockchain Filter.
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct Filter { pub struct Filter {
/// Blockchain will be searched from this block. /// Blockchain will be searched from this block.
pub from_block: BlockId, pub from_block: BlockId,
@ -114,7 +113,7 @@ impl Filter {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use filter::Filter; use filter::Filter;
use client::BlockId; use ids::BlockId;
use log_entry::LogEntry; use log_entry::LogEntry;
#[test] #[test]

View File

@ -17,11 +17,10 @@
//! Unique identifiers. //! Unique identifiers.
use util::hash::H256; use util::hash::H256;
use header::BlockNumber; use {BlockNumber};
/// Uniquely identifies block. /// Uniquely identifies block.
#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum BlockId { pub enum BlockId {
/// Block's sha3. /// Block's sha3.
/// Querying by hash is always faster. /// Querying by hash is always faster.
@ -38,7 +37,6 @@ pub enum BlockId {
/// Uniquely identifies transaction. /// Uniquely identifies transaction.
#[derive(Debug, PartialEq, Clone, Hash, Eq)] #[derive(Debug, PartialEq, Clone, Hash, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub enum TransactionId { pub enum TransactionId {
/// Transaction's sha3. /// Transaction's sha3.
Hash(H256), Hash(H256),
@ -48,7 +46,6 @@ pub enum TransactionId {
} }
/// Uniquely identifies Trace. /// Uniquely identifies Trace.
#[cfg_attr(feature = "ipc", binary)]
pub struct TraceId { pub struct TraceId {
/// Transaction /// Transaction
pub transaction: TransactionId, pub transaction: TransactionId,
@ -58,7 +55,6 @@ pub struct TraceId {
/// Uniquely identifies Uncle. /// Uniquely identifies Uncle.
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct UncleId { pub struct UncleId {
/// Block id. /// Block id.
pub block: BlockId, pub block: BlockId,

View File

@ -14,27 +14,33 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
pub mod transaction; //! Types used in the public API
pub mod ids;
pub mod receipt; extern crate ethcore_util as util;
pub mod tree_route; extern crate ethjson;
pub mod blockchain_info; extern crate rlp;
pub mod log_entry;
pub mod trace_types; #[cfg(test)]
pub mod executed; extern crate rustc_hex;
pub mod block_status;
pub mod account_diff; pub mod account_diff;
pub mod state_diff; pub mod basic_account;
pub mod verification_queue_info; pub mod block_status;
pub mod filter; pub mod blockchain_info;
pub mod trace_filter;
pub mod call_analytics; pub mod call_analytics;
pub mod transaction_import; pub mod filter;
pub mod block_import_error; pub mod ids;
pub mod restoration_status; pub mod log_entry;
pub mod snapshot_manifest;
pub mod mode; pub mod mode;
pub mod pruning_info; pub mod pruning_info;
pub mod receipt;
pub mod restoration_status;
pub mod security_level; pub mod security_level;
pub mod encoded; pub mod snapshot_manifest;
pub mod basic_account; pub mod state_diff;
pub mod trace_filter;
pub mod tree_route;
pub mod verification_queue_info;
/// Type for block number.
pub type BlockNumber = u64;

View File

@ -21,13 +21,13 @@ use util::{H256, Address, Bytes, HeapSizeOf, Hashable};
use util::bloom::Bloomable; use util::bloom::Bloomable;
use rlp::*; use rlp::*;
use basic_types::LogBloom; use {BlockNumber};
use header::BlockNumber;
use ethjson; use ethjson;
pub type LogBloom = ::util::H2048;
/// A record of execution for a `LOG` operation. /// A record of execution for a `LOG` operation.
#[derive(Default, Debug, Clone, PartialEq, Eq)] #[derive(Default, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LogEntry { pub struct LogEntry {
/// The address of the contract executing at the point of the `LOG` operation. /// The address of the contract executing at the point of the `LOG` operation.
pub address: Address, pub address: Address,
@ -82,7 +82,6 @@ impl From<ethjson::state::Log> for LogEntry {
/// Log localized in a blockchain. /// Log localized in a blockchain.
#[derive(Default, Debug, PartialEq, Clone)] #[derive(Default, Debug, PartialEq, Clone)]
#[cfg_attr(feature = "ipc", binary)]
pub struct LocalizedLogEntry { pub struct LocalizedLogEntry {
/// Plain log entry. /// Plain log entry.
pub entry: LogEntry, pub entry: LogEntry,

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