Merge branch 'master' into tx_queue_timeout
This commit is contained in:
commit
40fc3dc060
@ -33,7 +33,7 @@ env:
|
|||||||
global:
|
global:
|
||||||
# GH_TOKEN
|
# GH_TOKEN
|
||||||
- secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw=
|
- secure: bumJASbZSU8bxJ0EyPUJmu16AiV9EXOpyOj86Jlq/Ty9CfwGqsSXt96uDyE+OUJf34RUFQMsw0nk37/zC4lcn6kqk2wpuH3N/o85Zo/cVZY/NusBWLQqtT5VbYWsV+u2Ua4Tmmsw8yVYQhYwU2ZOejNpflL+Cs9XGgORp1L+/gMRMC2y5Se6ZhwnKPQlRJ8LGsG1dzjQULxzADIt3/zuspNBS8a2urJwlHfGMkvHDoUWCviP/GXoSqw3TZR7FmKyxE19I8n9+iSvm9+oZZquvcgfUxMHn8Gq/b44UbPvjtFOg2yam4xdWXF/RyWCHdc/R9EHorSABeCbefIsm+zcUF3/YQxwpSxM4IZEeH2rTiC7dcrsKw3XsO16xFQz5YI5Bay+CT/wTdMmJd7DdYz7Dyf+pOvcM9WOf/zorxYWSBOMYy0uzbusU2iyIghQ82s7E/Ahg+WARtPgkuTLSB5aL1oCTBKHqQscMr7lo5Ti6RpWLxEdTQMBznc+bMr+6dEtkEcG9zqc6cE9XX+ox3wTU6+HVMfQ1ltCntJ4UKcw3A6INEbw9wgocQa812CIASQ2fE+SCAbz6JxBjIAlFUnD1lUB7S8PdMPwn9plfQgKQ2A5YZqg6FnBdf0rQXIJYxQWKHXj/rBHSUCT0tHACDlzTA+EwWggvkP5AGIxRxm8jhw=
|
||||||
- TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer"
|
- TARGETS="-p ethash -p ethcore-util -p ethcore -p ethsync -p ethcore-rpc -p parity -p ethminer -p ethjson"
|
||||||
- ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}"
|
- ARCHIVE_SUFFIX="-${TRAVIS_OS_NAME}-${TRAVIS_TAG}"
|
||||||
- KCOV_FEATURES=""
|
- KCOV_FEATURES=""
|
||||||
- KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov"
|
- KCOV_CMD="./kcov-master/tmp/usr/local/bin/kcov --exclude-pattern /usr/,/.cargo,/root/.multirust,src/tests,util/json-tests,util/src/network/tests,sync/src/tests,ethcore/src/tests,ethcore/src/evm/tests target/kcov"
|
||||||
@ -70,6 +70,7 @@ after_success: |
|
|||||||
$KCOV_CMD target/debug/deps/ethsync-* &&
|
$KCOV_CMD target/debug/deps/ethsync-* &&
|
||||||
$KCOV_CMD target/debug/deps/ethcore_rpc-* &&
|
$KCOV_CMD target/debug/deps/ethcore_rpc-* &&
|
||||||
$KCOV_CMD target/debug/deps/ethminer-* &&
|
$KCOV_CMD target/debug/deps/ethminer-* &&
|
||||||
|
$KCOV_CMD target/debug/deps/ethjson-* &&
|
||||||
$KCOV_CMD target/debug/parity-* &&
|
$KCOV_CMD target/debug/parity-* &&
|
||||||
[ $TRAVIS_BRANCH = master ] &&
|
[ $TRAVIS_BRANCH = master ] &&
|
||||||
[ $TRAVIS_PULL_REQUEST = false ] &&
|
[ $TRAVIS_PULL_REQUEST = false ] &&
|
||||||
|
131
Cargo.lock
generated
131
Cargo.lock
generated
@ -11,7 +11,6 @@ dependencies = [
|
|||||||
"ethcore-devtools 1.1.0",
|
"ethcore-devtools 1.1.0",
|
||||||
"ethcore-rpc 1.1.0",
|
"ethcore-rpc 1.1.0",
|
||||||
"ethcore-util 1.1.0",
|
"ethcore-util 1.1.0",
|
||||||
"ethjson 0.1.0",
|
|
||||||
"ethminer 1.1.0",
|
"ethminer 1.1.0",
|
||||||
"ethsync 1.1.0",
|
"ethsync 1.1.0",
|
||||||
"fdlimit 0.1.0",
|
"fdlimit 0.1.0",
|
||||||
@ -20,7 +19,6 @@ dependencies = [
|
|||||||
"rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rpassword 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -43,10 +41,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aster"
|
name = "aster"
|
||||||
version = "0.13.1"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -54,7 +52,7 @@ name = "bigint"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"arrayvec 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.5 (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)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"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)",
|
||||||
@ -141,7 +139,7 @@ source = "git+https://github.com/tomusdrw/rust-ctrlc.git#f4927770f89eca80ec25091
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -165,7 +163,7 @@ name = "docopt"
|
|||||||
version = "0.6.78"
|
version = "0.6.78"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"strsim 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -181,7 +179,7 @@ version = "0.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -218,7 +216,7 @@ dependencies = [
|
|||||||
"ethcore-devtools 1.1.0",
|
"ethcore-devtools 1.1.0",
|
||||||
"ethcore-util 1.1.0",
|
"ethcore-util 1.1.0",
|
||||||
"ethjson 0.1.0",
|
"ethjson 0.1.0",
|
||||||
"heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -244,14 +242,14 @@ dependencies = [
|
|||||||
"ethcore-util 1.1.0",
|
"ethcore-util 1.1.0",
|
||||||
"ethminer 1.1.0",
|
"ethminer 1.1.0",
|
||||||
"ethsync 1.1.0",
|
"ethsync 1.1.0",
|
||||||
"jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-http-server 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-http-server 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"transient-hashmap 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -268,7 +266,7 @@ dependencies = [
|
|||||||
"env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"env_logger 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
"eth-secp256k1 0.5.4 (git+https://github.com/ethcore/rust-secp256k1)",
|
||||||
"ethcore-devtools 1.1.0",
|
"ethcore-devtools 1.1.0",
|
||||||
"heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"igd 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"igd 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"itertools 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"json-tests 0.1.0",
|
"json-tests 0.1.0",
|
||||||
@ -297,9 +295,9 @@ dependencies = [
|
|||||||
"ethcore-util 1.1.0",
|
"ethcore-util 1.1.0",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -325,7 +323,7 @@ dependencies = [
|
|||||||
"ethcore 1.1.0",
|
"ethcore 1.1.0",
|
||||||
"ethcore-util 1.1.0",
|
"ethcore-util 1.1.0",
|
||||||
"ethminer 1.1.0",
|
"ethminer 1.1.0",
|
||||||
"heapsize 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"heapsize 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (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)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -355,11 +353,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heapsize"
|
name = "heapsize"
|
||||||
version = "0.3.3"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -391,27 +388,27 @@ dependencies = [
|
|||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.7.2"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cookie 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cookie 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"httparse 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"httparse 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -422,7 +419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.6.16 (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)",
|
||||||
"regex 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.1.58 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"xml-rs 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
"xml-rs 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"xmltree 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"xmltree 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -442,23 +439,23 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-core"
|
name = "jsonrpc-core"
|
||||||
version = "2.0.0"
|
version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_codegen 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-http-server"
|
name = "jsonrpc-http-server"
|
||||||
version = "3.0.0"
|
version = "3.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hyper 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"jsonrpc-core 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"jsonrpc-core 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicase 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -466,7 +463,7 @@ name = "kernel32-sys"
|
|||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -498,7 +495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "librocksdb-sys"
|
name = "librocksdb-sys"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
source = "git+https://github.com/arkpar/rust-rocksdb.git#ebb602fc74b4067f9f51310bdc0401b8e59b7156"
|
source = "git+https://github.com/arkpar/rust-rocksdb.git#ae44ef33ed1358ffc79aa05ed77839d555daba33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
@ -533,6 +530,14 @@ dependencies = [
|
|||||||
"serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@ -542,11 +547,11 @@ dependencies = [
|
|||||||
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"miow 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"net2 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"nix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"nix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -555,20 +560,20 @@ version = "0.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"net2 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"net2 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net2"
|
name = "net2"
|
||||||
version = "0.2.22"
|
version = "0.2.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -667,20 +672,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quasi"
|
name = "quasi"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quasi_codegen"
|
name = "quasi_codegen"
|
||||||
version = "0.7.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aster 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aster 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -703,7 +708,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "0.1.56"
|
version = "0.1.58"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aho-corasick 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -720,7 +725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "rocksdb"
|
name = "rocksdb"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "git+https://github.com/arkpar/rust-rocksdb.git#ebb602fc74b4067f9f51310bdc0401b8e59b7156"
|
source = "git+https://github.com/arkpar/rust-rocksdb.git#ae44ef33ed1358ffc79aa05ed77839d555daba33"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"librocksdb-sys 0.2.3 (git+https://github.com/arkpar/rust-rocksdb.git)",
|
"librocksdb-sys 0.2.3 (git+https://github.com/arkpar/rust-rocksdb.git)",
|
||||||
@ -734,7 +739,7 @@ dependencies = [
|
|||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -790,14 +795,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_codegen"
|
name = "serde_codegen"
|
||||||
version = "0.7.0"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aster 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"aster 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quasi 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"quasi_codegen 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"quasi_codegen 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -837,18 +842,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex"
|
name = "syntex"
|
||||||
version = "0.29.0"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"syntex_syntax 0.29.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"syntex_syntax 0.30.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syntex_syntax"
|
name = "syntex_syntax"
|
||||||
version = "0.29.1"
|
version = "0.30.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -867,7 +872,7 @@ version = "0.2.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -885,7 +890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -921,7 +926,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"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)",
|
||||||
@ -992,7 +997,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1005,7 +1010,7 @@ name = "ws2_32-sys"
|
|||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -27,8 +27,6 @@ ethsync = { path = "sync" }
|
|||||||
ethminer = { path = "miner" }
|
ethminer = { path = "miner" }
|
||||||
ethcore-devtools = { path = "devtools" }
|
ethcore-devtools = { path = "devtools" }
|
||||||
ethcore-rpc = { path = "rpc", optional = true }
|
ethcore-rpc = { path = "rpc", optional = true }
|
||||||
ethjson = { path = "json" }
|
|
||||||
serde_json = "0.7.0"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["rpc"]
|
default = ["rpc"]
|
||||||
@ -41,10 +39,6 @@ travis-nightly = ["ethcore/json-tests", "dev"]
|
|||||||
path = "parity/main.rs"
|
path = "parity/main.rs"
|
||||||
name = "parity"
|
name = "parity"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
path = "parity/rpctest.rs"
|
|
||||||
name = "rpctest"
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = false
|
debug = false
|
||||||
lto = false
|
lto = false
|
||||||
|
@ -24,7 +24,6 @@ use state::*;
|
|||||||
use verification::PreverifiedBlock;
|
use verification::PreverifiedBlock;
|
||||||
|
|
||||||
/// A block, encoded as it is on the block chain.
|
/// A block, encoded as it is on the block chain.
|
||||||
// TODO: rename to Block
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
/// The header of this block.
|
/// The header of this block.
|
||||||
@ -76,8 +75,6 @@ impl Decodable for Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Internal type for a block's common elements.
|
/// Internal type for a block's common elements.
|
||||||
// TODO: rename to ExecutedBlock
|
|
||||||
// TODO: use BareBlock
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ExecutedBlock {
|
pub struct ExecutedBlock {
|
||||||
base: Block,
|
base: Block,
|
||||||
@ -85,6 +82,7 @@ pub struct ExecutedBlock {
|
|||||||
receipts: Vec<Receipt>,
|
receipts: Vec<Receipt>,
|
||||||
transactions_set: HashSet<H256>,
|
transactions_set: HashSet<H256>,
|
||||||
state: State,
|
state: State,
|
||||||
|
traces: Option<Vec<Trace>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of references to `ExecutedBlock` fields that are publicly accessible.
|
/// A set of references to `ExecutedBlock` fields that are publicly accessible.
|
||||||
@ -99,11 +97,21 @@ pub struct BlockRefMut<'a> {
|
|||||||
pub receipts: &'a Vec<Receipt>,
|
pub receipts: &'a Vec<Receipt>,
|
||||||
/// State.
|
/// State.
|
||||||
pub state: &'a mut State,
|
pub state: &'a mut State,
|
||||||
|
/// Traces.
|
||||||
|
pub traces: &'a Option<Vec<Trace>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExecutedBlock {
|
impl ExecutedBlock {
|
||||||
/// Create a new block from the given `state`.
|
/// Create a new block from the given `state`.
|
||||||
fn new(state: State) -> ExecutedBlock { ExecutedBlock { base: Default::default(), receipts: Default::default(), transactions_set: Default::default(), state: state } }
|
fn new(state: State, tracing: bool) -> ExecutedBlock {
|
||||||
|
ExecutedBlock {
|
||||||
|
base: Default::default(),
|
||||||
|
receipts: Default::default(),
|
||||||
|
transactions_set: Default::default(),
|
||||||
|
state: state,
|
||||||
|
traces: if tracing {Some(Vec::new())} else {None},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a structure containing individual references to all public fields.
|
/// Get a structure containing individual references to all public fields.
|
||||||
pub fn fields(&mut self) -> BlockRefMut {
|
pub fn fields(&mut self) -> BlockRefMut {
|
||||||
@ -113,6 +121,7 @@ impl ExecutedBlock {
|
|||||||
uncles: &self.base.uncles,
|
uncles: &self.base.uncles,
|
||||||
state: &mut self.state,
|
state: &mut self.state,
|
||||||
receipts: &self.receipts,
|
receipts: &self.receipts,
|
||||||
|
traces: &self.traces,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,6 +143,9 @@ pub trait IsBlock {
|
|||||||
/// Get all information on receipts in this block.
|
/// Get all information on receipts in this block.
|
||||||
fn receipts(&self) -> &Vec<Receipt> { &self.block().receipts }
|
fn receipts(&self) -> &Vec<Receipt> { &self.block().receipts }
|
||||||
|
|
||||||
|
/// Get all information concerning transaction tracing in this block.
|
||||||
|
fn traces(&self) -> &Option<Vec<Trace>> { &self.block().traces }
|
||||||
|
|
||||||
/// Get all uncles in this block.
|
/// Get all uncles in this block.
|
||||||
fn uncles(&self) -> &Vec<Header> { &self.block().base.uncles }
|
fn uncles(&self) -> &Vec<Header> { &self.block().base.uncles }
|
||||||
}
|
}
|
||||||
@ -171,9 +183,9 @@ pub struct SealedBlock {
|
|||||||
|
|
||||||
impl<'x> OpenBlock<'x> {
|
impl<'x> OpenBlock<'x> {
|
||||||
/// Create a new OpenBlock ready for transaction pushing.
|
/// Create a new OpenBlock ready for transaction pushing.
|
||||||
pub fn new(engine: &'x Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self {
|
pub fn new(engine: &'x Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes, author: Address, gas_floor_target: U256, extra_data: Bytes) -> Self {
|
||||||
let mut r = OpenBlock {
|
let mut r = OpenBlock {
|
||||||
block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce())),
|
block: ExecutedBlock::new(State::from_existing(db, parent.state_root().clone(), engine.account_start_nonce()), tracing),
|
||||||
engine: engine,
|
engine: engine,
|
||||||
last_hashes: last_hashes,
|
last_hashes: last_hashes,
|
||||||
};
|
};
|
||||||
@ -249,11 +261,13 @@ impl<'x> OpenBlock<'x> {
|
|||||||
pub fn push_transaction(&mut self, t: SignedTransaction, h: Option<H256>) -> Result<&Receipt, Error> {
|
pub fn push_transaction(&mut self, t: SignedTransaction, h: Option<H256>) -> Result<&Receipt, Error> {
|
||||||
let env_info = self.env_info();
|
let env_info = self.env_info();
|
||||||
// info!("env_info says gas_used={}", env_info.gas_used);
|
// info!("env_info says gas_used={}", env_info.gas_used);
|
||||||
match self.block.state.apply(&env_info, self.engine, &t) {
|
match self.block.state.apply(&env_info, self.engine, &t, self.block.traces.is_some()) {
|
||||||
Ok(receipt) => {
|
Ok(outcome) => {
|
||||||
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
self.block.transactions_set.insert(h.unwrap_or_else(||t.hash()));
|
||||||
self.block.base.transactions.push(t);
|
self.block.base.transactions.push(t);
|
||||||
self.block.receipts.push(receipt);
|
let t = outcome.trace;
|
||||||
|
self.block.traces.as_mut().map(|traces| traces.push(t.expect("self.block.traces.is_some(): so we must be tracing: qed")));
|
||||||
|
self.block.receipts.push(outcome.receipt);
|
||||||
Ok(&self.block.receipts.last().unwrap())
|
Ok(&self.block.receipts.last().unwrap())
|
||||||
}
|
}
|
||||||
Err(x) => Err(From::from(x))
|
Err(x) => Err(From::from(x))
|
||||||
@ -339,7 +353,7 @@ impl IsBlock for SealedBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Enact the block given by block header, transactions and uncles
|
/// Enact the block given by block header, transactions and uncles
|
||||||
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Header], engine: &Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
||||||
{
|
{
|
||||||
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
if ::log::max_log_level() >= ::log::LogLevel::Trace {
|
||||||
let s = State::from_existing(db.spawn(), parent.state_root().clone(), engine.account_start_nonce());
|
let s = State::from_existing(db.spawn(), parent.state_root().clone(), engine.account_start_nonce());
|
||||||
@ -347,7 +361,7 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut b = OpenBlock::new(engine, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone());
|
let mut b = OpenBlock::new(engine, tracing, db, parent, last_hashes, header.author().clone(), x!(3141562), header.extra_data().clone());
|
||||||
b.set_difficulty(*header.difficulty());
|
b.set_difficulty(*header.difficulty());
|
||||||
b.set_gas_limit(*header.gas_limit());
|
b.set_gas_limit(*header.gas_limit());
|
||||||
b.set_timestamp(header.timestamp());
|
b.set_timestamp(header.timestamp());
|
||||||
@ -357,22 +371,22 @@ pub fn enact(header: &Header, transactions: &[SignedTransaction], uncles: &[Head
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||||
pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
pub fn enact_bytes(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
||||||
let block = BlockView::new(block_bytes);
|
let block = BlockView::new(block_bytes);
|
||||||
let header = block.header();
|
let header = block.header();
|
||||||
enact(&header, &block.transactions(), &block.uncles(), engine, db, parent, last_hashes)
|
enact(&header, &block.transactions(), &block.uncles(), engine, tracing, db, parent, last_hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||||
pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
pub fn enact_verified(block: &PreverifiedBlock, engine: &Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<ClosedBlock, Error> {
|
||||||
let view = BlockView::new(&block.bytes);
|
let view = BlockView::new(&block.bytes);
|
||||||
enact(&block.header, &block.transactions, &view.uncles(), engine, db, parent, last_hashes)
|
enact(&block.header, &block.transactions, &view.uncles(), engine, tracing, db, parent, last_hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<SealedBlock, Error> {
|
pub fn enact_and_seal(block_bytes: &[u8], engine: &Engine, tracing: bool, db: Box<JournalDB>, parent: &Header, last_hashes: LastHashes) -> Result<SealedBlock, Error> {
|
||||||
let header = BlockView::new(block_bytes).header_view();
|
let header = BlockView::new(block_bytes).header_view();
|
||||||
Ok(try!(try!(enact_bytes(block_bytes, engine, db, parent, last_hashes)).seal(engine, header.seal())))
|
Ok(try!(try!(enact_bytes(block_bytes, engine, tracing, db, parent, last_hashes)).seal(engine, header.seal())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -391,7 +405,7 @@ mod tests {
|
|||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||||
let b = b.close();
|
let b = b.close();
|
||||||
let _ = b.seal(engine.deref(), vec![]);
|
let _ = b.seal(engine.deref(), vec![]);
|
||||||
}
|
}
|
||||||
@ -405,14 +419,14 @@ mod tests {
|
|||||||
let mut db_result = get_temp_journal_db();
|
let mut db_result = get_temp_journal_db();
|
||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close().seal(engine.deref(), vec![]).unwrap();
|
let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]).close().seal(engine.deref(), vec![]).unwrap();
|
||||||
let orig_bytes = b.rlp_bytes();
|
let orig_bytes = b.rlp_bytes();
|
||||||
let orig_db = b.drain();
|
let orig_db = b.drain();
|
||||||
|
|
||||||
let mut db_result = get_temp_journal_db();
|
let mut db_result = get_temp_journal_db();
|
||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let e = enact_and_seal(&orig_bytes, engine.deref(), db, &genesis_header, vec![genesis_header.hash()]).unwrap();
|
let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()]).unwrap();
|
||||||
|
|
||||||
assert_eq!(e.rlp_bytes(), orig_bytes);
|
assert_eq!(e.rlp_bytes(), orig_bytes);
|
||||||
|
|
||||||
@ -430,7 +444,7 @@ mod tests {
|
|||||||
let mut db_result = get_temp_journal_db();
|
let mut db_result = get_temp_journal_db();
|
||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let mut open_block = OpenBlock::new(engine.deref(), db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]);
|
let mut open_block = OpenBlock::new(engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()], Address::zero(), x!(3141562), vec![]);
|
||||||
let mut uncle1_header = Header::new();
|
let mut uncle1_header = Header::new();
|
||||||
uncle1_header.extra_data = b"uncle1".to_vec();
|
uncle1_header.extra_data = b"uncle1".to_vec();
|
||||||
let mut uncle2_header = Header::new();
|
let mut uncle2_header = Header::new();
|
||||||
@ -438,14 +452,14 @@ mod tests {
|
|||||||
open_block.push_uncle(uncle1_header).unwrap();
|
open_block.push_uncle(uncle1_header).unwrap();
|
||||||
open_block.push_uncle(uncle2_header).unwrap();
|
open_block.push_uncle(uncle2_header).unwrap();
|
||||||
let b = open_block.close().seal(engine.deref(), vec![]).unwrap();
|
let b = open_block.close().seal(engine.deref(), vec![]).unwrap();
|
||||||
|
|
||||||
let orig_bytes = b.rlp_bytes();
|
let orig_bytes = b.rlp_bytes();
|
||||||
let orig_db = b.drain();
|
let orig_db = b.drain();
|
||||||
|
|
||||||
let mut db_result = get_temp_journal_db();
|
let mut db_result = get_temp_journal_db();
|
||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let e = enact_and_seal(&orig_bytes, engine.deref(), db, &genesis_header, vec![genesis_header.hash()]).unwrap();
|
let e = enact_and_seal(&orig_bytes, engine.deref(), false, db, &genesis_header, vec![genesis_header.hash()]).unwrap();
|
||||||
|
|
||||||
let bytes = e.rlp_bytes();
|
let bytes = e.rlp_bytes();
|
||||||
assert_eq!(bytes, orig_bytes);
|
assert_eq!(bytes, orig_bytes);
|
||||||
|
@ -54,6 +54,9 @@ impl Default for BlockChainConfig {
|
|||||||
|
|
||||||
/// Interface for querying blocks by hash and by number.
|
/// Interface for querying blocks by hash and by number.
|
||||||
pub trait BlockProvider {
|
pub trait BlockProvider {
|
||||||
|
/// True if we store full tracing information for transactions.
|
||||||
|
fn have_tracing(&self) -> bool;
|
||||||
|
|
||||||
/// Returns true if the given block is known
|
/// Returns true if the given block is known
|
||||||
/// (though not necessarily a part of the canon chain).
|
/// (though not necessarily a part of the canon chain).
|
||||||
fn is_known(&self, hash: &H256) -> bool;
|
fn is_known(&self, hash: &H256) -> bool;
|
||||||
@ -177,6 +180,9 @@ impl BlockProvider for BlockChain {
|
|||||||
self.query_extras_exist(hash, &self.block_details)
|
self.query_extras_exist(hash, &self.block_details)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We do not store tracing information.
|
||||||
|
fn have_tracing(&self) -> bool { false }
|
||||||
|
|
||||||
/// Get raw block data
|
/// Get raw block data
|
||||||
fn block(&self, hash: &H256) -> Option<Bytes> {
|
fn block(&self, hash: &H256) -> Option<Bytes> {
|
||||||
{
|
{
|
||||||
|
@ -211,7 +211,7 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
let last_hashes = self.build_last_hashes(header.parent_hash.clone());
|
let last_hashes = self.build_last_hashes(header.parent_hash.clone());
|
||||||
let db = self.state_db.lock().unwrap().spawn();
|
let db = self.state_db.lock().unwrap().spawn();
|
||||||
|
|
||||||
let enact_result = enact_verified(&block, engine, db, &parent, last_hashes);
|
let enact_result = enact_verified(&block, engine, self.chain.have_tracing(), db, &parent, last_hashes);
|
||||||
if let Err(e) = enact_result {
|
if let Err(e) = enact_result {
|
||||||
warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
warn!(target: "client", "Block import failed for #{} ({})\nError: {:?}", header.number(), header.hash(), e);
|
||||||
return Err(());
|
return Err(());
|
||||||
@ -398,6 +398,7 @@ impl<V> BlockChainClient for Client<V> where V: Verifier {
|
|||||||
|
|
||||||
let mut b = OpenBlock::new(
|
let mut b = OpenBlock::new(
|
||||||
engine,
|
engine,
|
||||||
|
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
|
||||||
self.state_db.lock().unwrap().spawn(),
|
self.state_db.lock().unwrap().spawn(),
|
||||||
match self.chain.block_header(&h) { Some(ref x) => x, None => {return None} },
|
match self.chain.block_header(&h) { Some(ref x) => x, None => {return None} },
|
||||||
self.build_last_hashes(h.clone()),
|
self.build_last_hashes(h.clone()),
|
||||||
|
@ -25,4 +25,5 @@ pub use account::*;
|
|||||||
pub use transaction::*;
|
pub use transaction::*;
|
||||||
pub use log_entry::*;
|
pub use log_entry::*;
|
||||||
pub use receipt::*;
|
pub use receipt::*;
|
||||||
pub use action_params::*;
|
pub use action_params::*;
|
||||||
|
pub use trace::*;
|
@ -299,7 +299,7 @@ mod tests {
|
|||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
let b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||||
let b = b.close();
|
let b = b.close();
|
||||||
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
|
assert_eq!(b.state().balance(&Address::zero()), U256::from_str("4563918244f40000").unwrap());
|
||||||
}
|
}
|
||||||
@ -312,7 +312,7 @@ mod tests {
|
|||||||
let mut db = db_result.take();
|
let mut db = db_result.take();
|
||||||
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
engine.spec().ensure_db_good(db.as_hashdb_mut());
|
||||||
let last_hashes = vec![genesis_header.hash()];
|
let last_hashes = vec![genesis_header.hash()];
|
||||||
let mut b = OpenBlock::new(engine.deref(), db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
let mut b = OpenBlock::new(engine.deref(), false, db, &genesis_header, last_hashes, Address::zero(), x!(3141562), vec![]);
|
||||||
let mut uncle = Header::new();
|
let mut uncle = Header::new();
|
||||||
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
let uncle_author = address_from_hex("ef2d6d194084c2de36e0dabfce45d046b37d1106");
|
||||||
uncle.author = uncle_author.clone();
|
uncle.author = uncle_author.clone();
|
||||||
|
@ -65,7 +65,7 @@ pub enum Error {
|
|||||||
|
|
||||||
/// Evm result.
|
/// Evm result.
|
||||||
///
|
///
|
||||||
/// Returns gas_left if execution is successfull, otherwise error.
|
/// Returns gas_left if execution is successful, otherwise error.
|
||||||
pub type Result = result::Result<U256, Error>;
|
pub type Result = result::Result<U256, Error>;
|
||||||
|
|
||||||
/// Evm interface.
|
/// Evm interface.
|
||||||
|
@ -41,26 +41,35 @@ pub fn contract_address(address: &Address, nonce: &U256) -> Address {
|
|||||||
pub struct Executed {
|
pub struct Executed {
|
||||||
/// Gas paid up front for execution of transaction.
|
/// Gas paid up front for execution of transaction.
|
||||||
pub gas: U256,
|
pub gas: U256,
|
||||||
|
|
||||||
/// Gas used during execution of transaction.
|
/// Gas used during execution of transaction.
|
||||||
pub gas_used: U256,
|
pub gas_used: U256,
|
||||||
|
|
||||||
/// Gas refunded after the execution of transaction.
|
/// Gas refunded after the execution of transaction.
|
||||||
/// To get gas that was required up front, add `refunded` and `gas_used`.
|
/// To get gas that was required up front, add `refunded` and `gas_used`.
|
||||||
pub refunded: U256,
|
pub refunded: U256,
|
||||||
|
|
||||||
/// Cumulative gas used in current block so far.
|
/// Cumulative gas used in current block so far.
|
||||||
///
|
///
|
||||||
/// `cumulative_gas_used = gas_used(t0) + gas_used(t1) + ... gas_used(tn)`
|
/// `cumulative_gas_used = gas_used(t0) + gas_used(t1) + ... gas_used(tn)`
|
||||||
///
|
///
|
||||||
/// where `tn` is current transaction.
|
/// where `tn` is current transaction.
|
||||||
pub cumulative_gas_used: U256,
|
pub cumulative_gas_used: U256,
|
||||||
|
|
||||||
/// Vector of logs generated by transaction.
|
/// Vector of logs generated by transaction.
|
||||||
pub logs: Vec<LogEntry>,
|
pub logs: Vec<LogEntry>,
|
||||||
|
|
||||||
/// Addresses of contracts created during execution of transaction.
|
/// Addresses of contracts created during execution of transaction.
|
||||||
/// Ordered from earliest creation.
|
/// Ordered from earliest creation.
|
||||||
///
|
///
|
||||||
/// eg. sender creates contract A and A in constructor creates contract B
|
/// eg. sender creates contract A and A in constructor creates contract B
|
||||||
///
|
///
|
||||||
/// B creation ends first, and it will be the first element of the vector.
|
/// B creation ends first, and it will be the first element of the vector.
|
||||||
pub contracts_created: Vec<Address>
|
pub contracts_created: Vec<Address>,
|
||||||
|
/// Transaction output.
|
||||||
|
pub output: Bytes,
|
||||||
|
/// The trace of this transaction.
|
||||||
|
pub trace: Option<Trace>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction execution result.
|
/// Transaction execution result.
|
||||||
@ -71,38 +80,37 @@ pub struct Executive<'a> {
|
|||||||
state: &'a mut State,
|
state: &'a mut State,
|
||||||
info: &'a EnvInfo,
|
info: &'a EnvInfo,
|
||||||
engine: &'a Engine,
|
engine: &'a Engine,
|
||||||
depth: usize
|
depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Executive<'a> {
|
impl<'a> Executive<'a> {
|
||||||
/// Basic constructor.
|
/// Basic constructor.
|
||||||
pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self {
|
pub fn new(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine) -> Self {
|
||||||
Executive::new_with_depth(state, info, engine, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Populates executive from parent properties. Increments executive depth.
|
|
||||||
pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self {
|
|
||||||
Executive::new_with_depth(state, info, engine, depth + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper constructor. Should be used to create `Executive` with desired depth.
|
|
||||||
/// Private.
|
|
||||||
fn new_with_depth(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, depth: usize) -> Self {
|
|
||||||
Executive {
|
Executive {
|
||||||
state: state,
|
state: state,
|
||||||
info: info,
|
info: info,
|
||||||
engine: engine,
|
engine: engine,
|
||||||
depth: depth
|
depth: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Populates executive from parent properties. Increments executive depth.
|
||||||
|
pub fn from_parent(state: &'a mut State, info: &'a EnvInfo, engine: &'a Engine, parent_depth: usize) -> Self {
|
||||||
|
Executive {
|
||||||
|
state: state,
|
||||||
|
info: info,
|
||||||
|
engine: engine,
|
||||||
|
depth: parent_depth + 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates `Externalities` from `Executive`.
|
/// Creates `Externalities` from `Executive`.
|
||||||
pub fn as_externalities<'_>(&'_ mut self, origin_info: OriginInfo, substate: &'_ mut Substate, output: OutputPolicy<'_>) -> Externalities {
|
pub fn as_externalities<'_>(&'_ mut self, origin_info: OriginInfo, substate: &'_ mut Substate, output: OutputPolicy<'_, '_>) -> Externalities {
|
||||||
Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output)
|
Externalities::new(self.state, self.info, self.engine, self.depth, origin_info, substate, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This funtion should be used to execute transaction.
|
/// This funtion should be used to execute transaction.
|
||||||
pub fn transact(&'a mut self, t: &SignedTransaction) -> Result<Executed, Error> {
|
pub fn transact(&'a mut self, t: &SignedTransaction, tracing: bool) -> Result<Executed, Error> {
|
||||||
let sender = try!(t.sender());
|
let sender = try!(t.sender());
|
||||||
let nonce = self.state.nonce(&sender);
|
let nonce = self.state.nonce(&sender);
|
||||||
|
|
||||||
@ -143,9 +151,9 @@ impl<'a> Executive<'a> {
|
|||||||
self.state.inc_nonce(&sender);
|
self.state.inc_nonce(&sender);
|
||||||
self.state.sub_balance(&sender, &U256::from(gas_cost));
|
self.state.sub_balance(&sender, &U256::from(gas_cost));
|
||||||
|
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(tracing);
|
||||||
|
|
||||||
let res = match t.action {
|
let (gas_left, output) = match t.action {
|
||||||
Action::Create => {
|
Action::Create => {
|
||||||
let new_address = contract_address(&sender, &nonce);
|
let new_address = contract_address(&sender, &nonce);
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
@ -159,7 +167,7 @@ impl<'a> Executive<'a> {
|
|||||||
code: Some(t.data.clone()),
|
code: Some(t.data.clone()),
|
||||||
data: None,
|
data: None,
|
||||||
};
|
};
|
||||||
self.create(params, &mut substate)
|
(self.create(params, &mut substate), vec![])
|
||||||
},
|
},
|
||||||
Action::Call(ref address) => {
|
Action::Call(ref address) => {
|
||||||
let params = ActionParams {
|
let params = ActionParams {
|
||||||
@ -175,12 +183,12 @@ impl<'a> Executive<'a> {
|
|||||||
};
|
};
|
||||||
// TODO: move output upstream
|
// TODO: move output upstream
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
self.call(params, &mut substate, BytesRef::Flexible(&mut out))
|
(self.call(params, &mut substate, BytesRef::Flexible(&mut out)), out)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// finalize here!
|
// finalize here!
|
||||||
Ok(try!(self.finalize(t, substate, res)))
|
Ok(try!(self.finalize(t, substate, gas_left, output)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exec_vm(&mut self, params: ActionParams, unconfirmed_substate: &mut Substate, output_policy: OutputPolicy) -> evm::Result {
|
fn exec_vm(&mut self, params: ActionParams, unconfirmed_substate: &mut Substate, output_policy: OutputPolicy) -> evm::Result {
|
||||||
@ -241,15 +249,27 @@ impl<'a> Executive<'a> {
|
|||||||
// if destination is a contract, do normal message call
|
// if destination is a contract, do normal message call
|
||||||
|
|
||||||
// part of substate that may be reverted
|
// part of substate that may be reverted
|
||||||
let mut unconfirmed_substate = Substate::new();
|
let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some());
|
||||||
|
|
||||||
|
// transaction tracing stuff. None if there's no tracing.
|
||||||
|
let mut trace_info = substate.subtraces.as_ref().map(|_| (TraceAction::from_call(¶ms), self.depth));
|
||||||
|
let mut trace_output = trace_info.as_ref().map(|_| vec![]);
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output))
|
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::Return(output, trace_output.as_mut()))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// if there's tracing, make up trace_info's result with trace_output and some arithmetic.
|
||||||
|
if let Some((TraceAction::Call(ref mut c), _)) = trace_info {
|
||||||
|
if let Some(output) = trace_output {
|
||||||
|
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
trace!("exec: sstore-clears={}\n", unconfirmed_substate.sstore_clears_count);
|
trace!("exec: sstore-clears={}\n", unconfirmed_substate.sstore_clears_count);
|
||||||
trace!("exec: substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate);
|
trace!("exec: substate={:?}; unconfirmed_substate={:?}\n", substate, unconfirmed_substate);
|
||||||
self.enact_result(&res, substate, unconfirmed_substate);
|
|
||||||
|
self.enact_result(&res, substate, unconfirmed_substate, trace_info);
|
||||||
trace!("exec: new substate={:?}\n", substate);
|
trace!("exec: new substate={:?}\n", substate);
|
||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
@ -267,7 +287,7 @@ impl<'a> Executive<'a> {
|
|||||||
self.state.snapshot();
|
self.state.snapshot();
|
||||||
|
|
||||||
// part of substate that may be reverted
|
// part of substate that may be reverted
|
||||||
let mut unconfirmed_substate = Substate::new();
|
let mut unconfirmed_substate = Substate::new(substate.subtraces.is_some());
|
||||||
|
|
||||||
// create contract and transfer value to it if necessary
|
// create contract and transfer value to it if necessary
|
||||||
let prev_bal = self.state.balance(¶ms.address);
|
let prev_bal = self.state.balance(¶ms.address);
|
||||||
@ -278,15 +298,26 @@ impl<'a> Executive<'a> {
|
|||||||
self.state.new_contract(¶ms.address, prev_bal);
|
self.state.new_contract(¶ms.address, prev_bal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut trace_info = substate.subtraces.as_ref().map(|_| (TraceAction::from_create(¶ms), self.depth));
|
||||||
|
let mut trace_output = trace_info.as_ref().map(|_| vec![]);
|
||||||
|
let created = params.address.clone();
|
||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract)
|
self.exec_vm(params, &mut unconfirmed_substate, OutputPolicy::InitContract(trace_output.as_mut()))
|
||||||
};
|
};
|
||||||
self.enact_result(&res, substate, unconfirmed_substate);
|
|
||||||
|
if let Some((TraceAction::Create(ref mut c), _)) = trace_info {
|
||||||
|
if let Some(output) = trace_output {
|
||||||
|
c.result = res.as_ref().ok().map(|gas_left| (c.gas - *gas_left, created, output));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.enact_result(&res, substate, unconfirmed_substate, trace_info);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finalizes the transaction (does refunds and suicides).
|
/// Finalizes the transaction (does refunds and suicides).
|
||||||
fn finalize(&mut self, t: &SignedTransaction, substate: Substate, result: evm::Result) -> ExecutionResult {
|
fn finalize(&mut self, t: &SignedTransaction, substate: Substate, result: evm::Result, output: Bytes) -> ExecutionResult {
|
||||||
let schedule = self.engine.schedule(self.info);
|
let schedule = self.engine.schedule(self.info);
|
||||||
|
|
||||||
// refunds from SSTORE nonzero -> zero
|
// refunds from SSTORE nonzero -> zero
|
||||||
@ -326,7 +357,9 @@ impl<'a> Executive<'a> {
|
|||||||
refunded: U256::zero(),
|
refunded: U256::zero(),
|
||||||
cumulative_gas_used: self.info.gas_used + t.gas,
|
cumulative_gas_used: self.info.gas_used + t.gas,
|
||||||
logs: vec![],
|
logs: vec![],
|
||||||
contracts_created: vec![]
|
contracts_created: vec![],
|
||||||
|
output: output,
|
||||||
|
trace: None,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
@ -337,12 +370,14 @@ impl<'a> Executive<'a> {
|
|||||||
cumulative_gas_used: self.info.gas_used + gas_used,
|
cumulative_gas_used: self.info.gas_used + gas_used,
|
||||||
logs: substate.logs,
|
logs: substate.logs,
|
||||||
contracts_created: substate.contracts_created,
|
contracts_created: substate.contracts_created,
|
||||||
|
output: output,
|
||||||
|
trace: substate.subtraces.and_then(|mut v| v.pop()),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enact_result(&mut self, result: &evm::Result, substate: &mut Substate, un_substate: Substate) {
|
fn enact_result(&mut self, result: &evm::Result, substate: &mut Substate, un_substate: Substate, maybe_info: Option<(TraceAction, usize)>) {
|
||||||
match *result {
|
match *result {
|
||||||
Err(evm::Error::OutOfGas)
|
Err(evm::Error::OutOfGas)
|
||||||
| Err(evm::Error::BadJumpDestination {..})
|
| Err(evm::Error::BadJumpDestination {..})
|
||||||
@ -353,7 +388,7 @@ impl<'a> Executive<'a> {
|
|||||||
},
|
},
|
||||||
Ok(_) | Err(evm::Error::Internal) => {
|
Ok(_) | Err(evm::Error::Internal) => {
|
||||||
self.state.clear_snapshot();
|
self.state.clear_snapshot();
|
||||||
substate.accrue(un_substate)
|
substate.accrue(un_substate, maybe_info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,7 +426,7 @@ mod tests {
|
|||||||
state.add_balance(&sender, &U256::from(0x100u64));
|
state.add_balance(&sender, &U256::from(0x100u64));
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0, factory);
|
let engine = TestEngine::new(0, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
@ -408,8 +443,8 @@ mod tests {
|
|||||||
// TODO: just test state root.
|
// TODO: just test state root.
|
||||||
}
|
}
|
||||||
|
|
||||||
evm_test!{test_create_contract: test_create_contract_jit, test_create_contract_int}
|
evm_test!{test_create_contract_out_of_depth: test_create_contract_out_of_depth_jit, test_create_contract_out_of_depth_int}
|
||||||
fn test_create_contract(factory: Factory) {
|
fn test_create_contract_out_of_depth(factory: Factory) {
|
||||||
// code:
|
// code:
|
||||||
//
|
//
|
||||||
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||||
@ -450,7 +485,7 @@ mod tests {
|
|||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100));
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0, factory);
|
let engine = TestEngine::new(0, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
@ -462,6 +497,135 @@ mod tests {
|
|||||||
assert_eq!(substate.contracts_created.len(), 0);
|
assert_eq!(substate.contracts_created.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evm_test!{test_call_to_create: test_call_to_create_jit, test_call_to_create_int}
|
||||||
|
fn test_call_to_create(factory: Factory) {
|
||||||
|
// code:
|
||||||
|
//
|
||||||
|
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 52
|
||||||
|
// 60 1d - push 29
|
||||||
|
// 60 03 - push 3
|
||||||
|
// 60 17 - push 17
|
||||||
|
// f0 - create
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 55 sstore
|
||||||
|
//
|
||||||
|
// other code:
|
||||||
|
//
|
||||||
|
// 60 10 - push 16
|
||||||
|
// 80 - duplicate first stack item
|
||||||
|
// 60 0c - push 12
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 39 - copy current code to memory
|
||||||
|
// 60 00 - push 0
|
||||||
|
// f3 - return
|
||||||
|
|
||||||
|
let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
|
||||||
|
|
||||||
|
let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
|
||||||
|
let address = contract_address(&sender, &U256::zero());
|
||||||
|
// TODO: add tests for 'callcreate'
|
||||||
|
//let next_address = contract_address(&address, &U256::zero());
|
||||||
|
let mut params = ActionParams::default();
|
||||||
|
params.address = address.clone();
|
||||||
|
params.sender = sender.clone();
|
||||||
|
params.origin = sender.clone();
|
||||||
|
params.gas = U256::from(100_000);
|
||||||
|
params.code = Some(code.clone());
|
||||||
|
params.value = ActionValue::Transfer(U256::from(100));
|
||||||
|
let mut state_result = get_temp_state();
|
||||||
|
let mut state = state_result.reference_mut();
|
||||||
|
state.add_balance(&sender, &U256::from(100));
|
||||||
|
let info = EnvInfo::default();
|
||||||
|
let engine = TestEngine::new(5, factory);
|
||||||
|
let mut substate = Substate::new(true);
|
||||||
|
|
||||||
|
let gas_left = {
|
||||||
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
|
let output = BytesRef::Fixed(&mut[0u8;0]);
|
||||||
|
ex.call(params, &mut substate, output).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("trace: {:?}", substate.subtraces);
|
||||||
|
let expected_trace = Some(vec![ Trace {
|
||||||
|
depth: 0,
|
||||||
|
action: TraceAction::Call(TraceCall {
|
||||||
|
from: x!("cd1722f3947def4cf144679da39c4c32bdc35681"),
|
||||||
|
to: x!("b010143a42d5980c7e5ef0e4a4416dc098a4fed3"),
|
||||||
|
value: x!(100),
|
||||||
|
gas: x!(100000),
|
||||||
|
input: vec![],
|
||||||
|
result: Some((x!(55248), vec![]))
|
||||||
|
}),
|
||||||
|
subs: vec![Trace {
|
||||||
|
depth: 1,
|
||||||
|
action: TraceAction::Create(TraceCreate {
|
||||||
|
from: x!("b010143a42d5980c7e5ef0e4a4416dc098a4fed3"),
|
||||||
|
value: x!(23),
|
||||||
|
gas: x!(67979),
|
||||||
|
init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85],
|
||||||
|
result: Some((x!(3224), x!("c6d80f262ae5e0f164e5fde365044d7ada2bfa34"), vec![96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53])),
|
||||||
|
}),
|
||||||
|
subs: vec![]
|
||||||
|
}]
|
||||||
|
} ]);
|
||||||
|
assert_eq!(substate.subtraces, expected_trace);
|
||||||
|
assert_eq!(gas_left, U256::from(44_752));
|
||||||
|
}
|
||||||
|
|
||||||
|
evm_test!{test_create_contract: test_create_contract_jit, test_create_contract_int}
|
||||||
|
fn test_create_contract(factory: Factory) {
|
||||||
|
// code:
|
||||||
|
//
|
||||||
|
// 60 10 - push 16
|
||||||
|
// 80 - duplicate first stack item
|
||||||
|
// 60 0c - push 12
|
||||||
|
// 60 00 - push 0
|
||||||
|
// 39 - copy current code to memory
|
||||||
|
// 60 00 - push 0
|
||||||
|
// f3 - return
|
||||||
|
|
||||||
|
let code = "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap();
|
||||||
|
|
||||||
|
let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
|
||||||
|
let address = contract_address(&sender, &U256::zero());
|
||||||
|
// TODO: add tests for 'callcreate'
|
||||||
|
//let next_address = contract_address(&address, &U256::zero());
|
||||||
|
let mut params = ActionParams::default();
|
||||||
|
params.address = address.clone();
|
||||||
|
params.sender = sender.clone();
|
||||||
|
params.origin = sender.clone();
|
||||||
|
params.gas = U256::from(100_000);
|
||||||
|
params.code = Some(code.clone());
|
||||||
|
params.value = ActionValue::Transfer(x!(100));
|
||||||
|
let mut state_result = get_temp_state();
|
||||||
|
let mut state = state_result.reference_mut();
|
||||||
|
state.add_balance(&sender, &U256::from(100));
|
||||||
|
let info = EnvInfo::default();
|
||||||
|
let engine = TestEngine::new(5, factory);
|
||||||
|
let mut substate = Substate::new(true);
|
||||||
|
|
||||||
|
let gas_left = {
|
||||||
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
|
ex.create(params.clone(), &mut substate).unwrap()
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("trace: {:?}", substate.subtraces);
|
||||||
|
let expected_trace = Some(vec![Trace {
|
||||||
|
depth: 0,
|
||||||
|
action: TraceAction::Create(TraceCreate {
|
||||||
|
from: params.sender,
|
||||||
|
value: x!(100),
|
||||||
|
gas: params.gas,
|
||||||
|
init: vec![96, 16, 128, 96, 12, 96, 0, 57, 96, 0, 243, 0, 96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53, 85],
|
||||||
|
result: Some((x!(3224), params.address, vec![96, 0, 53, 84, 21, 96, 9, 87, 0, 91, 96, 32, 53, 96, 0, 53])),
|
||||||
|
}),
|
||||||
|
subs: vec![]
|
||||||
|
} ]);
|
||||||
|
assert_eq!(substate.subtraces, expected_trace);
|
||||||
|
assert_eq!(gas_left, U256::from(96_776));
|
||||||
|
}
|
||||||
evm_test!{test_create_contract_value_too_high: test_create_contract_value_too_high_jit, test_create_contract_value_too_high_int}
|
evm_test!{test_create_contract_value_too_high: test_create_contract_value_too_high_jit, test_create_contract_value_too_high_int}
|
||||||
fn test_create_contract_value_too_high(factory: Factory) {
|
fn test_create_contract_value_too_high(factory: Factory) {
|
||||||
// code:
|
// code:
|
||||||
@ -504,7 +668,7 @@ mod tests {
|
|||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100));
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0, factory);
|
let engine = TestEngine::new(0, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
@ -556,7 +720,7 @@ mod tests {
|
|||||||
state.add_balance(&sender, &U256::from(100));
|
state.add_balance(&sender, &U256::from(100));
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(1024, factory);
|
let engine = TestEngine::new(1024, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
@ -617,7 +781,7 @@ mod tests {
|
|||||||
|
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0, factory);
|
let engine = TestEngine::new(0, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
@ -662,7 +826,7 @@ mod tests {
|
|||||||
state.init_code(&address, code.clone());
|
state.init_code(&address, code.clone());
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0, factory);
|
let engine = TestEngine::new(0, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
let gas_left = {
|
let gas_left = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
@ -699,7 +863,7 @@ mod tests {
|
|||||||
|
|
||||||
let executed = {
|
let executed = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t).unwrap()
|
ex.transact(&t, false).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(executed.gas, U256::from(100_000));
|
assert_eq!(executed.gas, U256::from(100_000));
|
||||||
@ -732,7 +896,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t)
|
ex.transact(&t, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -763,7 +927,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t)
|
ex.transact(&t, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -796,7 +960,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t)
|
ex.transact(&t, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -829,7 +993,7 @@ mod tests {
|
|||||||
|
|
||||||
let res = {
|
let res = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
ex.transact(&t)
|
ex.transact(&t, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
@ -859,7 +1023,7 @@ mod tests {
|
|||||||
state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap());
|
state.add_balance(&sender, &U256::from_str("152d02c7e14af6800000").unwrap());
|
||||||
let info = EnvInfo::default();
|
let info = EnvInfo::default();
|
||||||
let engine = TestEngine::new(0, factory);
|
let engine = TestEngine::new(0, factory);
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
|
|
||||||
let result = {
|
let result = {
|
||||||
let mut ex = Executive::new(&mut state, &info, &engine);
|
let mut ex = Executive::new(&mut state, &info, &engine);
|
||||||
|
@ -23,12 +23,12 @@ use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult};
|
|||||||
use substate::*;
|
use substate::*;
|
||||||
|
|
||||||
/// Policy for handling output data on `RETURN` opcode.
|
/// Policy for handling output data on `RETURN` opcode.
|
||||||
pub enum OutputPolicy<'a> {
|
pub enum OutputPolicy<'a, 'b> {
|
||||||
/// Return reference to fixed sized output.
|
/// Return reference to fixed sized output.
|
||||||
/// Used for message calls.
|
/// Used for message calls.
|
||||||
Return(BytesRef<'a>),
|
Return(BytesRef<'a>, Option<&'b mut Bytes>),
|
||||||
/// Init new contract as soon as `RETURN` is called.
|
/// Init new contract as soon as `RETURN` is called.
|
||||||
InitContract
|
InitContract(Option<&'b mut Bytes>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transaction properties that externalities need to know about.
|
/// Transaction properties that externalities need to know about.
|
||||||
@ -62,18 +62,19 @@ pub struct Externalities<'a> {
|
|||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
schedule: Schedule,
|
schedule: Schedule,
|
||||||
output: OutputPolicy<'a>
|
output: OutputPolicy<'a, 'a>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Externalities<'a> {
|
impl<'a> Externalities<'a> {
|
||||||
/// Basic `Externalities` constructor.
|
/// Basic `Externalities` constructor.
|
||||||
pub fn new(state: &'a mut State,
|
pub fn new(state: &'a mut State,
|
||||||
env_info: &'a EnvInfo,
|
env_info: &'a EnvInfo,
|
||||||
engine: &'a Engine,
|
engine: &'a Engine,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
output: OutputPolicy<'a>) -> Self {
|
output: OutputPolicy<'a, 'a>
|
||||||
|
) -> Self {
|
||||||
Externalities {
|
Externalities {
|
||||||
state: state,
|
state: state,
|
||||||
env_info: env_info,
|
env_info: env_info,
|
||||||
@ -190,20 +191,31 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
|
|
||||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||||
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, evm::Error> {
|
fn ret(&mut self, gas: &U256, data: &[u8]) -> Result<U256, evm::Error> {
|
||||||
match &mut self.output {
|
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
||||||
&mut OutputPolicy::Return(BytesRef::Fixed(ref mut slice)) => unsafe {
|
to.as_mut().map(|b| **b = data.to_owned());
|
||||||
|
};
|
||||||
|
match self.output {
|
||||||
|
OutputPolicy::Return(BytesRef::Fixed(ref mut slice), ref mut copy) => {
|
||||||
|
handle_copy(copy);
|
||||||
|
|
||||||
let len = cmp::min(slice.len(), data.len());
|
let len = cmp::min(slice.len(), data.len());
|
||||||
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
unsafe {
|
||||||
|
ptr::copy(data.as_ptr(), slice.as_mut_ptr(), len);
|
||||||
|
}
|
||||||
Ok(*gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
&mut OutputPolicy::Return(BytesRef::Flexible(ref mut vec)) => unsafe {
|
OutputPolicy::Return(BytesRef::Flexible(ref mut vec), ref mut copy) => {
|
||||||
|
handle_copy(copy);
|
||||||
|
|
||||||
vec.clear();
|
vec.clear();
|
||||||
vec.reserve(data.len());
|
vec.reserve(data.len());
|
||||||
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
unsafe {
|
||||||
vec.set_len(data.len());
|
ptr::copy(data.as_ptr(), vec.as_mut_ptr(), data.len());
|
||||||
|
vec.set_len(data.len());
|
||||||
|
}
|
||||||
Ok(*gas)
|
Ok(*gas)
|
||||||
},
|
},
|
||||||
&mut OutputPolicy::InitContract => {
|
OutputPolicy::InitContract(ref mut copy) => {
|
||||||
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas);
|
||||||
if return_cost > *gas {
|
if return_cost > *gas {
|
||||||
return match self.schedule.exceptional_failed_code_deposit {
|
return match self.schedule.exceptional_failed_code_deposit {
|
||||||
@ -211,14 +223,16 @@ impl<'a> Ext for Externalities<'a> {
|
|||||||
false => Ok(*gas)
|
false => Ok(*gas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle_copy(copy);
|
||||||
|
|
||||||
let mut code = vec![];
|
let mut code = vec![];
|
||||||
code.reserve(data.len());
|
code.reserve(data.len());
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::copy(data.as_ptr(), code.as_mut_ptr(), data.len());
|
ptr::copy(data.as_ptr(), code.as_mut_ptr(), data.len());
|
||||||
code.set_len(data.len());
|
code.set_len(data.len());
|
||||||
}
|
}
|
||||||
let address = &self.origin_info.address;
|
self.state.init_code(&self.origin_info.address, code);
|
||||||
self.state.init_code(address, code);
|
|
||||||
Ok(*gas - return_cost)
|
Ok(*gas - return_cost)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,7 +326,7 @@ mod tests {
|
|||||||
TestSetup {
|
TestSetup {
|
||||||
state: get_temp_state(),
|
state: get_temp_state(),
|
||||||
engine: get_test_spec().to_engine().unwrap(),
|
engine: get_test_spec().to_engine().unwrap(),
|
||||||
sub_state: Substate::new(),
|
sub_state: Substate::new(false),
|
||||||
env_info: get_test_env_info()
|
env_info: get_test_env_info()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -323,7 +337,7 @@ mod tests {
|
|||||||
let mut setup = TestSetup::new();
|
let mut setup = TestSetup::new();
|
||||||
let state = setup.state.reference_mut();
|
let state = setup.state.reference_mut();
|
||||||
|
|
||||||
let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract);
|
let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None));
|
||||||
|
|
||||||
assert_eq!(ext.env_info().number, 100);
|
assert_eq!(ext.env_info().number, 100);
|
||||||
}
|
}
|
||||||
@ -332,7 +346,7 @@ mod tests {
|
|||||||
fn can_return_block_hash_no_env() {
|
fn can_return_block_hash_no_env() {
|
||||||
let mut setup = TestSetup::new();
|
let mut setup = TestSetup::new();
|
||||||
let state = setup.state.reference_mut();
|
let state = setup.state.reference_mut();
|
||||||
let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract);
|
let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None));
|
||||||
|
|
||||||
let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap());
|
let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap());
|
||||||
|
|
||||||
@ -351,7 +365,7 @@ mod tests {
|
|||||||
env_info.last_hashes.push(test_hash.clone());
|
env_info.last_hashes.push(test_hash.clone());
|
||||||
}
|
}
|
||||||
let state = setup.state.reference_mut();
|
let state = setup.state.reference_mut();
|
||||||
let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract);
|
let ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None));
|
||||||
|
|
||||||
let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap());
|
let hash = ext.blockhash(&U256::from_str("0000000000000000000000000000000000000000000000000000000000120000").unwrap());
|
||||||
|
|
||||||
@ -363,7 +377,7 @@ mod tests {
|
|||||||
fn can_call_fail_empty() {
|
fn can_call_fail_empty() {
|
||||||
let mut setup = TestSetup::new();
|
let mut setup = TestSetup::new();
|
||||||
let state = setup.state.reference_mut();
|
let state = setup.state.reference_mut();
|
||||||
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract);
|
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None));
|
||||||
|
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
@ -387,7 +401,7 @@ mod tests {
|
|||||||
let state = setup.state.reference_mut();
|
let state = setup.state.reference_mut();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract);
|
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None));
|
||||||
ext.log(log_topics, &log_data);
|
ext.log(log_topics, &log_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,7 +416,7 @@ mod tests {
|
|||||||
let state = setup.state.reference_mut();
|
let state = setup.state.reference_mut();
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract);
|
let mut ext = Externalities::new(state, &setup.env_info, &*setup.engine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None));
|
||||||
ext.suicide(&refund_account);
|
ext.suicide(&refund_account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,18 +16,19 @@
|
|||||||
|
|
||||||
use super::test_common::*;
|
use super::test_common::*;
|
||||||
use client::{BlockChainClient, Client, ClientConfig};
|
use client::{BlockChainClient, Client, ClientConfig};
|
||||||
use pod_state::*;
|
|
||||||
use block::Block;
|
use block::Block;
|
||||||
use ethereum;
|
use ethereum;
|
||||||
use tests::helpers::*;
|
use tests::helpers::*;
|
||||||
use devtools::*;
|
use devtools::*;
|
||||||
|
use spec::Genesis;
|
||||||
|
use ethjson;
|
||||||
|
|
||||||
pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
||||||
init_log();
|
init_log();
|
||||||
let json = Json::from_str(::std::str::from_utf8(json_data).unwrap()).expect("Json is invalid");
|
let tests = ethjson::blockchain::Test::load(json_data).unwrap();
|
||||||
let mut failed = Vec::new();
|
let mut failed = Vec::new();
|
||||||
|
|
||||||
for (name, test) in json.as_object().unwrap() {
|
for (name, blockchain) in tests.deref() {
|
||||||
let mut fail = false;
|
let mut fail = false;
|
||||||
{
|
{
|
||||||
let mut fail_unless = |cond: bool| if !cond && !fail {
|
let mut fail_unless = |cond: bool| if !cond && !fail {
|
||||||
@ -39,37 +40,36 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
|||||||
|
|
||||||
flush!(" - {}...", name);
|
flush!(" - {}...", name);
|
||||||
|
|
||||||
let blocks: Vec<(Bytes, bool)> = test["blocks"].as_array().unwrap().iter().map(|e| (xjson!(&e["rlp"]), e.find("blockHeader").is_some())).collect();
|
|
||||||
let mut spec = match era {
|
let mut spec = match era {
|
||||||
ChainEra::Frontier => ethereum::new_frontier_test(),
|
ChainEra::Frontier => ethereum::new_frontier_test(),
|
||||||
ChainEra::Homestead => ethereum::new_homestead_test(),
|
ChainEra::Homestead => ethereum::new_homestead_test(),
|
||||||
};
|
};
|
||||||
let s = PodState::from_json(test.find("pre").unwrap());
|
|
||||||
spec.set_genesis_state(s);
|
let genesis = Genesis::from(blockchain.genesis());
|
||||||
spec.overwrite_genesis(test.find("genesisBlockHeader").unwrap());
|
let state = From::from(blockchain.pre_state.clone());
|
||||||
|
spec.set_genesis_state(state);
|
||||||
|
spec.overwrite_genesis_params(genesis);
|
||||||
assert!(spec.is_state_root_valid());
|
assert!(spec.is_state_root_valid());
|
||||||
let genesis_hash = spec.genesis_header().hash();
|
|
||||||
assert_eq!(genesis_hash, H256::from_json(&test.find("genesisBlockHeader").unwrap()["hash"]));
|
|
||||||
|
|
||||||
let temp = RandomTempPath::new();
|
let temp = RandomTempPath::new();
|
||||||
{
|
{
|
||||||
let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap();
|
let client = Client::new(ClientConfig::default(), spec, temp.as_path(), IoChannel::disconnected()).unwrap();
|
||||||
assert_eq!(client.chain_info().best_block_hash, genesis_hash);
|
for b in &blockchain.blocks_rlp() {
|
||||||
for (b, is_valid) in blocks.into_iter() {
|
|
||||||
if Block::is_good(&b) {
|
if Block::is_good(&b) {
|
||||||
let _ = client.import_block(b.clone());
|
let _ = client.import_block(b.clone());
|
||||||
|
client.flush_queue();
|
||||||
|
client.import_verified_blocks(&IoChannel::disconnected());
|
||||||
}
|
}
|
||||||
client.flush_queue();
|
|
||||||
let imported_ok = client.import_verified_blocks(&IoChannel::disconnected()) > 0;
|
|
||||||
assert_eq!(imported_ok, is_valid);
|
|
||||||
}
|
}
|
||||||
fail_unless(client.chain_info().best_block_hash == H256::from_json(&test["lastblockhash"]));
|
fail_unless(client.chain_info().best_block_hash == blockchain.best_block.clone().into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fail {
|
if !fail {
|
||||||
flushln!("ok");
|
flushln!("ok");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("!!! {:?} tests from failed.", failed.len());
|
println!("!!! {:?} tests from failed.", failed.len());
|
||||||
failed
|
failed
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ impl<'a> TestExt<'a> {
|
|||||||
depth: usize,
|
depth: usize,
|
||||||
origin_info: OriginInfo,
|
origin_info: OriginInfo,
|
||||||
substate: &'a mut Substate,
|
substate: &'a mut Substate,
|
||||||
output: OutputPolicy<'a>,
|
output: OutputPolicy<'a, 'a>,
|
||||||
address: Address) -> Self {
|
address: Address) -> Self {
|
||||||
TestExt {
|
TestExt {
|
||||||
contract_address: contract_address(&address, &state.nonce(&address)),
|
contract_address: contract_address(&address, &state.nonce(&address)),
|
||||||
@ -227,19 +227,21 @@ fn do_json_test_for(vm: &VMType, json_data: &[u8]) -> Vec<String> {
|
|||||||
let out_of_gas = test.find("callcreates").map(|_calls| {
|
let out_of_gas = test.find("callcreates").map(|_calls| {
|
||||||
}).is_none();
|
}).is_none();
|
||||||
|
|
||||||
let mut substate = Substate::new();
|
let mut substate = Substate::new(false);
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
let (res, callcreates) = {
|
let (res, callcreates) = {
|
||||||
let mut ex = TestExt::new(&mut state,
|
let mut ex = TestExt::new(
|
||||||
&info,
|
&mut state,
|
||||||
&engine,
|
&info,
|
||||||
0,
|
&engine,
|
||||||
OriginInfo::from(¶ms),
|
0,
|
||||||
&mut substate,
|
OriginInfo::from(¶ms),
|
||||||
OutputPolicy::Return(BytesRef::Flexible(&mut output)),
|
&mut substate,
|
||||||
params.address.clone());
|
OutputPolicy::Return(BytesRef::Flexible(&mut output), None),
|
||||||
|
params.address.clone()
|
||||||
|
);
|
||||||
let evm = engine.vm_factory().create();
|
let evm = engine.vm_factory().create();
|
||||||
let res = evm.exec(params, &mut ex);
|
let res = evm.exec(params, &mut ex);
|
||||||
(res, ex.callcreates)
|
(res, ex.callcreates)
|
||||||
|
@ -69,7 +69,7 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
|||||||
let mut state = state_result.reference_mut();
|
let mut state = state_result.reference_mut();
|
||||||
state.populate_from(pre);
|
state.populate_from(pre);
|
||||||
state.commit();
|
state.commit();
|
||||||
let res = state.apply(&env, engine.deref(), &t);
|
let res = state.apply(&env, engine.deref(), &t, false);
|
||||||
|
|
||||||
if fail_unless(state.root() == &post_state_root) {
|
if fail_unless(state.root() == &post_state_root) {
|
||||||
println!("!!! {}: State mismatch (got: {}, expect: {}):", name, state.root(), post_state_root);
|
println!("!!! {}: State mismatch (got: {}, expect: {}):", name, state.root(), post_state_root);
|
||||||
@ -80,9 +80,9 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(r) = res {
|
if let Ok(r) = res {
|
||||||
if fail_unless(logs == r.logs) {
|
if fail_unless(logs == r.receipt.logs) {
|
||||||
println!("!!! {}: Logs mismatch:", name);
|
println!("!!! {}: Logs mismatch:", name);
|
||||||
println!("Got:\n{:?}", r.logs);
|
println!("Got:\n{:?}", r.receipt.logs);
|
||||||
println!("Expect:\n{:?}", logs);
|
println!("Expect:\n{:?}", logs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,7 @@ pub mod filter;
|
|||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod service;
|
pub mod service;
|
||||||
pub mod log_entry;
|
pub mod log_entry;
|
||||||
|
pub mod trace;
|
||||||
pub mod spec;
|
pub mod spec;
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
pub mod views;
|
pub mod views;
|
||||||
|
@ -82,7 +82,8 @@ impl From<ethjson::blockchain::Account> for PodAccount {
|
|||||||
code: a.code.into(),
|
code: a.code.into(),
|
||||||
storage: a.storage.into_iter().fold(BTreeMap::new(), |mut acc, (key, value)| {
|
storage: a.storage.into_iter().fold(BTreeMap::new(), |mut acc, (key, value)| {
|
||||||
let key: U256 = key.into();
|
let key: U256 = key.into();
|
||||||
acc.insert(H256::from(key), value.into());
|
let value: U256 = value.into();
|
||||||
|
acc.insert(H256::from(key), H256::from(value));
|
||||||
acc
|
acc
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ use pod_account::*;
|
|||||||
use ethjson;
|
use ethjson;
|
||||||
|
|
||||||
/// State of all accounts in the system expressed in Plain Old Data.
|
/// State of all accounts in the system expressed in Plain Old Data.
|
||||||
#[derive(Debug,Clone,PartialEq,Eq,Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
pub struct PodState (BTreeMap<Address, PodAccount>);
|
pub struct PodState (BTreeMap<Address, PodAccount>);
|
||||||
|
|
||||||
impl PodState {
|
impl PodState {
|
||||||
|
@ -146,7 +146,7 @@ mod tests {
|
|||||||
fn it_can_be_started() {
|
fn it_can_be_started() {
|
||||||
let spec = get_test_spec();
|
let spec = get_test_spec();
|
||||||
let temp_path = RandomTempPath::new();
|
let temp_path = RandomTempPath::new();
|
||||||
let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_with_port(40456), &temp_path.as_path());
|
let service = ClientService::start(ClientConfig::default(), spec, NetworkConfiguration::new_local(), &temp_path.as_path());
|
||||||
assert!(service.is_ok());
|
assert!(service.is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,16 @@ use pod_account::*;
|
|||||||
use pod_state::PodState;
|
use pod_state::PodState;
|
||||||
//use state_diff::*; // TODO: uncomment once to_pod() works correctly.
|
//use state_diff::*; // TODO: uncomment once to_pod() works correctly.
|
||||||
|
|
||||||
|
/// Used to return information about an `State::apply` operation.
|
||||||
|
pub struct ApplyOutcome {
|
||||||
|
/// The receipt for the applied transaction.
|
||||||
|
pub receipt: Receipt,
|
||||||
|
/// The trace for the applied transaction, if None if tracing is disabled.
|
||||||
|
pub trace: Option<Trace>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Result type for the execution ("application") of a transaction.
|
/// Result type for the execution ("application") of a transaction.
|
||||||
pub type ApplyResult = Result<Receipt, Error>;
|
pub type ApplyResult = Result<ApplyOutcome, Error>;
|
||||||
|
|
||||||
/// Representation of the entire state of all accounts in the system.
|
/// Representation of the entire state of all accounts in the system.
|
||||||
pub struct State {
|
pub struct State {
|
||||||
@ -209,17 +217,17 @@ impl State {
|
|||||||
|
|
||||||
/// Execute a given transaction.
|
/// Execute a given transaction.
|
||||||
/// This will change the state accordingly.
|
/// This will change the state accordingly.
|
||||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction) -> ApplyResult {
|
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
||||||
// let old = self.to_pod();
|
// let old = self.to_pod();
|
||||||
|
|
||||||
let e = try!(Executive::new(self, env_info, engine).transact(t));
|
let e = try!(Executive::new(self, env_info, engine).transact(t, tracing));
|
||||||
|
|
||||||
// TODO uncomment once to_pod() works correctly.
|
// TODO uncomment once to_pod() works correctly.
|
||||||
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
// trace!("Applied transaction. Diff:\n{}\n", StateDiff::diff_pod(&old, &self.to_pod()));
|
||||||
self.commit();
|
self.commit();
|
||||||
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
let receipt = Receipt::new(self.root().clone(), e.cumulative_gas_used, e.logs);
|
||||||
// trace!("Transaction receipt: {:?}", receipt);
|
// trace!("Transaction receipt: {:?}", receipt);
|
||||||
Ok(receipt)
|
Ok(ApplyOutcome{receipt: receipt, trace: e.trace})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit.
|
/// Commit accounts to SecTrieDBMut. This is similar to cpp-ethereum's dev::eth::commit.
|
||||||
|
@ -23,37 +23,45 @@ use common::*;
|
|||||||
pub struct Substate {
|
pub struct Substate {
|
||||||
/// Any accounts that have suicided.
|
/// Any accounts that have suicided.
|
||||||
pub suicides: HashSet<Address>,
|
pub suicides: HashSet<Address>,
|
||||||
|
|
||||||
/// Any logs.
|
/// Any logs.
|
||||||
pub logs: Vec<LogEntry>,
|
pub logs: Vec<LogEntry>,
|
||||||
|
|
||||||
/// Refund counter of SSTORE nonzero -> zero.
|
/// Refund counter of SSTORE nonzero -> zero.
|
||||||
pub sstore_clears_count: U256,
|
pub sstore_clears_count: U256,
|
||||||
/// Created contracts.
|
|
||||||
pub contracts_created: Vec<Address>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Substate {
|
/// Created contracts.
|
||||||
fn default() -> Self {
|
pub contracts_created: Vec<Address>,
|
||||||
Substate::new()
|
|
||||||
}
|
/// The trace during this execution or `None` if we're not tracing.
|
||||||
|
pub subtraces: Option<Vec<Trace>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Substate {
|
impl Substate {
|
||||||
/// Creates new substate.
|
/// Creates new substate.
|
||||||
pub fn new() -> Self {
|
pub fn new(tracing: bool) -> Self {
|
||||||
Substate {
|
Substate {
|
||||||
suicides: HashSet::new(),
|
suicides: Default::default(),
|
||||||
logs: vec![],
|
logs: Default::default(),
|
||||||
sstore_clears_count: U256::zero(),
|
sstore_clears_count: Default::default(),
|
||||||
contracts_created: vec![]
|
contracts_created: Default::default(),
|
||||||
|
subtraces: if tracing {Some(vec![])} else {None},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge secondary substate `s` into self, accruing each element correspondingly.
|
/// Merge secondary substate `s` into self, accruing each element correspondingly.
|
||||||
pub fn accrue(&mut self, s: Substate) {
|
pub fn accrue(&mut self, s: Substate, maybe_info: Option<(TraceAction, usize)>) {
|
||||||
self.suicides.extend(s.suicides.into_iter());
|
self.suicides.extend(s.suicides.into_iter());
|
||||||
self.logs.extend(s.logs.into_iter());
|
self.logs.extend(s.logs.into_iter());
|
||||||
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
|
self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count;
|
||||||
self.contracts_created.extend(s.contracts_created.into_iter());
|
self.contracts_created.extend(s.contracts_created.into_iter());
|
||||||
|
if let Some(info) = maybe_info {
|
||||||
|
self.subtraces.as_mut().expect("maybe_action is Some: so we must be tracing: qed").push(Trace {
|
||||||
|
action: info.0,
|
||||||
|
depth: info.1,
|
||||||
|
subs: s.subtraces.expect("maybe_action is Some: so we must be tracing: qed"),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,13 +72,13 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn created() {
|
fn created() {
|
||||||
let sub_state = Substate::new();
|
let sub_state = Substate::new(false);
|
||||||
assert_eq!(sub_state.suicides.len(), 0);
|
assert_eq!(sub_state.suicides.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accrue() {
|
fn accrue() {
|
||||||
let mut sub_state = Substate::new();
|
let mut sub_state = Substate::new(false);
|
||||||
sub_state.contracts_created.push(address_from_u64(1u64));
|
sub_state.contracts_created.push(address_from_u64(1u64));
|
||||||
sub_state.logs.push(LogEntry {
|
sub_state.logs.push(LogEntry {
|
||||||
address: address_from_u64(1u64),
|
address: address_from_u64(1u64),
|
||||||
@ -80,7 +88,7 @@ mod tests {
|
|||||||
sub_state.sstore_clears_count = x!(5);
|
sub_state.sstore_clears_count = x!(5);
|
||||||
sub_state.suicides.insert(address_from_u64(10u64));
|
sub_state.suicides.insert(address_from_u64(10u64));
|
||||||
|
|
||||||
let mut sub_state_2 = Substate::new();
|
let mut sub_state_2 = Substate::new(false);
|
||||||
sub_state_2.contracts_created.push(address_from_u64(2u64));
|
sub_state_2.contracts_created.push(address_from_u64(2u64));
|
||||||
sub_state_2.logs.push(LogEntry {
|
sub_state_2.logs.push(LogEntry {
|
||||||
address: address_from_u64(1u64),
|
address: address_from_u64(1u64),
|
||||||
@ -89,7 +97,7 @@ mod tests {
|
|||||||
});
|
});
|
||||||
sub_state_2.sstore_clears_count = x!(7);
|
sub_state_2.sstore_clears_count = x!(7);
|
||||||
|
|
||||||
sub_state.accrue(sub_state_2);
|
sub_state.accrue(sub_state_2, None);
|
||||||
assert_eq!(sub_state.contracts_created.len(), 2);
|
assert_eq!(sub_state.contracts_created.len(), 2);
|
||||||
assert_eq!(sub_state.sstore_clears_count, x!(12));
|
assert_eq!(sub_state.sstore_clears_count, x!(12));
|
||||||
assert_eq!(sub_state.suicides.len(), 1);
|
assert_eq!(sub_state.suicides.len(), 1);
|
||||||
|
111
ethcore/src/trace.rs
Normal file
111
ethcore/src/trace.rs
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright 2015, 2016 Ethcore (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/>.
|
||||||
|
|
||||||
|
//! Tracing datatypes.
|
||||||
|
use common::*;
|
||||||
|
|
||||||
|
/// Description of a _call_ action, either a `CALL` operation or a message transction.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct TraceCall {
|
||||||
|
/// The sending account.
|
||||||
|
pub from: Address,
|
||||||
|
/// The destination account.
|
||||||
|
pub to: Address,
|
||||||
|
/// The value transferred to the destination account.
|
||||||
|
pub value: U256,
|
||||||
|
/// The gas available for executing the call.
|
||||||
|
pub gas: U256,
|
||||||
|
/// The input data provided to the call.
|
||||||
|
pub input: Bytes,
|
||||||
|
/// The result of the operation; the gas used and the output data of the call.
|
||||||
|
pub result: Option<(U256, Bytes)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Description of a _create_ action, either a `CREATE` operation or a create transction.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct TraceCreate {
|
||||||
|
/// The address of the creator.
|
||||||
|
pub from: Address,
|
||||||
|
/// The value with which the new account is endowed.
|
||||||
|
pub value: U256,
|
||||||
|
/// The gas available for the creation init code.
|
||||||
|
pub gas: U256,
|
||||||
|
/// The init code.
|
||||||
|
pub init: Bytes,
|
||||||
|
/// The result of the operation; tuple of the gas used, the address of the newly created account and its code.
|
||||||
|
/// NOTE: Presently failed operations are not reported so this will always be `Some`.
|
||||||
|
pub result: Option<(U256, Address, Bytes)>,
|
||||||
|
// pub output: Bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Description of an action that we trace; will be either a call or a create.
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum TraceAction {
|
||||||
|
/// Action isn't yet known.
|
||||||
|
Unknown,
|
||||||
|
/// It's a call action.
|
||||||
|
Call(TraceCall),
|
||||||
|
/// It's a create action.
|
||||||
|
Create(TraceCreate),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
/// A trace; includes a description of the action being traced and sub traces of each interior action.
|
||||||
|
pub struct Trace {
|
||||||
|
/// The number of EVM execution environments active when this action happened; 0 if it's
|
||||||
|
/// the outer action of the transaction.
|
||||||
|
pub depth: usize,
|
||||||
|
/// The action being performed.
|
||||||
|
pub action: TraceAction,
|
||||||
|
/// The sub traces for each interior action performed as part of this call.
|
||||||
|
pub subs: Vec<Trace>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Trace {
|
||||||
|
fn default() -> Trace {
|
||||||
|
Trace {
|
||||||
|
depth: 0,
|
||||||
|
action: TraceAction::Unknown,
|
||||||
|
subs: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TraceAction {
|
||||||
|
/// Compose a `TraceAction` from an `ActionParams`, knowing that the action is a call.
|
||||||
|
pub fn from_call(p: &ActionParams) -> TraceAction {
|
||||||
|
TraceAction::Call(TraceCall {
|
||||||
|
from: p.sender.clone(),
|
||||||
|
to: p.address.clone(),
|
||||||
|
value: match p.value { ActionValue::Transfer(ref x) | ActionValue::Apparent(ref x) => x.clone() },
|
||||||
|
gas: p.gas.clone(),
|
||||||
|
input: p.data.clone().unwrap_or(vec![]),
|
||||||
|
result: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compose a `TraceAction` from an `ActionParams`, knowing that the action is a create.
|
||||||
|
pub fn from_create(p: &ActionParams) -> TraceAction {
|
||||||
|
TraceAction::Create(TraceCreate {
|
||||||
|
from: p.sender.clone(),
|
||||||
|
value: match p.value { ActionValue::Transfer(ref x) | ActionValue::Apparent(ref x) => x.clone() },
|
||||||
|
gas: p.gas.clone(),
|
||||||
|
init: p.code.clone().unwrap_or(vec![]),
|
||||||
|
result: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -278,6 +278,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BlockProvider for TestBlockChain {
|
impl BlockProvider for TestBlockChain {
|
||||||
|
fn have_tracing(&self) -> bool { false }
|
||||||
|
|
||||||
fn is_known(&self, hash: &H256) -> bool {
|
fn is_known(&self, hash: &H256) -> bool {
|
||||||
self.blocks.contains_key(hash)
|
self.blocks.contains_key(hash)
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ clippy = { version = "0.0.54", optional = true }
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
serde_codegen = { version = "0.7.0", optional = true }
|
serde_codegen = { version = "0.7.0", optional = true }
|
||||||
syntex = "0.29.0"
|
syntex = "0.30.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["serde_codegen"]
|
default = ["serde_codegen"]
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use uint::Uint;
|
use uint::Uint;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use hash::H256;
|
|
||||||
|
|
||||||
/// Blockchain test account deserializer.
|
/// Blockchain test account deserializer.
|
||||||
#[derive(Debug, PartialEq, Deserialize, Clone)]
|
#[derive(Debug, PartialEq, Deserialize, Clone)]
|
||||||
@ -31,7 +30,7 @@ pub struct Account {
|
|||||||
/// Nonce.
|
/// Nonce.
|
||||||
pub nonce: Uint,
|
pub nonce: Uint,
|
||||||
/// Storage.
|
/// Storage.
|
||||||
pub storage: BTreeMap<Uint, H256>,
|
pub storage: BTreeMap<Uint, Uint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -24,11 +24,11 @@ use blockchain::transaction::Transaction;
|
|||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
pub struct Block {
|
pub struct Block {
|
||||||
#[serde(rename="blockHeader")]
|
#[serde(rename="blockHeader")]
|
||||||
header: Header,
|
header: Option<Header>,
|
||||||
rlp: Bytes,
|
rlp: Bytes,
|
||||||
transactions: Vec<Transaction>,
|
transactions: Option<Vec<Transaction>>,
|
||||||
#[serde(rename="uncleHeaders")]
|
#[serde(rename="uncleHeaders")]
|
||||||
uncles: Vec<Header>,
|
uncles: Option<Vec<Header>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
//! Blockchain deserialization.
|
//! Blockchain deserialization.
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
use hash::H256;
|
||||||
use blockchain::state::State;
|
use blockchain::state::State;
|
||||||
use blockchain::header::Header;
|
use blockchain::header::Header;
|
||||||
use blockchain::block::Block;
|
use blockchain::block::Block;
|
||||||
@ -30,7 +31,7 @@ pub struct BlockChain {
|
|||||||
pub genesis_block: Header,
|
pub genesis_block: Header,
|
||||||
/// Genesis block rlp.
|
/// Genesis block rlp.
|
||||||
#[serde(rename="genesisRLP")]
|
#[serde(rename="genesisRLP")]
|
||||||
pub genesis_rlp: Bytes,
|
pub genesis_rlp: Option<Bytes>,
|
||||||
/// Blocks.
|
/// Blocks.
|
||||||
pub blocks: Vec<Block>,
|
pub blocks: Vec<Block>,
|
||||||
/// Post state.
|
/// Post state.
|
||||||
@ -39,14 +40,12 @@ pub struct BlockChain {
|
|||||||
/// Pre state.
|
/// Pre state.
|
||||||
#[serde(rename="pre")]
|
#[serde(rename="pre")]
|
||||||
pub pre_state: State,
|
pub pre_state: State,
|
||||||
|
/// Hash of best block.
|
||||||
|
#[serde(rename="lastblockhash")]
|
||||||
|
pub best_block: H256
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockChain {
|
impl BlockChain {
|
||||||
/// Returns genesis block rlp.
|
|
||||||
pub fn genesis_rlp(&self) -> Vec<u8> {
|
|
||||||
self.genesis_rlp.clone().into()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns blocks rlp.
|
/// Returns blocks rlp.
|
||||||
pub fn blocks_rlp(&self) -> Vec<Vec<u8>> {
|
pub fn blocks_rlp(&self) -> Vec<Vec<u8>> {
|
||||||
self.blocks.iter().map(|block| block.rlp()).collect()
|
self.blocks.iter().map(|block| block.rlp()).collect()
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::io::Read;
|
||||||
|
use serde_json;
|
||||||
|
use serde_json::Error;
|
||||||
use blockchain::blockchain::BlockChain;
|
use blockchain::blockchain::BlockChain;
|
||||||
|
|
||||||
/// Blockchain test deserializer.
|
/// Blockchain test deserializer.
|
||||||
@ -31,3 +34,10 @@ impl Deref for Test {
|
|||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Test {
|
||||||
|
/// Loads test from json.
|
||||||
|
pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
|
||||||
|
serde_json::from_reader(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -46,12 +46,8 @@ impl Visitor for BytesVisitor {
|
|||||||
let v = match value.len() {
|
let v = match value.len() {
|
||||||
0 => vec![],
|
0 => vec![],
|
||||||
2 if value.starts_with("0x") => vec![],
|
2 if value.starts_with("0x") => vec![],
|
||||||
_ if value.starts_with("0x") => try!(FromHex::from_hex(&value[2..]).map_err(|_| {
|
_ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]),
|
||||||
Error::custom(format!("Invalid hex value {}.", value).as_ref())
|
_ => FromHex::from_hex(value).unwrap_or(vec![]),
|
||||||
})),
|
|
||||||
_ => try!(FromHex::from_hex(value).map_err(|_| {
|
|
||||||
Error::custom(format!("Invalid hex value {}.", value).as_ref())
|
|
||||||
}))
|
|
||||||
};
|
};
|
||||||
Ok(Bytes(v))
|
Ok(Bytes(v))
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ use env_logger::LogBuilder;
|
|||||||
use ctrlc::CtrlC;
|
use ctrlc::CtrlC;
|
||||||
use util::*;
|
use util::*;
|
||||||
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
use util::panics::{MayPanic, ForwardPanic, PanicHandler};
|
||||||
|
use util::keys::store::*;
|
||||||
use ethcore::spec::*;
|
use ethcore::spec::*;
|
||||||
use ethcore::client::*;
|
use ethcore::client::*;
|
||||||
use ethcore::service::{ClientService, NetSyncMessage};
|
use ethcore::service::{ClientService, NetSyncMessage};
|
||||||
@ -55,7 +56,6 @@ use ethminer::{Miner, MinerService};
|
|||||||
use docopt::Docopt;
|
use docopt::Docopt;
|
||||||
use daemonize::Daemonize;
|
use daemonize::Daemonize;
|
||||||
use number_prefix::{binary_prefix, Standalone, Prefixed};
|
use number_prefix::{binary_prefix, Standalone, Prefixed};
|
||||||
use util::keys::store::*;
|
|
||||||
|
|
||||||
fn die_with_message(msg: &str) -> ! {
|
fn die_with_message(msg: &str) -> ! {
|
||||||
println!("ERROR: {}", msg);
|
println!("ERROR: {}", msg);
|
||||||
@ -315,7 +315,7 @@ impl Configuration {
|
|||||||
|
|
||||||
fn author(&self) -> Address {
|
fn author(&self) -> Address {
|
||||||
let d = self.args.flag_etherbase.as_ref().unwrap_or(&self.args.flag_author);
|
let d = self.args.flag_etherbase.as_ref().unwrap_or(&self.args.flag_author);
|
||||||
Address::from_str(d).unwrap_or_else(|_| {
|
Address::from_str(clean_0x(d)).unwrap_or_else(|_| {
|
||||||
die!("{}: Invalid address for --author. Must be 40 hex characters, without the 0x at the beginning.", d)
|
die!("{}: Invalid address for --author. Must be 40 hex characters, without the 0x at the beginning.", d)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ clippy = { version = "0.0.54", optional = true }
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
serde_codegen = { version = "0.7.0", optional = true }
|
serde_codegen = { version = "0.7.0", optional = true }
|
||||||
syntex = "0.29.0"
|
syntex = "0.30.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["serde_codegen"]
|
default = ["serde_codegen"]
|
||||||
|
17
rpc/rpctest/Cargo.toml
Normal file
17
rpc/rpctest/Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
description = "Rpc test client."
|
||||||
|
name = "rpctest"
|
||||||
|
version = "1.1.0"
|
||||||
|
license = "GPL-3.0"
|
||||||
|
authors = ["Ethcore <admin@ethcore.io>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ctrlc = { git = "https://github.com/tomusdrw/rust-ctrlc.git" }
|
||||||
|
docopt = "0.6"
|
||||||
|
rustc-serialize = "0.3"
|
||||||
|
ethcore = { path = "../../ethcore" }
|
||||||
|
ethcore-devtools = { path = "../../devtools" }
|
||||||
|
ethcore-rpc = { path = ".." }
|
||||||
|
ethcore-util = { path = "../../util" }
|
||||||
|
ethjson = { path = "../../json" }
|
||||||
|
serde_json = "0.7.0"
|
@ -37,9 +37,10 @@ use ethcore::ethereum;
|
|||||||
use ethcore::client::{BlockChainClient, Client, ClientConfig};
|
use ethcore::client::{BlockChainClient, Client, ClientConfig};
|
||||||
use devtools::RandomTempPath;
|
use devtools::RandomTempPath;
|
||||||
use util::IoChannel;
|
use util::IoChannel;
|
||||||
use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider};
|
use rpc::v1::tests::helpers::{TestSyncProvider, Config as SyncConfig, TestMinerService, TestAccountProvider, TestAccount};
|
||||||
use rpc::v1::{Eth, EthClient};
|
use rpc::v1::{Eth, EthClient, EthFilter, EthFilterClient};
|
||||||
use util::panics::MayPanic;
|
use util::panics::MayPanic;
|
||||||
|
use util::hash::Address;
|
||||||
|
|
||||||
const USAGE: &'static str = r#"
|
const USAGE: &'static str = r#"
|
||||||
Parity rpctest client.
|
Parity rpctest client.
|
||||||
@ -86,8 +87,9 @@ impl Configuration {
|
|||||||
process::exit(1);
|
process::exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|_| {
|
let tests: ethjson::blockchain::Test = serde_json::from_reader(file).unwrap_or_else(|err| {
|
||||||
println!("Invalid json file.");
|
println!("Invalid json file.");
|
||||||
|
println!("{:?}", err);
|
||||||
process::exit(2);
|
process::exit(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -117,9 +119,12 @@ impl Configuration {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
let miner = Arc::new(TestMinerService::default());
|
let miner = Arc::new(TestMinerService::default());
|
||||||
let accounts = Arc::new(TestAccountProvider::new(HashMap::new()));
|
let mut accs = HashMap::new();
|
||||||
|
accs.insert(Address::from(1), TestAccount::new("test"));
|
||||||
|
let accounts = Arc::new(TestAccountProvider::new(accs));
|
||||||
let server = rpc::RpcServer::new();
|
let server = rpc::RpcServer::new();
|
||||||
server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate());
|
server.add_delegate(EthClient::new(&client, &sync, &accounts, &miner).to_delegate());
|
||||||
|
server.add_delegate(EthFilterClient::new(&client, &miner).to_delegate());
|
||||||
|
|
||||||
let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port);
|
let url = format!("{}:{}", self.args.flag_jsonrpc_addr, self.args.flag_jsonrpc_port);
|
||||||
let panic_handler = server.start_http(url.as_ref(), "*", 1);
|
let panic_handler = server.start_http(url.as_ref(), "*", 1);
|
@ -103,7 +103,8 @@ impl<C, S, A, M, EM> EthClient<C, S, A, M, EM>
|
|||||||
timestamp: U256::from(view.timestamp()),
|
timestamp: U256::from(view.timestamp()),
|
||||||
difficulty: view.difficulty(),
|
difficulty: view.difficulty(),
|
||||||
total_difficulty: total_difficulty,
|
total_difficulty: total_difficulty,
|
||||||
uncles: vec![],
|
nonce: view.seal().get(1).map_or_else(H64::zero, |r| H64::from_slice(r)),
|
||||||
|
uncles: block_view.uncle_hashes(),
|
||||||
transactions: {
|
transactions: {
|
||||||
if include_txs {
|
if include_txs {
|
||||||
BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect())
|
BlockTransactions::Full(block_view.localized_transactions().into_iter().map(From::from).collect())
|
||||||
@ -111,7 +112,7 @@ impl<C, S, A, M, EM> EthClient<C, S, A, M, EM>
|
|||||||
BlockTransactions::Hashes(block_view.transaction_hashes())
|
BlockTransactions::Hashes(block_view.transaction_hashes())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
extra_data: Bytes::default()
|
extra_data: Bytes::new(view.extra_data())
|
||||||
};
|
};
|
||||||
to_value(&block)
|
to_value(&block)
|
||||||
},
|
},
|
||||||
@ -229,8 +230,8 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
fn block_transaction_count_by_hash(&self, params: Params) -> Result<Value, Error> {
|
fn block_transaction_count_by_hash(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(H256,)>(params)
|
from_params::<(H256,)>(params)
|
||||||
.and_then(|(hash,)| // match
|
.and_then(|(hash,)| // match
|
||||||
to_value(&take_weak!(self.client).block(BlockId::Hash(hash))
|
take_weak!(self.client).block(BlockId::Hash(hash))
|
||||||
.map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count()))))
|
.map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).transactions_count()))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_transaction_count_by_number(&self, params: Params) -> Result<Value, Error> {
|
fn block_transaction_count_by_number(&self, params: Params) -> Result<Value, Error> {
|
||||||
@ -239,24 +240,24 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM>
|
|||||||
BlockNumber::Pending => to_value(
|
BlockNumber::Pending => to_value(
|
||||||
&U256::from(take_weak!(self.miner).status().transactions_in_pending_block)
|
&U256::from(take_weak!(self.miner).status().transactions_in_pending_block)
|
||||||
),
|
),
|
||||||
_ => to_value(&take_weak!(self.client).block(block_number.into())
|
_ => take_weak!(self.client).block(block_number.into())
|
||||||
.map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).transactions_count())))
|
.map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).transactions_count())))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_uncles_count_by_hash(&self, params: Params) -> Result<Value, Error> {
|
fn block_uncles_count_by_hash(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(H256,)>(params)
|
from_params::<(H256,)>(params)
|
||||||
.and_then(|(hash,)|
|
.and_then(|(hash,)|
|
||||||
to_value(&take_weak!(self.client).block(BlockId::Hash(hash))
|
take_weak!(self.client).block(BlockId::Hash(hash))
|
||||||
.map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).uncles_count()))))
|
.map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).uncles_count()))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn block_uncles_count_by_number(&self, params: Params) -> Result<Value, Error> {
|
fn block_uncles_count_by_number(&self, params: Params) -> Result<Value, Error> {
|
||||||
from_params::<(BlockNumber,)>(params)
|
from_params::<(BlockNumber,)>(params)
|
||||||
.and_then(|(block_number,)| match block_number {
|
.and_then(|(block_number,)| match block_number {
|
||||||
BlockNumber::Pending => to_value(&U256::from(0)),
|
BlockNumber::Pending => to_value(&U256::from(0)),
|
||||||
_ => to_value(&take_weak!(self.client).block(block_number.into())
|
_ => take_weak!(self.client).block(block_number.into())
|
||||||
.map_or_else(U256::zero, |bytes| U256::from(BlockView::new(&bytes).uncles_count())))
|
.map_or(Ok(Value::Null), |bytes| to_value(&U256::from(BlockView::new(&bytes).uncles_count())))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ fn rpc_eth_block_transaction_count_by_hash() {
|
|||||||
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
||||||
"id": 1
|
"id": 1
|
||||||
}"#;
|
}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
|
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
@ -264,7 +264,7 @@ fn rpc_eth_uncle_count_by_block_hash() {
|
|||||||
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
"params": ["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],
|
||||||
"id": 1
|
"id": 1
|
||||||
}"#;
|
}"#;
|
||||||
let response = r#"{"jsonrpc":"2.0","result":"0x00","id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","result":null,"id":1}"#;
|
||||||
|
|
||||||
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
|
assert_eq!(EthTester::default().io.handle_request(request), Some(response.to_owned()));
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ impl MinerService for TestMinerService {
|
|||||||
where T: Fn(&Address) -> AccountDetails { unimplemented!(); }
|
where T: Fn(&Address) -> AccountDetails { unimplemented!(); }
|
||||||
|
|
||||||
/// Returns hashes of transactions currently in pending
|
/// Returns hashes of transactions currently in pending
|
||||||
fn pending_transactions_hashes(&self) -> Vec<H256> { unimplemented!(); }
|
fn pending_transactions_hashes(&self) -> Vec<H256> { vec![] }
|
||||||
|
|
||||||
/// Removes all transactions from the queue and restart mining operation.
|
/// Removes all transactions from the queue and restart mining operation.
|
||||||
fn clear_and_reset(&self, _chain: &BlockChainClient) { unimplemented!(); }
|
fn clear_and_reset(&self, _chain: &BlockChainClient) { unimplemented!(); }
|
||||||
|
@ -63,7 +63,8 @@ pub struct Block {
|
|||||||
pub difficulty: U256,
|
pub difficulty: U256,
|
||||||
#[serde(rename="totalDifficulty")]
|
#[serde(rename="totalDifficulty")]
|
||||||
pub total_difficulty: U256,
|
pub total_difficulty: U256,
|
||||||
pub uncles: Vec<U256>,
|
pub nonce: H64,
|
||||||
|
pub uncles: Vec<H256>,
|
||||||
pub transactions: BlockTransactions
|
pub transactions: BlockTransactions
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +79,7 @@ mod tests {
|
|||||||
fn test_serialize_block_transactions() {
|
fn test_serialize_block_transactions() {
|
||||||
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
let t = BlockTransactions::Full(vec![Transaction::default()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}]"#);
|
assert_eq!(serialized, r#"[{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x"}]"#);
|
||||||
|
|
||||||
let t = BlockTransactions::Hashes(vec![H256::default()]);
|
let t = BlockTransactions::Hashes(vec![H256::default()]);
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
@ -104,11 +105,12 @@ mod tests {
|
|||||||
timestamp: U256::default(),
|
timestamp: U256::default(),
|
||||||
difficulty: U256::default(),
|
difficulty: U256::default(),
|
||||||
total_difficulty: U256::default(),
|
total_difficulty: U256::default(),
|
||||||
|
nonce: H64::default(),
|
||||||
uncles: vec![],
|
uncles: vec![],
|
||||||
transactions: BlockTransactions::Hashes(vec![])
|
transactions: BlockTransactions::Hashes(vec![])
|
||||||
};
|
};
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&block).unwrap();
|
let serialized = serde_json::to_string(&block).unwrap();
|
||||||
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","author":"0x0000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x00","gasUsed":"0x00","gasLimit":"0x00","extraData":"0x00","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x00","difficulty":"0x00","totalDifficulty":"0x00","uncles":[],"transactions":[]}"#);
|
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x0000000000000000000000000000000000000000000000000000000000000000","author":"0x0000000000000000000000000000000000000000","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","number":"0x00","gasUsed":"0x00","gasLimit":"0x00","extraData":"0x","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","timestamp":"0x00","difficulty":"0x00","totalDifficulty":"0x00","nonce":"0x0000000000000000","uncles":[],"transactions":[]}"#);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use serde::de::Visitor;
|
|||||||
use util::common::FromHex;
|
use util::common::FromHex;
|
||||||
|
|
||||||
/// Wrapper structure around vector of bytes.
|
/// Wrapper structure around vector of bytes.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Default)]
|
||||||
pub struct Bytes(Vec<u8>);
|
pub struct Bytes(Vec<u8>);
|
||||||
|
|
||||||
impl Bytes {
|
impl Bytes {
|
||||||
@ -31,13 +31,6 @@ impl Bytes {
|
|||||||
pub fn to_vec(self) -> Vec<u8> { let Bytes(x) = self; x }
|
pub fn to_vec(self) -> Vec<u8> { let Bytes(x) = self; x }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Bytes {
|
|
||||||
fn default() -> Self {
|
|
||||||
// default serialized value is 0x00
|
|
||||||
Bytes(vec![0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for Bytes {
|
impl Serialize for Bytes {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
|
@ -67,7 +67,7 @@ mod tests {
|
|||||||
fn test_transaction_serialize() {
|
fn test_transaction_serialize() {
|
||||||
let t = Transaction::default();
|
let t = Transaction::default();
|
||||||
let serialized = serde_json::to_string(&t).unwrap();
|
let serialized = serde_json::to_string(&t).unwrap();
|
||||||
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x00"}"#);
|
assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x00","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x00","gasPrice":"0x00","gas":"0x00","input":"0x"}"#);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,8 @@ pub trait FixedHash: Sized + BytesConvertable + Populatable + FromStr + Default
|
|||||||
fn low_u64(&self) -> u64;
|
fn low_u64(&self) -> u64;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clean_0x(s: &str) -> &str {
|
/// Return `s` without the `0x` at the beginning of it, if any.
|
||||||
|
pub fn clean_0x(s: &str) -> &str {
|
||||||
if s.len() >= 2 && &s[0..2] == "0x" {
|
if s.len() >= 2 && &s[0..2] == "0x" {
|
||||||
&s[2..]
|
&s[2..]
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,6 +105,14 @@ impl NetworkConfiguration {
|
|||||||
config.listen_address = Some(SocketAddr::from_str(&format!("0.0.0.0:{}", port)).unwrap());
|
config.listen_address = Some(SocketAddr::from_str(&format!("0.0.0.0:{}", port)).unwrap());
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create new default configuration for localhost-only connection with random port (usefull for testing)
|
||||||
|
pub fn new_local() -> NetworkConfiguration {
|
||||||
|
let mut config = NetworkConfiguration::new();
|
||||||
|
config.listen_address = Some(SocketAddr::from_str("127.0.0.1:0").unwrap());
|
||||||
|
config.nat_enabled = false;
|
||||||
|
config
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tokens
|
// Tokens
|
||||||
@ -269,12 +277,12 @@ pub struct HostInfo {
|
|||||||
pub protocol_version: u32,
|
pub protocol_version: u32,
|
||||||
/// Client identifier
|
/// Client identifier
|
||||||
pub client_version: String,
|
pub client_version: String,
|
||||||
/// TCP connection port.
|
|
||||||
pub listen_port: u16,
|
|
||||||
/// Registered capabilities (handlers)
|
/// Registered capabilities (handlers)
|
||||||
pub capabilities: Vec<CapabilityInfo>,
|
pub capabilities: Vec<CapabilityInfo>,
|
||||||
|
/// Local address + discovery port
|
||||||
|
pub local_endpoint: NodeEndpoint,
|
||||||
/// Public address + discovery port
|
/// Public address + discovery port
|
||||||
public_endpoint: NodeEndpoint,
|
pub public_endpoint: Option<NodeEndpoint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostInfo {
|
impl HostInfo {
|
||||||
@ -307,7 +315,7 @@ struct ProtocolTimer {
|
|||||||
/// Root IO handler. Manages protocol handlers, IO timers and network connections.
|
/// Root IO handler. Manages protocol handlers, IO timers and network connections.
|
||||||
pub struct Host<Message> where Message: Send + Sync + Clone {
|
pub struct Host<Message> where Message: Send + Sync + Clone {
|
||||||
pub info: RwLock<HostInfo>,
|
pub info: RwLock<HostInfo>,
|
||||||
tcp_listener: Mutex<Option<TcpListener>>,
|
tcp_listener: Mutex<TcpListener>,
|
||||||
handshakes: Arc<RwLock<Slab<SharedHandshake>>>,
|
handshakes: Arc<RwLock<Slab<SharedHandshake>>>,
|
||||||
sessions: Arc<RwLock<Slab<SharedSession>>>,
|
sessions: Arc<RwLock<Slab<SharedSession>>>,
|
||||||
discovery: Mutex<Option<Discovery>>,
|
discovery: Mutex<Option<Discovery>>,
|
||||||
@ -321,13 +329,12 @@ pub struct Host<Message> where Message: Send + Sync + Clone {
|
|||||||
|
|
||||||
impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||||
/// Create a new instance
|
/// Create a new instance
|
||||||
pub fn new(config: NetworkConfiguration) -> Host<Message> {
|
pub fn new(config: NetworkConfiguration) -> Result<Host<Message>, UtilError> {
|
||||||
let listen_address = match config.listen_address {
|
let mut listen_address = match config.listen_address {
|
||||||
None => SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
None => SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
let udp_port = config.udp_port.unwrap_or(listen_address.port());
|
|
||||||
let keys = if let Some(ref secret) = config.use_secret {
|
let keys = if let Some(ref secret) = config.use_secret {
|
||||||
KeyPair::from_secret(secret.clone()).unwrap()
|
KeyPair::from_secret(secret.clone()).unwrap()
|
||||||
} else {
|
} else {
|
||||||
@ -342,7 +349,12 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
|s| KeyPair::from_secret(s).expect("Error creating node secret key"))
|
|s| KeyPair::from_secret(s).expect("Error creating node secret key"))
|
||||||
};
|
};
|
||||||
let path = config.config_path.clone();
|
let path = config.config_path.clone();
|
||||||
|
// Setup the server socket
|
||||||
|
let tcp_listener = try!(TcpListener::bind(&listen_address));
|
||||||
|
listen_address = SocketAddr::new(listen_address.ip(), try!(tcp_listener.local_addr()).port());
|
||||||
|
let udp_port = config.udp_port.unwrap_or(listen_address.port());
|
||||||
let local_endpoint = NodeEndpoint { address: listen_address, udp_port: udp_port };
|
let local_endpoint = NodeEndpoint { address: listen_address, udp_port: udp_port };
|
||||||
|
|
||||||
let mut host = Host::<Message> {
|
let mut host = Host::<Message> {
|
||||||
info: RwLock::new(HostInfo {
|
info: RwLock::new(HostInfo {
|
||||||
keys: keys,
|
keys: keys,
|
||||||
@ -350,12 +362,12 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
nonce: H256::random(),
|
nonce: H256::random(),
|
||||||
protocol_version: PROTOCOL_VERSION,
|
protocol_version: PROTOCOL_VERSION,
|
||||||
client_version: version(),
|
client_version: version(),
|
||||||
listen_port: 0,
|
|
||||||
capabilities: Vec::new(),
|
capabilities: Vec::new(),
|
||||||
public_endpoint: local_endpoint, // will be replaced by public once it is resolved
|
public_endpoint: None,
|
||||||
|
local_endpoint: local_endpoint,
|
||||||
}),
|
}),
|
||||||
discovery: Mutex::new(None),
|
discovery: Mutex::new(None),
|
||||||
tcp_listener: Mutex::new(None),
|
tcp_listener: Mutex::new(tcp_listener),
|
||||||
handshakes: Arc::new(RwLock::new(Slab::new_starting_at(FIRST_HANDSHAKE, MAX_HANDSHAKES))),
|
handshakes: Arc::new(RwLock::new(Slab::new_starting_at(FIRST_HANDSHAKE, MAX_HANDSHAKES))),
|
||||||
sessions: Arc::new(RwLock::new(Slab::new_starting_at(FIRST_SESSION, MAX_SESSIONS))),
|
sessions: Arc::new(RwLock::new(Slab::new_starting_at(FIRST_SESSION, MAX_SESSIONS))),
|
||||||
nodes: RwLock::new(NodeTable::new(path)),
|
nodes: RwLock::new(NodeTable::new(path)),
|
||||||
@ -365,14 +377,12 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
stats: Arc::new(NetworkStats::default()),
|
stats: Arc::new(NetworkStats::default()),
|
||||||
pinned_nodes: Vec::new(),
|
pinned_nodes: Vec::new(),
|
||||||
};
|
};
|
||||||
let port = listen_address.port();
|
|
||||||
host.info.write().unwrap().deref_mut().listen_port = port;
|
|
||||||
|
|
||||||
let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone();
|
let boot_nodes = host.info.read().unwrap().config.boot_nodes.clone();
|
||||||
for n in boot_nodes {
|
for n in boot_nodes {
|
||||||
host.add_node(&n);
|
host.add_node(&n);
|
||||||
}
|
}
|
||||||
host
|
Ok(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stats(&self) -> Arc<NetworkStats> {
|
pub fn stats(&self) -> Arc<NetworkStats> {
|
||||||
@ -397,50 +407,50 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
self.info.read().unwrap().client_version.clone()
|
self.info.read().unwrap().client_version.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_url(&self) -> String {
|
pub fn external_url(&self) -> Option<String> {
|
||||||
format!("{}", Node::new(self.info.read().unwrap().id().clone(), self.info.read().unwrap().public_endpoint.clone()))
|
self.info.read().unwrap().public_endpoint.as_ref().map(|e| format!("{}", Node::new(self.info.read().unwrap().id().clone(), e.clone())))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_public_interface(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
pub fn local_url(&self) -> String {
|
||||||
|
let r = format!("{}", Node::new(self.info.read().unwrap().id().clone(), self.info.read().unwrap().local_endpoint.clone()));
|
||||||
|
println!("{}", r);
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_public_interface(&self, io: &IoContext<NetworkIoMessage<Message>>) -> Result<(), UtilError> {
|
||||||
io.clear_timer(INIT_PUBLIC).unwrap();
|
io.clear_timer(INIT_PUBLIC).unwrap();
|
||||||
let mut tcp_listener = self.tcp_listener.lock().unwrap();
|
if self.info.read().unwrap().public_endpoint.is_some() {
|
||||||
if tcp_listener.is_some() {
|
return Ok(());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// public_endpoint in host info contains local adderss at this point
|
let local_endpoint = self.info.read().unwrap().local_endpoint.clone();
|
||||||
let listen_address = self.info.read().unwrap().public_endpoint.address.clone();
|
|
||||||
let udp_port = self.info.read().unwrap().config.udp_port.unwrap_or(listen_address.port());
|
|
||||||
let public_address = self.info.read().unwrap().config.public_address.clone();
|
let public_address = self.info.read().unwrap().config.public_address.clone();
|
||||||
let public_endpoint = match public_address {
|
let public_endpoint = match public_address {
|
||||||
None => {
|
None => {
|
||||||
let public_address = select_public_address(listen_address.port());
|
let public_address = select_public_address(local_endpoint.address.port());
|
||||||
let local_endpoint = NodeEndpoint { address: public_address, udp_port: udp_port };
|
let public_endpoint = NodeEndpoint { address: public_address, udp_port: local_endpoint.udp_port };
|
||||||
if self.info.read().unwrap().config.nat_enabled {
|
if self.info.read().unwrap().config.nat_enabled {
|
||||||
match map_external_address(&local_endpoint) {
|
match map_external_address(&local_endpoint) {
|
||||||
Some(endpoint) => {
|
Some(endpoint) => {
|
||||||
info!("NAT mappped to external address {}", endpoint.address);
|
info!("NAT mapped to external address {}", endpoint.address);
|
||||||
endpoint
|
endpoint
|
||||||
},
|
},
|
||||||
None => local_endpoint
|
None => public_endpoint
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
local_endpoint
|
public_endpoint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(addr) => NodeEndpoint { address: addr, udp_port: udp_port }
|
Some(addr) => NodeEndpoint { address: addr, udp_port: local_endpoint.udp_port }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup the server socket
|
self.info.write().unwrap().public_endpoint = Some(public_endpoint.clone());
|
||||||
*tcp_listener = Some(TcpListener::bind(&listen_address).unwrap());
|
info!("Public node URL: {}", self.external_url().unwrap());
|
||||||
self.info.write().unwrap().public_endpoint = public_endpoint.clone();
|
|
||||||
io.register_stream(TCP_ACCEPT).expect("Error registering TCP listener");
|
|
||||||
info!("Public node URL: {}", self.client_url());
|
|
||||||
|
|
||||||
// Initialize discovery.
|
// Initialize discovery.
|
||||||
let discovery = {
|
let discovery = {
|
||||||
let info = self.info.read().unwrap();
|
let info = self.info.read().unwrap();
|
||||||
if info.config.discovery_enabled && !info.config.pin {
|
if info.config.discovery_enabled && !info.config.pin {
|
||||||
Some(Discovery::new(&info.keys, listen_address.clone(), public_endpoint, DISCOVERY))
|
Some(Discovery::new(&info.keys, public_endpoint.address.clone(), public_endpoint, DISCOVERY))
|
||||||
} else { None }
|
} else { None }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -454,6 +464,8 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
io.register_timer(DISCOVERY_ROUND, 300).expect("Error registering discovery timer");
|
io.register_timer(DISCOVERY_ROUND, 300).expect("Error registering discovery timer");
|
||||||
*self.discovery.lock().unwrap().deref_mut() = Some(discovery);
|
*self.discovery.lock().unwrap().deref_mut() = Some(discovery);
|
||||||
}
|
}
|
||||||
|
try!(io.register_stream(TCP_ACCEPT));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maintain_network(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
fn maintain_network(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
||||||
@ -567,7 +579,7 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
fn accept(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
fn accept(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
||||||
trace!(target: "network", "Accepting incoming connection");
|
trace!(target: "network", "Accepting incoming connection");
|
||||||
loop {
|
loop {
|
||||||
let socket = match self.tcp_listener.lock().unwrap().as_ref().unwrap().accept() {
|
let socket = match self.tcp_listener.lock().unwrap().accept() {
|
||||||
Ok(None) => break,
|
Ok(None) => break,
|
||||||
Ok(Some((sock, _addr))) => sock,
|
Ok(Some((sock, _addr))) => sock,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -861,7 +873,8 @@ impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Messa
|
|||||||
fn timeout(&self, io: &IoContext<NetworkIoMessage<Message>>, token: TimerToken) {
|
fn timeout(&self, io: &IoContext<NetworkIoMessage<Message>>, token: TimerToken) {
|
||||||
match token {
|
match token {
|
||||||
IDLE => self.maintain_network(io),
|
IDLE => self.maintain_network(io),
|
||||||
INIT_PUBLIC => self.init_public_interface(io),
|
INIT_PUBLIC => self.init_public_interface(io).unwrap_or_else(|e|
|
||||||
|
warn!("Error initializing public interface: {:?}", e)),
|
||||||
FIRST_SESSION ... LAST_SESSION => self.connection_timeout(token, io),
|
FIRST_SESSION ... LAST_SESSION => self.connection_timeout(token, io),
|
||||||
FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.connection_timeout(token, io),
|
FIRST_HANDSHAKE ... LAST_HANDSHAKE => self.connection_timeout(token, io),
|
||||||
DISCOVERY_REFRESH => {
|
DISCOVERY_REFRESH => {
|
||||||
@ -945,7 +958,7 @@ impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Messa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().register_socket(event_loop).expect("Error registering discovery socket"),
|
DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().register_socket(event_loop).expect("Error registering discovery socket"),
|
||||||
TCP_ACCEPT => event_loop.register(self.tcp_listener.lock().unwrap().as_ref().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"),
|
TCP_ACCEPT => event_loop.register(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error registering stream"),
|
||||||
_ => warn!("Unexpected stream registration")
|
_ => warn!("Unexpected stream registration")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -986,7 +999,7 @@ impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Messa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().update_registration(event_loop).expect("Error reregistering discovery socket"),
|
DISCOVERY => self.discovery.lock().unwrap().as_ref().unwrap().update_registration(event_loop).expect("Error reregistering discovery socket"),
|
||||||
TCP_ACCEPT => event_loop.reregister(self.tcp_listener.lock().unwrap().as_ref().unwrap(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"),
|
TCP_ACCEPT => event_loop.reregister(self.tcp_listener.lock().unwrap().deref(), Token(TCP_ACCEPT), EventSet::all(), PollOpt::edge()).expect("Error reregistering stream"),
|
||||||
_ => warn!("Unexpected stream update")
|
_ => warn!("Unexpected stream update")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1054,6 +1067,6 @@ fn host_client_url() {
|
|||||||
let mut config = NetworkConfiguration::new();
|
let mut config = NetworkConfiguration::new();
|
||||||
let key = h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2");
|
let key = h256_from_hex("6f7b0d801bc7b5ce7bbd930b84fd0369b3eb25d09be58d64ba811091046f3aa2");
|
||||||
config.use_secret = Some(key);
|
config.use_secret = Some(key);
|
||||||
let host: Host<u32> = Host::new(config);
|
let host: Host<u32> = Host::new(config).unwrap();
|
||||||
assert!(host.client_url().starts_with("enode://101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c@"));
|
assert!(host.local_url().starts_with("enode://101b3ef5a4ea7a1c7928e24c4c75fd053c235d7b80c22ae5c03d145d0ac7396e2a4ffff9adee3133a7b05044a5cee08115fd65145e5165d646bde371010d803c@"));
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,7 @@ fn can_select_public_address() {
|
|||||||
assert!(pub_address.port() == 40477);
|
assert!(pub_address.port() == 40477);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[ignore]
|
||||||
#[test]
|
#[test]
|
||||||
fn can_map_external_address_or_fail() {
|
fn can_map_external_address_or_fail() {
|
||||||
let pub_address = select_public_address(40478);
|
let pub_address = select_public_address(40478);
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! fn main () {
|
//! fn main () {
|
||||||
//! let mut service = NetworkService::<MyMessage>::start(NetworkConfiguration::new_with_port(40412)).expect("Error creating network service");
|
//! let mut service = NetworkService::<MyMessage>::start(NetworkConfiguration::new_local()).expect("Error creating network service");
|
||||||
//! service.register_protocol(Arc::new(MyHandler), "myproto", &[1u8]);
|
//! service.register_protocol(Arc::new(MyHandler), "myproto", &[1u8]);
|
||||||
//!
|
//!
|
||||||
//! // Wait for quit condition
|
//! // Wait for quit condition
|
||||||
|
@ -28,6 +28,7 @@ use io::*;
|
|||||||
pub struct NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
pub struct NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
io_service: IoService<NetworkIoMessage<Message>>,
|
io_service: IoService<NetworkIoMessage<Message>>,
|
||||||
host_info: String,
|
host_info: String,
|
||||||
|
host: Arc<Host<Message>>,
|
||||||
stats: Arc<NetworkStats>,
|
stats: Arc<NetworkStats>,
|
||||||
panic_handler: Arc<PanicHandler>
|
panic_handler: Arc<PanicHandler>
|
||||||
}
|
}
|
||||||
@ -39,15 +40,16 @@ impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'stat
|
|||||||
let mut io_service = try!(IoService::<NetworkIoMessage<Message>>::start());
|
let mut io_service = try!(IoService::<NetworkIoMessage<Message>>::start());
|
||||||
panic_handler.forward_from(&io_service);
|
panic_handler.forward_from(&io_service);
|
||||||
|
|
||||||
let host = Arc::new(Host::new(config));
|
let host = Arc::new(try!(Host::new(config)));
|
||||||
let stats = host.stats().clone();
|
let stats = host.stats().clone();
|
||||||
let host_info = host.client_version();
|
let host_info = host.client_version();
|
||||||
try!(io_service.register_handler(host));
|
try!(io_service.register_handler(host.clone()));
|
||||||
Ok(NetworkService {
|
Ok(NetworkService {
|
||||||
io_service: io_service,
|
io_service: io_service,
|
||||||
host_info: host_info,
|
host_info: host_info,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
panic_handler: panic_handler
|
panic_handler: panic_handler,
|
||||||
|
host: host,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,12 +73,21 @@ impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'stat
|
|||||||
&mut self.io_service
|
&mut self.io_service
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns underlying io service.
|
/// Returns network statistics.
|
||||||
pub fn stats(&self) -> &NetworkStats {
|
pub fn stats(&self) -> &NetworkStats {
|
||||||
&self.stats
|
&self.stats
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Returns external url if available.
|
||||||
|
pub fn external_url(&self) -> Option<String> {
|
||||||
|
self.host.external_url()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns external url if available.
|
||||||
|
pub fn local_url(&self) -> String {
|
||||||
|
self.host.local_url()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<Message> MayPanic for NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
impl<Message> MayPanic for NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
fn on_panic<F>(&self, closure: F) where F: OnPanicListener {
|
||||||
|
@ -315,7 +315,7 @@ impl Session {
|
|||||||
.append(&host.protocol_version)
|
.append(&host.protocol_version)
|
||||||
.append(&host.client_version)
|
.append(&host.client_version)
|
||||||
.append(&host.capabilities)
|
.append(&host.capabilities)
|
||||||
.append(&host.listen_port)
|
.append(&host.local_endpoint.address.port())
|
||||||
.append(host.id());
|
.append(host.id());
|
||||||
self.connection.send_packet(&rlp.out())
|
self.connection.send_packet(&rlp.out())
|
||||||
}
|
}
|
||||||
|
@ -97,21 +97,21 @@ impl NetworkProtocolHandler<TestProtocolMessage> for TestProtocol {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn net_service() {
|
fn net_service() {
|
||||||
let mut service = NetworkService::<TestProtocolMessage>::start(NetworkConfiguration::new_with_port(40414)).expect("Error creating network service");
|
let mut service = NetworkService::<TestProtocolMessage>::start(NetworkConfiguration::new_local()).expect("Error creating network service");
|
||||||
service.register_protocol(Arc::new(TestProtocol::new(false)), "myproto", &[1u8]).unwrap();
|
service.register_protocol(Arc::new(TestProtocol::new(false)), "myproto", &[1u8]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn net_connect() {
|
fn net_connect() {
|
||||||
|
::log::init_log();
|
||||||
let key1 = KeyPair::create().unwrap();
|
let key1 = KeyPair::create().unwrap();
|
||||||
let mut config1 = NetworkConfiguration::new_with_port(30354);
|
let mut config1 = NetworkConfiguration::new_local();
|
||||||
config1.use_secret = Some(key1.secret().clone());
|
config1.use_secret = Some(key1.secret().clone());
|
||||||
config1.nat_enabled = false;
|
|
||||||
config1.boot_nodes = vec![ ];
|
config1.boot_nodes = vec![ ];
|
||||||
let mut config2 = NetworkConfiguration::new_with_port(30355);
|
|
||||||
config2.boot_nodes = vec![ format!("enode://{}@127.0.0.1:30354", key1.public().hex()) ];
|
|
||||||
config2.nat_enabled = false;
|
|
||||||
let mut service1 = NetworkService::<TestProtocolMessage>::start(config1).unwrap();
|
let mut service1 = NetworkService::<TestProtocolMessage>::start(config1).unwrap();
|
||||||
|
let mut config2 = NetworkConfiguration::new_local();
|
||||||
|
info!("net_connect: local URL: {}", service1.local_url());
|
||||||
|
config2.boot_nodes = vec![ service1.local_url() ];
|
||||||
let mut service2 = NetworkService::<TestProtocolMessage>::start(config2).unwrap();
|
let mut service2 = NetworkService::<TestProtocolMessage>::start(config2).unwrap();
|
||||||
let handler1 = TestProtocol::register(&mut service1, false);
|
let handler1 = TestProtocol::register(&mut service1, false);
|
||||||
let handler2 = TestProtocol::register(&mut service2, false);
|
let handler2 = TestProtocol::register(&mut service2, false);
|
||||||
@ -125,14 +125,12 @@ fn net_connect() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn net_disconnect() {
|
fn net_disconnect() {
|
||||||
let key1 = KeyPair::create().unwrap();
|
let key1 = KeyPair::create().unwrap();
|
||||||
let mut config1 = NetworkConfiguration::new_with_port(30364);
|
let mut config1 = NetworkConfiguration::new_local();
|
||||||
config1.use_secret = Some(key1.secret().clone());
|
config1.use_secret = Some(key1.secret().clone());
|
||||||
config1.nat_enabled = false;
|
|
||||||
config1.boot_nodes = vec![ ];
|
config1.boot_nodes = vec![ ];
|
||||||
let mut config2 = NetworkConfiguration::new_with_port(30365);
|
|
||||||
config2.boot_nodes = vec![ format!("enode://{}@127.0.0.1:30364", key1.public().hex()) ];
|
|
||||||
config2.nat_enabled = false;
|
|
||||||
let mut service1 = NetworkService::<TestProtocolMessage>::start(config1).unwrap();
|
let mut service1 = NetworkService::<TestProtocolMessage>::start(config1).unwrap();
|
||||||
|
let mut config2 = NetworkConfiguration::new_local();
|
||||||
|
config2.boot_nodes = vec![ service1.local_url() ];
|
||||||
let mut service2 = NetworkService::<TestProtocolMessage>::start(config2).unwrap();
|
let mut service2 = NetworkService::<TestProtocolMessage>::start(config2).unwrap();
|
||||||
let handler1 = TestProtocol::register(&mut service1, false);
|
let handler1 = TestProtocol::register(&mut service1, false);
|
||||||
let handler2 = TestProtocol::register(&mut service2, true);
|
let handler2 = TestProtocol::register(&mut service2, true);
|
||||||
@ -145,7 +143,7 @@ fn net_disconnect() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn net_timeout() {
|
fn net_timeout() {
|
||||||
let config = NetworkConfiguration::new_with_port(30346);
|
let config = NetworkConfiguration::new_local();
|
||||||
let mut service = NetworkService::<TestProtocolMessage>::start(config).unwrap();
|
let mut service = NetworkService::<TestProtocolMessage>::start(config).unwrap();
|
||||||
let handler = TestProtocol::register(&mut service, false);
|
let handler = TestProtocol::register(&mut service, false);
|
||||||
while !handler.got_timeout() {
|
while !handler.got_timeout() {
|
||||||
|
Loading…
Reference in New Issue
Block a user